我在Spring Boot应用程序中设置了一个过滤器,以向MDC添加一些信息:
@Component
public class LogFilter implements Filter {
@Override
public void init(FilterConfig var1) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
MDC.put("tag", "Some information);
chain.doFilter(request, response);
} finally {
MDC.clear();
}
}
@Override
public void destroy() { }
}
这对于我的大多数应用程序都可以正常工作,但是对于某些产生了线程的操作,此过滤器不会接收这些消息。
例如,在下面的块中,回调方法在单独的线程中发生,因此第一个log.info
的呼叫被我的LogFilter
接听,但是log.info
和{不是我的回调函数中的{1}}。
log.error
通常,似乎没有在private void publishMessage(String message) {
log.info("Message received. Sending to Kafka topic");
CompletableFuture<ListenableFuture<SendResult<String, String>>> future = CompletableFuture.supplyAsync(() -> kafkaTemplate.send("myTopic", message));
try {
future.get().addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
@Override
public void onSuccess(SendResult<String, String> result) {
log.info("Kafka topic " + myTopic + " published to successfully");
}
@Override
public void onFailure(Throwable ex) {
log.error("Kafka error: " + ex.getMessage());
}
});
} catch (Exception e) {
log.error("Kafka has failed you for the last time");
}
}
线程之一中发生的任何日志事件都绕过http-nio-8080-exec-X
。我在做什么错了?
我尝试过的无效的东西:
LogFilter
扩展LogFilter
,使用GenericFilterBean
代替@Bean
,然后在我的主Application类中向@Component
注册该bean FilterRegistrationBean
和/或@WebFilter(urlPatterns = {"/*"}, description = "MDC Filter")
答案 0 :(得分:1)
MDC上下文仅适用于当前正在运行的线程,但您的回调将在其他线程中调用。
一种解决方法是实施ListenableFutureCallback
:
private static class MyListenableFutureCallback
implements ListenableFutureCallback<SendResult<String, String>> {
private Map<String,String> contextMap = MDC.getCopyOfContextMap();
@Override
public void onSuccess(SendResult<String, String> result) {
MDC.setContextMap(contextMap); //add MDC context here
log.info("Kafka topic " + myTopic + " published to successfully");
}
@Override
public void onFailure(Throwable ex) {
MDC.setContextMap(contextMap); //add MDC context here
log.error("Kafka error: " + ex.getMessage());
}
}
最后:
future.get().addCallback(new MyListenableFutureCallback()).
描述了一种更一致的方法