SpringBoot logback log printing adds trace_uuid tracking interface request output log (including thread pool unified configuration)

In order to facilitate project log query, you can add a custom identifier to the log configuration file and add a uuid to the log header to achieve the purpose of adding a unique identifier for the same interface request identifier.

Here’s a simple way:
1. By looking at the slf4j source code comments, the MDC class in the org.slf4j package provides MDC (Mapped Diagnostic Contexts) for log4j and logback, which is a thread-safe container for storing diagnostic logs. )] function, the static method put(String key, String val) in the MDC class can put the custom identification key into the MDCAdapter. Finally, through the reflection mechanism, the key corresponds to the identification key in the xml configuration, and the value of the key identification is added. Enter the log content.

2. Add a custom logo to the logback-spring.xml configuration file. Add [%X{trace_uuid}] to the configuration.

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <!-- Console output log -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%X{trace_uuid}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%level] [%thread] [%c] %L - %msg%n</pattern>
        </encoder>
    </appender>
    <!--Generate a log file every day and save the log file for 30 days. -->
    <appender name="DayFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>logs/log.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/log.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>[%X{trace_uuid}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%level] [%thread] [%c] %L - %msg%n</pattern>
        </encoder>
    </appender>
    <!--Specify the logger name as the package name or full class name and specify whether the level additivity setting is passed to the root logger -->
    <logger name="slf4j" level="INFO" additivity="false">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="DayFile"/>
    </logger>
    <!--The classes under the slf4j2 package are passed to the root logger at the ERROR level-->
    <logger name="slf4j2" level="ERROR"/>
    <!--Root logger control-->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="DayFile"/>
    </root>
</configuration>

Depending on the actual situation of the project, find the project interface request entry, which can be the interceptor, AOP of the Controller layer, token verification, etc., and add the following line of code:

MDC.put("trace_uuid", UUID.randomUUID().toString());

Original link: https://blog.csdn.net/qq_36599564/article/details/99947049

However, the specific implementation has not been explained yet.

1. Web request to print uuid

You can use interceptors, Controller layer AOP, token verification, etc. I use interceptors to implement it here.

1. Define an interceptor

import org.slf4j.MDC;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * Link ID interceptor
 *
 */
public class TraceIdInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        MDC.put("trace_uuid", UUID.randomUUID().toString());
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // Do nothing
    }


}

2. Configure interceptor

import cn.quant_cloud.ly.interceptor.TraceIdInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * web configuration class
 *
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TraceIdInterceptor());
    }
}

2. Thread pool unified configuration printing UUID

What I actually configured here is Spring Boot’s schdule thread pool, and it is the same when converted to other thread pools.

import org.slf4j.MDC;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import javax.validation.constraints.NotNull;
import java.util.UUID;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;

/**
 * Scheduled task configuration class
 *
 */
@EnableScheduling
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        //Open a thread scheduling pool
        ThreadPoolTaskScheduler taskScheduler = new CustomerThreadPoolTaskScheduler();
        //Set the thread pool size to 1: prevent multiple scheduled tasks from executing concurrently
        taskScheduler.setPoolSize(1);
        taskScheduler.initialize();
        taskRegistrar.setTaskScheduler(taskScheduler);
    }

    public static class CustomerThreadPoolTaskScheduler extends ThreadPoolTaskScheduler {
        @Override
        protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
            return new CustomerScheduledExecutorService(poolSize, threadFactory, rejectedExecutionHandler);
        }
    }
    public static class CustomerScheduledExecutorService extends ScheduledThreadPoolExecutor {
        @Override
        protected void beforeExecute(Thread t, Runnable r) {
            //Bind the link tracking ID to the thread context before execution
            MDC.put("trace_uuid", UUID.randomUUID().toString());
        }
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            //Clear link tracking ID after execution
            MDC.remove("trace_uuid");
        }
        public CustomerScheduledExecutorService(int corePoolSize, @NotNull ThreadFactory threadFactory, @NotNull RejectedExecutionHandler handler) {
            super(corePoolSize, threadFactory, handler);
        }
    }
}