web-dev-qa-db-fra.com

Comment utiliser correctement slf4j MDC dans spring-webflux WebFilter

J'ai référencé avec le billet de blog Journalisation contextuelle avec Reactor Context et MDC mais je ne sais pas comment accéder au contexte du réacteur dans WebFilter.

@Component
public class RequestIdFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        List<String> myHeader =  exchange.getRequest().getHeaders().get("X-My-Header");

        if (myHeader != null && !myHeader.isEmpty()) {
            MDC.put("myHeader", myHeader.get(0));
        }

        return chain.filter(exchange);
    }
}
9
bitweaver

Vous pouvez faire quelque chose de similaire à ci-dessous, vous pouvez définir le context avec n'importe quelle classe que vous aimez, pour cet exemple, je viens d'utiliser des en-têtes - mais une classe personnalisée fera très bien l'affaire. Si vous le définissez ici, alors toute journalisation avec des gestionnaires, etc. aura également accès à context.
Le logWithContext ci-dessous, définit le MDC et l'efface ensuite. Évidemment, cela peut être remplacé par tout ce que vous aimez.

public class RequestIdFilter  implements WebFilter {

    private Logger LOG = LoggerFactory.getLogger(RequestIdFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        HttpHeaders headers = exchange.getRequest().getHeaders();
        return chain.filter(exchange)
                .doAfterSuccessOrError((r, t) -> logWithContext(headers, httpHeaders -> LOG.info("Some message with MDC set")))
                .subscriberContext(Context.of(HttpHeaders.class, headers));
    }

    static void logWithContext(HttpHeaders headers, Consumer<HttpHeaders> logAction) {
        try {
            headers.forEach((name, values) -> MDC.put(name, values.get(0)));
            logAction.accept(headers);
        } finally {
            headers.keySet().forEach(MDC::remove);
        }

    }

}
9
Kevin Hussey