關於log4j的使用說明

今天要分享的內容是log4j的使用。

每個系統都有日誌記錄,而多數都是用的log4j,以爲會配置了,懂了,發現還是有些細節的問題,要問,說不上來

先來直接看配置吧和測試用例吧

jar包的依賴

    <!-- log4j support -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

log4j.properties文件如下,放在你的web的resource下面,推薦maven標準工程來

### 設置###
log4j.rootLogger = DEBUG,stdout,D,E

log4j.logger.A=DEBUG, stdout
log4j.logger.A.B=INFO, stdout  

### 輸出信息到控制擡 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 輸出DEBUG 級別以上的日誌到=D://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 輸出ERROR 級別以上的日誌到=D://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =D://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

測試用例


import org.apache.log4j.Logger;

/**
 * @author hankun
 * @create 2017-06-06 18:32
 */
public class log4jTtest {
    private static Logger logger = Logger.getLogger(log4jTtest.class);
    private static Logger loggerA = Logger.getLogger("A");
    private static Logger loggerA_B = Logger.getLogger("A.B");

    /**
     * @param args
     */
    public static void main(String[] args) {

        // 記錄debug級別的信息
        logger.debug("This is debug message.");
        // 記錄info級別的信息
        logger.info("This is info message.");
        // 記錄error級別的信息
        logger.error("This is error message.");

        loggerA_B.info("repeat three times in console");
        loggerA.info("repeat two times in console");
        logger.info("repeat one times in console");
    }

}

注意上面的輸出結果,你知道輸出啥內容,則,就真正理解了

[DEBUG] 2017-06-06 19:05:03,477 method:log4jTtest.main(log4jTtest.java:18)
This is debug message.
[INFO ] 2017-06-06 19:05:03,479 method:log4jTtest.main(log4jTtest.java:20)
This is info message.
[ERROR] 2017-06-06 19:05:03,479 method:log4jTtest.main(log4jTtest.java:22)
This is error message.
[INFO ] 2017-06-06 19:05:03,479 method:log4jTtest.main(log4jTtest.java:24)
repeat three times in console
[INFO ] 2017-06-06 19:05:03,479 method:log4jTtest.main(log4jTtest.java:24)
repeat three times in console
[INFO ] 2017-06-06 19:05:03,479 method:log4jTtest.main(log4jTtest.java:24)
repeat three times in console
[INFO ] 2017-06-06 19:05:03,480 method:log4jTtest.main(log4jTtest.java:25)
repeat two times in console
[INFO ] 2017-06-06 19:05:03,480 method:log4jTtest.main(log4jTtest.java:25)
repeat two times in console
[INFO ] 2017-06-06 19:05:03,480 method:log4jTtest.main(log4jTtest.java:26)
repeat one times in console

問題如下

  1. 前面的三個輸出,不用解釋,都明白爲啥
  2. 爲啥那個loggerA_B,輸出了三次,而loggerA輸出了二次,logger輸出了一次?

log4j幾個重要的概念

  • logger組件
    1. 簡單的說,它就是決定了應用程序中,哪些代碼哪些地方,有可能輸出日誌
    2. 這也就是爲什麼,每個類裏面上來,就是,logger的初始化,它決定了這個類有資格輸出日誌
    3. 首先Log4J中總是存在一個rootLogger,即使沒有顯示配置也是存在的,並且默認輸出級別爲DEBUG。
    4. Log4J中的層次是用’.’來分隔的,如log4j.logger.com.example.test,這裏並不是說log4j.logger後面一定是具體的包名乃至類名,
  • appender組件
    1. 輸出地,也就是你的日誌想輸出到哪裏,把上面的logger裏面的日誌
    2. 再簡單點,就是輸出到控制檯和文件裏面,也就是上面的配置stdout和D和E
    3. 這個需要和下面的這個概念配合
  • 輸出控制的概念
    1. Log4j默認把日誌信息分爲五個等級 all debug info warn error fatal off
    2. 只有大於設置的級別,纔會打印日誌,低於則忽略
    3. log4j.appender.threshold=ERROR,這種配置用於控制,一個appender的輸出級別
  • 繼承的概念
    1. log4j.rootLogger=DEBUG, Console
    2. log4j.logger.A=DEBUG, Console
    3. log4j.logger.A.B=INFO, Console
    4. A.B繼承A,再繼承最頂級的root
    5. Log4j是根據Log的名字來判斷繼承關係的

來解釋一下,上面的輸出結果

  1. 首先是,debug,info和error前三個日誌輸出,它們的logger是log4jTtest.class初始化的,繼承根logger,因此就是debug級別,同時因爲還有D和E的兩個appender,所以你在d盤可以看到,有一個info的文件還有一個error的文件,這個日誌輸出沒問題
  2. 然後就是解釋那重複的三個,因爲loggerA_B,它是根據A.B這個參數初始化的,是有繼承的,滿足A.B的info級別的日誌輸出,必然滿足A的logger的日誌輸出,當然還有默認的根輸出,因此三次
  3. 而那個兩次的,它的logger是loggerA,繼承於根,因此,info的時候,它本身輸出一次,根也輸出一次,就是兩次了。
  4. 最後一個,用的是默認的根,當然,只能輸出一次了

問題來了,怎麼避免重複,因爲繼承父的logger?

log4j.additivity.A.B=false
logger A.B的日誌僅會輸出到自己Console中,不會繼承任何父logger的appender。

就加上面的這句,就解決了問題

總結

之前反反覆覆看了很多次,關於日誌log4j的配置,每次看完以爲會了,但是到了項目裏面,總是不知道,自己有時候打印的日誌到底跑哪裏去了,或者去哪裏看?
總結其原因就是,對於細節沒有掌握理解到位,比如就是這個logger的概念,如果你真正的明白了,就知道了

誰能產生日誌?logger

日誌放哪裏?appender

什麼級別的日誌纔會輸出?日誌級別

他們是相互獨立的組件,單獨配置,又是相互配合,一起使用的,n*m的這種概念

因此上面的配置文件,一個logger可以對應多個appender,而appender之間又是彼此獨立的。

發佈了107 篇原創文章 · 獲贊 8 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章