Log4j
Log4j
通过配置文件(log4j.xml或log4j.properties)控制日志的输出,包括输出格式、输出形式、输出级别等,主要组件是apache的log4jjar包和配置文件;
一、组件:log4j jar包和配置文件
二、应用步骤
(1)在classpath下添加配置文件
(2)class内引入 import
org.apache.log4j.Logger
(3)声明一个logger private static
Logger logger = Logger.getLogger(ClassName.class);
(4)在程序中的相应位置加入输出信息:logger.info("用户登录:"+user.getAccount());
三、配置文件说明
1、 log4j.rootCategory=INFO, stdout , R
此句为将等级为INFO的日志信息输出到stdout和R这两个目的地,stdout和R的定义在下面的代码,可以任意起名。
等级可分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,如果配置OFF则不打出任何信息,如果配置为INFO这样只显示INFO, WARN, ERROR的log信息,而DEBUG信息不会被显示,优先级:ALL < DEBUG < INFO <WARN < ERROR < FATAL < OFF2、 log4j.appender.stdout=org.apache.log4j.ConsoleApp此句为定义名为stdout的输出端是哪种类型,可以是
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
3、
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
此句为定义名为stdout的输出端的layout是哪种类型,可以是
org.apache.log4j.HTMLLayout(以HTML表格形式布局,
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串,
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息
4、 log4j.appender.stdout.layout.ConversionPattern= [QC]
%p [%t] %C.%M(%L) | %m%n
如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern,打印参数如下:
%m 输出代码中指定的消息;
%M 输出打印该条日志的方法名;
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL;
%r 输出自应用启动到输出该log信息耗费的毫秒数;
%c 输出所属的类目,通常就是所在类的全名;
%t 输出产生该日志事件的线程名;
%n 输出一个回车换行符,Windows平台为"rn”,Unix平台为"n”;
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-dd HH:mm:ss,SSS},输出类似:2002-10-18
22:10:28,921;
%l 输出日志事件的发生位置,及在代码中的行数;
[QC]是log信息的开头,可以为任意字符,一般为项目简称。
输出的信息:[TS] DEBUG [main]
AbstractBeanFactory.getBean(189) | Returning cached instance of singleton bean
'MyAutoProxy'
6、
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender 此句与第3行一样。定义名为R的输出端的类型为每天产生一个日志文件。
7、 log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log 此句为定义名为R的输出端的文件名和路径为D:\\Tomcat 5.5\\logs\\qc.log可以自行修改。
以下是设置框架包中日志级别
这些包的设置可根据项目的实际情况而自行定制。
8、 log4j.logger.com. neusoft =DEBUG 指定com.neusoft包下的所有类的等级为DEBUG。
9、 log4j.logger.com.opensymphony.oscache=ERROR
10、log4j.logger.net.sf.navigator=ERROR 这两句是把这两个包下出现的错误的等级设为ERROR,如果项目中没有配置EHCache,则不需要这两句。
11、 log4j.logger.org.apache.commons=ERROR
12、 log4j.logger.org.apache.struts=WARN 这两句是struts的包。
13、log4j.logger.org.displaytag=ERROR 这句是displaytag的包。(QC问题列表页面所用)
14、 log4j.logger.org.springframework=DEBUG
此句为Spring的包。
15、log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
16、log4j.logger.org.hibernate=DEBUG 此两句是hibernate的包。
四、配置文件解
Log4j支持两种配置文件格式,一种是XML(标准通用标记语言下的一个应用)格式的文件,一种是Java特性文件log4j.properties(键=值)。
下面将介绍使用log4j.properties文件作为配置文件的方法:
①、配置根Logger Logger 负责处理日志记录的大部分操作。
其语法为: log4j.rootLogger =
[ level ] , appenderName, appenderName, …
其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的总开关。比如在这里定义了INFO级别,只有等于及高于这个级别的才进行处理,则应用程序中所有DEBUG级别的日志信息将不被打印出来。ALL:打印所有的日志,OFF:关闭所有的日志输出。 appenderName就是指定日志信息输出到哪个地方。可同时指定多个输出目的地。
②、配置日志信息输出目的地 Appender
Appender 负责控制日志记录操作的输出。
其语法为:
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.optionN = valueN
这里的appenderName为在①里定义的,可任意起名。
其中,Log4j提供的appender有以下几种:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),可通过log4j.appender.R.MaxFileSize=100KB设置文件大小,还可通过log4j.appender.R.MaxBackupIndex=1设置为保存一个备份文件。
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
例如:log4j.appender.stdout=org.apache.log4j.ConsoleAppender
定义一个名为stdout的输出目的地,ConsoleAppender为控制台。
③、配置日志信息的格式布局Layout Layout 负责格式化Appender的输出。
其语法为:
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
…
log4j.appender.appenderName.layout.optionN = valueN
其中,Log4j提供的layout有以下几种:
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
格式化日志信息
Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下:
%m 输出代码中指定的消息;
%M 输出打印该条日志的方法名;
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL;
%r 输出自应用启动到输出该log信息耗费的毫秒数;
%c 输出所属的类目,通常就是所在类的全名;
%t 输出产生该日志事件的线程名;
%n 输出一个回车换行符,Windows平台为"rn”,Unix平台为"n”;
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-dd HH:mm:ss,SSS},输出类似:2002-10-18
22:10:28,921;
%l 输出日志事件的发生位置,及在代码中的行数。
另:log4j.appender.FILE.Threshold Threshold是个全局的过滤器,它将把低于所设置的level的信息过滤不显示出来。
五、log4j.properties与log4j.xml
log4j.properties配置文件,配置简单,但不支持复杂过滤器filter,log4j.xml虽然配置文件看似复杂,但支持复杂过滤器和Log4j的新特性。推荐使用log4j.xml
1、路径问题:d:/log/abc.log 可以指定但分隔符是斜线 不是windows特有的反斜线
2、如果在程序中使用log.setLevel(Level.DEBUG);设置了日志级别 会覆盖配置文件中配置的日志级别
附上log4j.xml示例:
<?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> <!--过滤器设置输出的级别--> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <param name="levelMin" value="debug" /> <param name="levelMax" value="warn" /> <param name="AcceptOnMatch" value="true" /> </filter> </appender> <appender name="myFile" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="D:/output.log" /><!-- 设置日志输出文件名 --> <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 --> <param name="Append" value="true" /> <param name="MaxBackupIndex" value="10" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%p (%c:%L)- %m%n" /> </layout> </appender> <appender name="activexAppender" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="E:/activex.log" /> <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{MMdd HH:mm:ss SSS\} %-5p] [%t] %c{3\} - %m%n" /> </layout> </appender> <!-- 指定logger的设置,additivity指示是否遵循缺省的继承机制--> <logger name="com.runway.bssp.activeXdemo" additivity="false"> <priority value ="info"/> <appender-ref ref="activexAppender" /> </logger> <!-- 根logger的设置--> <root> <priority value ="debug"/> <appender-ref ref="myConsole"/> <appender-ref ref="myFile"/> </root> </log4j:configuration>
六、Log4j启动过程
除了Log4j之外,还需要一个common-logging来协同进行日志记录。common-logging是一个日志的管理框架,具体的事情还是交由log4j来进行记录。
源码:
Logger getLogger(Class clazz)
{
return LogManager.getLogger(clazz.getName());
}
转入LogManager,首先应该注意的是这个类的static块, 这个块其实就是一个加载log4j配置文件的过程。即在程序启动之初,在JVM需要加载这个类时,这个初始化块会自动运行,并且加载整个配置,以完成log4j的启动。
Java代码
Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
......
OptionConverter.selectAndConfigure(url, configuratorClassName,
LogManager.getLoggerRepository());
上面的所有代码均完成两件事,第一件事就是构造一个ROOT的Logger对象,此对象作为所有logger对象的最上层,其它logger的相应属性均从这个对象进行继承或改写,就好像java里的继承一样,这个类是内定的,不能由配置文件直接指定,且root都是在最顶层的,其他logger均在此下,这样形成一个完整的logger树。下层可以引用上层,上层管理下层。 第二件事则是去寻找配置文件的地址信息,通过各种方法都寻找log4j.xml或log4j.properties文件,然后对文件进行解析。(在此处,通过properties文件进行解析)
Java代码
OptionConverter.void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy)
这个方法会最终通过指定的文件解析类(此处是PropertyConfigurator)进行解析,转入。
Java代码
configurator.doConfigure(url, hierarchy)
这个方法将,url转化成一个properties对象,进行解析。
Java代码
doConfigure(props, hierarchy); 进入这个方法
Java代码
String value = properties.getProperty(LogLog.DEBUG_KEY);//即log4j.debug
if(value == null)
value = properties.getProperty("log4j.configDebug");
if(value != null)
LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
上面方法读取一个关于log4j自身的debug Level信息,主要用于log4j内部在解析时调用(因为log4j还不能使用logger对象进行写信息,它用到一个LogLog的类,来模拟logger记录,用于在自身解析的过程中输出一些信息),一般来说,这个都用不到。
主要的信息集中在以下三句话:
Java代码
configureRootCategory(properties, hierarchy);
configureLoggerFactory(properties);
parseCatsAndRenderers(properties, hierarchy);
configureRootCategory(properties, hierarchy);
configureLoggerFactory(properties);
parseCatsAndRenderers(properties, hierarchy);
第一句话用于解析root根对象上的相关配置。
第二句话用于解析loggerFactory(factory用于创建logger对象)
第三句话用于解析除rootLogger之外的其他logger以及render信息。
当然上面这个方法,即不是尽为rootLogger服务,对于其他logger也调用这个方法,故上面在解析Level时,对root作了单独判断(因为rootLogger的Level不能为空,至少均需要一个值)。处理Level,即将level值简单设置在logger上即可以了。
接下来即解析appender信息,通过紧接着level后面的字符串,按列表方式进行解析,然后将appender加入logger的appenderList(即要进行信息处理的监听器表)中。进入parseAddpender(解析appender)即是解析appender对象,通过log4j.appender.X的前缀(X表示在rootLogger后的appender名称)来取得appender类名,并尝试实例化,然后根据appender来判断是否需要再解析appender的layout(即log4j.appender.X.layout这个键),解析并设置相应属性,最后分别解析appender本身的属性信息和layout的属性信息。(通过ProperSetter这个类,根据javaBean属性映射,将指定后缀后的信息当作一个键,后缀在属性文件中的值作为指定键的值,并将这个键值映射,通过javaBean设置到相应的对象上)至此,rootLogger即解析完毕。
第二句:解析loggerFactory,略。
第三句:解析其他logger信息。
至此,整个log4j的配置信息已经完成,而这个配置是由JVM保证线程化的(即只能被加载一次),在使用时整个配置已经加载成功,得到的已经是从配置信息中得到的logger对象了。
七、Log4j加载配置文件位置的顺序:
默认情况下,log4j 会自动加载classpath 中的配置文件。而且没有打包的log4j.properties 优先于大在jar 包中的log4j.properties 文件。
加载顺序:
1 Trying to find [" + resource + "] using context classloader
" + classLoader + "." 加载本工程中的配置文件
2 Trying to find [" + resource + "] using " + classLoader
+ " class loader. 加载jar 包中的配置文件
3 Trying to find [" + resource + "] using
ClassLoader.getSystemResource(). 加载系统类路径的配置文件
八、日志级别三层过滤:根记录器,子记录器,Appender的Threshold配置级别
所有包中都会使用logger.debug(),logger.info(),logger.warn(),logger.error()来设置不同级别的日志记录,那么什么样的日志才会被打印出来呢?
按照日志记录过滤的顺序来看:根据记录器配置的级别,大于这个级别的将被记录,小于的过滤掉以后也不会被记录;
主记录器设定的级别,如果对同一包配置子记录器,不管级别高低,子记录器级别会覆盖根记录器级别;
然后Appender的Threshold配置级别,如果级别高于记录器级别 则按此级别输出,否则按记录器级别输出;