日志框架系列講解文章
日志框架 - 基于spring-boot - 使用入門
日志框架 - 基于spring-boot - 設(shè)計(jì)
日志框架 - 基于spring-boot - 實(shí)現(xiàn)1 - 配置文件
日志框架 - 基于spring-boot - 實(shí)現(xiàn)2 - 消息定義及消息日志打印
日志框架 - 基于spring-boot - 實(shí)現(xiàn)3 - 關(guān)鍵字與三種消息解析器
日志框架 - 基于spring-boot - 實(shí)現(xiàn)4 - HTTP請求攔截
日志框架 - 基于spring-boot - 實(shí)現(xiàn)5 - 線程切換
日志框架 - 基于spring-boot - 實(shí)現(xiàn)6 - 自動裝配
在前文 日志框架 - 基于spring-boot - 使用入門 中,我介紹了日志框架的使用。
但讀者看到了可能云里霧里的,因?yàn)闆]有代碼也沒有設(shè)計(jì)說明。所以你猜的沒錯!這一次就要來向各位觀眾揭示這小玩意里面的道道。
源起混亂的日志代碼
在前文已經(jīng)解釋過為什么要新造一個日志框架。
但我想靠文字不能有深切的體會。
下面是我在讀別人代碼時經(jīng)??吹降拇a:
logger.info("#{}#{}#{}#{}#{}", new String[]{
orderInfo.getOrderNo() /*訂單號*/,
orderInfo.getTradeCode() /*交易代碼*/,
orderInfo.getReqSys() /*請求方系統(tǒng)*/,
orderInfo.getLocale() /*區(qū)域代碼*/,
"req done" /*日志內(nèi)容*/})
沒有粗暴的用字符串相加,說明開發(fā)人員已經(jīng)有一點(diǎn)水平了,但是……
這段代碼意味著多糟糕的事情呢?。?/strong>
寫上面這段代碼的可能是某個加班熬夜到神志模糊的程序員,更糟的是他借差迷糊勁把其中的兩行寫反了!
不對照著日志規(guī)范細(xì)扣,基本沒有人能發(fā)現(xiàn)問題。
為了讓W(xué)EB層的Controller與業(yè)務(wù)層的Service都能這樣打印,Service層接口硬生生插入一個orderInfo,變成這樣。
public void service(SomeThing toServed, OrderInfo orderInfo)
業(yè)務(wù)代碼里面充斥著這樣的代碼,寫的人不知疲倦,看的我心煩意亂了。
于是乎,我下定決心!要有一個日志框架,好好教人打日志。
logger.info("req done" /*日志內(nèi)容*/)
必須像上面這樣寫日志代碼,其它的內(nèi)容全部實(shí)現(xiàn)自動填充!
設(shè)計(jì)原則
好!現(xiàn)在就來開始動手設(shè)計(jì)理想中的框架。但是在動手之前,還需要想清楚兩件事。
- 第一,要走的更遠(yuǎn),需要站在巨人的肩膀上。我無意實(shí)現(xiàn)一個跟log4j與logback之類雷同的框架。要利用上log4j或logback的特性,最好能兼容它們倆。
- 第二,一個好用的框架要做到稱手。要對普通開發(fā)人員透明,減少使用者的學(xué)習(xí)成本。
考慮到以上兩點(diǎn),并結(jié)合我們應(yīng)用常見的開發(fā)場景,我最終選定這個框架基于spring-boot實(shí)現(xiàn)。因?yàn)閟pring-boot提供了眾多實(shí)用的機(jī)制可供選擇。享受spring-boot帶來便利的同時,也為spring-boot做一些貢獻(xiàn),互利互惠。
基本概念
- 在我們系統(tǒng)中,一個應(yīng)用經(jīng)常能過HTTP或MQ與外部應(yīng)用溝通,我把溝通的內(nèi)容稱為消息。
- 消息中攜帶了許多關(guān)鍵信息,如前面提到的OrderNo、TradeCode等,需要被記錄打印,我將其稱為關(guān)鍵字。
- 我將系統(tǒng)常用日志分為三類,分別是系統(tǒng)運(yùn)行日志、消息日志、告警日志,它們各自輸出到不同的文件中。它們會被采集分析,分別服務(wù)于運(yùn)維人員、分析系統(tǒng)、監(jiān)控系統(tǒng)。由于對接系統(tǒng)不同,因此它們有各自的日志格式定義。
總體設(shè)計(jì)

如圖展示,里層綠色為應(yīng)用層,指業(yè)務(wù)開發(fā)人員編寫的業(yè)務(wù)代碼;外層藍(lán)色部分為框架層,包含日志框架的各個功能模塊。
簡單地說,日志框架有以下要點(diǎn):
- 在請求進(jìn)入業(yè)務(wù)層之前進(jìn)行攔截,獲得消息(Message)。
- 根據(jù)關(guān)鍵字(Keyword),使用解析器(MessageResolver)提取消息(Message)中的值。關(guān)鍵字(Keyword)及其值保存于MDC之中。
- 打印日志時,將MDC中的值按格式自動填充到指定位置。
- 提供一個@MessageToLog注解,在函數(shù)上使用,將函數(shù)的返回值視作消息(Message),打印到消息日志中。
- 對系統(tǒng)運(yùn)行日志,消息日志,告警日志三種不同的日志類型,有各自的追加器(Appender),分別寫入到不同的文件中。
實(shí)現(xiàn)
具體代碼實(shí)現(xiàn),且聽下回分解。
日志框架系列講解文章
日志框架 - 基于spring-boot - 使用入門
日志框架 - 基于spring-boot - 設(shè)計(jì)
日志框架 - 基于spring-boot - 實(shí)現(xiàn)1 - 配置文件
日志框架 - 基于spring-boot - 實(shí)現(xiàn)2 - 消息定義及消息日志打印
日志框架 - 基于spring-boot - 實(shí)現(xiàn)3 - 關(guān)鍵字與三種消息解析器
日志框架 - 基于spring-boot - 實(shí)現(xiàn)4 - HTTP請求攔截
日志框架 - 基于spring-boot - 實(shí)現(xiàn)5 - 線程切換
日志框架 - 基于spring-boot - 實(shí)現(xiàn)6 - 自動裝配