前言
日志通常不會在需求階段作為一個功能單獨提出來,也不會在產品方案中看到它的細節。但是,這絲毫不影響它在任何一個系統中的重要的地位。
今天就來介紹一下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.groovy -
Log4j
:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml -
Log4j2
:log4j2-spring.xml, log4j2.xml -
JDK (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的日志選型以及如何自定義日志配置就介紹到這里,如果覺得有所收獲,不妨點個關注,分享一波,將是對作者最大的鼓勵!!!
