1

在 Spring Batch 中,通过日志记录跟踪执行线程会很棒。但是,MDC 似乎不起作用。

MDC.put("process", "batchJob"); logger.info("{}; status={}", getJobName(), batchStatus.name());

有人让 MDC 在 Spring Batch 中工作吗?

4

1 回答 1

0

我通过添加JobExecutionListener这样的方法解决了它:

public class Slf4jBatchJobListener implements JobExecutionListener {

    private static final String DEFAULT_MDC_UUID_TOKEN_KEY = "Slf4jMDCFilter.UUID";
    private final Logger logger = LoggerFactory.getLogger(getClass());

    public void beforeJob(JobExecution jobExecution) {
        String token = UUID.randomUUID().toString().toUpperCase();
        MDC.put(DEFAULT_MDC_UUID_TOKEN_KEY, token);
        logger.info("Job {} with id {} starting...", jobExecution.getJobInstance().getJobName(), jobExecution.getId());
    }

    public void afterJob(JobExecution jobExecution) {
        logger.info("Job {} with id {} ended.", jobExecution.getJobInstance().getJobName(), jobExecution.getId());
        MDC.remove(DEFAULT_MDC_UUID_TOKEN_KEY);
    }
}

因为有些作业是多线程的,所以我还必须添加一个 TaskDecorator 以便将 DMC 从父线程复制到子线程,如下所示:

public class Slf4JTaskDecorator implements TaskDecorator {

    @Override
    public Runnable decorate(Runnable runnable) {
        Map<String, String> contextMap = MDC.getCopyOfContextMap();
        return () -> {
            try {
                MDC.setContextMap(contextMap);
                runnable.run();
            } finally {
                MDC.clear();
            }
        };
    }
}

将 TaskDecorator 设置为 TaskExecutor:

@Bean
public TaskExecutor taskExecutor(){
    SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("spring_batch");
    taskExecutor.setConcurrencyLimit(maxThreads);
    taskExecutor.setTaskDecorator(new Slf4JTaskDecorator());
    return taskExecutor;
}

最后,更新属性中的日志记录模式:

logging:
  pattern:
    level: "%5p %X{Slf4jMDCFilter.UUID}"
于 2021-07-12T12:27:15.060 回答