log4j配置总结

转载请注明文章出处:https://ssrvps.org/archives/4332

log4j是阿帕奇日志服务(Apache Logging Services)旗下的一款强大的开源日志输出工具。log4j使用上简洁便利,高效且拓展性强,几乎是Java编程的必备依赖包。除Java专用的log4j,阿帕奇日志服务网站还有log4net、log4php等其他编程语言对应的包。

项目使用log4j作为日志组件,出于细分日志的需求,要对配置文件做较大变动。之前对一些概念理解不是很到位,趁此机会抽空回顾官方的教程,收获不少。因项目使用的1.2系列的jar包,本文整理自1.2版本的官方文档。

重要概念

先回顾log4j中的三个重要概念:logger、appender和layout。三者合力决定日志是否应该输出、输出到哪里、输出格式是什么。

Logger

logger是输出日志的对象实例。除根logger外,其余均是命名logger,通常以调用的类名为其名字。名字中的点(.)是log4j划分层级的依据(与包package的组织方式相同),例如名字为com.tlanyan的logger是com.tlanyan.service的logger的父级。

根logger是logger中的特殊存在,原因有三:

  1. 它总是存在,无需手动创建;
  2. 它的输出等级不能为空(null);
  3. 不能通过名字获取其引用,只能通过Logger.getRootLogger获取。

信息分为六种等级:trace、debug、info、warn、error和fatal,分别对应Logger类的六个打印方法。等级之间有大小关系,trace等级最低,fatal最高。

理解logger的层级和继承是正确使用log4j的关键,即log4j不能确定某个值时,默认会向上回溯直到找到根logger。例如根logger的appender默认总是被子logger继承,会导致子logger中的信息多次输出,冗余又低效;子级的level继承自父级,低于父级的信息会被无意间过滤,等等。

Appender

appender是日志输出的目的地,每个appender是实现了Appender接口的类具现化实例。常用的appender类有:

  1. FileAppender及其子类:将日志输出到文件中;
  2. ConsoleAppender,将日志输出到标准输出;
  3. JDBCAppender,将日志保存到数据库。

除了配置常规属性值,appender中一个重要的特性是过滤器(filter)。过滤器对到达appender的信息做进一步过滤,最终确定是否输出。常用的过滤器有LevelRangeFilterStringMatchFilter

Layout

layout(布局)隶属于appender,对信息进行输出前的格式化。例如增加打印时间,调用的文件名、线程等,或者按照xml格式输出日志。最常用的布局是PatternLayout,可配置的成员变量是ConversionPattern,格式与C语言中的printf函数相同,具体含义请参考官方文档。

配置

配置log4j的方式主要有三种:1. 通过程序代码;2. 键值对形式的properties配置文件;3. xml配置文件。后两者简单易懂,且支持修改文件后配置即时生效,建议采用。

layout在appender中配置,所以配置文件主要由两部分组成:logger和appender。xml文件格式良好,层级关系更明显,相对properties文件本人更偏爱xml格式。下面是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="INFO" class="org.apache.log4j.RollingFileAppender">
        <param name="File" value="./logs/app-info.log"/>
        <param name="Append" value="true"/>
        <param name="MaxFileSize" value="50MB"/>
                 <param name="MaxBackupIndex" value="10"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%-5r][%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l %m%n"/>
        </layout>
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="LevelMin" value="INFO"/>
            <param name="LevelMax" value="INFO"/>
        </filter>
    </appender>

    <appender name="pay" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="./logs/pay-data.log"/>
        <param name="DatePattern" value="'.'yyyy-MM-dd"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%-5r][%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l %m%n"/>
        </layout>
    </appender>

    <appender name="ERROR" class="org.apache.log4j.RollingFileAppender">
        <param name="File" value="./logs/app-error.log"/>
        <param name="Append" value="true"/>
        <param name="MaxFileSize" value="50MB" />
        <param name="MaxBackupIndex" value="20" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%-5r][%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l %m%n"/>
        </layout>
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="LevelMin" value="WARN"/>
            <param name="LevelMax" value="ERROR"/>
        </filter>
    </appender>

    <logger name="com.tlanyan.pay" additivity="false">
        <level value="info"/>
        <appender-ref ref="pay"/>
    </logger>

    <root>
        <level value="info"/>
        <appender-ref ref="INFO"/>
        <appender-ref ref="ERROR"/>
    </root>

</log4j:configuration>

配置文件定义了三个appender,两个logger。注意根logger没有名字,要用root来引用。名字为pay的logger不继承父级(additivity="false"),所以其中的信息不会输出到app-info.log中。

建议在程序入口配置log4j并监听配置文件:

 DOMConfigurator.configureAndWatch("config/log4j.xml", 10000L);

通过监听文件变化,可实现配置在修改后即时生效,无需改动代码,也无需重启程序。

参考

  1. http://logging.apache.org/log4j/1.2/manual.html
  2. http://logging.apache.org/log4j/1.2/apidocs/index.html
留言评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Captcha Code