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的全局异步和混合异步也不要同时出现