Loggers 配置解析(log4j.xml)
Loggers 配置解析
我们通过下面的例子来理解 log4j 的 Loggers 配置是如何决定日志输出规则的。
<Loggers><!-- 根Logger:全局配置 --><Root level="debug"><AppenderRef ref="consoleAppender" level="info"/><AppenderRef ref="allFileAppender" level="all"/><AppenderRef ref="debugFileAppender" level="debug"/><AppenderRef ref="infoFileAppender" level="info"/><AppenderRef ref="warnFileAppender" level="warn"/><AppenderRef ref="errorFileAppender" level="error"/></Root><!-- 自定义Logger:特定模块配置 --><Logger level="trace" name="com.ruoyi.admin.log"><AppenderRef ref="allFileAppender" level="all"/></Logger></Loggers>
这个配置结合了根 Logger 和自定义 Logger,并实现了分模块、分级别的日志记录策略。理解关键在于层级关系、继承机制和级别过滤的相互作用。
日志输出规则
- 层级继承
- 所有 Logger 默认继承根 Logger 配置
com.ruoyi.admin.log
及其子包的日志优先使用自定义 Logger 配置。即有子类的情况优先采用子类定义的规则。这点可以类比 Java 中的父类与子类关系。
- additivity 属性
- 未显式设置时默认为
true
(即日志会同时传递给自定义 Logger 和根 Logger) - 这可能导致重复记录(稍后详解)
- 未显式设置时默认为
- 双层过滤
日志需通过:- Logger 级别过滤(第一层)
- Appender 级别过滤(第二层)
各 Appender 输出内容分析
1. 根 Logger 的 Appender(处理非 com.ruoyi.admin.log
包日志)
Appender | 输出内容 | 实际输出级别范围 |
---|---|---|
consoleAppender | 所有包的INFO+日志 | INFO, WARN, ERROR, FATAL |
allFileAppender | 所有包的DEBUG+日志(不包含TRACE) | DEBUG, INFO, WARN, ERROR |
debugFileAppender | 所有包的DEBUG+日志 | DEBUG, INFO, WARN, ERROR |
infoFileAppender | 所有包的INFO+日志 | INFO, WARN, ERROR, FATAL |
warnFileAppender | 所有包的WARN+日志 | WARN, ERROR, FATAL |
errorFileAppender | 所有包的ERROR+日志 | ERROR, FATAL |
📌 注意:根Logger的
level="debug"
过滤掉了TRACE日志,因此allFileAppender
也捕获不到TRACE
2. 自定义Logger的Appender(专用于com.ruoyi.admin.log
包)
Appender | 输出内容 | 实际输出级别范围 |
---|---|---|
allFileAppender | com.ruoyi.admin.log 包的TRACE+日志 | TRACE, DEBUG, INFO, WARN, ERROR |
3. 关键交叉点:com.ruoyi.admin.log
包的日志
由于additivity=true
(默认),该包的日志会同时被:
- 自定义Logger处理
- 根Logger处理
具体输出示例(以DEBUG日志为例)
- 自定义Logger路径
DEBUG日志 → 通过trace级别 → allFileAppender(level=all) → 输出
- 根Logger路径
DEBUG日志 → 通过debug级别 → 根Logger的Appender二次过滤:
allFileAppender(level=all) → 输出
debugFileAppender(level=debug) → 输出
infoFileAppender(level=info) → 丢弃
- …其他同理
结果:重复记录问题
allFileAppender 会记录两次 com.ruoyi.admin.log
的DEBUG日志,表现为 allFileAppender 指定的日志输出文件中会打印两次相同的日志。
- 来自自定义Logger
- 来自根Logger
优化建议:避免重复记录
增加additivity="false"
属性:
<Logger level="trace" name="com.ruoyi.admin.log" additivity="false"><AppenderRef ref="allFileAppender" level="all"/>
</Logger>
优化后效果:
日志来源 | allFileAppender | 其他Appender |
---|---|---|
非com.ruoyi.admin.log | 根Logger的DEBUG+日志 | 按各自级别过滤 |
com.ruoyi.admin.log | 该包的TRACE+日志 | 不再出现 |
即只有 allFileAppender 能输出 com.runyi.admin.log 及其子包中的日志。
最终输出总结(优化后配置)
Appender | 输出内容 | 覆盖范围 |
---|---|---|
consoleAppender | 全局INFO+日志(不含特殊包) | 非特殊包 |
allFileAppender | 全局DEBUG+日志 + 特殊包TRACE+日志 | 所有包,不同级别 |
debugFileAppender | 全局DEBUG+日志(不含特殊包) | 非特殊包 |
infoFileAppender | 全局INFO+日志(不含特殊包) | 非特殊包 |
warnFileAppender | 全局WARN+日志(不含特殊包) | 非特殊包 |
errorFileAppender | 全局ERROR+日志(不含特殊包) | 非特殊包 |
特殊包:
com.ruoyi.admin.log
及其子包
这种配置实现了:
- 生产环境安全:默认只记录DEBUG+日志
- 关键模块追踪:特定包记录最详细的TRACE日志。可以调试用。
- 分类存储:不同级别日志分离到不同文件
- 控制台精简:只显示INFO+关键信息