springboot+logback 日誌輸出企業實踐(上)
摘要:本篇文章針對 springboot 應用開發中,如何使用 logback,結合在企業中的實踐,創建 springboot 示例,然後對 logback 的配置進行詳細說明,實現按日誌級別輸出日誌文件功能。因此一般都使用自定義配置,通過 xml 文件對 logback 的日誌輸出進行配置。
tags: springboot logback log
一句話概括:在 java 應用開發過程中,日誌輸出與記錄是重要一環,logback 是當前的首選日誌框架,本文將對 springboot+logback 的使用及在企業的實踐進行詳細描述。
1.引言
在 java 應用開發過程中,日誌輸出與記錄是重要的一環,有了日誌,我們可以定位錯誤與異常,追蹤應用運行情況,記錄應用訪問時間等等。在學習 hello world
時就會使用 System.out.println()
來輸出內容,當涉及到複雜一點的日誌輸出,最好是引入成熟的日誌框架,曾經 log4j 是流行的日誌框架,現在已被它的繼任者 logback 替代,它更快,更小,更靈活。在 springboot 的開發中,默認已經自帶了 logback,可直接使用。本文基本 springboot+logback,結合在企業中的實踐,對日誌的輸出及配置進行詳細說明,具體有如下內容:
-
logback 簡要介紹
-
使用 springboot+logback 構建示例工程及配置描述
-
logback 配置文件的詳述及使用
如需看源碼,本文 示例工程地址 [1] : https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo
2.logback 簡介
logback 官網地址 [2] : http://logback.qos.ch
,從官網的介紹, logback 是 log4j 框架的作者開發的新一代日誌框架,是 log4j 的繼任者,它更快,更小, 效率更高、能夠適應各種運行環境,同時天然支持 slf4j。slf4j,即 Simple Logging Facade For Java
,它是對各類日誌框架的統一抽象,即定義了接口,具體使用哪個日誌 框架由運行時綁定實現。
logback 主要由三個模塊構成,分別是 logback-core
, logback-classic
及 logback-access
,其中 logback-core
是基礎核心,另外兩個均依賴它。 logback-classic
實現了簡單日誌門面 SLF4J
;而 logback-access
主要作爲一個與 Servlet
容器交互的模塊,如 tomcat
或者 jetty
,提供與 HTTP
訪問相關的一些功能。
3. springboot 默認日誌框架-logback
本章節將使用 springboot+logback 構建示例工程,並對 logback 基本配置進行描述。
3.1 springboot 示例工程搭建
(1) 創建項目:通過 Spring Initializr 頁面 [3] 生成一個添加了 web 模塊及 lombok 模塊的 Spring Boot 項目。
(2)添加示例功能:
-
首先添加幾個通用包:vo,controller,service,model,分別存放視圖層模型,控制層,服務層,數據模型層等代碼。
-
針對用戶增刪改查功能,對應有數據模型 User,UserController,UserService,統一返回視圖模型 ResponseResult。
(3)添加日誌輸出
-
在 UserService 類中添加 lombok 提供的
@Slf4j
註解,這樣可直接在此類中使用log
進行日誌輸出,避免自己使用LoggerFactory.getLogger
來新建。 -
在對應的方法中使用
debug
,info
,warn
,error
等方法輸出日誌。如log.debug("get user by id:{}", id)
。
注意:此處具體代碼不列出(詳細可看 示例源碼 [4] )。
至此,示例工程構建完成,可正常運行工程,查看工程的依賴情況,可以發現,springboot 已默認支持 logback。如下:
3.2 日誌輸出與基本配置
3.2.1 日誌默認輸出
如上所示,默認情況下,springboot 使用 logback 進行日誌輸出,輸出日誌爲 INFO 級別,輸出位置是控制檯。啓動示例工程,示例輸出如下:
控制檯日誌輸出的內容格式很清晰,分別是
-
時間日期:格式是
yyyy-MM-dd HH:mm:ss.SSS
-
日誌級別:輸出>=INFO 級別的日誌(ERROR, WARN, INFO)
-
進程 ID
-
分隔符:
---
-
線程名:線程名在方括號(
[]
)內 -
logger 名:類的名稱
-
日誌內容
3.2.2 基本配置
在 springboot 在配置文件 application.properties
中,可以設置日誌相關的內容,如下:
關於日誌的配置有很多,後面我們主要使用自定義配置,因此不作詳細說明,此處主要講兩個,日誌級別控制及日誌文件輸出。
-
日誌級別控制,設置格式爲
logging.leve.*=LEVEL
,其中*爲包名或 logger 名,LEVEL 有:TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
。 -
日誌輸出到文件,默認日誌只輸出到控制檯,不寫文件,可以配置
logging.file.name
或logging.file.path
來指定日誌輸出文件。logging.file.name
設置文件, 會在項目的當前路徑下生成此文件名的日誌文件 。logging.path
設置目錄,會在此目錄下創建 spring.log 文件。 默認情況下,日誌文件的大小達到 10MB 時會切分一次,產生新的日誌文件注意:二者不能同時使用,如若同時使用,則只有 logging.file 生效
3.3 自定義 logback 配置
上面在 properties 文件中對日誌進行基本的配置,但配置能力較弱,不夠靈活。因此一般都使用自定義配置,通過 xml 文件對 logback 的日誌輸出進行配置。
3.3.1 logback 配置文件加載順序
在 springboot 應用中,對於 logback 的配置文件,默認情況下,配置文件放在 src/main/resources
下,支持的配置文件名稱如下:
-
logback-spring.xml
-
logback-spring.groovy
-
logback.xml
-
logback.groovy
Spring Boot 官方推薦優先使用帶有-spring 的文件名配置(如有 logback-spring.xml,則不會使用 logback.xml) 。當然,若需要對配置文件名進行修改,或者希望把配置文件放到其它目錄下,可以通過 logging.config 屬性指定自定義的名字,如 logging.config=classpath:config/log-config.xml
,則使用 resources/config
下的 log-config.xml 配置。
注,一般情況下,按默認規則(在 resources 目錄下,使用 logback-spring.xml)即可。另外有了這個配置文件後,前面提到的在 properties 文件中的 logging 配置則不需要了。
3.3.2 logback 配置文件示例
這裏先直接給出配置文件的示例,後面章節將對配置文件內容進行詳細說明。如下所示,配置文件主要功能是把日誌按格式輸出到控制檯和文件中,並且文件按日誌輸出級別分別輸出到獨立文件,文件按時間滾動(每天一個日誌文件,保留 30 天)。完整配置內容可見源碼中的 logback-spring.xml
文件。
<configuration scan="true" scanPeriod="1 seconds"> ...//略 <!-- 日誌輸出格式 --> <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5level [%15thread] [%40.40logger{40}] [%10method,%line] : %msg%n"/> <!-- 控制檯輸出日誌 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>${log.pattern}</pattern> </layout> </appender> <!-- 文件輸出日誌, 滾動(時間/文件大小)輸出策略 --> <appender name="DEBUGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 過濾器,只記錄debug級別的日誌 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>DEBUG</level> <OnMismatch>DENY</OnMismatch> <OnMatch>ACCEPT</OnMatch> </filter> <!-- 日誌文件路徑及文件名 --> <File>${log.path}/${logfile.prefix}-debug.log</File> <!-- 日誌記錄器的滾動策略,按日期記錄 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日誌輸出格式 --> <FileNamePattern>${log.path}/${logfile.prefix}-debug.%d{yyyy-MM-dd}.log</FileNamePattern> <!-- 日誌保留天數 --> <maxHistory>30</maxHistory> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>${log.pattern}</Pattern> </layout> </appender> ...//略 <!-- 日誌級別,不向上級傳遞日誌內容,日誌按appender-ref輸出 --> <logger name="me.mason.demo.simplelogback.service.UserService" level="WARN" additivity="false"> <appender-ref ref="STDOUT"/> </logger> <!-- 日誌輸出 --> <root level="DEBUG"> <appender-ref ref="STDOUT"/> <appender-ref ref="DEBUGFILE"/> ...//略 </root> </configuration>
4. logback 配置文件詳述
logback 配置文件決定日誌輸出格式、日誌輸出位置、輸出文件策略等內容,因此需要對 logback 配置文件的結構及相關元素內容進行了解。
4.1 配置文件結構
配置文件總體來說內容比較簡單,主要三個元素:
這三個元素中,logger 和 root 可視爲同一類,都是日誌組件,可以把 root 當作是特殊 logger,是根,必須配置。logger 配置解答從哪裏獲取日誌,輸出什麼級別日誌問題。appender 配置是指出日誌以什麼格式輸出,日誌如何過濾,輸出文件後如何處理的問題。另外,還有可選的 property 及 contextName 元素,分別變量和應用上下文名稱。
4.2 根元素 configuration
4.2.1 屬性配置
根元素 configuration 有三個屬性可以設置,如下:
-
debug:默認爲 false,若設置爲 true,則打印出 logback 內部日誌信息
-
scan:默認值爲 true,若設置爲 true,配置文件如果發生改變,將會被重新加載。
-
scanPeriod:與 scan 配合使用,當 scan 爲 true 時,此屬性生效,默認的時間間隔爲 1 分鐘,設置監測配置文件是否有修改的時間間隔,如果沒有給出時間單位,默認單位是毫秒。如可以設置爲
scanPeriod="30 seconds"
每 30 秒檢測一次。
4.2.2 定義上下文名稱和變量
-
contextName 元素,每一個日誌組件(logger)都會關聯到日誌上下文,默認上下文名稱是'default',用於標識應用,如果多個應用輸出到同一個地方,就有必要使用
%contextName
來區別。 -
property 元素,定義變量,有 name 和 value 屬性,定義變量後,可以使“${name}”來使用變量。在配置中多個地方的值使用到相同的內容時,就有必要把相同內容設置變量,通過引用來設置。如示例工程中的日誌文件名稱前綴、日誌路徑、日誌輸出格式。
注意,定義的變量只能在配置文件的值中進行引用,不能在元素屬性中引用。如配置文件中有很多屬性是 class
,裏面的內容只能寫類的全路徑,儘管類前綴都相同,但不能用變量替換。
4.3 日誌輸出組件 appender
此元素是主要配置項,表示以什麼格式輸出,日誌如何過濾,輸出文件後如何處理。appender 結構如下:
appender
有兩個屬性 name
和 class
; name
指定 appender
名稱, class
指定 appender
的全限定名。appender 默認有以下幾種:
-
ConsoleAppender:把日誌添加到控制檯,類名
ch.qos.logback.core.ConsoleAppender
-
FileAppender:把日誌添加到文件,類名
ch.qos.logback.core.FileAppender
-
RollingFileAppender:滾動記錄文件,FileAppender 的子類,當符合條件(大小、時間),日誌進行切分,記錄到其他文件。類名:
ch.qos.logback.core.rolling.RollingFileAppender
。
實踐過程中,一般使用 ConsoleAppender 及 RollingFileAppender 即可,若需要自定義如把日誌輸出到消息隊列,可以自定義實現 AppenderBase 接口。
ConsoleAppender 比較簡單,只需要使用 layout 元素,按日誌輸出格式即可,如下:
<!-- 控制檯輸出日誌 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>${log.pattern}</pattern> </layout> </appender>
RollingFileAppender 的配置相對多一點,包括 File、filter,rollingPolicy,encoder 和 layout 元素。其中 filter 可以過濾日誌,因此,若需要把日誌按級別輸出到不同的文件中,因此,定義多個 RollingFileAppender(如對應 DEBUG、INFO、WARN、ERROR),分別按日誌級別過濾即可。下面分別進行說明:
4.3.1 File 配置
配置文件輸出的路徑及文件名,一般把路徑和文件名前綴定義到變量(property 中),如下:
<!--日誌文件前綴,即應用名稱 --> <property name="logfile.prefix" value="logback-demo"/> <!--日誌路徑,可寫相對路徑,也可寫絕對路徑 --> <property name="log.path" value="logs"/> ...//略 <File>${log.path}/${logfile.prefix}-debug.log</File>
4.3.2 filter 配置
filter 可以爲 appender
添加一個或多個過濾器,對日誌進行過濾。過濾器有 ThresholdFilter
和 LevelFilter
,前者是臨界值過濾器,過濾掉低於指定臨界值的日誌;後者是級別過濾器,根據日誌級別進行過濾, 如果日誌級別等於配置級別 ,過濾器會根據 onMath
(符合過濾條件的操作) 和 onMismatch
(不符合過濾條件的操作)接收(ACCEPT)或拒絕(DENY)日誌。按前面需求,把日誌按不同級別分別輸出到各自文件中,需要多個 RollingFileAppender
元素,每個元素下對應的 level
是 DEBUG,INFO,WARN 和 ERROR。
<!-- 過濾器,只記錄debug級別的日誌 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>DEBUG</level> <OnMismatch>DENY</OnMismatch> <OnMatch>ACCEPT</OnMatch> </filter>
4.3.3 rollingPolicy 配置
此元素描述滾動策略,有 TimeBasedRollingPolicy
、 SizeAndTimeBasedRollingPolicy
、 FixedWindowRollingPolicy
、 SizeBasedTriggeringPolicy
。分別是基於時間滾動,基於大小和時間滾動,固定窗口滾動和大小觸發,其中 FixedWindowRollingPolicy
一般和 SizeBasedTriggeringPolicy
同時使用。下面以 TimeBasedRollingPolicy
爲例,以天爲單位輸出日誌,每天一個日誌。
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日誌輸出格式 --> <FileNamePattern>${log.path}/${logfile.prefix}-debug.%d{yyyy-MM-dd}.log</FileNamePattern> <!-- 日誌保留天數 --> <maxHistory>30</maxHistory> </rollingPolicy>
FileNamePattern
表示日誌的路徑及名稱,此處是按日期輸出,即 %d{yyyy-MM-dd}
格式。 maxHistory
表示日誌最多保留天數,大於這些天數後,前面的日誌會刪除。
對於 SizeAndTimeBasedRollingPolicy
,如下所示:
<!-- 按日期滾動 --> <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern> <!-- 文件大小最大是100M,保存60日,總大小最大爲20G --> <maxFileSize>100MB</maxFileSize> <maxHistory>60</maxHistory> <totalSizeCap>20GB</totalSizeCap>
注意, %i
和 %d
標識符都是強制性的。每當日誌文件在當前時間段結束之前達到文件最大值時,它將以遞增的 %d
索引存檔,從 0 開始。
4.3.4 layout 配置
layout
元素較簡單,只需要設置輸出的格式即可。
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5level [%15thread] %40.40logger{40} [%10method,%line] : %msg%n"/> ...//略 <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>${log.pattern}</Pattern> </layout>
4.3.5 輸出格式控制
對於日誌輸出格式的控制,使用 logback 的保留字進行控制,保留字很多,建議查閱 官網文檔 [5] ,下面對常用進行說明:
保留字 | 作用 |
---|---|
c { length } lo { length } logger { length } | 輸出日誌的 logger 名,可有一個整型參數,功能是縮短 logger 名,最右的點符號之後的類名始終顯示,設置爲 0 表示只輸入 logger 最右邊點符號之後的字符串。 |
C { length } class { length } | 輸出執行記錄請求的調用者的全限定名。參數與上面的一樣。儘量避免使用,除非執行速度不造成任何問題。 |
contextName cn | 輸出上下文名稱。 |
d { pattern } date { pattern } | 輸出日誌的打印日誌,模式語法與 java.text.SimpleDateFormat 兼容。 |
L / line | 輸出執行日誌請求的行號。儘量避免使用,除非執行速度不造成任何問題。 |
m / msg / message | 輸出應用程序提供的信息。 |
M / method | 輸出執行日誌請求的方法名。儘量避免使用,除非執行速度不造成任何問題。 |
n | 輸出平臺相關的分行符“\n”或者“\r\n”。 |
p / le / level | 輸出日誌級別。 |
t / thread | 輸出產生日誌的線程名。 |
另外,格式還有一個對齊功能,通過在 %
後面添加 -
、 .
及數字進行控制。符號 -
是可選修飾符,表示是 左對齊 ,接着是可選的 最小寬度 修飾符,用十進制數表示。如果字符小於最小寬度,則左填充或右填充,默認是左填充(即右對齊),填充符爲空格。 最大寬度 修飾符,符號是點號"."後面加十進制數。如果字符大於最大寬度,則從前面截斷。點符號“.”後面加減號“-”在加數字,表示從尾部截斷。
例如:%-40.40logger{40} 表示按 40 字符輸出 logger 名,左對齊,若小於 40 字符的則填充空格,超過 40 則從左邊截斷。
對於控制檯,還可以控制顏色,如前面 springboot 的默認輸出就有顏色,如下:
格式 | 描述 |
---|---|
%black | 黑色 |
%red | 紅色 |
%green | 綠色 |
%yellow | 黃色 |
%blue | 藍色 |
%magenta | 品紅 |
%cyan | 青色 |
%white | 白色 |
%gray | 灰色 |
%highlight | 高亮色 |
%bold | 強化上面的顏色,例如%boldRed,%boldBlack |
4.4 日誌組件 logger 及 root
logger
用來設置某一個類或者某個包的日誌輸出級別、以及關聯 appender
指定輸出位置,有三個屬性:
-
name:指定的包名或者類名
-
level:輸出日誌級別,如果未設置此級別,那麼當前
logger
會向上繼承最近一個非空級別,級別以 name 區分,如 x 和 x.y,x 則是 x.y 的父級。 -
additivity:是否將日誌向上級傳遞,默認爲 true
logger 通過設置子節點 appender-ref
來指定日誌輸出位置,可以設置多個 appender-ref
。 root
是一個特殊的 logger
, 是所有 logger
的根節點,元素名爲 root
,沒有父級別,只有一個屬性 level
,默認爲 DEBUG 。
4.4.1 logger 配置,
此處對某個具體的類進行配置輸出進行設置,由於設置了 WARN
級別, additivity
爲 true
,而且關聯 STDOUT
的 appender,因此此類的>= WARN
的日誌會輸出到控制檯。同時會把日誌上傳到父級,即 root。若 root 也有配置 STDOUT
的輸出的話,會發現此日誌在控制檯輸出兩次。若 additivity
爲 false
,則不會。
<!-- 日誌級別,不向上級傳遞日誌內容,日誌按appender-ref輸出 --> <logger name="me.mason.demo.simplelogback.service.UserService" level="WARN" additivity="true"> <appender-ref ref="STDOUT"/> </logger>
4.4.2 root 配置
logger 可以不配置,但 root 元素是必須配置的,需要告訴 logback 把日誌輸出到哪裏。如下,只需要關聯日誌需要輸出的 appender
即可。前面已經有 STDOUT
控制檯及按日誌級別設置了各個文件 appender
,此處直接關聯即可。
<root level="DEBUG"> <appender-ref ref="STDOUT"/> <appender-ref ref="DEBUGFILE"/> <appender-ref ref="INFOFILE"/> <appender-ref ref="WARNFILE"/> <appender-ref ref="ERRORFILE"/> </root>
經過以上的配置,彙總到 logback-spring.xml
中,啓動運行程序,即可看到控制檯會按格式輸出日誌,同時會在應用根目錄下創建 logs
目錄存放日誌文件,且日誌格式是按配置輸出,如下:
5. 總結
本篇文章針對 springboot 應用開發中,如何使用 logback,結合在企業中的實踐,創建 springboot 示例,然後對 logback 的配置進行詳細說明,實現按日誌級別輸出日誌文件功能。但在實際開發中,還有不少需要改進的地方,包括多環境配置,日誌輸出效率問題,分佈式系統請求 ID 追蹤問題等,將在下篇文章進行講解。
本文中使用的示例代碼已放在 github [6] : https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo
,有興趣的同學可以 pull 代碼,結合示例一起學習。
往期文章
參考資料
示例工程地址: https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo/logback-simple-demo
官網地址: http://logback.qos.ch/
Spring Initializr 頁面: https://start.spring.io/
示例源碼: https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo/logback-simple-demo
官網文檔: http://logback.qos.ch/manual/layouts.html
github: https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo/logback-simple-demo
logback官網: http://logback.qos.ch/
logback中文手冊: http://www.logback.cn/
logback github: https://github.com/qos-ch/logback
看完這個不會配置 logback ,請你喫瓜: https://juejin.im/post/5b51f85c5188251af91a7525
如果文章對你有幫助,歡迎轉發分享~
- end -
關注瞭解更多幹貨
關注:Mason技術記錄
更多幹貨等着你