不知道你有沒有經(jīng)歷過被日志支配的恐懼?我就經(jīng)歷過,以前在服務(wù)器上要找到一個請求經(jīng)過所有鏈路的日志,并串聯(lián)起來發(fā)現(xiàn)真的好難,而且有了日志還沒用,最好還有有參數(shù),有響應(yīng)可以串聯(lián)起來整個業(yè)務(wù)邏輯,最大程度進行場景復(fù)原,那段找日志的時光真是不堪回首,令人難忘,好在后來我離開了再沒去服務(wù)器上看過日志了。
針對這種場景,怎么解呢?針對每次請求如果我們生成一個id,每次打印日志的時候都把這個id打印出來,那么當我們搜索每次請求的時候,根據(jù)這個id進行搜索就行了,本文也是基于這個思路來實現(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來進行舉例

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

Log4j2配置

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

后臺日志如下

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

然后在Log4j中進行如下配置即可

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

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