Log4j2迁移:getLoggers获取日志器数量远少于Log4j1问题排查
问题:Log4j2升级后获取的日志器数量远少于Log4j1
我正在将应用升级至Log4j2,大部分功能正常,但运行时出现异常行为:
- 在Log4j1中调用
Enumeration loggers = LogManager.getCurrentLoggers();能返回600+个日志器(符合预期); - 切换到Log4j2后,我把代码改成
LoggerContext context = (LoggerContext) LogManager.getContext(false); Collection<Logger> allLoggers = context.getLoggers();,却只返回约180个日志器。
目前无法查看新的配置文件,但该文件是基于旧版本的正确实现改写的。我注意到返回的日志器仅来自配置文件中声明的某一个日志器(所有日志器结构一致且使用相同的Appender)。
编辑1
缺失的日志器均来自第三方库,已配置SLF4J-Log4j2桥接,但似乎存在问题?
编辑2
以下是Maven依赖树中的日志相关依赖:
[INFO] +- org.hibernate:hibernate-core:jar:5.1.13.Final:compile [INFO] | +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile [INFO] | \- commons-logging:commons-logging:jar:1.1.1:compile [INFO] +- org.apache.logging.log4j:log4j-api:jar:2.24.0:compile [INFO] +- org.apache.logging.log4j:log4j-core:jar:2.24.0:compile [INFO] +- org.apache.logging.log4j:log4j-slf4j-impl:jar:2.24.0:runtime [INFO] | \- org.slf4j:slf4j-api:jar:1.7.36:compile [INFO] +- org.apache.logging.log4j:log4j-1.2-api:jar:2.24.0:compile
解决思路
1. 核心差异:Log4j1与Log4j2的日志器获取逻辑
Log4j1的getCurrentLoggers()会返回所有已创建的日志器实例,包括第三方库动态生成的;而Log4j2的context.getLoggers()默认只返回配置文件中显式声明的日志器,以及被显式调用过日志接口且配置了非默认级别/Appender的日志器。
2. 第三方库日志器未被捕获的原因
从依赖树看,存在两处关键缺失:
- Commons Logging未桥接:Hibernate依赖的
commons-logging:1.1.1没有被桥接到SLF4J/Log4j2,这部分日志器不会进入Log4j2的上下文。 - JBoss Logging未绑定SLF4J:
jboss-logging默认不会自动转向SLF4J,其生成的日志器无法被Log4j2捕获。
3. 具体修复步骤
- 添加Commons Logging到SLF4J的桥接依赖:
该依赖会替换原生Commons Logging实现,将日志请求转发到SLF4J,最终由Log4j2处理。<dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.36</version> <scope>runtime</scope> </dependency> - 配置JBoss Logging使用SLF4J:
在JVM启动参数中添加-Djboss.logging.provider=slf4j,或者在项目的jboss-logging.properties文件中设置jboss.logging.provider=slf4j。 - 触发动态日志器实例化:
Log4j2仅会记录被实际调用过的动态日志器,需要触发第三方库的日志输出(比如执行Hibernate数据库操作)后,再调用context.getLoggers()。
4. 验证方式
修改后重启应用,触发第三方库日志操作,再调用获取日志器的方法,数量应接近之前的600+;也可通过Log4j2的JMX控制台查看所有日志器,确认是否包含第三方库实例。
内容的提问来源于stack exchange,提问作者Polyphase29
相关产品推荐
相关产品推荐

