Threshold

log4j提供了Appender的Threshold属性,可以设置该appender输出什么级别的日志。看一个例子:

log4j.rootLogger=info,stdout,infolog,warnlog,errorlog

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{MM-dd HH:mm:ss}] [%p] [%c:%L] %m%n

log4j.appender.infolog = org.apache.log4j.DailyRollingFileAppender
log4j.appender.infolog.Threshold = INFO
log4j.appender.infolog.File = /data/logs/logtest/test.log
log4j.appender.infolog.layout = org.apache.log4j.PatternLayout
log4j.appender.infolog.layout.ConversionPattern = [%d{MM-dd HH:mm:ss}] [%p] [%c:%L] %m%n

log4j.appender.warnlog = org.apache.log4j.DailyRollingFileAppender
log4j.appender.warnlog.Threshold = WARN
log4j.appender.warnlog.File = /data/logs/logtest/test_warn.log
log4j.appender.warnlog.layout = org.apache.log4j.PatternLayout
log4j.appender.warnlog.layout.ConversionPattern = [%d{MM-dd HH:mm:ss}] [%p] [%c:%L] %m%n

log4j.appender.errorlog = org.apache.log4j.DailyRollingFileAppender
log4j.appender.errorlog.Threshold = ERROR
log4j.appender.errorlog.File = /data/logs/logtest/test_error.log
log4j.appender.errorlog.layout = org.apache.log4j.PatternLayout
log4j.appender.errorlog.layout.ConversionPattern = [%d{MM-dd HH:mm:ss}] [%p] [%c:%L] %m%n

经过测试发现,在test.log文件中同时输出了info、warn和error级别的日志,test_warn.log中也同时输出了warn、error级别的日志。原因是因为:log4j.appender.D.Threshold 表示打印大于、等于该级别的日志,由于ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF,所以warn、error级别日志在info中也打印了出来。

上面的结果显然不是我们想要的,因为这样的话相当于info日志中含有所有的日志信息,不但造成冗余,而且也会让warn日志跟error日志显得没有存在的必要。更多的情况下我们希望info日志中只有INFO级别的日志,warn日志中只有WARN级别的日志,同样error日志中也只有ERROR级别的日志。

解决方案

1、log4j的filter:

log4j.rootLogger=info,stdout,infolog,warnlog,errorlog

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{MM-dd HH:mm:ss}] [%p] [%c:%L] %m%n

log4j.appender.infolog = org.apache.log4j.DailyRollingFileAppender
log4j.appender.infolog.Threshold = INFO
log4j.appender.infolog.File = /data/logs/logtest/test.log
log4j.appender.infolog.layout = org.apache.log4j.PatternLayout
log4j.appender.infolog.layout.ConversionPattern = [%d{MM-dd HH:mm:ss}] [%p] [%c:%L] %m%n
log4j.appender.infolog.filter.infoFilter = org.apache.log4j.varia.LevelRangeFilter
log4j.appender.infolog.filter.infoFilter.LevelMin = INFO
log4j.appender.infolog.filter.infoFilter.LevelMax = INFO

log4j.appender.warnlog = org.apache.log4j.DailyRollingFileAppender
log4j.appender.warnlog.Threshold = WARN
log4j.appender.warnlog.File = /data/logs/logtest/test_warn.log
log4j.appender.warnlog.layout = org.apache.log4j.PatternLayout
log4j.appender.warnlog.layout.ConversionPattern = [%d{MM-dd HH:mm:ss}] [%p] [%c:%L] %m%n
log4j.appender.warnlog.filter.warnFilter = org.apache.log4j.varia.LevelRangeFilter
log4j.appender.warnlog.filter.warnFilter.LevelMin = WARN
log4j.appender.warnlog.filter.warnFilter.LevelMax=WARN

log4j.appender.errorlog = org.apache.log4j.DailyRollingFileAppender
log4j.appender.errorlog.Threshold = ERROR
log4j.appender.errorlog.File = /data/logs/logtest/test_error.log
log4j.appender.errorlog.layout = org.apache.log4j.PatternLayout
log4j.appender.errorlog.layout.ConversionPattern = [%d{MM-dd HH:mm:ss}] [%p] [%c:%L] %m%n

经测试,上面的配置可以实现:info级别的日志只在test.log中打印;error级别的只打印在test_error.log中,warn级别的打印在test_warn.log中。

2、重写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.threshold == null && priority.isGreaterOrEqual(this.threshold) && this.getThreshold().isGreaterOrEqual(priority);
}
}

接下来在log4j.properties文件中修改log4j.appender.info=com.xxx.MyLog4jAppender即可。