log4j2的MDC或ThreadContext子线程获取不到父线程数据

最近遇到一个问题,使用slf4j和log4j2日志框架时,需要将请求的id放入到打印日志中。因为MDC和ThreadContext是跟线程绑定的,所以遇到了子线程无法读取父线程MDC和ThreadContext的问题,网上搜了很多,有各种各样的答案,折腾了一天,总算搞定了,今天花点时间把答案总结梳理一下,希望大家能少走弯路。

问题现象:在父线程中使用了MDC.put("key","value")或者ThreadContext.put("key","value"),在子线程中使用MDC.get("key")或ThreadContext.get("key")或使用%X{key}打印日志都无法读取到对应值。

方法一:最简单的方法但是最容易踩坑。

使用MDC.getCopyOfContextMap()和MDC.setContextMap(MAP<String,String>),根据方法名我想当然以为在父线程中setContextMap,在子线程中getCopyOfContextMap,然而并不是这样!!!下面是正确的写法。

 

应该是先在父线程getCopyOfContextMap,再在子线程setContextMap。翻一下源码,其实也能理解,要先生成了map对象,然后里面存放了父线程的数据,在子线程中把它放到MDC中,那么子线程就可以读取其中的数据了,完美。

方法二:改系统变量,又是一个大坑。

我本地的项目是一个java项目,只有一个类,然后我按照网上的办法初始化了log4j2.isThreadContextMapInheritable为true。代码如下

 这个很简单就成功了,但是,换到开发环境上的web项目,就死活不行了。经过分析发现,必须在Logger对象第一次初始化之前,就要把环境变量设置进去。。。

然后就去tomcat的配置文件里面搞了,在catalina,.sh或catalina.bat里面,给JAVA_OPTS加上-Dlog4j2.isThreadContextMapInheritable=true。重启应用完活。

方法三:昨天读了一下午源码,也找到了,但是脑子就是没反应过来,气死了。

在resources目录下,增加log4j2.component.properties文件,在里面写上isThreadContextMapInheritable=true,这样log4j2会自己去读取配置文件,就不用再改其他地方了,这个在源码里面可以找到。

这三种办法都亲测可行,但是昨天在网上找资料,都写的比较简单,在这总结一下,希望能对大家有帮忙把。

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值