不知道你有沒有經(jīng)歷過被日志支配的恐懼?我就經(jīng)歷過,以前在服務(wù)器上要找到一個請求經(jīng)過所有鏈路的日志,并串聯(lián)起來發(fā)現(xiàn)真的好難,而且有了日志還沒用,最好還有有參數(shù),有響應(yīng)可以串聯(lián)起來整個業(yè)務(wù)邏輯,最大程度進(jìn)行場景復(fù)原,那段找日志的時光真是不堪回首,令人難忘,好在后來我離開了再沒去服務(wù)器上看過日志了。
針對這種場景,怎么解呢?針對每次請求如果我們生成一個id,每次打印日志的時候都把這個id打印出來,那么當(dāng)我們搜索每次請求的時候,根據(jù)這個id進(jìn)行搜索就行了,本文也是基于這個思路來實現(xiàn)這個功能的。
請求鏈路
client ---> Tomcat ---> other API
為了簡化我們的請求邏輯,這里假設(shè)client訪問我們的tomcat,然后tomcat訪問外部服務(wù)
記錄請求參數(shù)以及響應(yīng)
為了記錄請求參數(shù)以及響應(yīng)結(jié)果,我們需要借助Filter來解決這個問題

記錄Restful請求以及響應(yīng)
一般而言,我們的服務(wù)會調(diào)用其他服務(wù),無論你是使用的dubbo還是http,我們都能通過攔截器來記錄請求和響應(yīng)參數(shù),我們以rest來進(jìn)行舉例

?
由于我們的response是stream,我們想要消費(fèi)多次(一次返回給調(diào)用者,一次用于記錄),所以我們必須對這個response進(jìn)行封裝

?
Log4j2配置

?
至此,我們的日志記錄已經(jīng)初具雛形了,這個時候當(dāng)我們訪問后端請求時,就可以通過返回的requestId去服務(wù)器上查詢這次請求的鏈路日志

?
后臺日志如下

?
查詢時我們可以使用這樣的命令
cat api.log | grep ${requestId}
這樣就足夠了嗎?不,還不夠好。我們可以將我們的日志發(fā)送到ElasticSearch,然后通過Kibana進(jìn)行搜索,這樣就不用每次查看日志都還要登錄服務(wù)器了
自定義Appender
由于需要將日志發(fā)送到ES,所以我們需要自定義appender來發(fā)送日志,一個簡單的appender的如下

?
然后在Log4j中進(jìn)行如下配置即可

?
這里我的es使用的是本地安裝的es,所以在運(yùn)行的時候需要先啟動es
在Kibana中查詢

?
至此,我們的日志平臺就搭建起來了,以后別人就別想那么容易的推鍋給你了。
所有的代碼我都上傳到了我的github: (
https://github.com/generalthink/code)
以供大家參考
總結(jié)
核心思想就是讓 requestId出現(xiàn)在需要記錄日志的各個地方,然后通過requestId串聯(lián)起來。
都看到這里了,不點(diǎn)個贊嗎?
作者|think123|掘金