Log4j必知必会

1、简要介绍

       Log4j是Apache提供的一个开源日志操作包,其功能十分强大,操作极其简单,所以很多开源项目和企业级开发过程中都会选择它作为日志记录工具。据说Jakarta小组曾建议Sun公司使用log4j作为JDK1.4的日志工具,但没有被采纳。后来他们开发了common logging兼容log4j和jdk的logging,common logging对不同log框架进行了简单的封装,日志输出的时候都是调用具体的框架,本身并不提供统一的定义文件,由各log框架自定义配置文件。

      Log4j主要由三个重要组件组成:1)Logger,核心组件代表了log4j的日志记录器,能够对日志信息进行分类筛选,决定什么日志信息被输出、什么日志信息应该忽略;2)Appender,指定日志信息输出地方,可以是控制台、文件、数据库等;3)Layout,指定日志信息输出格式。

       写程序的过程中,我们会在很多可能出错的地方输出大量的日志信息。当程序调试完成后便不需要这些信息,如果手工一个个删,对大型程序来说费时费力,不太可行。通过日志分级,加入不想输出INFO级别的日志信息,则将Logger组件的级别调高即可。log4j一共有五种日志级别:fatal、error、warn、info、debug。

       Log4j提供了一个root logger作为所有logger的“祖先”(如同Java中的Object类),它永远存在,且不能通过名字引用,而是Logger.getRootLogger()方法取得。可在配置文件中方便配置存在继承关系的Logger组件,凡是在符号"."后面的组件都会成为符号"."前面logger组件的子类。如果子类logger没有定义日志级别,则将继承父类的日志级别,如果定义了,就不会继承父类日志级别。默认情况下,子类logger会继承父类所有的appender,把它们加入到自己的appender。如果把子类logger组件的additivity标识设置成false,那它就不会继承父类appender。默认additivity值为false。


2、基本使用方法

      a)定义配置文件

       对于log4j的配置,它支持java properties文件和xml文件,建议使用后者,因为filter等功能properties文件不支持。主要涉及定义appender、logger和root logger。

       logger标签子元素level标识输出最低级别(默认是debug),appender-ref则引用配置中的appender,可以多个;其属性name是标识,additivity表示在层级关系中是否向上查找。

        appender标签有两个重要的子标签便是layout和filter。        

        layout表示日志输出的格式,log4j支持的layout有TTCCLayout, HTMLLayout, PatternLayout, SimpleLayout和XMLLayout,常用的是PatternLayout,性能最好的是SimpleLayout(因为它足够 simple)。PatternLayout支持的模式选项说明如下:

%m:输出日志消息内容.
%p: 输出日志事件的priority(DEBUG、INFO等).
%r: 输出自程序启动后到当前的时间差,似乎用处不大。
%c: 输出category名称,也就是getLogger函数的参数,用处也不大。
%t: 输出当前的线程名,一些多线程环境中或许用的上。

      下面的参数有性能问题,对性能要求高的场景需要做好度量。

%d: 输出时间,可以指定时间格式,比如 %d{HH:mm:ss,SSS} 或 %d{dd MMM yyyy HH:mm:ss,SSS}等。
%C: 输出调用日志类方法者的fully-qualified类名,默认是输出全路径(也就是包名+类名),也可以限定{n}表示输出全称的最后n个部分,比如”com.foo.SomeClass”, 模式%C{1}将输出”SomeClass”。
%M:输出调用日志类方法者的方法名。
%F: 输出调用日志类方法者的文件名。
%L: 输出调用日志类方法者的行号。
%l: 输出调用日志类方法者的源代码位置,它是%C.%M(%F:%L)的简称。


        上面的输出选项中,和调用者位置相关的选项会有性能问题。这是因为,为了得到这些信息,log4j调用 Throwable.getStackTrace()来得到整个调用过程的栈信息,自底向上比较调用的函数名,直到找到日志函数(debug等)的上一级函数名,然后通过反射得到一系列位置信息。这个过程显然要比其他几项的取得复杂的多,但它对分析日志查找问题却是很有用的。我的一个建议是,对于info 级别的日志,就不需要打出调用位置等信息,对于debug、warning和error则需要。另一个,输出时间也是很有必要的,否则做统计查问题都无从下手。

        log4j中的filter可以指定appender要输出的日志等级范围,这可以实现在应用中把不同等级的日志打到不同文件中。像debug、info 级别,每天会产生很多,也多用来做统计分析;而warning和error级别的日志是需要监控处理的,并且人还有可能上去查看;所以把两者分开就显得很有必要。对于有特别需求的日志,也可以单独打到一个文件里去。下面是使用filter的一个样例:

