Log4j2详解

介绍

Apache Log4j 2是对Log4j的升级,它比其前身Log4j 1提供了显著的改进。并提供了许多在Logback中可用的改进,同时修复了Logback体系结构中的一些固有问题。

日志等级

共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF

  • All:最低等级的,用于打开所有日志记录.

  • Trace:追踪,指定细粒度比DEBUG更低的信息事件。

  • Debug:指出细粒度信息事件对调试应用程序是非常有帮助的.

  • Info:消息在粗粒度级别上突出强调应用程序的运行过程.

  • Warn:输出警告及warn以下级别的日志.

  • Error:输出错误信息日志.

  • Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志.

  • OFF:最高等级的,用于关闭所有日志记录.

配置全解

默认配置文件(XML)

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorinterval="5">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="error">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

配置属性详解(xml)

Configuration

Configuration有两个属性:status 和 monitorinterval

  • status: 用来指定log4j本身的打印日志的级别.

  • monitorinterval: 用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s。

Appenders

Appender负责将LogEvents传递到目的地。每个Appender都必须实现Appender接口,常用的有三种子节点:Console、RollingFile、File。

Loggers

Loggers节点,常见的有两种:Root和Logger.

Console

Console节点用来定义输出到控制台的Appender.

  • name:指定Appender的名字.

  • target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT.

  • PatternLayout:输出格式,不设置默认为:%m%n.

说明

常用的格式

  • %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)的组合,包括类目名、发生的线程,以及在代码中的行数
  • %x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中
  • %%:输出一个"%"字符
  • %F:输出日志消息产生时所在的文件名称
  • %L:输出代码中的行号
  • %m:输出代码中指定的消息,产生的日志具体信息
  • %n:输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"输出日志信息换行

可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。

  • %20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。
  • %-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,"-"号指定左对齐。
  • %.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
  • %20.30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边较远输出的字符截掉。

<!--这个输出控制台的配置-->
<Console name="Console" target="SYSTEM_OUT">
    <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>

File

FileAppender用于将日志写入到一个文件中,该文件由fileName参数指定。有几个重要的参数:

  • name:指定Appender的名字

  • fileName:指定输出日志的目的文件带全路径的文件名。

  • append:默认为true,记录追加到文件的最后,否则就先清除以前的记录再写入

  • bufferedIO:默认true,记录将会写入到缓存区,当缓存区满的时候,就会写入磁盘。或者如果设置immediateFlush将会立即写入。文件锁定不能和bufferedIO一起使用

  • bufferSize:当bufferedIO设置为true时,默认是8192 bytes

  • locking:是否对文件上锁,当有多个线程可能同时写该文件时需要考虑上锁,但对文件上锁会影响系统的性能,所以需要谨慎使用。默认值是false

  • PatternLayout:输出格式,不设置默认为:%m%n


<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->
<!--append = true : 保留启动前的日志,追加新日志,false: 清空原有日志-->
<File name="log" fileName="log/all.log" append="true">
    <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>

完整参数见官网

RollingFile

RollingFileAppender是一个非常有意思的输出器。它将日志信息写入一个文件后,会判断是否满足封存文件的要求,若满足,则除非封存文件的动作。RollingFileAppender需要TriggeringPolicy来指定触发封存的条件,另外还需要RolloverStrategy来告诉输出器如何封存文件。

  • name:指定Appender的名字

  • fileName:指定输出日志的目的文件带全路径的文件名。

  • append:默认为true,记录追加到文件的最后,否则就先清除以前的记录再写入

  • bufferedIO:默认true,记录将会写入到缓存区,当缓存区满的时候,就会写入磁盘。或者如果设置immediateFlush将会立即写入。文件锁定不能和bufferedIO一起使用

  • bufferSize:当bufferedIO设置为true时,默认是8192 bytes

  • locking:是否对文件上锁,当有多个线程可能同时写该文件时需要考虑上锁,但对文件上锁会影响系统的性能,所以需要谨慎使用。默认值是false

  • PatternLayout:输出格式,不设置默认为:%m%n

  • filePattern:新建文件名称格式和路径

