Как записать контекст в журналах, когда задача запускается несколькими потоками - PullRequest
0 голосов
/ 03 июля 2019

В некоторых случаях мы отправляем задачу в другие потоки, но будет затруднительно передать некоторый контекст в другой поток и войти в систему явно. Есть ли простой способ сделать это.

мы используем log4j2 и sl4j, и я пытаюсь использовать ThreadContext, но обнаружил, что он не работает.

Pattern :
[%level{length=15}] %date [%t]【%X{context}】【%X】[%logger:%line] >>> %msg%n"

код

public static void main(String[] args) {
        log.info("starting=====================================");
        ThreadContext.put("context", UUID.randomUUID().toString().replace("-", ""));
        ExecutorService es = Executors.newCachedThreadPool();

        for(int i = 0 ; i<5;i++) {
            int index=  i ;
            es.submit(new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                    log.info("task in es {}", index);
                    return null;
                }

            });
        };

        for(int i = 0 ; i<5;i++) {
            int index=  i ;
            new Thread(new Runnable() {
                @Override
                public void run() {

                    log.info("task in new thread  {}", index);
                }
            }).start();
        };



        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("ending=====================================");
        ThreadContext.remove("context");
        es.shutdown();
//

    }

выход:

[INFO] 2019-07-03 17:57:18,750 [main]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:26] >>> starting=====================================
[INFO] 2019-07-03 17:57:18,835 [Thread-3]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:51] >>> task in new thread  2
[INFO] 2019-07-03 17:57:18,835 [Thread-1]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:51] >>> task in new thread  0
[INFO] 2019-07-03 17:57:18,835 [pool-2-thread-1]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:38] >>> task in es 0
[INFO] 2019-07-03 17:57:18,835 [Thread-5]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:51] >>> task in new thread  4
[INFO] 2019-07-03 17:57:18,835 [Thread-4]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:51] >>> task in new thread  3
[INFO] 2019-07-03 17:57:18,836 [pool-2-thread-3]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:38] >>> task in es 2
[INFO] 2019-07-03 17:57:18,836 [pool-2-thread-2]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:38] >>> task in es 1
[INFO] 2019-07-03 17:57:18,836 [pool-2-thread-4]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:38] >>> task in es 3
[INFO] 2019-07-03 17:57:18,836 [pool-2-thread-5]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:38] >>> task in es 4
[INFO] 2019-07-03 17:57:18,836 [Thread-2]【】【{}】[com.oppo.finance.fundcenter.core.FundCenterMain:51] >>> task in new thread  1
[INFO] 2019-07-03 17:57:19,834 [main]【ed65cef8478b499995f0bf95c8d71c20】【{context=ed65cef8478b499995f0bf95c8d71c20}】[com.oppo.finance.fundcenter.core.FundCenterMain:63] >>> ending=====================================

как мы видим, контекст работает только в исходном основном потоке, его нельзя передать ни одному потоку, созданному new Thread или созданному ExecutorService

Ответы [ 2 ]

0 голосов
/ 03 июля 2019

Из документации

The MDC is managed on a per thread basis. To enable automatic inheritance of copies of the MDC to newly created threads, enable the Log4j system property.

Так что установите для этого свойства значение true

-Dlog4j2.isThreadContextMapInheritable=true

И дочерние потоки наследуют контекст, и вам не нужно управлять контекстом для каждого потокавручную.

Второй вариант - вообще не использовать контекст журнала (обычно это проблема наследования контекста в пулах потоков и исполнителях), и вы можете различать потоки журнала по имени потока.

вы можете установить имя потока, как это в вашем Runnable:

Thread.currentThread().setName("SPECIFIC_NAME");
0 голосов
/ 03 июля 2019

log4j2, контекст slf4j связан с ThreadLocal. вам нужно установить контекст для каждого потока вручную

...