logback打印日誌輸出線程ID:mvc攔截器模式

一、前言

經常處理業務問題的同仁,一定都經常與日誌打交道。當併發量高、多線程編程時,日誌往往是一大堆,爲了快速精確的定位、處理問題,我們需要區分各個用戶的不同會話請求,需要從一坨坨日誌中做鏈路追蹤。

思路:在輸出日誌的時候,將每個線程的ID同時輸出,當然前提是保證每個線程的ID是唯一的。sl4j 提供的一個工具類MDC,支持 logback和log4j,作用就是擴展變量值到日誌中並輸出。

二、MVC攔截器模式輸出線程ID

  1. 加入POM引用
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

     

  2. 自定義日誌攔截器
    package cn.wuhg.climbing.service.design.patterns.sessionid.mvcfilter;
    
    import lombok.extern.slf4j.Slf4j;
    import org.slf4j.MDC;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.UUID;
    
    /**
     * 日誌攔截器
     */
    @Slf4j
    @Component
    public class LogInterceptor implements HandlerInterceptor {
        // 會話ID
        private final static String SESSION_ID = "sessionId";
    
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) {
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            MDC.put(SESSION_ID, uuid);
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {
            MDC.remove(SESSION_ID);
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        }
    }
    

     

  3. 重寫MCV過濾器
    package cn.wuhg.climbing.service.design.patterns.sessionid.mvcfilter;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @Configuration
    public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
        @Autowired
        private LogInterceptor logInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(logInterceptor);
            super.addInterceptors(registry);
        }
    }
    

     

  4. logback配置
    ​
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <contextName>SpringBootDemo</contextName>
        <property name="LOG_PATH" value="ToolLogs" />
        <!--設置系統日誌目錄 -->
        <property name="APPDIR" value="design-patterns" />
        <!-- 日誌記錄器,日期滾動記錄 -->
        <appender name="FILEALL"
    		class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${LOG_PATH}/${APPDIR}/logs.log</file>
            <!-- 日誌記錄器的滾動策略,按日期,按大小記錄 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- 歸檔的日誌文件的路徑,例如今天是2013-12-21日誌,當前寫的日誌文件路徑爲file節點指定,可以將此文件與file指定文件路徑設置爲不同路徑,從而將當前日誌文件或歸檔日誌文件置不同的目錄。 
    				而2013-12-21的日誌文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
                <fileNamePattern>${LOG_PATH}/${APPDIR}/logs-%d{yyyy-MM-dd}.%i.log
    			</fileNamePattern>
                <!-- 除按日誌記錄之外,還配置了日誌文件不能超過20M,若超過20M,日誌文件會以索引0開始, 命名日誌文件,例如log-error-2013-12-21.0.log -->
                <timeBasedFileNamingAndTriggeringPolicy
    				class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>20MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <!-- 追加方式記錄日誌 -->
            <append>true</append>
            <!-- 日誌文件的格式 -->
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{sessionId}] %-5level %class.%method Line:%-3L - %msg%n</pattern>
                <charset>utf-8</charset>
            </encoder>
        </appender>
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <!--encoder 默認配置爲PatternLayoutEncoder -->
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{sessionId}] %-5level %class.%method Line:%-3L - %msg%n</pattern>
                <charset>utf-8</charset>
            </encoder>
            <!--此日誌appender是爲開發使用,只配置最底級別,控制檯輸出的日誌級別是大於或等於此級別的日誌信息 -->
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>debug</level>
            </filter>
        </appender>
        <!-- 生產環境下,將此級別配置爲適合的級別,以免日誌文件太多或影響程序性能 -->
        <root level="INFO">
            <appender-ref ref="FILEALL" />
            <appender-ref ref="STDOUT" />
        </root>
    </configuration>
    
    ​

     

  5. Controller接口
    ​
    @LogId
    @GetMapping("/log")
        public void logId(){
        log.info("測試slf4j日誌線程ID");
    }
    
    ​

     

  6. 日誌截圖

三、往期推薦

logback打印日誌輸出線程ID:切面模式

 

作者:Smile瀟灑Tel 

轉載請註明出處,謝謝合作!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章