SpringBoot使用TraceId進(jìn)行日志追蹤的實現(xiàn)
查詢?nèi)罩镜耐袋c:項目中每當(dāng)我們查詢?nèi)罩镜臅r候都是看前端請求什么接口,根據(jù)一些關(guān)鍵字進(jìn)入服務(wù)器查詢?nèi)罩局惺欠裼羞@個關(guān)鍵字,然而這個關(guān)鍵字在日志里面并不是唯一的,所以要生成一個唯一的標(biāo)識,每一次請求都是唯一的一串字符,查詢會過濾掉很多無用的信息,快捷查找到這次請求。為了解決這個痛點,就使用了TraceId。
一、TraceId 定義
用于標(biāo)識某一次具體的請求ID。當(dāng)用戶的請求進(jìn)入系統(tǒng)后,會在RPC調(diào)用網(wǎng)絡(luò)的第一層生成一個全局唯一的traceId,并且會隨著每一層的RPC調(diào)用,不斷往后傳遞,這樣的話通過traceId就可以把一次用戶請求在系統(tǒng)中調(diào)用的路徑串聯(lián)起來。
在分布式系統(tǒng)中,一個請求可能會涉及多個服務(wù)和組件的調(diào)用,而traceId可以幫助我們追蹤和查看整個請求的流程和調(diào)用鏈
二、TraceId的請求流程
在最開始請求系統(tǒng)時候生成一個全局唯一的traceId,放在http 請求header中,系統(tǒng)接收到請求后,從header中取出這個traceId,放入MDC中,這個traceId伴隨著這整個請求的調(diào)用周期,即當(dāng)一個服務(wù)調(diào)用另外一個服務(wù)的時候,需要將traceId往下傳遞,從而形成一條鏈路。
注意:這次的traceId主要是用UUID來生成的,前端生成traceId,后端攔截器攔截到了做一層判斷,如果前端有,就不需要后端生成,而且只需要將前端的這個traceId發(fā)給后端人員,后端人員就能直接能定位到日志,不需要再讓前端給請求的是什么接口,所以建議是前端來生成traceId。
三、SpringBoot整合TraceId
(一)添加一個logback.xml
logback.xml內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <property name="LOG_PATH" value="/xxx/log"/> <!-- 項目的日志路徑 --> <property name="LOG_FILE" value="xxx"/> <property name="DATE_PATH" value="${LOG_PATH}/%d{yyyy-MM-dd}"/> <!-- 日志輸出格式 --> <property name="log.pattern.console" value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) [traceId:%X{traceId}] %highlight(%-5level) %boldMagenta(%logger{10}) - %cyan(%msg%n)"/> <property name="log.pattern.file" value="%d{HH:mm:ss.SSS} [%thread] [traceId:%X{traceId}] %-5level %logger{20} - [%method,%line] - %msg%n"/> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <include resource="org/springframework/boot/logging/logback/console-appender.xml"/> <!-- 控制臺輸出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${log.pattern.console}</pattern> <charset>utf8</charset> </encoder> </appender> <!-- 日志文件fzwyapi-admin.log --> <appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_PATH}/${LOG_FILE}.log</file> <append>true</append> <encoder> <!-- <pattern>${CONSOLE_LOG_PATTERN}</pattern>--> <pattern>${log.pattern.file}</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern> ${DATE_PATH}/%i.log </fileNamePattern> <maxHistory>15</maxHistory> <totalSizeCap>20GB</totalSizeCap> <maxFileSize>50MB</maxFileSize> </rollingPolicy> </appender> <appender name="fileError" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <file>${LOG_PATH}/${LOG_FILE}.error.log</file> <append>true</append> <encoder> <!-- <pattern>${CONSOLE_LOG_PATTERN}</pattern>--> <pattern>${log.pattern.file}</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern> ${DATE_PATH}/%i.error.log </fileNamePattern> <maxHistory>15</maxHistory> <totalSizeCap>20GB</totalSizeCap> <maxFileSize>50MB</maxFileSize> </rollingPolicy> </appender> <root level="info"> <appender-ref ref="fileAppender"/> <appender-ref ref="fileError"/> <appender-ref ref="STDOUT"/> </root> </configuration>
(二)添加TraceId工具類
TraceIdUtil.java
package xxx; import org.slf4j.MDC; import java.util.UUID; /** * @author lyc * @date 2024/10/17 * @funtion */ public class TraceIdUtil { public static final String TRACE_ID = "traceId"; public static String getTraceId() { String traceId = MDC.get(TRACE_ID); return traceId == null ? "" : traceId; } public static void setTraceId(String traceId) { MDC.put(TRACE_ID, traceId); } public static void remove() { MDC.remove(TRACE_ID); } public static void clear() { MDC.clear(); } public static String generateTraceId() { return UUID.randomUUID().toString().replace("-", ""); } }
(三)添加TraceId攔截器
SystemTraceIdInterceptor.java
package xxx; import xxx.TraceIdUtil; 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; /** * @author lyc * @date 2024/10/17 * @funtion */ @Component public class SystemTraceIdInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { //如果有上層調(diào)用就用上層的ID String traceId = request.getHeader(TraceIdUtil.TRACE_ID); if (traceId == null) { traceId = TraceIdUtil.generateTraceId(); } MDC.put(TraceIdUtil.TRACE_ID, traceId); //配置traceId到響應(yīng)header中 response.setHeader(TraceIdUtil.TRACE_ID, MDC.get(TraceIdUtil.TRACE_ID)); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { //調(diào)用結(jié)束后刪除 MDC.remove(TraceIdUtil.TRACE_ID); } }
(四)InterceptorConfig配置TraceId攔截器
TraceIdUtil.java
package xxx.config; import xxx.SystemTraceIdInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; /** * @author lyc * @updated: 2024/10/17 * @funtion */ @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Resource private SystemTraceIdInterceptor systemTraceIdInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { //配置鏈路追蹤traceId攔截器 registry.addInterceptor(systemTraceIdInterceptor).addPathPatterns("/**"); } }
四、效果
到此這篇關(guān)于SpringBoot使用TraceId進(jìn)行日志追蹤的實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot TraceId日志追蹤內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
elasticsearch集群cluster主要功能詳細(xì)分析
這篇文章主要為大家介紹了elasticsearch集群cluster主要功能詳細(xì)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04Java實現(xiàn)的各種排序算法(插入排序、選擇排序算法、冒泡排序算法)
本文是小編給大家?guī)淼膉ava各種排序算法知識,包括插入排序、選擇排序算法、冒泡排序算法,代碼簡單易懂,需要的朋友可以參考下2016-08-08java實現(xiàn)fibonacci數(shù)列學(xué)習(xí)示例分享(斐波那契數(shù)列)
這篇文章主要介紹了fibonacci數(shù)列(斐波那契數(shù)列)示例,大家參考使用吧2014-01-01Java?Scanner?類讀取一維數(shù)組二維數(shù)組示例詳解
這篇文章主要為大家介紹了Java?Scanner?類讀取一維數(shù)組二維數(shù)組示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11