说明

  • filePattern文件名若以.gz结尾,文件会被压缩
  • filePattern文件名若以.log结尾,文件不会被压缩
  • Policies:是组合滚动日志策略的标签,指定滚动日志的策略,就是什么时候进行新建日志文件输出日志

  • Filters: 是组合过滤器的标签,它包含的子标签是具体的过滤器

 <RollingFile name="RollingFileInfo" fileName="logs/info.log"
             filePattern="logs/info-%d{yyyy-MM-dd HH-mm}-%i.log.gz">
    <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
    <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
    <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
    <Policies>
        <!--4分钟rollover一次-->
        <TimeBasedTriggeringPolicy interval="4"/>
        <!--文件大小-->
        <SizeBasedTriggeringPolicy size="1 MB"/>
    </Policies>
    <!--文件数量-->
    <DefaultRolloverStrategy max="3"/>
</RollingFile>

Policies 滚动日志的策略

  • TimeBasedTriggeringPolicy

说明

基于时间的滚动策略

  • 此参数需要与filePattern结合使用,规定了触发rollover的频率,默认值为1。
  • 假设interval为4,若filePattern的最小时间粒度为小时(如yyyy-MM-dd HH),则每4小时触发一次rollover。
  • 假设interval为2,若filePattern的最小时间粒度为小时(如yyyy-MM-dd HH:mm ),则每2分钟触发一次rollover。
  • 指明是否对interval进行调节,默认为false。若modulate为true,会以0为开始对interval进行偏移计算。例如,最小时间粒度为小时,当前为3:00,interval为4,则以后触发rollover的时间依次为4:00,8:00,12:00,16:00,...。
<RollingFile>
    <!--单独使用-->
    <!--<TimeBasedTriggeringPolicy interval="4"/>-->
    <!--组合使用-->
    <Policies>
        <TimeBasedTriggeringPolicy interval="4"/>
    </Policies>
</RollingFile>

  • SizeBasedTriggeringPolicy

说明

基于指定文件大小的滚动策略

  • 这一触发策略基于对log文件大小的判断。当log文件大于设定的阈值时,将触发封存动作。可设定的log文件大小的单位有bytes、KB、MB或GB。
<RollingFile>
    <!--单独使用-->
    <!--<SizeBasedTriggeringPolicy size="1 MB"/>-->
    <!--组合使用-->
    <Policies>
        <SizeBasedTriggeringPolicy size="1 MB"/>
    </Policies>
</RollingFile>

  • OnStartupTriggeringPolicy

说明

  • 它会自行判断log文件的创建时间和JVM的启动时间。若log文件的创建时间早于JVM的启动时间,则将原来的log文件封存,然后创建一个新的空白log文件。
  • minSize:文件必须滚动的最小大小。无论文件大小如何,0大小都会导致滚动。默认值是1,这将防止滚动一个空文件。
<RollingFile>
    <!--单独使用-->
    <!--<OnStartupTriggeringPolicy/>-->
    <!--组合使用-->
    <Policies>
        <OnStartupTriggeringPolicy />
    </Policies>
</RollingFile>

  • CompositeTriggeringPolicy

说明

复合型触发策略

  • 对应标签Policies
  • 即将多个触发条件组合到一起,这些触发条件是或的关系,只要其中一个条件满足,则触发封存动作。
<RollingFile>
    <Policies>
       <TimeBasedTriggeringPolicy interval="4"/>
       <SizeBasedTriggeringPolicy size="1 MB"/>
   </Policies>
</RollingFile>

RolloverStrategy

  • DefaultRolloverStrategy

说明

文件命名模式下保留文件的个数

  • fileIndex:有两个选择“max”或“min”。设置为“max”意味着将最新的日志信息封存在序号较大的封存文件中。“min”则相反。默认为max
  • min: 封存文件的序号的起始值,默认值为1
  • max: 封存文件的序号的最大值
  • compressionLevel:压缩等级,0-9,只对zip有效

假设fileIndex设置为min,min属性设置为1,max属性设置为3,文件名是“foo”。,文件名模式为“foo-%i.log”,最新的日志在index小的文件中。

  • rollover=0时,所有日志都输入到foo.log中
  • rollover=1时,foo.log会重命名为foo-1.log,并创建新的foo.log的文件写入
  • rollover=2时,foo-1.log会重命名为foo-2.log,foo.log会重命名为foo-1.log,并创建新的foo.log的文件写入
  • rollover=3时,foo-2.log会重命名为foo-3.log,foo-1.log会重命名为foo-2.log,foo.log会重命名为foo-1.log,并创建新的foo.log的文件写入
  • rollover=4时,foo-3.log文件会被删除,foo-2.log会重命名为foo-3.log,foo-1.log会重命名为foo-2.log,foo.log会重命名为foo-1.log,并创建新的foo.log的文件写入

假设fileIndex设置为max,min属性设置为1,max属性设置为3,文件名是“foo”。,文件名模式为“foo-%i.log”,最新的日志在index大的文件中。

  • rollover=0时,所有日志都输入到foo.log中
  • rollover=1时,foo.log会重命名为foo-1.log,并创建新的foo.log的文件写入
  • rollover=2时,foo.log会重命名为foo-2.log,并创建新的foo.log的文件写入
  • rollover=3时,foo.log会重命名为foo-3.log,并创建新的foo.log的文件写入
  • rollover=4时,foo-1.log文件会被删除,foo-2.log会重命名为foo-1.log,foo-3.log会重命名为foo-2.log,foo.log会重命名为foo-3.log,并创建新的foo.log的文件写入

<RollingFile>
    <DefaultRolloverStrategy max="3"/>
</RollingFile>

  • Delete on Rollover

说明

  • 2.5+引入删除操作,该操作使用户能够控制在翻转时删除哪些文件,而不是使用DefaultRolloverStrategy max属性。
  • Delete操作允许用户配置一个或多个条件,这些条件选择要相对于基本目录删除的文件。
  • basePath:扫描日志文件根路径,必须配置
  • maxDepth:日志文件可见的层级,默认为1,最大值为Integer.MAX_VALUE,若为1,只扫描根目录下的文件,若为MAX_VALUE扫描所有层级的文件。
  • IfFileName:删除的条件之一,文件名称匹配
  • IfLastModified:删除的条件之一,文件最后修改时间匹配
  • IfAny:要保留的文件
  • IfAccumulatedFileSize:按文件大小保留最近文件,exceeds="100 GB",保留最近100GB的文件
  • IfAccumulatedFileCount:按文件数量,exceeds="10",保留最近的10个文件

<DefaultRolloverStrategy>
    <Delete basePath="logs_2" maxDepth="2">
        <IfFileName glob="*/info-*.log.gz"/>
        <IfLastModified age="60d"/>
        <!--要保留的文件-->
        <IfAny>
            <IfAccumulatedFileSize exceeds="100 GB" />
            <IfAccumulatedFileCount exceeds="10" />
        </IfAny>
    </Delete>
</DefaultRolloverStrategy>

更多Rollover见官网

filters

说明

日志过滤器

  • onMatch和onMismatch可选的值分别是,ACCEPT(接受), DENY(拒绝), NEUTRAL(中立)
  • Accept意味着其他的Filter都不应该再被调用,而事件应该被处理。
  • Deny意味着事件应该被立即忽略,且将控制讲给调用处。
  • Neutral代表事件应该被传递给其他的Filter。如果没有其他Filter,则事件将被处理。
  • ThresholdFilter

说明

日志等级过滤器

  • level:日志等级,比如debug,info等
<RollingFile>
    <!--单独使用-->
    <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
    <!--<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>-->
    <!--组合使用-->
    <filters>
        <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
    </filters>
</RollingFile>

  • RegexFilter

说明

正则过滤器

  • regex:正则表达式

<RollingFile>
    <!--单独使用-->
    <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
    <!--<RegexFilter regex="*.pay.*" onMatch="ACCEPT" onMismatch="DENY"/>-->
    <!--组合使用-->
    <filters>
        <RegexFilter regex="*.pay.*"  onMatch="ACCEPT" onMismatch="DENY"/>
    </filters>
</RollingFile>

  • TimeFilter

说明

时间段过滤器

  • start:开始时间
  • end:截止时间

<RollingFile>
    <!--单独使用-->
    <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
    <!--<TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="DENY"/>-->
    <!--组合使用-->
    <filters>
        <TimeFilter start="05:00:00" end="05:30:00" onMatch="ACCEPT" onMismatch="DENY"/>
    </filters>
</RollingFile>

更多Filters见官网

loggers

  • Root节点来指定项目的根日志,如果没有单独指定Logger,那么默认使用Root日志输出

说明

  • 定义的appender必须要在loggers里面声明才能生效
  • level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
  • AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender.
<Loggers>
    <Root level="info">
        <AppenderRef ref="Console" />
    </Root>
</Loggers>

  • Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
<Loggers>
    <Root level="info">
        <AppenderRef ref="Console" />
    </Root>
</Loggers>

说明

