1, Introduction to MDC
MDC (Mapped Diagnostic Contexts) maps diagnostic contexts. This feature is a function provided by logback to facilitate logging under multi-threaded conditions.
Some applications use multithreading to process requests from multiple users. During the use of a user, there may be multiple different threads to process. A typical example is a Web application server. When a user accesses a page, the application server may create a new thread to process the request, or reuse the existing thread from the thread pool. During a user's session, multiple threads may have processed the user's request. This makes it difficult to distinguish the logs corresponding to different users. When you need to track the relevant log records of a user in the system, it becomes very troublesome.
MDC is used to solve the above problems. MDC can be regarded as a hash table bound to the current thread, and key value pairs can be added to it. The content contained in MDC can be accessed by code executed in the same thread. The child thread of the current thread will inherit the contents of the MDC in its parent thread. When logging is required, you only need to obtain the required information from MDC. The content of MDC is saved by the program at an appropriate time. For a Web application, this data is usually saved at the beginning of the request being processed.
2, MDC implements log tracking
One system provides services for other systems to call. When other systems call, the request header carries a unique request ID and outputs this requestId to the log. In this way, the two systems will directly form an execution chain and connect them in series with requestId. When an error occurs, you can query the corresponding request log at the caller, You can also query the request log at the server. It is very convenient to locate the problem. There are many places to output the log. You can use MDC to cooperate with the pattern in logback.
3, HandlerInterceptor interceptor
Related introduction:
SpringBoot uses filters, interceptors, AOPs, and their differences and execution order - splitting heaven and building land - blog Garden
HandlerInterceptor_dekulugu's blog - CSDN blog_ handlerinterceptor
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class TokenInterceptor implements HandlerInterceptor { private static final Logger logger = LoggerFactory.getLogger(TokenInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { //Add MDC log String appkey = request.getHeader("appkey"); MDC.put("LOG_TRACK_ID", appkey); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { //Remove MDC log MDC.remove("LOG_TRACK_ID"); } }
4, logback file
<?xml version="1.0" encoding="UTF-8"?> <configuration> <property name="logLevel" value="INFO"></property> <property name="logPath" value="./logs"></property> <property name="maxHistory" value="31"/> <property name="maxFileSize" value="100MB"/> <property name="totalSizeCap" value="200GB"/> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] [%X{logTrackId}] %-5level %logger{35} - %msg %n</pattern> </encoder> </appender> <appender name="FILE_INFO" class="ch.qos.logback.classic.sift.SiftingAppender"> <!--discriminator Discriminator, according to logTrackId this key Corresponding value Identify log events and delegate them to specific appender Write log--> <discriminator> <key>logTrackId</key> <defaultValue>default</defaultValue> </discriminator> <sift> <!--Specific log writing appender,every last logTrackId Create a file--> <appender name="FILE-${logTrackId}" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--Specify file path directly--> <append>true</append> <encoder charset="UTF-8"> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] [%X{logTrackId}] %-5level %logger{35} - %msg%n</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!--Defines the format of the file name when the file is scrolled--> <fileNamePattern>${logPath}/%d{yyyy-MM-dd}/${logTrackId}-%i.log</fileNamePattern> <maxHistory>${maxHistory}</maxHistory> <maxFileSize>${maxFileSize}</maxFileSize> <totalSizeCap>${totalSizeCap}</totalSizeCap> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> </appender> </sift> </appender> <!-- Asynchronous output --> <appender name="ASYNC-INFO" class="ch.qos.logback.classic.AsyncAppender"> <!-- Do not lose logs.default,If 80 of the queue%already expired,Will be discarded TRACT,DEBUG,INFO Level log --> <discardingThreshold>0</discardingThreshold> <!-- Change the depth of the default queue,This value affects performance.The default value is 256 --> <queueSize>512</queueSize> <!-- Add additional appender,At most one can be added --> <appender-ref ref="FILE_INFO"/> </appender> <root level="${logLevel}"> <appender-ref ref="STDOUT"/> <appender-ref ref="FILE_INFO"/> </root> </configuration>
Related learning links: New understanding of logback (2): MDC log tracking and log customization effect of logback_ IT-CRUD-CSDN blog