<appender name="TRACE" class="org.apache.log4j.ConsoleAppender">
      <layout class="org.apache.log4j.PatternLayout">
              <param name="ConversionPattern" value="[%t] %-5p %c - %m%n" />
      </layout>
      <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="levelMin" value="DEBUG" />
            <param name="levelMax" value="INFO" />
          </filter>
          <filter class="org.apache.log4j.varia.DenyAllFilter" />
</appender>


       LevelRangeFilter可以指定某个范围(从levelMin到levelMax)的等级,在上面的配置中,如果没有 DenyAllFilter,表示从DEBUG到INFO级别的日志不做处理,而加了DenyAllFilter后含义反转,表示该appender只打印从DEBUG到INFO的日志。log4j中另一个实用的filter是LevelMatchFilter,它准确的匹配某个日志等级。

       下面是一个比较完整的xml格式log4j配置文件,请参考:

<?xml version='1.0' encoding='GBK' ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--dtd_and_header_are_useless-->

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- ===================================================================== -->
<!-- 以下是appender的定义 -->
<!-- ===================================================================== -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
       <layout class="org.apache.log4j.PatternLayout">
           <param name="ConversionPattern" value="[%7r] %6p - %30.30c - %m \n" />
       </layout>
       <filter class="org.apache.log4j.varia.LevelRangeFilter">
          <param name="LevelMin" value="INFO" />
          <param name="LevelMax" value="FATAL " />
       </filter>
</appender>
<appender name="PROJECT" class="org.apache.log4j.DailyRollingFileAppender">
       <param name="file" value="/export/home/tomcat/logs/jss_open_web.haha0832.com/project/jss-web.log" />
       <param name="append" value="false" />
       <param name="encoding" value="GBK" />
       <param name="threshold" value="info" />
       <layout class="org.apache.log4j.PatternLayout">
       <param name="ConversionPattern"
                   value="%d [%X{requestURIWithQueryString}] %-5p %C.%M(%F:%L) - %m%n" />
  </layout>
</appender>

  <!-- Declare the SMTPAppender -->
    <appender name="EMAIL"  class="com.jd.jss.shared.log.CustomSMTPAppender">
        <param name="Threshold" value="ERROR"/>
        <param name="BufferSize" value="128" />
        <param name="SMTPHost" value="mail.360buy.com" />
        <param name="From" value="boss_error@haha0832.com" />
        <param name="SMTPUsername" value="boss_error" />
        <param name="SMTPPassword" value="CLOUD_2012" />
        <param name="To" value="huanggang@haha0832.comluoshi@haha0832.com,cdzhoujianjun@haha0832.comqingting@haha0832.com" />
        <param name="Subject" value="[JSS Open Web Production SMTPAppender]JSS OPEN Error Msg." />
        <layout class="org.apache.log4j.PatternLayout">         
              <param name="ConversionPattern" value="[%d{ISO8601}]  %-5p %C.%M(%F:%L) %c %m%n"/>
        </layout>
    </appender>
<!-- ===================================================================== -->
<!-- 以下是logger的定义 -->
<!-- ===================================================================== --> 
<logger name="com.jd" additivity="false">
      <level value="ERROR" />
      <appender-ref ref="jssWebAppender" />
      <appender-ref ref="CONSOLE" />
      <appender-ref ref="EMAIL" />
</logger> 


<!-- ===================================================================== -->
<!-- Root logger的定义 -->
<!-- ===================================================================== -->
<root>
      <level value="ERROR" />
      <appender-ref ref="PROJECT" />
      <appender-ref ref="CONSOLE" />
      <appender-ref ref="EMAIL" />
</root>
</log4j:configuration>


      b)程序中使用日志      

      在程序中使用Log4j之前,首先要将commons-logging-1.1.1.jar和logging-log4j-1.2.6.jar导入到classpath中,并将log4j.properties放于src根目录中。接下来就可以使用了。

       使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:public static Logger getLogger( String name), 通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。Name一般取本类的名字,比如: static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;

注:推荐使用commons-logging结合log4j进行日志记录 
private static Log logger = LogFactory.getLog(Yourclass.class);

       当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方,要想记录详细的错误堆栈信息,需使用log.error(message,throwable);这个方法,其语法如下: 
      Logger.debug ( Object message ) ; 
      Logger.info ( Object message ) ; 
      Logger.warn ( Object message ) ; 
      Logger.error ( Object message ) ;

      对于web程序,spring它提供了一个初始化log4j的监听类,当然你也可以自已写个servlet初始化log4j。在spring框架中,可以在web.xml配置一个监听类来初始化log4j。spring2.5的监听类配置:

<context-param>  
     <param-name>log4jConfigLocation</param-name>  
     <param-value>/WEB-INF/classes/log4j.properties</param-value> 
</context-param>  
<listener>  
      <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> 
</listener>

3、注意事项

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值