在 Spring Batch 中,通过日志记录跟踪执行线程会很棒。但是,MDC 似乎不起作用。
MDC.put("process", "batchJob");
logger.info("{}; status={}", getJobName(), batchStatus.name());
有人让 MDC 在 Spring Batch 中工作吗?
在 Spring Batch 中,通过日志记录跟踪执行线程会很棒。但是,MDC 似乎不起作用。
MDC.put("process", "batchJob");
logger.info("{}; status={}", getJobName(), batchStatus.name());
有人让 MDC 在 Spring Batch 中工作吗?
我通过添加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}"