Logstash/Gelf未存储全部MDC内容问题排查与解决咨询
问题分析与解决方案
核心问题1:日志生成时机与MDC字段设置时机不匹配
你的额外字段(结果、耗时等)是在ictx.proceed()执行完成后的finally块中才放入MDC的,但SoapLogHandler的日志是在ictx.proceed()内部输出的——此时这些字段还未被添加到MDC中,自然不会出现在日志里。
核心问题2:Logger配置范围覆盖不全
当前JsonLog handler仅绑定到org.somepackgs.SoapLogHandler这个Logger,拦截器GeneralInterceptor的日志没有关联该handler,所以拦截器的日志不会写入JSON文件;而如果只配置拦截器的Logger,SOAP日志又会丢失。
具体解决方案
1. 调整日志输出时机,确保MDC字段已存在
把需要包含完整MDC字段的日志输出逻辑移到拦截器的finally块中,此时所有业务结果、耗时等字段都已设置完成,日志会自动包含这些内容。如果需要保留SoapLogHandler的原有日志,可以在拦截器中补充一条汇总日志。
示例调整后的拦截器代码:
@AroundInvoke public Object run(InvocationContext ictx) throws Exception { String requestId = UUID.randomUUID().toString(); MDC.put("requestId", requestId); long startTime = System.currentTimeMillis(); Object obj = null; String resultStatus = "SUCCESS"; try{ // 业务校验与执行 obj = ictx.proceed(); } catch (Exception ex) { resultStatus = "FAILED"; throw ex; // 不要吞掉异常,保证业务异常流程正常执行 } finally { // 计算耗时并写入MDC long elapsedTime = System.currentTimeMillis() - startTime; MDC.put("resultStatus", resultStatus); MDC.put("elapsedTimeMs", String.valueOf(elapsedTime)); // 输出包含完整MDC字段的日志(可选择用SoapLogHandler或拦截器自己的Logger) LoggerFactory.getLogger(SoapLogHandler.class).info("Request processed - requestId: {}", requestId); // LoggerFactory.getLogger(GeneralInterceptor.class).info("Request completed"); MDC.clear(); // 必须清理MDC,避免线程池复用导致的字段污染 } return obj; }
2. 配置Logger覆盖所有需要的日志来源
要同时记录SOAP日志和拦截器日志,需要让两个Logger都关联JsonLog handler,修改standalone.xml的日志配置:
<profile> <subsystem xmlns="urn:jboss:domain:logging:3.0"> <!-- 保留原有的JsonLog handler和JsonFormatter配置 --> <periodic-rotating-file-handler name="JsonLog" autoflush="true"> <!-- ... 原有配置 ... --> </periodic-rotating-file-handler> <!-- ... 其他handler ... --> <!-- 给SoapLogHandler添加JsonLog handler --> <logger category="org.somepackgs.SoapLogHandler" use-parent-handlers="true"> <level name="INFO"/> <handlers> <handler name="JsonLog"/> </handlers> </logger> <!-- 给GeneralInterceptor添加JsonLog handler --> <logger category="org.somepackgs.GeneralInterceptor" use-parent-handlers="true"> <level name="INFO"/> <handlers> <handler name="JsonLog"/> </handlers> </logger> <!-- 保留原有的JsonFormatter配置 --> <formatter name="JsonFormatter"> <!-- ... 原有配置 ... --> </formatter> </subsystem> </profile>
如果希望所有应用日志都写入JSON文件,可以简化配置,把JsonLog handler添加到ROOT logger:
<root-logger> <level name="INFO"/> <handlers> <handler name="JsonLog"/> <!-- 保留原有控制台/文件handler,避免丢失其他日志渠道 --> <handler name="CONSOLE"/> <handler name="FILE"/> </handlers> </root-logger>
3. 确认JsonFormatter配置有效性
你的JsonFormatter已经开启了includeFullMdc="true"和mdcProfiling="true",这部分配置是正确的——只要日志生成时MDC中有对应的字段,就会自动被包含到JSON日志中。
内容的提问来源于stack exchange,提问作者Morteza Asadi
相关产品推荐
相关产品推荐

