How to use MDC of logback and SLF4J with spring boot to capture unique tracking in the POST request json?
Asked Answered
M

2

13

We are using:

  • Spring Boot
  • Slf4J
  • Logback
  • ELK stack

Now we want to use MDC to add the unique tracking number, which is provided in the POST request JSON, to every log statement for a given request.

I googled some blog posts, those are not useful for me much.

Below is the logback.xml which we are using

<configuration>
    <property name="PROJECT_ID" value="template-api"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

Can anyone provide some help on how to get this done please?

Macklin answered 4/10, 2017 at 11:7 Comment(0)
R
10

Sorry, don't have enough rep to write comment. This is more correct, fully working code, based on @glytching answer:

@Component
public class MDCFilter extends OncePerRequestFilter {

    @Autowired
    private TrackingnumberGenerator trackGen;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        MDC.put("trackingNumber", trackGen.getTrackingNumber());
        try {
            filterChain.doFilter(request, response);
        } finally {
            MDC.remove("trackingNumber");
        }
    }
}
Rostand answered 1/12, 2019 at 20:32 Comment(0)
F
9

You can use Logback's Mapped Diagnotic Context to propagate a unique tracking number to every log message.

There are two parts to this:

  • Push your unique tracking number into MDC e.g. MDC.put("uniqueTrackingNumber", the_unique_tracking_number);

  • Include the MDC entry in your log statements. You do this by specifying it in your logging pattern. So, if you store the unique tracking number in a MDC entry named uniqueTrackingNumber then you would include it in your emitted log events by defining a layout like this:

<layout class="ch.qos.logback.classic.PatternLayout">
    <Pattern>
        %d{yyyy-MM-dd HH:mm:ss} [%thread] [%X{uniqueTrackingNumber}] %-5level %logger{36} - %msg%n
    </Pattern>
</layout>

More details in the docs.

I presume that the scope of a "unique tracking number" is limited to a request (or a single 'flow' through your application)? If so, then you'll want to identify some throttle point where you can push the MDC value on the way in. In the Spring Boot world this is likely to be a Filter. Something like this, perhaps:

@Component 
public static class UniqueTrackingNumberFilter extends OncePerRequestFilter() {

    @Override
    protected abstract void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                    throws ServletException, IOException {
        // presumably this is extracted from the request (or defaulted, if not supplied)
        int uniqueTrackingNumber = ;
        MDC.put("uniqueTrackingNumber", uniqueTrackingNumber);
    }
}

Alternatively you could extend Logback's MDCInsertingServletFilter to extract whatever you want from the request and push it into MDC.

Feer answered 4/10, 2017 at 11:27 Comment(4)
You also need to clear the uniqueTrackingNumber from the MDC?Ningsia
Yes, have a look at the finally block in MDCInsertingServletFilter.doFilter() for an example of that.Feer
Use %mdc to print multiple values present in MDC without having to know each keyExpectorant
You need filterChain.doFilter(request, response); at the end. Otherwise your request will get filtered.Ponderous

© 2022 - 2024 — McMap. All rights reserved.