How can I make the MDC available during logging in a spring controller advice?

Viewed 1251

I have a spring-boot web application which makes use of logback's MDC context to enrich the log with custom data. I have the following implementation in place which makes available some custom data associated with "customKey" and it properly gets logged after adding %X{customKey} to the logging pattern in the logback configuration:

public class MDCFilter extends OncePerRequestFilter implements Ordered {

@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest,
        HttpServletResponse httpServletResponse,
        FilterChain filterChain) throws ServletException, IOException {
        try {

            MDC.put("customKey", "someValue");          

            filterChain.doFilter(httpServletRequest, httpServletResponse);
        } catch(Throwable t) {
            LOG.error("Uncaught exception occurred", t);
            throw t;
        } finally {
            MDC.remove("customKey");
        }
    }

    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE - 4;
    }
}

This works fine as long as no uncaught exceptions are being thrown. To handle these I have a controller advice in place. Sadly the MDC is not available during logging in the controller advice anymore since it has already been cleaned up. If I understand correctly spring determines the responsible ExceptionHandler by using the HandlerExceptionResolverComposite - implementation which registers itself with the lowest precedence - hence it comes last after the MDC has already been cleaned up.

My qurestion now is: How should I register my filter so that the MDC is still available during logging in the controller advice?

I think one option would be to remove the MDC.remove(...) call from the finally block of the filter and instead implement a ServletRequestListener which does the cleanup of the MDC in the requestDestroyed - method. But since the filter is used in multiple web modules I would need to make sure that the ServletRequestListener is also declared in every existing and prospective module along with the MDCFilter which seems kind of error-prone to me. Moreover I would prefer it if the filter responsible for adding data to the MDC also takes care of its removal.

0 Answers
Related