log4j学习
log4j是通用的记录日志开源组件,主要有log4j2、log4j、log4net、log4c++、log4php几个版本,其实现在更流行使用slf4j了,但是slf4j也只是定义了一些接口,具体的日志实现还得靠log4j,logback,commons logging等等,使用它是为了可以方便的切换使用日志的种类,Log4j目前应该是使用最广泛的,本文先介绍log4j,下次介绍log4j2。Log4j官网:http://logging.apache.org/
看下log4j的类图
Logger---日志写出器,供程序员输出日志信息
Appender----日志目的地,把格式化好的日志信息输出到指定的地方去
ConsoleAppender ---目的地为控制台的Appender
FileAppender ---目的地为文件的Appender
RollingFileAppender ---目的地为大小受限的文件的Appender
DailyRollingFileAppender---以时间为周期写日志文件
Layout---日志格式化器,用来把程序员的requestlogging request格式化成字符串
PatternLayout ---用指定的pattern格式化logging request的Layout
Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。日志信息的优先级从高到低有OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、ALL,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;而输出格式则控制了日志信息的显示内容。
使用Log4j的时候,需要设置配置文件,有两种方式log4j.properties,或者log4j.xml,我习惯上喜欢使用xml格式的,看起来就更舒服。开始我们的实验吧,实验中碰到问题,再解决。
本实例是在spring mvc项目中使用log4j记录日志。
第一步、maven引入log4j的jar
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
第二步、web.xml添加相关配置
1、 添加log4j的配置文件路径
方法一、放在项目外,这个路径和tomcat是同级的
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>file:/opt/onlinemarket/config/log4j_onlinemarke_web.xml</param-value>
</context-param>
方法二、配置文件放在项目中,路径:src\main\resources\META-INF\log4j_onlinemarke_web.xml
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:META-INF/log4j_onlinemarke_web.xml
</param-value>
</context-param>
2、添加log4j配置侦听器
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
第三步、log4j_onlinemarke_web.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="LOG.Console" class="org.apache.log4j.ConsoleAppender">
<!--日志输出排版样式-->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{HH:mm:ss,SSS}] %m%n" />
</layout>
<!--配置输出级别过滤器,这里DEBUG到FATAL都会输出到控制台了-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<!--param name="LevelMin" value="FATAL" /--><!--生产时为FATAL、本地为INFO -->
<param name="LevelMin" value="DEBUG" />
<param name="LevelMax" value="FATAL" />
</filter>
</appender>
<!--配置文本文件输出-->
<appender name="LOG.onlinemarketweb" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="/opt/logs/onlinemarket/onlinemarket-web/onlinemarket-web.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<param name="append" value="true" />
<param name="encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d] [%-5p] %c{2} - %m%n" />
</layout>
</appender>
<!--以下是引用外部jar包中的日志输出级别及输出的方式,也可以不配置-->
<!-- additivity指示是否叠加输出log,如果是false,
在org.springframework logger中日志不会被其它logger满足条件的logger(比如root设置成level是debug,这里是info的,只输出info以上级别的输出 -->
<logger name="org.springframework" additivity="true">
<level value="INFO" />
<appender-ref ref="LOG.Console" />
<appender-ref ref="LOG.onlinemarketweb" />
</logger>
<logger name="java.sql" additivity="true">
<level value="INFO" />
<appender-ref ref="LOG.Console" />
<appender-ref ref="LOG.onlinemarketweb" />
</logger>
<logger name="com.ibatis">
<level value="debug" />
<appender-ref ref="LOG.Console" />
<appender-ref ref="LOG.onlinemarketweb" />
</logger>
<logger name="com.ibatis.common.jdbc.SimpleDataSource">
<level value="debug" />
<appender-ref ref="LOG.Console" />
<appender-ref ref="LOG.onlinemarketweb" />
</logger>
<logger name="com.ibatis.common.jdbc.ScriptRunner">
<level value="debug" />
<appender-ref ref="LOG.Console" />
<appender-ref ref="LOG.onlinemarketweb" />
</logger>
<logger name="com.ibatis.common.jdbc.SqlMapClientDelegate">
<level value="debug" />
<appender-ref ref="LOG.Console" />
<appender-ref ref="LOG.onlinemarketweb" />
</logger>
<logger name="java.sql.Connection">
<level value="debug" />
</logger>
<logger name="java.sql.Statement">
<level value="debug" />
</logger>
<logger name="java.sql.PreparedStatement">
<level value="debug" />
</logger>
<logger name="java.sql.ResultSet">
<level value="debug" />
</logger>
<!--根log级别及输出方式,各个logger如果不另行配置则继承根log的配置-->
<root>
<level value="INFO" />
<appender-ref ref="LOG.Console" />
<appender-ref ref="LOG.onlinemarketweb" />
</root>
</log4j:configuration>
相关配置说明:
1、关于Appender
1).ConsoleAppender选项
Threshold=WARN:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
Target=System.err:默认情况下是:System.out,指定输出控制台
2).FileAppender选项
Threshold=WARN:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
File=mylog.txt:指定消息输出到mylog.txt文件。
Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
3).DailyRollingFileAppender选项
Threshold=WARN:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
File=mylog.txt:指定消息输出到mylog.txt文件。
Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
DatePattern='.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。当然也可以指定按月、周、天、时和分。即对应的格式如下:
1)'.'yyyy-MM: 每月
2)'.'yyyy-ww: 每周
3)'.'yyyy-MM-dd: 每天
4)'.'yyyy-MM-dd-a: 每天两次
5)'.'yyyy-MM-dd-HH: 每小时
6)'.'yyyy-MM-dd-HH-mm: 每分钟
4).RollingFileAppender选项
Threshold=WARN:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
File=mylog.txt:指定消息输出到mylog.txt文件。
Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
MaxFileSize=100KB: 后缀可以是KB, MB或者是 GB.在日志文件到达该大小时,将会自动滚动,即将原来的内容移到mylog.log.1文件。
MaxBackupIndex=2:指定可以产生的滚动文件的最大数。
2、关于layout
1). log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
"fully.qualified.name.of.layout.class" 可以指定下面4个格式中的一个:
a.org.apache.log4j.HTMLLayout(以HTML表格形式布局)
b.org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
c.org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
d.org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
1.HTMLLayout选项
LocationInfo=true:默认值是false,输出java文件名称和行号
Title=my app file:默认值是 Log4J Log Messages.
2.PatternLayout选项
ConversionPattern=%m%n :指定怎样格式化指定的消息。
3.XMLLayout 选项
LocationInfo=true:默认值是false,输出java文件和行号
2). log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
这里需要说明的就是日志信息格式中几个符号所代表的含义:
-X号: X信息输出时左对齐;
%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%r: 输出自应用启动到输出该log信息耗费的毫秒数
%c: 输出日志信息所属的类目,通常就是所在类的全名
%t: 输出产生该日志事件的线程名
%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%: 输出一个"%"字符
%F: 输出日志消息产生时所在的文件名称
%L: 输出代码中的行号
%m: 输出代码中指定的消息,产生的日志具体信息
%n: 输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"输出日志信息换行
可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
1)%20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。
2)%-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,"-"号指定左对齐。
3)%.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
4)%20.30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边交远销出的字符截掉。
第四步、代码中的用法
Logger logger=Logger.getLogger(Log4jAction.class);
//代码设置appender,layout,level
// Appender newAppender=new FileAppender();
// Layout layout=new Layout() {
//
// @Override
// public void activateOptions() {
// // TODO Auto-generated method stub
//
// }
//
// @Override
// public boolean ignoresThrowable() {
// // TODO Auto-generated method stub
// return false;
// }
//
// @Override
// public String format(LoggingEvent arg0) {
// // TODO Auto-generated method stub
// return null;
// }
// };
// newAppender.setLayout(layout);
// logger.addAppender(newAppender);
// Level level=Level.INFO;
// logger.setLevel(level);
logger.debug("log debug");
logger.trace("log trace");
logger.info("log info");
logger.warn("log warn");
logger.error("log error");
logger.fatal("log fatal");
总结:
如果在程序运行中输出大量日志,显然会对应用的性能造成一定的影响。Log4J对性能的影响取决于以下因素:
日志输出目的地:输出到控制台的速度和输出到文件系统的速度是不一样的。
日志输出格式:格式简单,速度也更快。
日志级别:日志级别设置的越低,输出的日志内容越多,对性能的影响也越大。
所以,我们一般记录一下关键业务日志,尽量少对系统的性能造成影响。