我正在使用 Spring Boot 和 MDC 来记录 REST API 应用程序中每个日志条目的附加上下文。我已在主线程中设置 MDC,但数据不会传播到我的 REST 控制器中创建的子线程。
这是我当前日志输出的简化示例:
> thread: main, data1: foo, data2: bar, data3: null, message: some log entry
> thread: main, data1: foo, data2: bar, data3: null, message: some other log entry
> thread: http-nio-1234-1, data1: null, data2: null, data3: foobar, message: some other log entry
> thread: http-nio-1234-2, data1: null, data2: null, data3: foobar, message: some other log entry
可以看到,data1和data2(在主线程中设置)仅在主线程日志中可用,而data3(在子线程中设置)在所有子线程中都可用。
如何确保来自主线程的MDC数据传播到非异步线程的子线程?
我找到了大量有关将 MDC 数据传递到异步线程的文档,但这不适用于我的场景,因为它们不是异步的。
我正在使用 Spring Boot 和日志框架 SLF4J。任何建议或见解将不胜感激。
我的主要应用程序代码如下:
public class MyApiApplication implements CommandLineRunner {
public static void main(final String[] args) {
SpringApplication application = new SpringApplication(MyApiApplication.class);
application.addInitializers(new SomeInitializer());
application.run(args);
}
}
我尝试了异步传递,如下所示(来自此答案https://stackoverflow.com/a/60741586/928666):
public class MyApiApplication implements CommandLineRunner {
public static void main(final String[] args) { ... }
@Override
public ThreadPoolTaskExecutor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolExecutor();
executor.setTaskDecorator(new MdcTaskDecorator());
executor.initialize;
return executor;
}
}
// MdcTaskDecorator
class MdcTaskDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
Map<String, String> contextMap = MDC.getCopyOfContextMap();
return () -> {
try {
MDC.setContextMap(contextMap);
runnable.run();
} finally {
MDC.clear();
}
};
}
}
您需要创建自己的处理程序来实现
HandlerInterceptor
并在 preHandle
中设置 MDC 上下文。
没有通用的方法可以让所有线程使用您的 MDC 上下文,除非您想参与运行时代码操作的黑暗魔法。