# 六角鼠年鐵人賽 Week 13 - Spring Boot - 一次搞懂 LogBack 設定 ==大家好,我是 "為了拿到金角獎盃而努力著" 的文毅青年 - Kai== ## 名句 Steven Paul Jobs :::info We don’t get a chance to do that many things, and every one should be really excellent. ::: ## 主題 今天來跟大家分享處理 LogBack 部分 在上一篇文章中已經介紹了諸多 LOG 的套件,今天再來說說 LogBack 幫助開發者處理 log 輸出設定的方式。 ## What is LogBack ? Logback 是原 Log4j 設計師後續開發的一款 Log 套件。 原先設計師準備要做的 Log4j v2 關於 **Log 套件與程式解耦合**的事情被 SLF4j 給搶先設計出來了,因此在 Log4j2 就不再多做重工,而是專注於與 Lambda 結合的處理,這也成為了後續 Logback 得以被設計出的原因。 Logback 在繼承了 Log4j 極為優秀的架構下,以優化效能更好、完整封裝 SLF4j 的功能,取代了 SLF4j 的存在。 我們可以從下面 Logback 核心的模組略知一二: - logback-core:Logback 的核心模組,不多說 - logback-classic:是 Log4j 模組的改良版本,完整封裝 SLF4j 套件的功能 - logback-access:是整合 Servlet containers 的模組,讓開發者可以紀錄 HTTP-access logs ## Logback 的優勢 Logback 不僅取代了 SLF4j,同時也在應用方面漸漸替代掉了 Log4j,那讓我們來了解一下,到底 Logback 有什麼樣的優勢讓他可以替換掉幾乎日 Java Log處理兩大龍頭的 SLF4j 和 Log4j 吧! ### - 效能的優化 Logback 的核心模組基本上是使用與 Log4j 相同的模組,但在路徑的處理上經過了優化,使其讀取的效能增加了十倍以上,這是一個不小的差距。同時也在初始化的內存部分進行了改寫,使其動用更少的資源完成相同的事情。 ### - logback-classic 在原先的 Log4j 中因為缺少解耦合的功能,因此只能一直綁定 SLF4j ,但在使用 Logback 時,因為內建封裝了所有 SLF4j 的功能,使開發者不需要處理整合兩套件的事情。 另外一項優點就是,當文件被改寫時,Logback-classic 套件有自動重載配置文件的功能,並不會創建一條新的執行緒去處理這件事情,使其過程不會有多線程的影響,且速度非常快速。 ### - 配置文件 Logback 會要求開發師建立 logback.xml 文件,雖然這部分相較 Log4j 和 SLF4j 麻煩,但也因其配置文件提供強大的設定功能,讓其不僅沒有成為缺點,還被大大的當作了指標性的優點。 例如給不同環境 (開發、測試、上線) 使用的 Log 並輸出到不同的 output 等處理。 不難想像 Logback 在一釋出就得到開發者熱烈的迴響與高使用率的狀況。 ### - 自動壓縮與自動刪除 Logback 透過文件設定可以執行包含 **自動壓縮 Log File** 與 **自動刪除 Log File** 的功能,可以通過控制文件容量大小或是時間的條件進行動作,幫助開發者能將處理Log的動作變更為自動化的過程。 ### - Filter 以往在處理 Log 時,Log4j 僅有 Log Level 讓開發者做控制,如今加入了 Filter 的功能讓處理上可以更加有彈性,例如有時候在追一個比較細部的問題時,Log Level 會調整到 Trace 甚至 All 但其實開發者只需要看特定的細節,不需要額外過多無用的訊息,Filter 功能可以幫助做到篩掉多餘的訊息。 ### - Lilith Event Log View,類似 Log4j 的 ChainSaw,可參考 [官方開發人員建議的 Lilith 教學 github](https://github.com/huxi/lilith) ### - SiftingAppender Logback 與 Log4j 一樣,將撰寫 Log 這件事情交給 Appender 來完成,而 SiftingAppender 則是更上一層將 Log 分配給不同 Appender 處理的部分。他可以依照開發者的設計概念將 Log 給到指定的 Appender 做輸出。 具體的方式是針對個別的 Appender 給出指定的 TaskID,在實際的程式中,僅需要再塞入 Log 的同時也塞入指定的 TaskID 即可。 ### - 充分的測試與官方文件 最後的最後,是官方提過 Logback 的釋出是經歷了非常長時間的反覆測試,並且測試的方式與嚴謹程度比起 Log4j 還要多很多,同時官方也提供了 200 多頁相關 API 與設計文件,這也是大大超出了 Log4j 的文件數量。 ## Logback 的配置 Logback 文件的配置基本的四個部分: - **logger** - Log 的記錄器,會關連到對應的 context 上,可以儲存 Log 對象、定義類型與級別。 - **logger context** - 負責實體化 logger,並會依照 logger 級別進行樹狀結構的排列,其取得實體的方式為透過 LoggerFactory.getLogger(String loggerName),因此取出的 logger 會因傳入的參數而取得同一個實體 - **Appender** - 指定 Log 輸出的目的,可以是 Console、File、API、甚至是 DB 和 UNIX Syslog等 - **layout** - 將 Log 訊息 Format 後的在進行輸出,可以有效控制想要的 Log 訊息格式 Logback 的配置語法也非常的靈活,因此無法使用 DTD 或 XML Schema 的語法進行撰寫,而在程式啟用時,Logback 會嘗試做以下事情去尋找開發者是否有建構相關的文件: 1. 在 classpath 下查找 logback-test.xml 文件 2. 在 classpath 下查找 logback.xml 文件 3. 若上述文件都不存在,則 logback 會自動建立 Basic Configuration 進行配置,且僅會配置將 Log 輸出到 Console 這個動作而已 ## 配置文件的結構 ### 最基本的 <configuration> 根節點,內容可以包含**多個** Appender 和 Logger,但只能有**一個** root 節點。 其餘還有 contextName、property、timestamp等子節點,但最主要的是 Appender、Logger、root 三個。 ```xml <configuration> <appender></appender> <appender></appender> <appender></appender> ... <logger></logger> <logger></logger> <logger></logger> ... <root></root> </configuration> ``` <configuration> 的三個屬性功用為以下: - **<scan>**: 當配置文件被修改時,是否進行重載,預設值為 true - **<scanPeriod>**: 當進行重載時,文件更新後到啟動重載的時間間格設定,預設單位為毫秒,預設為60000ms,也就是1分鐘 - **<debug>**: 是否印出 Logback 服務運行的 Log,預設為 false ```xml <configuration scan="true" scanPeriod="60 seconds" debug="false"> <!-- 其他配置... --> </configuration>  ``` ### 子節點 <contextName> <property> <timestamp> <appender> 四個包在 <configuration> 節點內的設定,下面一一介紹各功能與設定方式 ```xml <configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="APP_Name" value="myAppName" /> <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/> <contextName>myAppName</contextName> <!--其他配置省略--> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> </appender> </configuration> ``` - **<property>**: 是一個設計固定的 Name 和 Value 的參數,可插入到標註為 ${} 的文中 - **<contextName>**: 用來配置 LoggerContext 名稱,對應到個別 Logger上,預設值為 default - **<timestamp>**: 獲取時間戳記的設定,其擁有的屬性分別為以下: - **key**: 此 timestamp 的名稱 - **datePattern**: 此timestamp 的時間格式,依照 java.txt.SimpleDateFormat 的方式,將當前時間轉換為指定格式的文字訊息 - **<appender>**: 負責設定撰寫 Log 的模組節點,由以下屬性組成: - **name**: 此 appender 的名稱 - **class**: 此 appender 參考的類別程式,其中又有以下分別: - **ConsoleAppender**: 輸出到 Console 的類別程式 - **FileAppender**: 輸出到文件的類別程式 - **RollingFileAppender**: 輸出到文件的類別程式,會依照設定條件進行 Log File 的分裝。 - 另外還有 **SocketAppender、SMTPAppender、DBAppender、SyslogAppender、SiftingAppender** 等幫助開發者將 Log 輸出到不同目的的處理 > 個別部分可再自行詳細了解其設定,內容都很簡單 ### 子節點 <logger> 用作設置某一個 class 或是 Package 的 Log Level 以及指定 Appender。 ```xml <logger name="kai.logback" level="INFO" /> <logger name="kai.logback.tests" level="WARN" /> ``` ### 子節點 <root> 與 <logger> 相同元素組成,不同是 <root> 為所有 <logger> 的上級,只有一個 level 屬性可使用,並無法像 logger 一樣用 name 指定實體 class 或Package。但一樣可以指定使用的 Appender ```xml <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> </appender> <logger name="kai.logback" level="INFO" /> <logger name="kai.logback.tests" level="WARN" /> <root level="debug"> <appender-ref ref="STDOUT" /> </root> </configuration> ``` ## DEMO 這是 Kai 寫的一個基本的 logback.xml 範例,做到最基本的輸出 console 和輸出一個 file,並且這個 file 會依照容量大小達到 10 mb 時候進行壓縮,並建立一個新的 file 繼續存後續的 log。 ```xml <?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- for output on console --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n </Pattern> </layout> </appender> <!-- for output in a log file --> <property name="DEV_HOME" value="E:/eclipse/LOG" /> <appender name="FILEOUT" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${DEV_HOME}/debug.log</file> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} - %msg%n </Pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>${DEV_HOME}/archived/debug.%d{yyyy-MM-dd}.%i.log </fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> </appender> <root level="info"> <appender-ref ref="STDOUT" /> <appender-ref ref="FILEOUT" /> </root> </configuration> ``` ## 結語 :::danger Logback 的介紹到這裡,差不多就可以把 Log 系列套件做一個結束了,若有想了解更多的朋友其實都可以透過文內的提及的詞彙找到需要的內容。 而因實際業務面需求廣泛且設計多元,介紹太多面向的處理方式會顯得無用且冗長,Kai 這邊僅會介紹基礎應用,後續的需求還是得靠個人對於實際業務的了解與流程做客製化的處理才行。 希望大家都有從中學到東西~ 如果有任何問題,請留言給 Kai~ 下一篇將會介紹的是 JUnit 5 單元測試套件的學習分享 [六角鼠年鐵人賽 Week 14 - Spring Boot - JUnit 5 單元測試](/WhKNTGsiRWeetW0gMNxeXQ) ::: 首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA) ###### tags: `Spring Boot`,`w3HexSchool`