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即可。
- 使用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起來~