做了很多项目,系统的LOG记录一直用LOG4J,但一直是网上搜索复制使用,包括级别的配置也是在网上找现成的,虽然大概知道如何配置,但对其原理并不是很清楚。当前项目要求按级别配置多个LOG文件,包括系统的BUG、错误、业务日志、系统操作日志均使用LOG4J配置,今天花了几小时去深入了解了下LOG4J,受益良多。
- LOG4J简要说明
简单废话几句吧,Log4j是Apache的一个开放源代码项目,通过LOG4J可以将内容输出到控制台或写入磁盘文件,非常方便系统的LOG记录与代码调试,当然也支持自定义输出格式,自定义配置输入内容等等,总之,LOG4J非常之方便。 - LOG4J基本配置说明
基本配置:
#配置根Logger
log4j.rootLogger=[level],appenderName1,appenderName2, …
#配置日志信息输出目的地Appender
log4j.appender.appenderName=
fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1=value1 …
log4j.appender.appenderName.optionN=valueN
#配置日志信息的格式(布局)
log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1=value1 …
log4j.appender.appenderName.layout.optionN=valueN
[level] 是日志输出级别,共有5级:Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。如果设置级别为INFO,则优先级高于等于INFO级别(如:INFO、WARN、ERROR)的日志信息将可以被输出,小于该级别的如DEBUG将不会被输出。
FATAL 0
ERROR 3
WARN 4
INFO 6
DEBUG 7
Appender 为日志输出目的地,Log4j提供的appender有以下几种:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
Layout:日志输出格式,Log4j提供的layout有以下几种:
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
打印参数: Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,如下:
%m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},输出类似:2002年10月18日 22 : 10 : 28 , 921
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java: 10 )
- 企业级应用配置
按级别输出日志到不同文件位置
网上贴的最多的log4j.properties的设置是这样的
log4j.rootLogger=info,stdout,info,debug,error
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n
log4j.logger.info=info
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n
log4j.appender.info.datePattern='.'yyyy-MM-dd
log4j.appender.info.Threshold = INFO
log4j.appender.info.append=true
log4j.appender.info.File=${webApp.root}/WEB-INF/logs/info.log
log4j.logger.debug=debug
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n
log4j.appender.debug.datePattern='.'yyyy-MM-dd
log4j.appender.debug.Threshold = DEBUG
log4j.appender.debug.append=true
log4j.appender.debug.File=${webApp.root}/WEB-INF/logs/debug.log
log4j.logger.error=error
log4j.appender.error=org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.layout=org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n
log4j.appender.error.datePattern='.'yyyy-MM-dd
log4j.appender.error.Threshold = ERROR
log4j.appender.error.append=true
log4j.appender.error.File=${webApp.root}/WEB-INF/logs/error.log
而实际上这部分代码解决不了按照LOG4J的级别文件进行文件输出。而它的作用是输出INFO级别以上的内容到${webApp.root}/WEB-INF/logs/info.log中,所以info.log文件中包含了ERROR级别的文件。
正确的解法是:
定义自己的Appender类,继承DailyRollingFileAppender,改写针对Threshold 的设置说明。
源代码记载:
public boolean isAsSevereAsThreshold(Priority priority){
return threshold == null || priority.isGreaterOrEqual(threshold);
}
重写 isAsSevereAsThreshold(Priority priority)方法
public class LogAppender extends DailyRollingFileAppender {
@Override
public boolean isAsSevereAsThreshold(Priority priority) {
//只判断是否相等,而不判断优先级
return this.getThreshold().equals(priority);
}
}
这样,进行唯一判断,只有当Threshold与priority一致时,才进行输出,就实现了真正Log4j按照级别输出日志文件。
在log4j.properties中,将配置文件作如下修改:
log4j.logger.info=info
log4j.appender.info=com.company.LogAppender
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n
log4j.appender.info.datePattern='.'yyyy-MM-dd
log4j.appender.info.Threshold = INFO
log4j.appender.info.append=true
log4j.appender.info.File=${webApp.root}/WEB-INF/logs/info.log
到此,即完成了按照Log4j按照日志级别输出到不同文件中的功能。
整理很网朋友讲解:
http://blog.csdn.net/projava/article/details/7344839
http://www.blogjava.net/zJun/archive/2006/06/28/55511.html
http://blog.sina.com.cn/s/blog_9c7ba64d01012z02.html
2015/03/01更新
针对以上,我找到了一个解决办法。
配置文件具体代码如下:
log4j.rootLogger=info,stdout,info,error
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-ddHH\:mm\:ss}[%-5p\:%r][%F\:%-3L]%x%m%n
log4j.logger.info=info
log4j.appender.info=com.ronglian.util.DailyRollingFileAppender
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%-d{yyyy-MM-ddHH\:mm\:ss}[%-5p\:%r][%F\:%-3L]%x%m%n
log4j.appender.info.Threshold=INFO
log4j.appender.info.append=true
log4j.appender.info.File=e\:/bgisample/logs/info/info.log
log4j.logger.error=error
log4j.appender.error=com.ronglian.util.DailyRollingFileAppender
log4j.appender.error.layout=org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern=%-d{yyyy-MM-ddHH\:mm\:ss}[%-5p\:%r][%F\:%-3L]%x%m%n
log4j.appender.error.Threshold=ERROR
log4j.appender.error.append=true
log4j.appender.error.File=e\:/bgisample/logs/error/error.log
###Systemlog###
log4j.logger.syslog=INFO,syslog,stdout
log4j.additivity.syslog=false
log4j.appender.syslog=com.ronglian.util.DailyRollingFileAppender
log4j.appender.syslog.File=e\:/bgisample/logs/sys/sys.log
log4j.appender.syslog.Threshold=INFO
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern=%-d{yyyy-MM-ddHH\:mm\:ss}[%-5p\:%r][%F\:%-3L]%x%m%n
###Systemlog###
log4j.logger.bizlog=INFO,bizlog,stdout
log4j.additivity.bizlog=false
log4j.appender.bizlog=com.ronglian.util.DailyRollingFileAppender
log4j.appender.bizlog.File=e\:/bgisample/logs/biz/biz.log
log4j.appender.bizlog.Threshold=INFO
log4j.appender.bizlog.layout=org.apache.log4j.PatternLayout
log4j.appender.bizlog.layout.ConversionPattern=%-d{yyyy-MM-ddHH\:mm\:ss}[%-5p\:%r][%F\:%-3L]%x%m%n
测试代码:
private static Logger log1 = Logger.getLogger(SysLogAspectAdvice.class);
private static Logger log2 = Logger.getLogger(SysLogAspectAdvice.class);
private static Logger log3 = Logger.getLogger(SysLogAspectAdvice.class);
private static Logger log4 = Logger.getLogger("syslog");
private static Logger log5 = Logger.getLogger("bizlog");
public static void main(String[] args) {
log1.info("info");
log2.debug("debug");
log3.error("error");
log4.info("syslog");
log5.info("bizlog");
}
输出效果: