1. 概述

Apache Log4j2是对Log4j的升级,在其基础上进行了重大改进,并提供了Logback中可用的许多改进,同时修复了Logback架构中的一些问题,被誉为是目前最优秀的Java日志框架。

1.1. Log4j2特点

性能提升
Log4j2包含基于LMAX Disruptor库的下一代异步记录器,在多线程中,异步记录器的吞吐量比Log4j和Logback高18倍,且延迟低
自动重新加载配置
与Logback一样可以在修改时自动重新加载其配置,不同之处在于其重新配置发生时不会丢失日志事件
高级过滤
支持基于Log事件中的上下文数据、标记,正则表达式和其他组件进行过滤。过滤器还可以与记录器关联,可以在任何这些情况下使用通用的Filter类
插件架构
使用插件模式配置组件,无需编写代码来创建和配置Appender、Layout、Pattern Converter等,在配置了的情况下,会自动识别插件并使用
无垃圾机制
在稳态日志记录期间,Log4j2在独立应用程序中是无垃圾的,在Web应用程序中是低垃圾,这减少了垃圾收集器的压力,并且可以提供更好的响应性能

2. 引入核心依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!--排除原始依赖,以此去除logback引用-->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--引入log4j2依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

3. 新建log4j2.xml配置文件

log4j2默认加载类路径resources下log4j2.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration monitorInterval="30">

    <Properties>
        <Property name="LOG_PATH">C:/logs</Property>
    </Properties>

    <Appenders>
        <!--配置控制台输出-->
        <Console name="consoleAppender" target="SYSTEM_OUT">
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%-5level] [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%p] - %l - %m%n"/>
        </Console>
        <!--配置文件输出-->
        <!--$${date:yyyy-MM-dd}:根据日期当天创建一个文件夹-->
        <RollingFile name="infoFileAppender" fileName="${LOG_PATH}/info.log" filePattern="${LOG_PATH}/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}-%i.log.gz">
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="2MB"/>
            </Policies>
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
        <RollingFile name="errorFileAppender" fileName="${LOG_PATH}/error.log" filePattern="${LOG_PATH}/$${date:yyyy-MM-dd}/error-%d{yyyy-MM-dd}-%i.log.gz">
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <!--在系统启动时,触发拆分规则,产生一个日志文件-->
                <OnStartupTriggeringPolicy/>
                <!--按照时间节点进行拆分,拆分规则根据filePattern-->
                <TimeBasedTriggeringPolicy/>
                <!--按照文件大小进行拆分-->
                <SizeBasedTriggeringPolicy size="2MB"/>
            </Policies>
            <!--在同一目录下,文件的个数限制,超过限制时会覆盖最早日期的日志-->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Logger name="org.springframework" level="ERROR"/>
        <Root level="INFO">
            <AppenderRef ref="consoleAppender"/>
            <AppenderRef ref="infoFileAppender"/>
            <AppenderRef ref="errorFileAppender"/>
        </Root>
    </Loggers>
</Configuration>

4. 配置文件节点解释

Configuration
根节点,其常用属性有

  • status:日志框架实现自身的日志级别,OFF > FATAL > ERROR > WARN > INFO > DEBUG >
    TRACE > ALL
  • monitorInterval:重新读取配置文件的间隔时间,单位秒

Properties
属性,用来定义常量,在后面的其他配置项中可以通过${变量名}来引用
Appenders
输出源,用于定义日志输出的地方
RollingFile
滚动文件,用于拆分日志文件,其属性有

  • fileName:日志文件名称
  • filePattern:日志文件拆分后文件的命名规则

ThresholdFilter
阈值过滤器,日志事件是否输出,常用的属性有onMatch(该级别及以上)、onMismatch(该级别以下),其属性值有ACCEPT(接受)、DENY(拒绝)、NEUTRAL(中立)
PatternLayout
图案布局,日志输出的格式

  • %d:时间
  • %level:日志级别
  • %thread:线程名称
  • %c{1.}:logger名字
  • %m(msg):日志信息
  • %l:位置信息
  • %C:类名
  • %M:方法名
  • %F:文件名
  • %L:行号
  • %n:换行

更多详细资料可以查阅官网Policies
日志滚动策略,常用的标签有

  • TimeBasedTriggeringPolicy
  • SizeBasedTriggeringPolicy:日志文件大小滚动策略

DefaultRolloverStrategy
默认滚动策略,常用属性max,表示日志文件保存最大个数

5. 异步日志

Log4j2提供了两种实现异步日志的方式,一是通过AsyncAppender,二是通过AsyncLogger,这两种实现方式在设计和源码都不一样

5.1. AsyncAppender方式

通过引用别的Appender来实现,当有日志事件到达时,会开启另一个线程来处理,如果在Appender的时候出现异常,对应用来说时无法感知的。AsyncAppender在其引用的Appender之后配置,默认使用java.util.concurrent.ArrayBlockingQueue实现而不需要其他外部类库,当使用此Appender的时候,在多线程的环境下需要注意,阻塞队列容易受到锁竞争的影响,这可能会对性能产生影响,这时需要使用无锁的异步记录器(AsyncLogger)
在log4j2.xml配置文件的Appenders标签中添加如下配置

<!--配置异步日志-->
<Async name="asyncAppender">
    <AppenderRef ref="consoleAppender"/>
</Async>

在Root标签中添加如下配置

<AppenderRef ref="asyncAppender"/>

5.2. AsyncLogger方式

此种方式是官方推荐的,其可以使得调用Logger.log返回得更快,其有两种配置:全局异步和混合异步

5.2.1. 全局异步

全局异步:所有得日志都异步得记录,在配置文件上不用做任何改动,只需要在jvm启动得时候增加一个参数即可
在类路径resources目录下新建文件log4j2.component.properties,在文件中添加如下配置

Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
5.2.2. 混合异步

混合异步:在应用中同时使用同步日志和异步日志,这使得日志得配置方式更加灵活,一些特殊情况下无法完全处理异常就需要使用同步日志方式,而对于一些只记录一个程序日志的地方,使用异步日志将大幅提升性能,减少对应用本身的影响。混合异步的方式需要通过修改配置文件来实现,使用AsyncLogger标记配置
在Loggers标签中添加如下配置

<AsyncLogger name="com.xlhj.boot.log4j2" level="trace" includeLocation="false" additivity="false">
    <AppenderRef ref="consoleAppender"/>
</AsyncLogger>

includeLocation="false"表示去除日志记录中行号信息,因其影响日志记录效率
additivity="false"表示不继承rootLogger

5.3. 其他

AsyncAppender和AsyncLogger不要同时出现,如果同时出现,会以AsyncAppender为主
AsyncLogger的全局异步和混合异步也不要同时出现