How to trace your logs using SLF4J MDC

How do you use your logs for searching problem requests? For instance, you got a problem response, with all headers, response body, and you need to find appropriate logs. How would you do that?

Personally, I found it useful to write some words about MDC - Mapped Diagnostic Context. Shortly, it is a concept of mapping request specific information.


We will configure MDC in Spring Boot application. We will use SLF4J on top of Logback implementation. Using it all together, we will create a unique requestId for each request in our system.


We will use 4 components here: Spring Boot, Slf4j, Logback and Java

Spring Boot

Spring Boot will be used for managing dependency injection and registering pure Java Filter.


Simple Logging Facade is used for following abstraction principles. Additionally, MDC class is located inside slf4j dependency. Similar classes are inside log4j and logback dependencies.


Logback is used as one of logging providers

Pure Java

Java is used for writing simple Java Filter.

Affected files

package org.startup.queue.filter;

import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

public class MDCFilter implements Filter {

    public void init(FilterConfig filterConfig) throws ServletException { }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String requestId = httpRequest.getHeader("requestId");

        if (requestId == null) {
            requestId = UUID.randomUUID().toString();

        MDC.put("requestId", requestId);
        httpResponse.setHeader("requestId", requestId);

        try {
            chain.doFilter(request, response);
        } finally {

    public void destroy() {


How MDC handle multiple requests ? It works per thread using ThreadLocal:

public class BasicMDCAdapter implements MDCAdapter {

    private InheritableThreadLocal<Map<String, String>> inheritableThreadLocal = new InheritableThreadLocal<Map<String, String>>();

<?xml version="1.0" encoding="UTF-8"?>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
                %d{yyyy-MM-dd HH:mm:ss} %X{requestId} [%thread] %-5level %logger{36} - %msg%n

    <root level="error">
        <appender-ref ref="STDOUT" />



The result of this little trick is to have requestId in your headers:

HTTP/1.1 200 OK
requestId: 11ae099f-3d8f-4574-9c40-1c38613f6605

You can now use it as an identifier for searching your logs.