【问题标题】:log4j is not able to print MDC key-value pair in threadslog4j 无法在线程中打印 MDC 键值对
【发布时间】:2019-07-12 03:06:06
【问题描述】:

我将键值对设置为MDC.put("txnId", UUID.randomUUID().toString());,将 log4j.properties 设置为

log4j.appender.R.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}]  [%m] [%M] [%L] [%p] [%c] [%X{txnId}] %n

这在记录非线程日志时工作得非常好,但是 implements Runnable, txnId 的类的日志是空的。

下面是线程代码

public class ConsT implements Runnable{
    public ConsT() {

        }

        @Override
        public void run() {

            log.info("Start thread"));
    }

我尝试将我的值同时放入 org.apache.log4j.MDCorg.slf4j.MDC 中,但没有任何效果。

【问题讨论】:

    标签: java logging log4j slf4j mdc


    【解决方案1】:

    在创建新的 DeviceEventWorker 时将当前的 txnId 作为参数传递给构造函数

    new DeviceEventWorker(.... , MDC.get("txnId"));
    

    在run方法中再次设置

    public class DeviceEventWorker implements Runnable{
    
        private String txnId;
    
        public DeviceEventWorker(String tenantId, DeviceResource device, String eventName, LighthouseDevice lighthouseDevice, String txnId) {
                this.tenantId = tenantId;
                this.device = device;
                this.eventName = eventName;
                this.lighthouseDevice = lighthouseDevice;
                this.txnId = txnId;    
            }
    
            @Override
            public void run() {
                MDC.put("txnId", this.txnId);
                log.info("Start thread"));
        }
    ...
    }
    

    【讨论】:

      【解决方案2】:

      这个问题与Runnable 实例无关。 MDC 必须基于每个线程设置,因为它在内部使用ThreadLocal 来记住这些值。

      如果您直接使用ThreadExecutoService,您必须确保在Runnable 运行之前直接设置MDC 值。如果您使用线程池,则还必须在 Runnable 完成后将其清除。

      有很多方法可以实现它,但一种可能的方法是定义一个包装类:

      class MDCWrapper implements Runnable {
      
        private final Runnable target;
      
        @Override
        public void run() {
          MDC.put("txnId", UUID.randomUUID().toString());
          try {
            target.run();
          } finally {
            MDC.remove("txnId");
          }
        } 
      
      }   
      

      然后将其用作:

      Thread t = new Thread(new MDCWrapper(new DeviceEventWorker()));
      t.start();
      

      【讨论】:

      • 这是一些有针对性的解释。非常感谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-18
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-03
      相关资源
      最近更新 更多