时间段过滤器

  • level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
  • name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.
  • AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。
  • logger async 用的是无锁并发技术,必须引入Disruptor
  • includeLocation:位置信息,比如哪个类默认为true

<Loggers>
    <!--同步-->
    <Logger name="com.itxiaoer.logging.pay" level="trace" additivity="false">
        <AppenderRef ref="payRollingFile"/>
    </Logger>
    <!--异步-->
    <AsyncLogger name="com.itxiaoer.logging.biz" level="trace" additivity="false" includeLocation="true">
        <AppenderRef ref="bizRollingFile"/>
    </AsyncLogger>
    
    <Root level="info">
        <AppenderRef ref="Console" />
    </Root>
    <!--异步-->
    <!--<asyncRoot></asyncRoot>-->
</Loggers>

完整配置

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="TRACE" monitorinterval="5">
    <!--配置常量-->
    <Properties>
        <Property name="baseDir">logs</Property>
    </Properties>

    <Appenders>
        <!--这个输出控制台的配置-->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->
        <!--append = true : 保留启动前的日志,追加新日志,false: 清空原有日志-->
        <File name="log" fileName="${baseDir}/all.log" append="true">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
        </File>

        <RollingFile name="RollingFile_1" fileName="${baseDir}/logs_1/info.log"
                     filePattern="${baseDir}/logs_1/$${date:yyyy-MM}/info-%d{yyyy-MM-dd HH-mm}-%i.log.gz">
            <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
            <Policies>
                <!--4分钟rollover一次-->
                <TimeBasedTriggeringPolicy interval="4"/>
                <!--文件大小-->
                <SizeBasedTriggeringPolicy size="1 MB"/>
            </Policies>
            <!--文件数量-->
            <DefaultRolloverStrategy max="3"/>

        </RollingFile>

        <!--删除历史日志文件-->
        <RollingRandomessFile name="RollingFile_2" fileName="${baseDir}/logs_2/info.log"
                     filePattern="${baseDir}/logs_2/$${date:yyyy-MM}/info-%d{yyyy-MM-dd HH-mm}-%i.log.gz">
            <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
            <Policies>
                <!--1分钟rollover一次-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <!--文件大小-->
                <SizeBasedTriggeringPolicy size="1 MB"/>
            </Policies>
            <!--文件数量-->
            <DefaultRolloverStrategy>
                <Delete basePath="${baseDir}/logs_2" maxDepth="2">
                    <IfFileName glob="*/info-*.log.gz"/>
                    <IfLastModified age="5m"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingRandomessFile>
        <!--pay-->
        <RollingFile name="payRollingFile" fileName="${baseDir}/pay/info.log"
                     filePattern="${baseDir}/pay/$${date:yyyy-MM}/info-%d{yyyy-MM-dd HH-mm}-%i.log.gz">
            <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
            <Policies>
                <!--1分钟rollover一次-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <!--文件大小-->
                <SizeBasedTriggeringPolicy size="1 MB"/>
            </Policies>
            <!--文件数量-->
            <DefaultRolloverStrategy>
                <Delete basePath="${baseDir}/pay" maxDepth="2">
                    <IfFileName glob="*/info-*.log.gz"/>
                    <IfLastModified age="5m"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

        <!--biz-->
        <RollingFile name="bizRollingFile" fileName="${baseDir}/biz/info.log"
                     filePattern="${baseDir}/biz/$${date:yyyy-MM}/info-%d{yyyy-MM-dd HH-mm}-%i.log.gz">
            <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
            <Policies>
                <!--1分钟rollover一次-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <!--文件大小-->
                <SizeBasedTriggeringPolicy size="1 MB"/>
            </Policies>
            <!--文件数量-->
            <DefaultRolloverStrategy>
                <Delete basePath="${baseDir}/biz" maxDepth="2">
                    <IfFileName glob="*/info-*.log.gz"/>
                    <IfLastModified age="5m"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

    </Appenders>
    <Loggers>
        <Logger name="com.itxiaoer.logging.pay" level="trace" additivity="false">
            <AppenderRef ref="payRollingFile"/>
        </Logger>
        <AsyncLogger name="com.itxiaoer.logging.biz" level="trace" additivity="false">
            <AppenderRef ref="bizRollingFile"/>
        </AsyncLogger>
        <Root level="info">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="log"/>
            <AppenderRef ref="RollingFile_1"/>
            <AppenderRef ref="RollingFile_2"/>
        </Root>
    </Loggers>
</Configuration>

完整代码