我在我的 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
和 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
而不是@Component
,然后用@Component
注册那个 beanFilterRegistrationBean
在我的主应用程序类中 - 使用
@WebFilter(urlPatterns = {"/*"}, description = "MDC Filter")
和/或@ServletComponentScan
最佳答案
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()).
描述了一种更一致的方法Here
关于java - Spring Boot Filter 没有过滤我所有的日志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54206589/