SLF4J Fluent API的Marker被Log4j2配置忽略,非Fluent API正常
问题重现
使用SLF4J的LoggingEventBuilder(Fluent API)添加Marker时,Log4j2配置里的过滤器(比如NoMarkerFilter、MarkerFilter)会直接忽略这个Marker;但用SLF4J Logger的传统API(如trace(Marker marker, String msg))传递相同Marker时,过滤器能正常工作。
示例Log4j2配置:
NoMarkerFilter: onMatch: deny onMismatch: accept
代码对比:
private static final Marker marker = MarkerFactory.getMarker("TESTMARKER"); // 传统API:日志被正常接收输出 log.trace(marker, "This is logged using traditional api"); // Fluent API:日志被拒绝,无输出 log.atTrace().addMarker(marker).log("This is logged using fluent api");
使用的依赖版本:Lombok 6.6.1、log4j-core 2.19.0、log4j-slf4j2-impl 2.19.0
原因分析
这是Log4j2的SLF4J适配层(log4j-slf4j2-impl)在2.19.0版本中的已知bug——Fluent API传递的Marker没有被正确同步到Log4j2内部的LoggingEvent对象里,导致过滤器无法读取到Marker信息,进而按“无Marker”的逻辑处理日志。
解决方案
优先方案:升级Log4j2版本
该bug在Log4j2 2.20.0及后续版本中已经被官方修复。直接把你的log4j相关依赖升级到2.20.0或更高版本即可解决问题:
Maven依赖示例:
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.20.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j2-impl</artifactId> <version>2.20.0</version> </dependency>
Gradle依赖示例:
implementation 'org.apache.logging.log4j:log4j-core:2.20.0' implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.20.0'
临时替代方案(不升级版本)
如果暂时不能升级,只能绕过Fluent API,改用传统的带Marker的日志方法;或者自己写一个Logger包装类,在Fluent API调用后手动把Marker注入到日志事件中——不过这种方法会增加代码维护成本,不推荐。
验证
升级后重新运行代码,Fluent API添加的Marker会被Log4j2过滤器正确识别,log.atTrace().addMarker(marker).log(...)的日志会正常输出,符合NoMarkerFilter的规则(因为存在Marker,触发onMismatch=accept)。
内容的提问来源于stack exchange,提问作者Neel

