Spring Boot Filter无法过​​滤我的所有日​​志

时间:2019-01-15 20:48:58

标签: java spring spring-boot log4j logback

我在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。我在做什么错了?

我尝试过的无效的东西:

  1. LogFilter扩展LogFilter,使用GenericFilterBean代替@Bean,然后在我的主Application类中向@Component注册该bean
  2. 使用FilterRegistrationBean和/或@WebFilter(urlPatterns = {"/*"}, description = "MDC Filter")

1 个答案:

答案 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()).

Here

描述了一种更一致的方法