Log4j的使用

  OK,現在我們開始研究Log4j。Log4j是目前應用最廣泛的日誌空間,它分如下幾個日誌級別,日誌級別依次升高。級別高的level會屏蔽級別低的信息。
  TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF。
  比如設置INFO級別,TRACE,DEBUG就不會輸出,如果設置WARNING級別,則TRACE,DEBUG,INFO都不會輸出。
  Log4j初體驗
  現在我們編碼嘗試下Log4j。代碼如下:

package org.linkinpark.commons.logtest;  

import org.apache.log4j.Logger;  

public class Log4jTest  
{  

    public static Logger log = Logger.getLogger(Log4jTest.class);  

    /** 
     * @創建時間: 2016年2月22日 
     * @相關參數: 
     * @功能描述: 定義一個輸出日誌的方法 
     * <p> 
     * trace→debug→info→warn→error→fatal→off 
     * 級別依次升高,級別高的level會屏蔽級別低的level。 
     * </p> 
     */  
    public static void logTest()  
    {  
        log.trace("trace級別的日誌輸出");  
        log.info("info級別的日誌輸出");  
        log.debug("debug級別的日誌輸出");  
        log.warn("warn級別的日誌輸出");  
        log.error("error級別的日誌輸出");  
        log.fatal("fatal級別的日誌輸出");  
        try  
        {  
            System.out.println(9 / 0);  
        }  
        catch (RuntimeException e)  
        {  
            log.error(e.getMessage());  
        }  
    }  

    public static void main(String[] args)  
    {  
        logTest();  
    }  

}  

  這裏我們用maven來管理我們該測試項目,需要添加log4j的pom依賴。

<dependency>  
            <groupId>log4j</groupId>  
            <artifactId>log4j</artifactId>  
            <version>1.2.17</version>  
        </dependency>  

  日誌的配置例如輸出級別,輸出到哪裏,輸出什麼附加信息,輸出格式等,一般都要寫在配置文件log4j.properties中。

#   可設置級別:TRACE→DEBUG→INFO→WARNING→ERROR→FATAL→OFF  
#   高級別level會屏蔽低級別level。  
#   debug:顯示debug、info、error     
#   info:顯示info、error     

#log4j.rootLogger=DEBUG,console,file  
log4j.rootLogger=INFO,console  


#輸出到控制檯     
log4j.appender.console=org.apache.log4j.ConsoleAppender    
#設置輸出樣式     
log4j.appender.console.layout=org.apache.log4j.PatternLayout   
#日誌輸出信息格式爲  
log4j.appender.console.layout.ConversionPattern=[%-d{yyyy-MM-dd HH:mm:ss}]-[%t-%5p]-[%C-%M(%L)]: %m%n   

#輸出到文件(這裏默認爲追加方式)     
#log4j.appender.file=org.apache.log4j.FileAppender   
#log4j.appender.file.File=F:/LinkinPark/logs/Log4J.log   
#樣式爲TTCCLayout     
#log4j.appender.file.layout=org.apache.log4j.TTCCLayout    

#自定義樣式     
#%c 輸出所屬的類目,通常就是所在類的全名   
#%C 輸出Logger所在類的名稱,通常就是所在類的全名   
#%d 輸出日誌時間點的日期或時間,默認格式爲ISO8601,也可以在其後指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},%d{ABSOLUTE},%d{DATE}  
#%F 輸出所在類的類名稱,只有類名。  
#%l 輸出語句所在的行數,包括類名+方法名+文件名+行數  
#%L 輸出語句所在的行數,只輸出數字  
#%m 輸出代碼中指定的訊息,如log(message)中的message  
#%M 輸出方法名  
#%p 輸出日誌級別,即DEBUG,INFO,WARN,ERROR,FATAL  
#%r 輸出自應用啓動到輸出該log信息耗費的毫秒數  
#%t 輸出產生該日誌事件的線程名  
#%n 輸出一個回車換行符,Windows平臺爲“/r/n”,Unix平臺爲“/n”  
#%% 用來輸出百分號“%”  
#log4j.appender.Linkin.layout.ConversionPattern=%n[%l%d{yy/MM/dd HH:mm:ss:SSS}][%C-%M] %m    
#log4j.appender.Linkin.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss}[%C]-[%p] %m%n     
#log4j.appender.Linkin.layout.ConversionPattern = %d{ABSOLUTE} %5p %t %c{2}:%L - %m%n  

  OK,現在讓我們來看看控制檯輸出的日誌情況。

[2016-02-22 22:33:35]-[main- INFO]-[org.linkinpark.commons.logtest.Log4jTest-logTest(22)]: info級別的日誌輸出  
 [2016-02-22 22:33:35]-[main- WARN]-[org.linkinpark.commons.logtest.Log4jTest-logTest(24)]: warn級別的日誌輸出  
 [2016-02-22 22:33:35]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(25)]: error級別的日誌輸出  
 [2016-02-22 22:33:35]-[main-FATAL]-[org.linkinpark.commons.logtest.Log4jTest-logTest(26)]: fatal級別的日誌輸出  
 [2016-02-22 22:33:35]-[main-ERROR]-[org.linkinpark.commons.logtest.Log4jTest-logTest(33)]: / by zero  

  Log4j的使用十分靈活,功能也很強大。可以在配置文件中配置輸出樣式,可以把日誌輸出到屏幕,控制檯,各種樣式的文件,數據庫,FTP服務器,HTTP服務器,遠程實時監控程序,發送郵件到指定的郵箱,甚至是發送短信等。
  
  Log4J的應用

  Log4J是Apache的一個開源項目,通過使用Log4J,我們可以控制日誌信息輸送的目的地,輸出格式,通過設置日誌信息的級別還可以細緻地控制日誌的生成過程。
  1,Log4j的執行效率
  Log4j內部做了大量的優化,緩存工作,是輸出時對服務器的壓力,消耗時間,資源等都達到最小,比如下面2行代碼:

