Wildfly应用中SLF4J+Log4J2配置下MDC日志无法输出问题
Wildfly自定义Log4J2配置下MDC日志不显示的解决办法
我在Wildfly应用中尝试用JSON格式化器记录MDC日志,期望设置MDC值后每条日志都能显示所有MDC键值对。但因为部分老旧第三方库和Wildfly日志子系统冲突,只能通过jboss-deployment-structure.xml禁用Wildfly日志子系统,改用自定义Log4J2配置。使用JBoss日志系统时MDC正常输出,但切换后MDC内容未出现在日志里。
现有配置及代码
1. jboss-deployment-structure.xml配置
<jboss-deployment-structure> <deployment> <exclude-subsystems> <subsystem name="logging"/> </exclude-subsystems> <exclusions> <module name="org.jboss.logging"/> <module name="org.jboss.logmanager"/> <module name="org.apache.log4j"/> </exclusions> <local-last value="true"/> </deployment> </jboss-deployment-structure>
2. 原log4j2.xml配置
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <JsonLayout complete="true" compact="false"/> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
3. MDC使用代码片段
MDC.put("userId", "12345"); MDC.put("requestId", "abc-xyz-123"); logger.info("用户发起请求"); MDC.clear();
4. 当前日志输出(无MDC)
{ "timeMillis": 1699999999999, "thread": "default task-1", "level": "INFO", "loggerName": "com.example.MyService", "message": "用户发起请求", "endOfBatch": false, "loggerFqcn": "org.apache.logging.log4j.spi.AbstractLogger", "threadId": 1, "threadPriority": 5 }
5. 期望日志输出(包含MDC)
{ "timeMillis": 1699999999999, "thread": "default task-1", "level": "INFO", "loggerName": "com.example.MyService", "message": "用户发起请求", "userId": "12345", "requestId": "abc-xyz-123", "endOfBatch": false, "loggerFqcn": "org.apache.logging.log4j.spi.AbstractLogger", "threadId": 1, "threadPriority": 5 }
解决步骤
1. 确保Log4J2依赖完整
部署包必须包含以下核心依赖,避免类加载冲突:
log4j-corelog4j-api- 若使用JSON布局,需额外引入
log4j-layout-template-json(新版本Log4J2的JsonLayout依赖此包)
2. 修改log4j2.xml开启MDC支持
在JsonLayout中添加includeMdc="true"属性,强制包含所有MDC键值对:
修改后的log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <JsonLayout complete="true" compact="false" includeMdc="true"/> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration>
如果只需要包含特定MDC键,可改用显式配置:
<JsonLayout complete="true" compact="false"> <KeyValuePair key="userId" value="$${ctx:userId}"/> <KeyValuePair key="requestId" value="$${ctx:requestId}"/> </JsonLayout>
3. 验证类加载隔离
确认jboss-deployment-structure.xml的排除规则生效:启动应用时添加-verbose:class参数,检查org.apache.logging.log4j.ThreadContext类是否来自部署包内的Jar,而非Wildfly自带模块。
4. 对齐MDC API与实现
如果代码中用的是SLF4J的MDC类,必须引入log4j-slf4j-impl依赖,确保SLF4J绑定到Log4J2实现:
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>对应你的Log4J2版本</version> </dependency>
5. 确认配置加载优先级
将log4j2.xml的status设为DEBUG,查看启动日志中Log4J2加载的配置文件路径,确保加载的是自定义配置,而非Wildfly中的其他配置文件。
内容的提问来源于stack exchange,提问作者user1022022
相关产品推荐
相关产品推荐

