前言
對於一個web專案來說,日誌框架是必不可少的,日誌的記錄可以幫助我們在開發以及維護過程中快速的定位錯誤。相信很多人聽說過slf4j,log4j,logback,JDK Logging等跟日誌框架有關的詞語,所以這裡也簡單介紹下他們之間的關係。
關係
首先slf4j可以理解為規則的制定者,是一個抽象層,定義了日誌相關的介面。log4j,logback,JDK Logging都是slf4j的實現層,只是出處不同,當然使用起來也就各有千秋,這裡放一張網上的圖更明瞭的解釋了他們之間的關係:
為什麼使用slf4j+logback
我使用這個框架是因為一開始接觸的時候就用的這個,後來在網上了解到slf4j+logback也確實當下最流行的日誌框架,並且自己用著也確實很順手,也就一直用了下來。
在Spring boot中使用slf4j+logback日誌框架
新增配置檔案
在Spring boot使用是非常方便的,不需要我們有什麼額外的配置,因為Spring boot預設支援的就是slf4j+logback的日誌框架,想要靈活的定製日誌策略,只需要我們在src/main/resources下新增配置檔案即可,只是預設情況下配置檔案的命名需要符合以下規則:
logback。xml
logback-spring。xml
其中logback-spring。xml是官方推薦的,
並且只有使用這種命名規則,才可以配置不同環境使用不同的日誌策略這一功能。
配置檔案詳解
首先介紹配置檔案的關鍵節點:
框架介紹
scan:當配置檔案發生修改時,是否重新載入該配置檔案,兩個可選值true or false,預設為true。
scanPeriod:檢測配置檔案是否修改的時間週期,當沒有給出時間單位時預設單位為毫秒,預設值為一分鐘,需要注意的是這個屬性只有在scan屬性值為true時才生效。
debug:是否列印loback內部日誌資訊,兩個可選值true or false,預設為false。
根節點
name:指定該節點的名稱,方便之後的引用。
class:指定該節點的全限定名,所謂的全限定名就是定義該節點為哪種型別的日誌策略,比如我們需要將日誌輸出到控制檯,就需要指定class的值為ch。qos。logback。core。ConsoleAppender;需要將日誌輸出到檔案,則class的值為ch。qos。logback。core。FileAppender等。
name:用來指定受此
level:可選屬性,用來指定日誌的輸出級別,如果不設定,那麼當前
additivity:是否向上級傳遞輸出資訊,兩個可選值true or false,預設為true。
在該節點內可以新增子節點
介紹了根節點的三個主要的子節點,下面再介紹兩個不那麼重要但可以瞭解的子節點:
name:變數名
value:變數值
好了,介紹了上邊的節點我們就已經可以搭建一個簡單的配置檔案框架了,如下:
<?xml version=“1。0” encoding=“UTF-8”?><!—— 一般根節點不需要寫屬性了,使用預設的就好 ——>
上面搭建了框架,定義了一個輸出到控制檯的ConsoleAppender以及輸出到檔案的FileAppender,下面來細說這兩個最基本的日誌策略,並介紹最常用的滾動檔案策略的RollingFileAppender,這三種類型的日誌策略足夠我們的日常使用。
輸出到控制檯的ConsoleAppender的介紹:
先給出一個demo:
<!——定義一個將日誌輸出到控制檯的appender,名稱為STDOUT ——>
ConsoleAppender的功能是將日誌輸出到控制檯,有一個
該節點主要做兩件事:
把日誌資訊轉換成位元組陣列
將位元組陣列寫到輸出流
該節點的子節點
%date{}:輸出時間,可以在花括號內指定時間格式,例如-%data{yyyy-MM-dd HH:mm:ss},格式語法和java。text。SimpleDateFormat一樣,可以簡寫為%d{}的形式,使用預設的格式時可以省略{}。
%logger{}:日誌的logger名稱,可以簡寫為%c{},%lo{}的形式,使用預設的引數時可以省略{},可以定義一個整形的引數來控制輸出名稱的長度,有下面三種情況:
不輸入表示輸出完整的
輸入0表示只輸出
輸入其他數字表示輸出小數點最後邊點號之前的字元數量
%thread:產生日誌的執行緒名,可簡寫為%t
%line:當前列印日誌的語句在程式中的行號,可簡寫為%L
%level:日誌級別,可簡寫為%le,%p
%message:程式設計師定義的日誌列印內容,可簡寫為%msg,%m
%n:換行,即一條日誌資訊佔一行
介紹了常用的轉換符,我們再看看上邊的例子中我們定義的格式:
日誌的格式一目瞭然,可以看出我們在最前面加了[eran]的字串,這裡是我個人的使用習慣,一般將專案名統一展現在日誌前邊,而且在每個轉換符之間加了空格,這更便於我們檢視日誌,並且使用了>>字串來將%msg分割開來,更便於我們找到日誌資訊中我們關注的內容,這些東西大家可以自己按照自己的喜好來。
輸出到檔案的FileAppender
先給出一個demo:
<!——定義一個將日誌輸出到檔案的appender,名稱為FILE_LOG ——>
FileAppender表示將日誌輸出到檔案,常用幾個子節點:
顯而易見,樣例中我們的日誌策略表示,每次將日誌資訊追加到D:/test。log的檔案中。
滾動檔案策略RollingFileAppender介紹
按時間滾動TimeBasedRollingPolicy
demo如下:
RollingFileAppender是非常常用的一種日誌型別,表示滾動紀錄檔案,先將日誌記錄到指定檔案,當符合某種條件時,將日誌記錄到其他檔案,常用的子節點:
以上就是關於RollingFileAppender的常用介紹,上面的demo的配置也基本滿足了我們按照時間滾動TimeBasedRollingPolicy生成日誌的要求,下面再介紹一種常用的滾動型別SizeAndTimeBasedRollingPolicy,即按照時間和大小來滾動。
按時間和大小滾動SizeAndTimeBasedRollingPolicy
demo如下:
仔細觀察上邊demo中的
上邊的demo中多了一個
日誌過濾
級別介紹
在說級別過濾之前,先介紹一下日誌的級別資訊:
TRACE
DEBUG
INFO
WARN
ERROR
上述級別從上到下由低到高,我們開發測試一般輸出DEBUG級別的日誌,生產環境配置只輸出INFO級別甚至只輸出ERROR級別的日誌,這個根據情況而定,很靈活。
過濾節點
過濾器通常配置在Appender中,一個Appender可以配置一個或者多個過濾器,有多個過濾器時按照配置順序依次執行,當然也可以不配置,其實大多數情況下我們都不需要配置,但是有的情況下又必須配置,所以這裡也介紹下常用的也是筆者曾經使用過的兩種過率機制:級別過濾器LevelFilter和臨界值過濾器ThresholdFilter。
在此之前先說下
DENY:日誌將被過濾掉,並且不經過下一個過濾器
NEUTRAL:日誌將會到下一個過濾器繼續過濾
ACCEPT:日誌被立即處理,不再進入下一個過濾器
級別過濾器LevelFilter
過濾條件:只處理INFO級別的日誌,格式如下:
就如上邊的demo中的配置一樣,設定了級別為INFO,滿足的日誌返回ACCEPT即立即處理,不滿足條件的日誌則返回DENY即丟棄掉,這樣經過這一個過濾器就只有INFO級別的日誌會被打印出輸出。
臨界值過濾器ThresholdFilter
過濾條件:只處理INFO級別之上的日誌,格式如下:
當日志級別等於或高於臨界值時,過濾器返回NEUTRAL,當日志級別低於臨界值時,返回DENY。
帶過濾器的
下面給出一個帶過濾器的
上邊的demo中,我們給按時間和大小滾動SizeAndTimeBasedRollingPolicy的滾動型別加上了過濾條件。
非同步寫入日誌AsyncAppender
都知道,我們的日誌語句是嵌入在程式內部,如果寫入日誌以及程式執行的處於一個序列的狀態,那麼日誌的記錄就必然會阻礙程式的執行,加長程式的響應時間,無疑是一種極為損耗效率的方式,所以實際的專案中我們的日誌記錄一般都用非同步的方式來記錄,這樣就和主程式形成一種並行的狀態,不會影響我們程式的執行,這也是我們效能調優需要注意的一個點。
AsyncAppender並不處理日誌,只是將日誌緩衝到一個BlockingQueue裡面去,並在內部建立一個工作執行緒從佇列頭部獲取日誌,之後將獲取的日誌迴圈記錄到附加的其他appender上去,從而達到不阻塞主執行緒的效果。因此AsynAppender僅僅充當事件轉發器,必須引用另一個appender來寫日誌。
常用節點:
上邊花費了很長的篇幅介紹了
上文已經簡單介紹了
首先在這裡給出專案結構:
下面定義兩個
<!—— logger1 ——>
當存在多個
上邊我們定義了logger1和logger2,很明顯看出logger1是logger2的父級,以本例給出多個
流程圖看著一目瞭然,這裡就不再贅述,只是在實際的專案中我們一般都不讓
配置profile
profile即根據不同的環境使用不同的日誌策略,這裡舉例開發和生產環境:
<!—— 開發環境輸出到控制檯 ——>
可以看到我們只需要在
執行jar包時新增引數:
java -jar xxx。jar ——spring。profiles。active=prod
在專案的application。properties配置檔案中新增:
spring。profiles。active=prod
整合
最後將所有的模組整合在一起形成一個完整的配置檔案:
<?xml version=“1。0” encoding=“UTF-8”?>
程式碼中使用
終於到最後一步了,上邊介紹了怎麼配置logback-spring。xml配置檔案,下面介紹怎麼在專案中引入日誌物件,以及怎麼使用它輸出日誌,直接上程式碼:
package com。example。demo。controller;import org。slf4j。Logger;import org。slf4j。LoggerFactory;import org。springframework。web。bind。annotation。RequestMapping;import org。springframework。web。bind。annotation。RequestMethod;import org。springframework。web。bind。annotation。RestController;@RestControllerpublic class TestLog { private final static Logger log = LoggerFactory。getLogger(TestLog。class); @RequestMapping(value=“/log”,method=RequestMethod。GET) public void testLog() { log。trace(“trace級別的日誌”); log。debug(“debug級別日誌”); log。info(“info級別日誌”); log。warn(“warn級別的日誌”); log。error(“error級別日誌”); }}
在每一個需要使用日誌物件的方法裡邊都要定義一次private final static Logger log = LoggerFactory。getLogger(xxx。class);其中xxx代指當前類名,如果覺得這樣很麻煩,也可以透過@Slf4j註解的方式注入,但是這種方式需要新增pom依賴並且需要安裝lombok外掛,這裡就不概述了,需要了解的朋友可以自己google。