log.debug("debug級別的日誌輸出");  
log.info("info級別的日誌輸出"); 

  這兩句日誌可能被記錄到日誌文件中,但是寫的過程不同於常規的打開文件,寫文件,關閉文件等流程,頻繁的打開文件,關閉文件需要消耗大量的資源。Log4j只在初始化的時候打開文件,並保持對文件的寫控制,知道在系統結束的時候纔會關閉文件。這樣就使I/O次數達到最小,提高了運行效率。

  當輸出級別設置爲ERROR時,debug,info等低級別方法會因爲輸出級別小於error而直接返回,所以不會消耗太多的資源。這裏我們來看下debug()方法內部的實現代碼:

public void debug(Object message)  
    {  
        if (repository.isDisabled(Level.DEBUG_INT))  
            return;  
        if (Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel()))  
        {  
            forcedLog(FQCN, Level.DEBUG, message, null);  
        }  
    }  

  2,優化日誌代碼
  雖然設爲ERROR時debug()會直接返回,但是下面的代碼仍然會消耗額外的時間,原因是在執行debug()前,需要先將字符串進行連接。

log.debug("debug級別的日誌輸出"+i+"*"+j); // 有字符串拼接  

  如果想要避免這種消耗,最好使用isDebugEnabled()或者isEnabledFor()判斷一下,比如下面代碼:

if (log.isDebugEnabled())  
        {  
            log.debug("debug級別的日誌輸出");  
        }  
        if (log.isEnabledFor(Level.DEBUG))  
        {  
            log.debug("debug級別的日誌輸出");  
        }  

  3,log4j配置文件
  Log4j默認的配置文件爲log4j.properties。啓動時,會加載classpath下的log4j.properties初始化Log4j。如果文件不存在,Log4j會在控制檯打印如下信息,提示說沒有找到Log4j配置。比如我們現在只保留Java代碼,然後刪除掉log4j.properties配置文件,看控制檯報錯。

log4j:WARN No appenders could be found for logger (org.linkinpark.commons.logtest.Log4jTest).  
log4j:WARN Please initialize the log4j system properly.  
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.  

  OK,現在重新將log4j.properties配置文件加入到我們的項目classpath中,然後控制檯輸出日誌正常。這裏一定要注意要加載項目的Classpath中,在這裏我們隨便寫寫測試類,所以直接丟項目src下面就好了,編譯過後配置文件自動就放到了class的根目錄下了。
這裏寫圖片描述
  當然我們也可以使用其他的方式,只不過不推薦罷了。如果不使用默認的文件名log4j.properties,可以用PropertyConfigurator指定配置文件的路徑。比如下面的代碼,經過測試可行。當然還可以使用log4j.xml,只不過要在xml裏面加入log4j的secma,不推薦。這裏貼出使用Java類加載指定配置文件的代碼:

public static void logTest()  
    {  
        PropertyConfigurator.configure("/Users/LinkinPark/WorkSpace/linkin-log-test/src/main/java/org/linkinpark/commons/logtest/log4j.properties");  
        if (log.isDebugEnabled())  
        {  
            log.debug("debug級別的日誌輸出");  
        }  
    }  

  這裏也貼出PropertyConfigurator類configure()方法源碼:

static public void configure(String configFilename)  
    {  
        new PropertyConfigurator().doConfigure(configFilename, LogManager.getLoggerRepository());  
    }  


    public void doConfigure(String configFileName, LoggerRepository hierarchy)  
    {  
        Properties props = new Properties();  
        FileInputStream istream = null;  
        try  
        {  
            istream = new FileInputStream(configFileName);  
            props.load(istream);  
            istream.close();  
        }  
        catch (Exception e)  
        {  
            if (e instanceof InterruptedIOException || e instanceof InterruptedException)  
            {  
                Thread.currentThread().interrupt();  
            }  
            LogLog.error("Could not read configuration file [" + configFileName + "].", e);  
            LogLog.error("Ignoring configuration file [" + configFileName + "].");  
            return;  
        }  
        finally  
        {  
            if (istream != null)  
            {  
                try  
                {  
                    istream.close();  
                }  
                catch (InterruptedIOException ignore)  
                {  
                    Thread.currentThread().interrupt();  
                }  
                catch (Throwable ignore)  
                {  
                }  


            }  
        }  
        // If we reach here, then the config file is alright。嫁入到log4j中去了。  
        doConfigure(props, hierarchy);  
    }  

  OK,log4j的配置文件內容還是比較多的,我們下一篇來詳細的整理。這篇先這樣。



  這個世界上沒有知識是學不會的,不是嗎?如果一開始學不會,就可以把問題細化分解,然後學習更基本的知識。最後,所有問題都能變得和1+1=2一樣簡單,我們需要的只是時間。好了,最後給大家推薦一個學習Java的好網站JAVA自學網站–how2j.cn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章