1. 程式人生 > >Log4j各級別日誌重複列印的問題

Log4j各級別日誌重複列印的問題

今天在配置Log4j日誌的時候,發現日誌重複列印的問題。網上查了很多資料,發現介紹Log4j配置的文章數量不少,但提到這個問題的文章卻寥寥,解決了自己的問題以後,趕緊記錄一下。

本文基於log4j 1.2.17版本進行說明

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

一、問題描述

先來看一下日誌配置檔案:

#root日誌
log4j.rootLogger=INFO,stdout,info,warn,error

#控制檯日誌
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=%d %-5p %c{1}:%L - %m%n

#info級別日誌
log4j.appender.info=org.apache.log4j.RollingFileAppender log4j.appender.info.Threshold=INFO log4j.appender.info.File=/home/info.log log4j.appender.info.MaxFileSize=200MB log4j.appender.info.MaxBackupIndex=5 log4j.appender.info.layout=org.apache.log4j.PatternLayout log4j.appender.info.layout.ConversionPattern
=%d %-5p %l - %m%n #warn級別日誌 log4j.appender.warn=org.apache.log4j.RollingFileAppender log4j.appender.warn.Threshold=WARN log4j.appender.warn.File=/home/warn.log log4j.appender.warn.MaxFileSize=200MB log4j.appender.warn.MaxBackupIndex=5 log4j.appender.warn.layout=org.apache.log4j.PatternLayout log4j.appender.warn.layout.ConversionPattern=%d %-5p %l - %m%n #error級別日誌 log4j.appender.error=org.apache.log4j.RollingFileAppender log4j.appender.error.Threshold=ERROR log4j.appender.error.File=/home/error.log log4j.appender.error.MaxFileSize=200MB log4j.appender.error.MaxBackupIndex=5 log4j.appender.error.layout=org.apache.log4j.PatternLayout log4j.appender.error.layout.ConversionPattern=%d %-5p %l - %m%n

上面這個log4j.properties配置檔案是個非常常規的檔案,網上大多數講解Log4j配置資訊的文章也都是基於這樣一個模板展開的。

使用這套配置,毫無疑問日誌是可以正常列印的,但問題就是log4j.appender.info.Threshold指定的級別表示列印等於或者大於這個級別的日誌,這樣一來當執行下面程式碼的時候

Logger LOG = LoggerFactory.getLogger(Test.class);
LOG.info("info");
LOG.warn("warn");
LOG.error("error");

我們看到的現象是:
/home/info.log檔案中會列印info,warn,error三行日誌;
/home/warn.log檔案中會列印warn,error兩行;
/home/error.log檔案中只會列印error一行日誌。

上面的結果顯然不是我們想要的,因為這樣的話相當於info日誌中含有所有的日誌資訊,不但造成冗餘,而且也會讓warn日誌跟error日誌顯得沒有存在的必要。更多的情況下我們希望info日誌中只有INFO級別的日誌,warn日誌中只有WARN級別的日誌,同樣error日誌中也只有ERROR級別的日誌。

二、解決辦法

這裡提供兩種解決方案:
1. 重寫RollingFileAppender類中的isAsSevereAsThreshold方法。

預設的isAsSevereAsThreshold方法的實現為:

    public boolean isAsSevereAsThreshold(Priority priority) {
        return this.threshold == null || priority.isGreaterOrEqual(this.threshold);
    }

如果沒有設定threshold屬性則全部列印,否則列印大於等於threshold屬性的日誌。
我們繼承該類並重寫此方法,如下:

public class MyLog4jAppender extends RollingFileAppender {
    @Override
    public boolean isAsSevereAsThreshold(Priority priority) {
        return priority != null && this.getThreshold() != null
                && priority.isGreaterOrEqual(this.getThreshold())
                && this.getThreshold().isGreaterOrEqual(priority);
    }
}

並在log4j.properties檔案中修改log4j.appender.info=com.xxx.MyLog4jAppender即可。

  1. 使用filter進行日誌過濾

這個其實是Log4j自帶的方案,也是推薦方案,不知道為什麼網上的資料卻很少提到這點。
把log4j.properties配置檔案修改成如下:

#root日誌
log4j.rootLogger=INFO,stdout,info,warn,error

#控制檯日誌
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=%d %-5p %c{1}:%L - %m%n

#info級別日誌
log4j.appender.info=org.apache.log4j.RollingFileAppender
log4j.appender.info.Threshold=INFO
log4j.appender.info.File=/home/info.log
log4j.appender.info.MaxFileSize=200MB
log4j.appender.info.MaxBackupIndex=5
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%d %-5p %l - %m%n
log4j.appender.info.filter.infoFilter = org.apache.log4j.varia.LevelRangeFilter
log4j.appender.info.filter.infoFilter.LevelMin=INFO
log4j.appender.info.filter.infoFilter.LevelMax=INFO

#warn級別日誌
log4j.appender.warn=org.apache.log4j.RollingFileAppender
log4j.appender.warn.Threshold=WARN
log4j.appender.warn.File=/home/warn.log
log4j.appender.warn.MaxFileSize=200MB
log4j.appender.warn.MaxBackupIndex=5
log4j.appender.warn.layout=org.apache.log4j.PatternLayout
log4j.appender.warn.layout.ConversionPattern=%d %-5p %l - %m%n
log4j.appender.warn.filter.infoFilter = org.apache.log4j.varia.LevelRangeFilter
log4j.appender.warn.filter.infoFilter.LevelMin=WARN
log4j.appender.warn.filter.infoFilter.LevelMax=WARN

#error級別日誌
log4j.appender.error=org.apache.log4j.RollingFileAppender
log4j.appender.error.Threshold=ERROR
log4j.appender.error.File=/home/error.log
log4j.appender.error.MaxFileSize=200MB
log4j.appender.error.MaxBackupIndex=5
log4j.appender.error.layout=org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern=%d %-5p %l - %m%n
log4j.appender.error.filter.infoFilter = org.apache.log4j.varia.LevelRangeFilter
log4j.appender.error.filter.infoFilter.LevelMin=ERROR
log4j.appender.error.filter.infoFilter.LevelMax=ERROR

通過以上配置模板即可解決各級別日誌重複列印的問題。

今天是1024程式設計師節,兄弟們high起來~