log4j2配置
Log4j2 配置详解:从基础到实战的完整指南
Log4j2 作为主流的日志实现框架,以其高性能、灵活的配置和丰富的功能(如异步日志、动态配置)被广泛应用。其配置文件通过 XML、JSON 或 YAML 定义日志的输出目的地、格式、滚动策略等。本文基于 XML 配置格式,详细解析 Log4j2 的配置结构与核心功能。
Log4j2 配置文件基本结构
Log4j2 配置文件的根元素为<Configuration>,包含两大核心子元素:<Appenders>(日志输出目的地)和<Loggers>(日志器,控制日志流向)。基本结构如下:
<!-- status:Log4j2自身日志级别(如WARN,避免过多内部日志);monitorInterval:自动检测配置文件变更的间隔(秒) -->
<Configuration status="WARN" monitorInterval="30">
<!-- 日志输出目的地集合 -->
<Appenders>
<!-- 具体的Appender(如控制台、文件、滚动文件等) -->
<Appender name="控制台" ...>
<!-- 过滤器(可选) -->
<Filters>...</Filters>
<!-- 日志格式(必填) -->
<PatternLayout .../>
<!-- 滚动策略(仅滚动文件Appender需要) -->
<Policies>...</Policies>
<!-- 滚动规则(仅滚动文件Appender需要) -->
<DefaultRolloverStrategy .../>
</Appender>
</Appenders>
<!-- 日志器集合 -->
<Loggers>
<!-- 特定类/包的日志器 -->
<Logger name="com.example" level="INFO" additivity="false">
<AppenderRef ref="控制台"/> <!-- 关联Appender -->
</Logger>
<!-- 根日志器(默认日志器) -->
<Root level="INFO">
<AppenderRef ref="控制台"/>
</Root>
</Loggers>
</Configuration>
Appenders:日志输出目的地
<Appenders>定义日志的输出位置(如控制台、文件),每个<Appender>需指定name(唯一标识)和具体类型(如Console、File、RollingFile)。
1. Console:输出到控制台
最基础的 Appender,用于将日志输出到控制台(SYSTEM_OUT或SYSTEM_ERR)。
<Console name="stdout" target="SYSTEM_OUT"> <!-- target默认SYSTEM_OUT,可选SYSTEM_ERR(错误流) -->
<!-- 日志格式 -->
<PatternLayout
charset="UTF-8" <!-- 字符编码 -->
pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS}] %l [%m]%n" <!-- 格式模板 -->
/>
</Console>
pattern常用占位符(后续 Layout 通用):%d{格式}:日志时间(如%d{yyyy-MM-dd HH:mm:ss.SSS});%p:日志级别(如 INFO、WARN,%-5p表示左对齐占 5 位);%l:日志发生位置(类名、方法名、行号,如com.example.Test.main(Test.java:10));%m:日志消息;%n:换行符;%t:线程名;%X{key}:MDC 中的键值(如%X{traceId}输出追踪 ID)。
2. File:输出到固定文件
将日志输出到指定文件,不支持日志滚动(文件大小会无限增长,适合临时调试)。
<File
name="fileLog"
fileName="logs/app.log" <!-- 文件路径(相对路径基于项目根目录,绝对路径如D:/logs/app.log) -->
append="true" <!-- 是否追加(false则每次启动清空文件,默认true) -->
>
<PatternLayout charset="UTF-8" pattern="[%-5p %d{HH:mm:ss.SSS}] %m%n"/>
</File>
3. RollingFile:支持日志滚动(生产环境首选)
RollingFile是生产环境最常用的 Appender,支持按时间、大小分割日志文件(避免单文件过大),并自动清理旧日志。
<RollingFile
name="rollingLog"
fileName="logs/app.log" <!-- 当前日志文件路径 -->
filePattern="logs/archive/app-%d{yyyyMMdd}-%i.log.bz2" <!-- 滚动后文件命名格式(%i为序号,bz2表示压缩) -->
>
<!-- 日志格式 -->
<PatternLayout charset="UTF-8" pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS}] %l [%m]%n"/>
<!-- 日志滚动触发策略(满足任一条件即滚动) -->
<Policies>
<!-- 时间触发:按天滚动(依赖filePattern中的%d{yyyyMMdd}) -->
<TimeBasedTriggeringPolicy
interval="1" <!-- 滚动间隔(单位与filePattern的时间粒度一致,此处1表示1天) -->
modulate="true" <!-- 是否对齐到自然时间(如每天0点滚动,而非启动后24小时) -->
/>
<!-- 大小触发:单个文件超过100MB则滚动 -->
<SizeBasedTriggeringPolicy size="100 MB"/>
<!-- 定时触发:按Cron表达式滚动(如每天凌晨2点) -->
<CronTriggeringPolicy schedule="0 0 2 * * ?"/>
</Policies>
<!-- 滚动规则(文件数量控制与旧日志删除) -->
<DefaultRolloverStrategy max="30"> <!-- 同一目录下最大滚动文件数(超过则删除最旧的) -->
<!-- 自动删除7天前的日志 -->
<Delete basePath="logs/archive/" maxDepth="1"> <!-- basePath:日志存档目录;maxDepth:递归深度 -->
<IfFileName glob="app-*.log.bz2"/> <!-- 匹配文件名 -->
<IfLastModified age="7d"/> <!-- 保留7天内的日志(d=天,h=小时,m=分钟) -->
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
filePattern说明:
格式中的%d{yyyyMMdd}决定时间滚动粒度(如yyyyMM表示按月,yyyyMMddHH表示按小时);%i用于同一时间粒度内多次滚动(如 1 天内文件超过大小,生成app-20240520-1.log、app-20240520-2.log)。
4. Filter:日志过滤机制
Filter用于控制哪些日志能通过 Appender 输出,常用ThresholdFilter(按级别过滤)和LevelRangeFilter(按级别范围过滤)。
<RollingFile name="errorLog" ...>
<!-- 只输出ERROR及以上级别日志 -->
<ThresholdFilter
level="ERROR" <!-- 阈值级别 -->
onMatch="ACCEPT" <!-- 匹配时接受 -->
onMismatch="DENY" <!-- 不匹配时拒绝 -->
/>
<!-- 其他配置... -->
</RollingFile>
- 过滤逻辑:
ACCEPT:接受日志,后续 Filter 不再执行;DENY:拒绝日志,后续 Filter 不再执行;NEUTRAL:中立(交给后续 Filter 判断)。
Loggers:日志器(控制日志流向)
<Loggers>包含多个<Logger>和一个<Root>(根日志器),用于指定不同类 / 包的日志级别和输出目的地。
1. Logger:特定类 / 包的日志器
针对指定类或包配置日志行为,优先级高于Root。
<Logger
name="com.example.service" <!-- 类或包名(如"com.example"表示该包下所有类) -->
level="DEBUG" <!-- 日志级别(TRACE < DEBUG < INFO < WARN < ERROR < FATAL) -->
additivity="false" <!-- 是否继承Root的Appender(false=不继承,避免重复输出) -->
>
<AppenderRef ref="rollingLog"/> <!-- 关联的Appender -->
</Logger>
level作用:只输出该级别及以上的日志(如level="INFO"则不输出 DEBUG 和 TRACE)。
2. Root:根日志器
所有未被特定<Logger>匹配的类 / 包,将使用Root的配置(默认日志器)。
<Root level="INFO"> <!-- 全局默认级别 -->
<AppenderRef ref="stdout"/> <!-- 输出到控制台 -->
<AppenderRef ref="rollingLog"/> <!-- 同时输出到滚动文件 -->
</Root>
3. 避免日志重复输出
当Logger的additivity="true"(默认)时,日志会同时输出到Logger关联的 Appender 和Root关联的 Appender,导致重复。解决方式:
- 为
Logger设置additivity="false"; - 确保
Logger和Root的 Appender 不重复。
完整配置示例(生产环境参考)
<!-- 自动检测配置变更(30秒),Log4j2自身日志级别为WARN -->
<Configuration status="WARN" monitorInterval="30">
<Appenders>
<!-- 控制台输出(INFO及以上) -->
<Console name="Console" target="SYSTEM_OUT">
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout charset="UTF-8" pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS} %t] %l %m%n"/>
</Console>
<!-- 滚动文件:INFO级别日志 -->
<RollingFile name="InfoLog"
fileName="logs/info.log"
filePattern="logs/archive/info-%d{yyyyMMdd}-%i.log.gz">
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout charset="UTF-8" pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS} %t %X{traceId}] %l %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="50MB"/>
</Policies>
<DefaultRolloverStrategy max="30">
<Delete basePath="logs/archive/" maxDepth="1">
<IfFileName glob="info-*.log.gz"/>
<IfLastModified age="15d"/> <!-- 保留15天日志 -->
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<!-- 滚动文件:ERROR级别日志 -->
<RollingFile name="ErrorLog"
fileName="logs/error.log"
filePattern="logs/archive/error-%d{yyyyMMdd}-%i.log.gz">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout charset="UTF-8" pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS} %t %X{traceId}] %l %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="10MB"/> <!-- 错误日志量少,阈值设小 -->
</Policies>
<DefaultRolloverStrategy max="30">
<Delete basePath="logs/archive/" maxDepth="1">
<IfFileName glob="error-*.log.gz"/>
<IfLastModified age="30d"/> <!-- 错误日志保留30天 -->
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<!-- 第三方框架日志控制(如Spring、MyBatis,避免DEBUG级别的冗余日志) -->
<Logger name="org.springframework" level="INFO" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="InfoLog"/>
</Logger>
<Logger name="org.mybatis" level="INFO" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="InfoLog"/>
</Logger>
<!-- 应用核心包日志(DEBUG级别,便于调试) -->
<Logger name="com.example" level="DEBUG" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="InfoLog"/>
<AppenderRef ref="ErrorLog"/>
</Logger>
<!-- 根日志器(默认INFO级别) -->
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="InfoLog"/>
<AppenderRef ref="ErrorLog"/>
</Root>
</Loggers>
</Configuration>
关键配置要点总结
- 日志级别控制:
生产环境建议Root级别设为INFO,避免DEBUG/TRACE的冗余日志;特定包(如业务层)可设为DEBUG便于调试。 - 日志滚动策略:
- 结合
TimeBasedTriggeringPolicy(按时间归档)和SizeBasedTriggeringPolicy(避免单文件过大); - 通过
DefaultRolloverStrategy的Delete自动清理旧日志,防止磁盘占满。
- 结合
- 日志格式设计:
包含时间、级别、线程名、位置、消息,分布式系统需加入%X{traceId}实现链路追踪。 - 性能优化:
- 日志文件使用压缩(如
.gz、.bz2)减少磁盘占用; - 高并发场景启用 Log4j2 异步日志(需额外配置
AsyncAppender)。
- 日志文件使用压缩(如
- 避免重复输出:
为自定义Logger设置additivity="false",避免同时输出到Logger和Root的 Appender