log4j не может печатать пару ключ-значение MDC в потоках - PullRequest
0 голосов
/ 18 февраля 2019

Я устанавливаю пару ключ-значение как 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.MDC и org.slf4j.MDC, но ни одно не работает.

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

передать текущий txnId в качестве параметра в конструкторе при создании нового DeviceEventWorker

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

и установить его снова в методе запуска

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"));
    }
...
}
0 голосов
/ 18 февраля 2019

Эта проблема не имеет ничего общего с Runnable экземпляром.MDC должен быть установлен для каждого потока, поскольку он использует ThreadLocal для запоминания значений.

Если вы используете Thread напрямую или ExecutoService, вы должны убедиться, что значение MDC установлено непосредственно перед запуском Runnable.Если вы используете пул потоков, он также должен быть очищен после завершения 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();
...