前言
网上关于log4j的配置已经够多的了,我这里就不再说这部分。我重点讲解log4j的结构,原理。
简介
log4j三大组件,logger、appender、layout。
logger:日志器,用于标志某包的日志级别、日志目的地。日志级别、日志目的地对应Logger类中的两个属性,level、appender。
appender:追加器,日志的输出地,每个logger可以有多个追加器,比如控制台、文件、socket、进程等。appender类中有个属性是layout,用来设置日志格式。
layout:格式,有很多种格式,格式是appender类的一个属性。
日志级别有5种,由低到高分别是debug、info、warn、error、fatal
核心思想:
1、log4j有个根Logger,所有的Logger都会继承根Logger,既继承根Logger的日志级别,也继承根Logger的追加器。
关于这一点可以,用面向对象的思想来理解。
2、可以使用properties或xml配置log4j,但我极力推荐xml方式,因为xml能更好的表达继承层次关系。log4j在实现中,也会优先接在log4j.xml,如果没有log4j.xml再去加载log4j.properties
拿下边这个配置文件举例子
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' > <appender name="myConsole" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n" /> </layout> </appender> <logger name="com.mylogger" > <level value ="info"/> </logger> <!-- 根logger的设置--> <root> <level value ="debug"/> <appender-ref ref="myConsole"/> </root> </log4j:configuration>
定义的日志级别为debug,输出到myconsole追加器。其它logger默认级别是debug、追加器是myconsole
如果不定义级别,那么默认级别是debug。
Logger:
com.mylogger定义了日志级别,所以会覆盖继承自根logger的debug级别,但没有定义appender所以继承根logger的MyConsole。一言以盖之,com.mylogger包下,级别大有等于info的日志都会写入到myconsole
如果不想继承父类的appender,可以设置 additivity=false。比如
<logger name="com.mylogger" additivity="false"> <level value ="info"/> </logger>
appender:
追加器。这里只定义了一个。常用的还有FileAppender、RollingFileAppender、DailyRollingFileAppender,另外在appender中需要定义日志输出格式,这些查查api都能查到,我就不再多说。
在Eclipse中,编辑log4j.xml,无法智能提示
解压log4j.jar,在org/apache/log4j/xml中找到log4j.dtd文件,放入log4j.xml同级目录,就会提示了。
可能你会问,log4j.dtd为什么在xml目录下,而不是其它目录,这是因为xml包下的类(DOMConfigurator),需要使用log4j.dtd来校验log4j.xml的合法性。
log写入文件时,需要指定路径,通常使用catalina.home或者catalina.base系统属性。
<appender name="rootAppender" class="org.apache.log4j.FileAppender"> <param name="File" value="${catalina.home}/logs/his.log"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value=" %-4r [%t] %-5p %c %x %d{ISO8601} - %m%n"/> </layout> </appender>
NDC/MDC
在多线程环境下,同一时刻可能输出多条log,客户端与输出的log无法对应,更通俗一点的说法,不知道某条log是哪个客户端输出的。这个过程,专业的名词叫用户的跟踪。可以使用log4j提供的NDC(nested diagnostic context)、MDC(mappeded diagnostic context)来解决。
参考
log4j ibm developer works
NDC、MDC