前言
日誌通常不會在需求階段作為一個功能單獨提出來,也不會在產品方案中看到它的細節。但是,這絲毫不影響它在任何一個系統中的重要的地位。
今天就來介紹一下Spring Boot中的日誌如何配置。
Spring Boot 版本
本文基於的Spring Boot的版本是2.3.4.RELEASE
。
日誌級別
幾種常見的日誌級別由低到高分為:TRACE < DEBUG < INFO < WARN < ERROR < FATAL
。
如何理解這個日誌級別呢?很簡單,如果專案中的日誌級別設定為INFO
,那麼比它更低階別的日誌資訊就看不到了,即是TRACE
、DEBUG
日誌將會不顯示。
日誌框架有哪些?
常見的日誌框架有log4j
、logback
、log4j2
。
log4j
這個日誌框架顯示是耳熟能詳了,在Spring開發中是經常使用,但是據說log4j官方已經不再更新了,而且在效能上比logback
、log4j2
差了很多。
logback
是由log4j
創始人設計的另外一個開源日誌框架,logback相比之於log4j效能提升了10以上,初始化記憶體載入也更小了。作為的Spring Boot預設的日誌框架肯定是有著不小的優勢。
log4j2
晚於logback
推出,官網介紹效能比logback
高,但誰知道是不是王婆賣瓜自賣自誇,坊間流傳,log4j2在很多思想理念上都是照抄logback,因此即便log4j2是Apache官方專案,Spring等許多框架專案沒有將它納入主流。此處完全是作者道聽途說,不必當真,題外話而已。
日誌框架很多,究竟如何選擇能夠適應現在的專案開發,當然不是普通程式設計師考慮的,但是為了更高的追求,至少應該瞭解一下,哈哈。
Spring Boot 日誌框架
Spring Boot預設的日誌框架是logback
,既然Spring Boot能夠將其納入的預設的日誌系統,肯定是有一定的考量的,因此實際開發過程中還是不要更換。
原則上需要使用logback,需要新增以下依賴,但是既然是預設的日誌框架,當然不用重新引入依賴了。
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
Spring Boot中預設的日誌級別是INFO
,啟動專案日誌列印如下:
從上圖可以看出,輸出的日誌的預設元素如下:
時間日期:精確到毫秒 日誌級別:ERROR, WARN, INFO, DEBUG , TRACE 程式ID 分隔符:— 標識實際日誌的開始 執行緒名:方括號括起來(可能會截斷控制檯輸出) Logger名:通常使用原始碼的類名 日誌內容
程式碼中如何使用日誌?
在業務中肯定需要追溯日誌,那麼如何在自己的業務中輸出日誌呢?其實常用的有兩種方式,下面一一介紹。
第一種其實也是很早之前常用的一種方式,只需要在程式碼新增如下:
private final Logger logger= LoggerFactory.getLogger(DemoApplicationTests.class);
這種方式顯然比較雞肋,如果每個類中都新增一下豈不是很low。彆著急,lombok為我們解決了這個難題。
要想使用lombok,需要新增如下依賴:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
使用也是很簡單,只需要在類上標註一個註解@Slf4j
即可,如下:
@Slf4j
class DemoApplicationTests {
@Test
public void test(){
log.debug("輸出DEBUG日誌.......");
}
}
如何定製日誌級別?
Spring Boot中預設的日誌級別是INFO,但是可以自己定製日誌級別,如下:
logging.level.root=DEBUG
上面是將所有的日誌的級別都改成了DEBUG
,Spring Boot還支援package
級別的日誌級別調整,格式為:logging.level.xxx=xxx
,如下:
logging.level.com.example.demo=INFO
那麼完整的配置如下:
logging.level.root=DEBUG
logging.level.com.example.demo=INFO
日誌如何輸出到檔案中?
Spring Boot中日誌預設是輸出到控制檯的,但是在生產環境中顯示不可行的,因此需要配置日誌輸出到日誌檔案中。
其中有兩個重要配置如下:
logging.file.path
:指定日誌檔案的路徑logging.file.name
:日誌的檔名,預設為spring.log
注意:官方文件說這兩個屬性不能同時配置,否則不生效,因此只需要配置一個即可。
指定輸出的檔案為當前專案路徑的logs
檔案下,預設生成的日誌檔案為spring.log
,如下:
logging.file.path=./logs
日誌檔案中還有一些其他的屬性,比如日誌檔案的最大size,保留幾天的日誌等等,下面會介紹到。
如何定製日誌格式?
預設的日誌格式在第一張圖已經看到了,有時我們需要定製自己需要的日誌輸出格式,這樣在排查日誌的時候能夠一目瞭然。
定製日誌格式有兩個配置,分別是控制檯的輸出格式和檔案中的日誌輸出格式,如下:
logging.pattern.console
:控制檯的輸出格式logging.pattern.file
:日誌檔案的輸出格式
例如配置如下:
logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n
logging.pattern.file=%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n
上面的配置編碼的含義如下:
%d{HH:mm:ss.SSS}——日誌輸出時間
%thread——輸出日誌的程式名字,這在Web應用以及非同步任務處理中很有用
%-5level——日誌級別,並且使用5個字元靠左對齊
%logger- ——日誌輸出者的名字
%msg——日誌訊息
%n——平臺的換行符
如何自定義日誌配置?
Spring Boot官方文件指出,根據不同的日誌系統,可以按照如下的日誌配置檔名就能夠被正確載入,如下:
Logback
:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovyLog4j
:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xmlLog4j2
:log4j2-spring.xml, log4j2.xmlJDK (Java Util Logging)
:logging.properties
Spring Boot官方推薦優先使用帶有-spring的檔名作為你的日誌配置。因此只需要在src/resources
資料夾下建立logback-spring.xml
即可,配置檔案內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 定義日誌存放目錄 -->
<property name="logPath" value="logs"/>
<!-- 日誌輸出的格式-->
<property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t-%L] %-5level %logger{36} %L %M - %msg%xEx%n"/>
<contextName>logback</contextName>
<!--輸出到控制檯 ConsoleAppender-->
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<!--展示格式 layout-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
<!--過濾器,只有過濾到指定級別的日誌資訊才會輸出,如果level為ERROR,那麼控制檯只會輸出ERROR日誌-->
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
<!-- <level>ERROR</level>-->
<!-- </filter>-->
</appender>
<!--正常的日誌檔案,輸出到檔案中-->
<appender name="fileDEBUGLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--如果只是想要 Info 級別的日誌,只是過濾 info 還是會輸出 Error 日誌,因為 Error 的級別高,
所以我們使用下面的策略,可以避免輸出 Error 的日誌-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--過濾 Error-->
<level>Error</level>
<!--匹配到就禁止-->
<onMatch>DENY</onMatch>
<!--沒有匹配到就允許-->
<onMismatch>ACCEPT</onMismatch>
</filter>
<!--日誌名稱,如果沒有File 屬性,那麼只會使用FileNamePattern的檔案路徑規則
如果同時有<File>和<FileNamePattern>,那麼當天日誌是<File>,明天會自動把今天
的日誌改名為今天的日期。即,<File> 的日誌都是當天的。
-->
<File>${logPath}/log_demo.log</File>
<!--滾動策略,按照時間滾動 TimeBasedRollingPolicy-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--檔案路徑,定義了日誌的切分方式——把每一天的日誌歸檔到一個檔案中,以防止日誌填滿整個磁碟空間-->
<FileNamePattern>${logPath}/log_demo_%d{yyyy-MM-dd}.log</FileNamePattern>
<!--只保留最近90天的日誌-->
<maxHistory>90</maxHistory>
<!--用來指定日誌檔案的上限大小,那麼到了這個值,就會刪除舊的日誌-->
<!--<totalSizeCap>1GB</totalSizeCap>-->
</rollingPolicy>
<!--日誌輸出編碼格式化-->
<encoder>
<charset>UTF-8</charset>
<pattern>${PATTERN}</pattern>
</encoder>
</appender>
<!--輸出ERROR日誌到指定的檔案中-->
<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--如果只是想要 Error 級別的日誌,那麼需要過濾一下,預設是 info 級別的,ThresholdFilter-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>Error</level>
</filter>
<!--日誌名稱,如果沒有File 屬性,那麼只會使用FileNamePattern的檔案路徑規則
如果同時有<File>和<FileNamePattern>,那麼當天日誌是<File>,明天會自動把今天
的日誌改名為今天的日期。即,<File> 的日誌都是當天的。
-->
<File>${logPath}/error.log</File>
<!--滾動策略,按照時間滾動 TimeBasedRollingPolicy-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--檔案路徑,定義了日誌的切分方式——把每一天的日誌歸檔到一個檔案中,以防止日誌填滿整個磁碟空間-->
<FileNamePattern>${logPath}/error_%d{yyyy-MM-dd}.log</FileNamePattern>
<!--只保留最近90天的日誌-->
<maxHistory>90</maxHistory>
<!--用來指定日誌檔案的上限大小,那麼到了這個值,就會刪除舊的日誌-->
<!--<totalSizeCap>1GB</totalSizeCap>-->
</rollingPolicy>
<!--日誌輸出編碼格式化-->
<encoder>
<charset>UTF-8</charset>
<pattern>${PATTERN}</pattern>
</encoder>
</appender>
<!--指定最基礎的日誌輸出級別-->
<root level="DEBUG">
<!--appender將會新增到這個loger-->
<appender-ref ref="consoleLog"/>
<appender-ref ref="fileDEBUGLog"/>
<appender-ref ref="fileErrorLog"/>
</root>
<!-- 定義指定package的日誌級別-->
<logger name="org.springframework" level="DEBUG"></logger>
<logger name="org.mybatis" level="DEBUG"></logger>
<logger name="java.sql.Connection" level="DEBUG"></logger>
<logger name="java.sql.Statement" level="DEBUG"></logger>
<logger name="java.sql.PreparedStatement" level="DEBUG"></logger>
<logger name="io.lettuce.*" level="INFO"></logger>
<logger name="io.netty.*" level="ERROR"></logger>
<logger name="com.rabbitmq.*" level="DEBUG"></logger>
<logger name="org.springframework.amqp.*" level="DEBUG"></logger>
<logger name="org.springframework.scheduling.*" level="DEBUG"></logger>
<!--定義com.xxx..xx..xx包下的日誌資訊不上傳,直接輸出到fileDEBUGLog和fileErrorLog這個兩個appender中,日誌級別為DEBUG-->
<logger name="com.xxx.xxx.xx" additivity="false" level="DEBUG">
<appender-ref ref="fileDEBUGLog"/>
<appender-ref ref="fileErrorLog"/>
</logger>
</configuration>
當然,如果就不想用Spring Boot推薦的名字,想自己定製也行,只需要在配置檔案中指定配置檔名即可,如下:
logging.config=classpath:logging-config.xml
懵逼了,一堆配置什麼意思?彆著急,下面一一介紹。
configuration節點
這是一個根節點,其中的各個屬性如下:
scan
:當此屬性設定為true時,配置檔案如果發生改變,將會被重新載入,預設值為true。scanPeriod
:設定監測配置檔案是否有修改的時間間隔,如果沒有給出時間單位,預設單位是毫秒。當scan為true時,此屬性生效。預設的時間間隔為1分鐘。debug
:當此屬性設定為true時,將列印出logback內部日誌資訊,實時檢視logback執行狀態。預設值為false。
root節點
這是一個必須節點,用來指定基礎的日誌級別,只有一個level
屬性,預設值是DEBUG
。
該節點可以包含零個或者多個元素,子節點是appender-ref
,標記這個appender
將會新增到這個logger中。
contextName節點
標識一個上下文名稱,預設為default,一般用不到
property節點
標記一個上下文變數,屬性有name和value,定義變數之後可以使用${}
來獲取。
appender節點
用來格式化日誌輸出節點,有兩個屬性name
和class
,class用來指定哪種輸出策略,常用就是控制檯輸出策略和檔案輸出策略。
這個節點很重要,通常的日誌檔案需要定義三個appender,分別是控制檯輸出,常規日誌檔案輸出,異常日誌檔案輸出。
該節點有幾個重要的子節點,如下:
filter
:日誌輸出攔截器,沒有特殊定製一般使用系統自帶的即可,但是如果要將日誌分開,比如將ERROR級別的日誌輸出到一個檔案中,將除了ERROR
級別的日誌輸出到另外一個檔案中,此時就要攔截ERROR
級別的日誌了。encoder
: 和pattern節點組合用於具體輸出的日誌格式和編碼方式。file
: 節點用來指明日誌檔案的輸出位置,可以是絕對路徑也可以是相對路徑rollingPolicy
: 日誌回滾策略,在這裡我們用了TimeBasedRollingPolicy,基於時間的回滾策略,有以下子節點fileNamePattern,必要節點,可以用來設定指定時間的日誌歸檔。maxHistory
: 可選節點,控制保留的歸檔檔案的最大數量,超出數量就刪除舊檔案,,例如設定為30的話,則30天之後,舊的日誌就會被刪除totalSizeCap
: 可選節點,用來指定日誌檔案的上限大小,例如設定為3GB的話,那麼到了這個值,就會刪除舊的日誌
logger節點
可選節點,用來具體指明包的日誌輸出級別,它將會覆蓋root的輸出級別。 該節點有幾個重要的屬性如下:
name
:指定的包名level
:可選,日誌的級別addtivity
:可選,預設為true,將此logger的資訊向上級傳遞,將有root節點定義日誌列印。如果設定為false,將不會上傳,此時需要定義一個appender-ref
節點才會輸出。
總結
Spring Boot的日誌選型以及如何自定義日誌配置就介紹到這裡,如果覺得有所收穫,不妨點個關注,分享一波,將是對作者最大的鼓勵!!!