Spring項目如何實現(xiàn)帶請求鏈路id的日志記錄
我們在做java項目的時候通常需要通過請求日志來排查定位線上問題,在日志比較多而我們又需要查找整個請求的全部日志的時候會比較困難。所以,就需要在日志記錄的時候講同一個請求的關(guān)鍵日志用同一個唯一標(biāo)識串聯(lián)起來。這樣查找的時候就會比較好查找。下面來用java aop實現(xiàn)請求id的日志記錄。(該支持子線程繼承主線程請求id)
一:首先我們需要一個日志請求鏈路id切面類
注意:如果不考慮多線程則(第二步和第三步可以不要)
package com.iMagine.iMagine_pro.aop; import com.iMagine.iMagine_common.utils.UUIDUtil; import com.iMagine.iMagine_pro.utils.TokenUtil; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.MDC; import org.springframework.stereotype.Component; /** * @author 名一 * @ClassName TraceIdAspect * @description: 日志請求鏈路id切面處理 * @datetime 2024年 12月 16日 14:28 * @version: 1.0 */ @Slf4j @Aspect @Component public class TraceIdAspect { /** 鏈路追蹤id */ public final static String TRACE_ID = "TRACE_ID"; /** 用戶 */ public final static String USER = "USER"; /** * 鏈路id切點定義 */ @Pointcut("execution(* com.iMagine.iMagine_pro.controller.*.*(..))") public void TraceIdCut() { } /** * 鏈路id添加 */ @Before("TraceIdCut()") public void cutProcessBefore() { MDC.put(TRACE_ID, UUIDUtil.getUUID()); //以下代碼為記錄用戶信息,方便更直觀的識別日志操作人信息。若不需要可以將下面部分刪除 String nickname = TokenUtil.getNicknameByToken(); if (null == nickname){ nickname = "游客訪問"; } MDC.put(USER, nickname); } /** * 鏈路id清除 */ @After("TraceIdCut()") public void cutProcessAfter() { MDC.clear(); } }
package com.iMagine.iMagine_common.utils; import java.util.UUID; /** * @author 名一 * @ClassName UUIDUtil * @description: UUID工具類 * @datetime 2024年 04月 23日 11:49 * @version: 1.0 */ public class UUIDUtil { /** * 獲取UUID * * @return */ public static String getUUID() { //生產(chǎn)uuid并去掉uuid的短橫線 return UUID.randomUUID().toString().replace("-", ""); } }
二:創(chuàng)建一個處理多線程鏈路追蹤的工具類
package com.iMagine.iMagine_common.utils; import com.iMagine.iMagine_common.constant.SysConstant; import org.slf4j.MDC; import java.util.Map; /** * @author 名一 * @ClassName ThreadMdcUtil * @description: 多線程鏈路追蹤工具類 * @datetime 2024年 12月 16日 14:57 * @version: 1.0 */ public class ThreadMdcUtil { // 獲取唯一性標(biāo)識 public static String generateTraceId() { return UUIDUtil.getUUID(); } public static void setTraceIdIfAbsent() { if (MDC.get(SysConstant.TRACE_ID) == null) { MDC.put(SysConstant.TRACE_ID, generateTraceId()); } } /** * 用于父線程向線程池中提交任務(wù)時,將自身MDC中的數(shù)據(jù)復(fù)制給子線程 * * @param runnable 要執(zhí)行的線程 * @param context 父線程的mdc * @return 鏈路id傳遞后的任務(wù) */ public static Runnable wrap(final Runnable runnable, final Map<String, String> context) { return () -> { if (context == null) { MDC.clear(); } else { MDC.setContextMap(context); } setTraceIdIfAbsent(); try { runnable.run(); } finally { MDC.clear(); } }; } }
三:在往線程池放任務(wù)的時候做請求鏈路id傳遞
/** * 線程池添加 [ai server 相關(guān)操作(psot)]任務(wù) * * @param task 添加的任務(wù) */ public static void addSendPostThreadToThreadPool(SendPostThread task) { log.info("addSendPostThreadToThreadPool pool:{}, task:{}", pool, task); try { pool.execute(ThreadMdcUtil.wrap(task, MDC.getCopyOfContextMap())); } catch (Exception e) { log.error("addSendPostThreadToThreadPool error pool:{}, task:{}, e:", pool, task, e); } }
四:在日志配置里將鏈路追蹤id加入日志輸出格式的配置里
<!-- 日志輸出格式 (其中%X{TRACE_ID}是mdc里邊鏈路請求id的key,user-%X{USER}是用戶信息的key)--> <property name="ENCODER_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %X{TRACE_ID} user-%X{USER} %-5level %logger{32}-[%line] - %msg%n"/>
到此spring 項目實現(xiàn)帶請求鏈路id的日志記錄就完成了
到此這篇關(guān)于Spring項目如何實現(xiàn)帶請求鏈路id的日志記錄的文章就介紹到這了,更多相關(guān)Spring請求id日志記錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Swagger注解-@ApiModel和@ApiModelProperty的用法
這篇文章主要介紹了Swagger注解-@ApiModel和@ApiModelProperty的用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06詳解 Java Maximum redirects (100) exceeded
這篇文章主要介紹了詳解 Java Maximum redirects (100) exceeded的相關(guān)資料,需要的朋友可以參考下2017-05-05使用?EasyCode生成springboot+mybatis基礎(chǔ)程序的實現(xiàn)示例
本文主要介紹了使用?EasyCode生成springboot+mybatis基礎(chǔ)程序的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01