SpringBoot使用TraceId進(jìn)行日志追蹤的流程步驟
**查詢?nèi)罩镜耐袋c(diǎn):**項(xiàng)目中每當(dāng)我們查詢?nèi)罩镜臅r(shí)候都是看前端請(qǐng)求什么接口,根據(jù)一些關(guān)鍵字進(jìn)入服務(wù)器查詢?nèi)罩局惺欠裼羞@個(gè)關(guān)鍵字,然而這個(gè)關(guān)鍵字在日志里面并不是唯一的,所以要生成一個(gè)唯一的標(biāo)識(shí),每一次請(qǐng)求都是唯一的一串字符,查詢會(huì)過濾掉很多無用的信息,快捷查找到這次請(qǐng)求。為了解決這個(gè)痛點(diǎn),就使用了TraceId。
一、TraceId 定義
用于標(biāo)識(shí)某一次具體的請(qǐng)求ID。當(dāng)用戶的請(qǐng)求進(jìn)入系統(tǒng)后,會(huì)在RPC調(diào)用網(wǎng)絡(luò)的第一層生成一個(gè)全局唯一的traceId,并且會(huì)隨著每一層的RPC調(diào)用,不斷往后傳遞,這樣的話通過traceId就可以把一次用戶請(qǐng)求在系統(tǒng)中調(diào)用的路徑串聯(lián)起來。
在分布式系統(tǒng)中,一個(gè)請(qǐng)求可能會(huì)涉及多個(gè)服務(wù)和組件的調(diào)用,而traceId可以幫助我們追蹤和查看整個(gè)請(qǐng)求的流程和調(diào)用鏈
二、TraceId的請(qǐng)求流程
在最開始請(qǐng)求系統(tǒng)時(shí)候生成一個(gè)全局唯一的traceId,放在http 請(qǐng)求header中,系統(tǒng)接收到請(qǐng)求后,從header中取出這個(gè)traceId,放入MDC中,這個(gè)traceId伴隨著這整個(gè)請(qǐng)求的調(diào)用周期,即當(dāng)一個(gè)服務(wù)調(diào)用另外一個(gè)服務(wù)的時(shí)候,需要將traceId往下傳遞,從而形成一條鏈路。
注意:這次的traceId主要是用UUID來生成的,前端生成traceId,后端攔截器攔截到了做一層判斷,如果前端有,就不需要后端生成,而且只需要將前端的這個(gè)traceId發(fā)給后端人員,后端人員就能直接能定位到日志,不需要再讓前端給請(qǐng)求的是什么接口,所以建議是前端來生成traceId。
三、SpringBoot整合TraceId
(一)添加一個(gè)logback.xml
logback.xml內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_PATH" value="/xxx/log"/> <!-- 項(xiàng)目的日志路徑 -->
<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"/>
<!-- 控制臺(tái)輸出 -->
<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攔截器
InterceptorConfig.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("/**");
}
}
四、效果

以上就是SpringBoot使用TraceId進(jìn)行日志追蹤的流程步驟的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot TraceId日志追蹤的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring Boot實(shí)戰(zhàn)之發(fā)送郵件示例代碼
本篇文章主要介紹了Spring Boot實(shí)戰(zhàn)之發(fā)送郵件示例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-03-03
SpringBoot定時(shí)任務(wù)多實(shí)例互斥執(zhí)行的完整指南
Spring Boot 的 @Scheduled 寫定時(shí)任務(wù)很方便,但多實(shí)例部署時(shí)有個(gè)問題,同一個(gè)定時(shí)任務(wù)會(huì)在每臺(tái)機(jī)器上都觸發(fā)執(zhí)行,下面我們就來看看如何解決吧2026-01-01
淺析如何在Java應(yīng)用中優(yōu)雅的發(fā)送短信
很多業(yè)務(wù)場景里,我們都需要發(fā)送短信,比如登陸驗(yàn)證碼、告警、營銷通知、節(jié)日祝福等等,這篇文章,我們聊聊 Java 應(yīng)用中如何優(yōu)雅的發(fā)送短信,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2023-11-11
Mybatis返回值(resultType&resultMap)的具體使用
返回值屬性有兩種設(shè)置,一種是resultType,一種是resultMap,本文主要介紹了Mybatis返回值(resultType&resultMap)的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08
關(guān)于springboot-starter-undertow和tomcat的區(qū)別說明
這篇文章主要介紹了關(guān)于springboot-starter-undertow和tomcat的區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
IDEA下創(chuàng)建SpringBoot+MyBatis+MySql項(xiàng)目實(shí)現(xiàn)動(dòng)態(tài)登錄與注冊(cè)功能
這篇文章主要介紹了IDEA下創(chuàng)建SpringBoot+MyBatis+MySql項(xiàng)目實(shí)現(xiàn)動(dòng)態(tài)登錄與注冊(cè)功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
SpringMVC?RESTFul實(shí)戰(zhàn)案例刪除功能實(shí)現(xiàn)
這篇文章主要為大家介紹了SpringMVC?RESTFul實(shí)戰(zhàn)案例刪除功能實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05

