Spring Boot Filter не фильтрует все мои логи - PullRequest
0 голосов
/ 15 января 2019

В моем приложении 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() { }
}

Это прекрасно работает для большинства моих приложений, но для определенных операций, где создается поток, этот фильтр не принимает эти сообщения.

Например, в приведенном ниже блоке методы обратного вызова происходят в отдельном потоке, поэтому мой LogFilter получает первый вызов log.info, но в моих обратных вызовах 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. Что я делаю не так?

То, что я пробовал, не сработало:

  1. Имея LogFilter extension GenericFilterBean, используйте @Bean вместо @Component, а затем зарегистрируйте этот бин с помощью FilterRegistrationBean в моем основном классе Application
  2. Использование @WebFilter(urlPatterns = {"/*"}, description = "MDC Filter") и / или @ServletComponentScan

1 Ответ

0 голосов
/ 16 января 2019

Контекст 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()).

описан более последовательный способ сделать это Здесь

...