Adding transaction id or trace Id for each request in spring boot for tracing the log easily.

Adding transaction id or trace Id for each request in spring boot for tracing the log easily.

As most of us use spring boot as our got to framework for web development. And Also we are rapidly moving towards the Micro Services, One concern is to effectively monitor and  trace the Application's Log. So In this distributed era we adapted to have Transaction Id/Trace ID to trace the request propagation from start to end. This article will help with Intercepting all the request check if the header has the "X-Trace-Id" field, if so add it to the current context or else create new Transaction Id  and print it using log4js logs context without changing much existing of code.

Now Lets dig into the Configuration part.

@Component
public class AppMvcInterceptor implements HandlerInterceptor {
    
    private String TRACE_HEADER = "X-Trace-Id";
    
    public AppMvcInterceptor() {
        MDC.put("transactionId", UUID.randomUUID().toString());
    }



    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String traceID = UUID.randomUUID().toString();
        if (request.getHeader(TRACE_HEADER) != null || !request.getHeader(TRACE_HEADER).isEmpty()) {
            traceID = request.getHeader(TRACE_HEADER);
        }
        MDC.put("transactionId", traceID);
        return true;
    }
}

This Spring way to write the interceptor which intercept all the http request, so i have Override the pre handle method to check the header for "X-Trace-Id" if available add the MDC context of log4j. So MDC is called as Mapped Diagnostic Context, so as name suggest we are mapping additional value for broaden the aspect of the logging.

Next step is to instruct MVC context to register this interceptor.

@Component
public class AppMvcConfig implements WebMvcConfigurer {
    @Autowired
    AppMvcInterceptor appMvcInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(appMvcInterceptor);
    }
}

So Now, each and every request of our application has the transactionId in our MDC context  so we can access this information by `MDC.get("transactionId")`,  this will help us to pass the same transaction Id to next Micro-service call.

As see the the log in our console or file append this `[%X{transactionId}]` to our logging patter of log4j . for example my log4j looks like this

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="[%X{transactionId}] %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>