logback和log4j日志框架堆棧信息添加TraceId方式
背景
TraceId是我在項(xiàng)目上自定義的,作為鏈路追蹤來使用。至于為什么沒有用市面上skywalking此類現(xiàn)成的鏈路追蹤,是因?yàn)槟壳斑@個(gè)項(xiàng)目是boot單體,也不是分布式,不想引入過多比較復(fù)雜的依賴項(xiàng),造成不必要的維護(hù)麻煩。
使用traceId只是來準(zhǔn)確定位某個(gè)請求的日志信息,自己實(shí)現(xiàn)的話比較輕量化,也能夠滿足項(xiàng)目的開發(fā)和維護(hù)需求。
當(dāng)請求訪問時(shí),被過濾器攔截到,生成一個(gè)唯一的traceId存放在MDC中(分布式項(xiàng)目可以通過請求頭獲取上游服務(wù)傳過來的traceId),MDC是ThreadLocal類型線程安全的。
日志xml配置寫上traceId會(huì)自動(dòng)讀取MDC。
logback日志框架
由于之前項(xiàng)目是使用的logback日志框架,如果只在xml日志文件中配置traceId的話,當(dāng)報(bào)錯(cuò)時(shí)候輸出的堆棧信息內(nèi)不會(huì)保存traceId。
到時(shí)候線上排查問題,無法通過grep命令篩選出來報(bào)錯(cuò)的堆棧信息,也就不能快速定位代碼中的報(bào)錯(cuò)位置。
堆棧信息不攜帶traceId
xml配置文件中的配置
堆棧信息攜帶traceId
logback想要在堆棧信息中添加traceId需要繼承ThrowableProxyConverter,重寫里面的方法。
import ch.qos.logback.classic.pattern.ThrowableProxyConverter; import ch.qos.logback.classic.spi.IThrowableProxy; import org.apache.commons.lang3.StringUtils; import org.slf4j.MDC; public class CompressedStackTraceConverter extends ThrowableProxyConverter { public CompressedStackTraceConverter() { } @Override protected String throwableProxyToString(IThrowableProxy tp) { String original = super.throwableProxyToString(tp); String traceId = MDC.get("traceId"); if (StringUtils.isBlank(traceId)) { traceId = ""; } traceId = "\t[ably-stack]\t[" + traceId + "]"; return original.replaceAll("\n", traceId + "\n"); } }
此時(shí)的xml配置
<?xml version="1.0" encoding="UTF-8"?> <configuration> <conversionRule conversionWord="ex" converterClass="com.example.springbootdemo.configuration.httpglobal.CompressedStackTraceConverter"/> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern xml:space="preserve"> %d{yyyy-MM-dd HH:mm:ss.SSS}|-|%lsn|-|%thread|-|%X{traceType}|-|%X{traceId}|-|%logger{80}:%L|-|%msg|-|%ex|-|%n </pattern> </encoder> </appender> <root level="info"> <appender-ref ref="STDOUT"/> </root> </configuration>
這樣logback框架就可以打印堆棧信息的時(shí)候攜帶traceId了
log4j日志框架
目前這個(gè)新項(xiàng)目使用的log4j這個(gè)框架,這里的traceId也是放在MDC中。
堆棧信息不攜帶traceId
堆棧信息攜帶traceId
當(dāng)我配置好traceId后,開始配置堆棧信息中的traceId,發(fā)現(xiàn)ThrowableProxyConverter是logback包下面的,無法使用它來添加。
于是我在網(wǎng)上找是否log4j有對應(yīng)的像logback這種接口可以操作堆棧信息的。無果!(也有可能我沒找到)。
后來偶然查到%throwable可以支持更改單個(gè)堆棧跟蹤元素,我就想可不可以使用它來添加traceId。
通過了解%throwable的常用方法,看到了配合{suffix(pattern)}使用,可以在每個(gè)堆棧幀的末尾添加模式輸出。
于是抱著試一試的態(tài)度就打印traceId,結(jié)果是可以的。
對應(yīng)的traceId在堆棧信息以及主日志中都打印了出來
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
IntelliJ IDEA 2020最新激活碼(親測有效,可激活至 2089 年
這篇文章主要介紹了IntelliJ IDEA 2021最新激活碼(親測有效,可激活至 2089 年),非常不錯(cuò),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04java并發(fā)編程工具類PriorityBlockingQueue優(yōu)先級隊(duì)列
這篇文章主要為大家介紹了java并發(fā)編程工具類PriorityBlockingQueue優(yōu)先級隊(duì)列的方法示例應(yīng)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03詳解備忘錄模式及其在Java設(shè)計(jì)模式編程中的實(shí)現(xiàn)
這篇文章主要介紹了詳解備忘錄模式及其在Java設(shè)計(jì)模式編程中的實(shí)現(xiàn),備忘錄模式數(shù)據(jù)的存儲(chǔ)過程中應(yīng)當(dāng)注意淺拷貝和深拷貝的問題,需要的朋友可以參考下2016-04-04java數(shù)據(jù)隨機(jī)分頁實(shí)現(xiàn)方案
本文主要介紹了java數(shù)據(jù)隨機(jī)分頁實(shí)現(xiàn)方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06Spring實(shí)戰(zhàn)之使用@Resource配置依賴操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用@Resource配置依賴操作,結(jié)合實(shí)例形式分析了Spring使用@Resource配置依賴具體步驟、實(shí)現(xiàn)及測試案例,需要的朋友可以參考下2019-12-12Java統(tǒng)計(jì)50個(gè)10到50之間整數(shù)的隨機(jī)出現(xiàn)次數(shù)
這篇文章主要為大家詳細(xì)介紹了Java統(tǒng)計(jì)50個(gè)10到50之間整數(shù)的隨機(jī)出現(xiàn)次數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07