Logback 簡介
Logback 是一個穩定、高效、快速的 Java 日誌框架,作為 log4j 的改良版,它與 log4j 相比擁有更多特性,也帶來了很大的效能提升,具體改進可以檢視官方文件。
Logback 主要分為三個模組
- logback-core:核心模組,作為 classic 和 access 模組的基礎
- logback-classic:實現了 slf4j API,配合 slf4j 使用,可以方便的切換其他日誌框架
- logback-access:與Servlet容器(如Tomcat和Jetty)整合,提供了 HTTP 訪問日誌介面
Logback 載入
Logback 啟動載入時會按一下順序查詢配置檔案
- 在系統配置檔案 System Properties 中尋找是否有 logback.configurationFile 對應的 value
- 在 classpath 下尋找是否有 logback.groovy(logback支援groovy與xml兩種配置方式)
- 在 classpath 下尋找是否有 logback-test.xml
- 在 classpath 下尋找是否有 logback.xml
當查詢到任意一項配置存在後就不進行後續掃描了,會使用該配置檔案進行初始化,如果沒有查詢到配置檔案,Logback會建立一個向控制檯輸出日誌的配置。
Logback 配置
根節點 configuration
configuration 是配置檔案的根節點,有三個屬性:
- debug:預設值為false,設定為true時,將列印出 logback 內部日誌資訊,實時檢視 logback 執行狀態。
- scan:預設值為true,設定為true時,配置檔案如果發生改變,將會被重新載入。
- scanPeriod:當 scan 為 true 時,此屬性才會生效。設定掃描配置檔案是否有修改的時間間隔,預設單位是毫秒。預設的時間間隔為1分鐘(60 second)
配置程式碼:
<configuration scan="true" scanPeriod="60 second" debug="true">
</configuration>
複製程式碼
設定上下文名稱 contextName
每個 logger 都關聯到 logger 上下文,預設上下文名稱為 “default”。但可以使用<contextName>設定成其他名字,用於區分不同應用程式的記錄。一旦設定,不能修改。
配置程式碼:
<contextName>new context name</contextName>
複製程式碼
設定變數 property
property 是用來定義變數的標籤,設定之後可以用 ${變數名} 訪問,有三個屬性:
- name:變數名稱
- value:變數值
- file:指定配置檔案的路徑,它的作用在於,如果有多個配置資訊的話,可以直接寫在配置檔案中,然後通過file引入
- resource:作用與 file 一樣,不同的是它可以直接從 classpath 路徑下引入配置檔案
配置程式碼:
<!-- name value 形式 -->
<property name="APP_Name" value="MyApp"/>
<contextName>${APP_Name}</contextName>
複製程式碼
<!-- file 形式 -->
variables.properties:
APP_Name=MyApp
LOG_PATH=logs
<property file="src/main/java/config/variables.properties" />
<contextName>${APP_Name}</contextName>
複製程式碼
<!-- resource 形式 -->
variables.properties:
APP_Name=MyApp
LOG_PATH=logs
<property resource="variables.properties" />
<contextName>${APP_Name}</contextName>
複製程式碼
configuration 子節點 logger、root
logger 用來設定某一個類或者某個包的日誌輸出級別、以及輸出位置(指定 appender),有三個屬性:
- name:指定的包名或者類名
- level:輸出日誌級別,如果未設定此級別,那麼當前 logger 會向上繼承最近一個非空級別,root 預設有一個 level 為 debug
- additivity:是否將日誌向上級傳遞,預設為 true
logger 通過設定子節點 appender-ref 來指定日誌輸出位置,一個 logger 可以設定多個 appender-ref
配置程式碼:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>[%d{HH:mm:ss.SSS}] [%5level] [%thread] %logger{36} %msg%n</Pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<logger name="X" level="INFO" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
<logger name="X.Y" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
複製程式碼
root 是一個特殊的 logger , 是所有 logger 的根節點,因為已經被命名為 root 同時也沒有父級別,所以只有一個屬性 level,預設為 DEBUG
配置程式碼:
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC"/>
</root>
複製程式碼
level 繼承示例1:
logger name | level | 實際 level |
---|---|---|
root | DEBUG | DEBUG |
X | 未設定 | DEBUG |
X.Y | 未設定 | DEBUG |
X.Y.Z | 未設定 | DEBUG |
示例1只有 root 設定了一個級別,X,X.Y 和 X.Y.Z 這三個 logger 未設定日誌輸出級別,因此向上繼承 root 的級別,即 DEBUG
level 繼承示例2:
logger name | level | 實際 level |
---|---|---|
root | ERROR | ERROR |
X | INFO | INFO |
X.Y | DEBUG | DEBUG |
X.Y.Z | WARN | WARN |
示例2所有 logger 都設定了一個日誌級別,等級繼承不起作用。
level 繼承示例3:
logger name | level | 實際 level |
---|---|---|
root | DEBUG | DEBUG |
X | INFO | INFO |
X.Y | 未設定 | INFO |
X.Y.Z | WARN | WARN |
示例3 X.Y 沒有設定日誌級別,向上繼承最近一個有日誌級別的 logger X 的值。
level 繼承示例4:
logger name | level | 實際 level |
---|---|---|
root | DEBUG | DEBUG |
X | INFO | INFO |
X.Y | 未設定 | INFO |
X.Y.Z | 未設定 | INFO |
示例4 X.Y 和 X.Y.Z 沒有設定日誌級別,向上繼承最近一個有日誌級別的 logger X 的值。
configuration 子節點 appender
appender 是負責寫日誌的元件,有兩個屬性(使用時都必須配置):
- name:設定 appender 的名稱,供後面 logger 設定引用
- class:設定 appender 的全路徑類名,例:ch.qos.logback.core.ConsoleAppender
appender 可以包含零個或一個 layout ,零個或多個 encoder 元素以及零個或多個 filter 元素。除了這三個元素之外,還可以包含與 appender 類的 JavaBean 屬性相對應的任意數量的元素,如: file 指定日誌檔名稱。
- layout:對日誌進行格式化
- encoder: encoder 是0.9.19版本之後引進的,以前的版本使用 layout ,logback極力推薦的是使用 encoder 而不是 layout
- filter:對日誌進行過濾
appender 常用的有以下幾種:
- ConsoleAppender:輸出到控制檯,或者更確切地說是輸出到 System.out 或 System.err,前者是預設目標。
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
<target>
System.err
</target>
</appender>
複製程式碼
- FileAppender:輸出到檔案,目標檔案由 file 指定。如果該檔案已存在,則根據 append 屬性的值確定追加或者清空檔案。
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>testFile.log</file>
<append>true</append>
<!-- set immediateFlush to false for much higher logging throughput -->
<immediateFlush>true</immediateFlush>
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
複製程式碼
- RollingFileAppender:繼承自 FileAppender ,提供了滾動記錄的功能,先將日誌記錄到指定檔案,當觸發某個條件時,將日誌記錄到其他檔案。有兩個重要的子節點 rollingPolicy 和 triggeringPolicy
- rollingPolicy:指定發生滾動時 RollingFileAppender 的行為,例如可以切換日誌檔案
- triggeringPolicy:指定 RollingFileAppender 何時觸發滾動。
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logFile.log</file>
<!-- 根據時間來制定滾動策略,既負責滾動也負責觸發滾動。 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天生成日誌檔案 -->
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 保留最近30天的日誌檔案 -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>mylog.txt</file>
<!-- 基於檔案大小和時間的滾動策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每天生成日誌檔案 -->
<fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
<!-- 每個日誌檔案最多 100MB, 保留 60 天, 最多 20 GB-->
<maxFileSize>100MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
複製程式碼
- AsyncAppender:非同步記錄日誌,它僅僅作為一個排程者,因此必須引用另一個 appender 來做日誌輸出。
- discardingThreshold:預設情況下,當阻塞佇列剩餘容量為20%時,它將丟棄級別為 TRACE,DEBUG 和 INFO 的事件,僅保留級別為 WARN 和 ERROR 的事件。設定為0即可保留所有事件。
- queueSize:阻塞佇列的最大容量。預設情況下,queueSize 為 256。
- appender-ref:表示 AsyncAppender 使用哪個具體的 appender 進行日誌輸出。
<!-- 非同步輸出 -->
<appender name ="ASYNC" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丟失日誌 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改預設的佇列的深度,該值會影響效能.預設值為256 -->
<queueSize>256</queueSize>
<!-- 新增附加的appender,最多隻能新增一個 -->
<appender-ref ref ="FILE"/>
</appender>
<logger name="X" level="DEBUG">
<appender-ref ref="ASYNC" />
</logger>
複製程式碼