預設日志Logback
SLF4J——Simple Logging Facade For Java,它是一個針對于各類Java日志架構的統一Facade抽象。Java日志架構衆多——常用的有java.util.logging, log4j, logback,commons-logging, Spring架構使用的是Jakarta Commons Logging API (JCL)。而SLF4J定義了統一的日志抽象接口,而真正的日志實作則是在運作時決定的——它提供了各類日志架構的binding。
Logback是log4j架構的作者開發的新一代日志架構,它效率更高、能夠适應諸多的運作環境,同時天然支援SLF4J。
預設情況下,Spring Boot會用Logback來記錄日志,并用INFO級别輸出到控制台。在運作應用程式和其他例子時,你應該已經看到很多INFO級别的日志了。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iNzQzM2IzNxUmNhRzNyUDNzYzX2IDMyYTMxEzLcBTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
從上圖可以看到,日志輸出内容元素具體如下:
- 時間日期:精确到毫秒
- 日志級别:ERROR, WARN, INFO, DEBUG or TRACE
- 程序ID
- 分隔符:— 辨別實際日志的開始
- 線程名:方括号括起來(可能會截斷控制台輸出)
- Logger名:通常使用源代碼的類名
- 日志内容
添加日志依賴
假如maven依賴中添加了spring-boot-starter-logging:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
那麼,我們的Spring Boot應用将自動使用logback作為應用日志架構,Spring Boot啟動的時候,由org.springframework.boot.logging.Logging-Application-Listener根據情況初始化并使用。
但是呢,實際開發中我們不需要直接添加該依賴,你會發現spring-boot-starter其中包含了 spring-boot-starter-logging,該依賴内容就是 Spring Boot 預設的日志架構 logback。
預設配置屬性支援
Spring Boot為我們提供了很多預設的日志配置,是以,隻要将spring-boot-starter-logging作為依賴加入到目前應用的classpath,則“開箱即用”。
下面介紹幾種在application.yml就可以配置的日志相關屬性。
控制台輸出
日志級别從低到高分為TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果設定為WARN,則低于WARN的資訊都不會輸出。
Spring Boot中預設配置ERROR、WARN和INFO級别的日志輸出到控制台。
在application.yml中配置debug=true,該屬性置為true的時候,核心Logger(包含嵌入式容器、hibernate、spring)會輸出更多内容,但是你自己應用的日志并不會輸出為DEBUG級别
# 日志配置
debug: true
檔案輸出
預設情況下,Spring Boot将日志輸出到控制台,不會寫到日志檔案。如果要編寫除控制台輸出之外的日志檔案,則需在application.yml中設定logging.file或logging.path屬性。
- logging.file,設定檔案,可以是絕對路徑,也可以是相對路徑。如:logging.file=AhutOne.log
- logging.path,設定目錄,會在該目錄下建立spring.log檔案,并寫入日志内容,如:logging.path=/log/myLog
如果隻配置 logging.file,會在項目的目前路徑下生成一個 xxx.log 日志檔案。
# 日志配置
logging:
file: log/AhutOne.log
如果隻配置 logging.path,在 /log/myLog檔案夾生成一個日志檔案為 spring.log
# 日志配置
logging:
path: log/myLog
注:二者不能同時使用,如若同時使用,則隻有logging.file生效
預設情況下,日志檔案的大小達到10MB時會切分一次,産生新的日志檔案,預設級别為:ERROR、WARN、INFO
級别控制
所有支援的日志記錄系統都可以在Spring環境中設定記錄級别(例如在application.yml中)
格式為:’logging.level.* = LEVEL’
- logging.level:日志級别控制字首,*為包名或Logger名
- LEVEL:選項TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
舉例:
# 日志配置
logging:
level:
# com.ahut包下所有class以DEBUG級别輸出
com.ahut: DEBUG
# root日志以WARN級别輸出
自定義日志配置
由于日志服務一般都在ApplicationContext建立前就初始化了,它并不是必須通過Spring的配置檔案控制。是以通過系統屬性和傳統的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的檔案名作為你的日志配置(如使用logback-spring.xml,而不是logback.xml),命名為logback-spring.xml的日志配置檔案,spring boot可以為它添加一些spring boot特有的配置項(下面會提到)。
上面是預設的命名規則,并且放在src/main/resources下面即可。
如果你即想完全掌控日志配置,但又不想用logback.xml作為Logback配置的名字,可以通過logging.config屬性指定自定義的名字:
# 日志配置
logging:
config: classpath:logging-config.xml
雖然一般并不需要改變配置檔案的名字,但是如果你想針對不同運作時Profile使用不同的日志配置,這個功能會很有用。
下面我們來看看一個普通的logback-spring.xml例子
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logback</contextName>
<property name="log.path" value=".\\test\\log\\"
<property name="log.file" value=".\\test\\logback.log"
<!--輸出到控制台 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>ERROR</level>
</filter> -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--輸出到檔案 -->
<appender name="file"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.file}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}logback.%d{yyyy-MM-dd_HH-mm}.log
</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console"
<appender-ref ref="file"
</root>
<!-- 列印執行的sql name指定mapper所在的包,additivity設定為true時,父級也會列印相應的資訊,相當于列印多次 -->
<logger name="com.ahut.mapper" level="DEBUG" additivity="false">
<appender-ref ref="console"
<appender-ref ref="file"
</logger>
<!-- logback為java中的包 -->
<!--<logger name="com.dudu.controller"/> -->
<!--logback.LogbackDemo:類的全路徑 -->
<!--<logger name="com.dudu.controller.LearnController" level="WARN" additivity="true"> -->
<!--<appender-ref ref="console"/> -->
<!--</logger> -->
<!-- 測試環境+開發環境. 多個使用逗号隔開. -->
<springProfile name="test,dev">
<logger name="com.ahut.action" level="info"
</springProfile>
<!-- 生産環境. -->
<springProfile name="prod">
<logger name="com.ahut.action" level="ERROR"
</springProfile>
</configuration>
根節點 <configuration>
包含的屬性
<configuration>
- scan:當此屬性設定為true時,配置檔案如果發生改變,将會被重新加載,預設值為true。
- scanPeriod:設定監測配置檔案是否有修改的時間間隔,如果沒有給出時間機關,預設機關是毫秒。當scan為true時,此屬性生效。預設的時間間隔為1分鐘。
- debug:當此屬性設定為true時,将列印出logback内部日志資訊,實時檢視logback運作狀态。預設值為false。
根節點
<configuration>
的子節點:
屬性一:設定上下文名稱 <contextName>
<contextName>
每個logger都關聯到logger上下文,預設上下文名稱為“default”。但可以使用
<contextName>
設定成其他名字,用于區分不同應用程式的記錄。一旦設定,不能修改,可以通過%contextName來列印日志上下文名稱。
<contextName>logback</contextName>
屬性二:設定變量 <property>
<property>
用來定義變量值的标簽,
<property>
有兩個屬性,name和value;其中name的值是變量的名稱,value的值時變量定義的值。通過
<property>
定義的值會被插入到logger上下文中。定義變量後,可以使“${}”來使用變量。
<property name="log.path" value=".\\logback.log"
子節點一 <appender>
<appender>
appender用來格式化日志輸出節點,有倆個屬性name和class,class用來指定哪種輸出政策,常用就是控制台輸出政策和檔案輸出政策。
控制台輸出ConsoleAppender:
<!--輸出到控制台 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>ERROR</level>
</filter> -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level
%logger{36} - %msg%n</pattern>
</encoder>
</appender>
<encoder>
表示對日志進行編碼:
- %d{HH: mm:ss.SSS}——日志輸出時間
- %thread——輸出日志的程序名字,這在Web應用以及異步任務進行中很有用
- %-5level——日志級别,并且使用5個字元靠左對齊
- %logger{36}——日志輸出者的名字
- %msg——日志消息
- %n——平台的換行符
ThresholdFilter為系統定義的攔截器,例如我們用ThresholdFilter來過濾掉ERROR級别以下的日志不輸出到檔案中。如果不用記得注釋掉,不然你控制台會發現沒日志~
輸出到檔案RollingFileAppender
另一種常見的日志輸出到檔案,随着應用的運作時間越來越長,日志也會增長的越來越多,将他們輸出到同一個檔案并非一個好辦法。RollingFileAppender用于切分檔案日志:
<!--輸出到檔案 -->
<appender name="file"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logback.%d{yyyy-MM-dd_HH-mm}.log
</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36}
- %msg%n</pattern>
</encoder>
</appender>
其中重要的是rollingPolicy的定義,上例中
<fileNamePattern>logback.%d{yyyy-MM-dd}.log</fileNamePattern>
定義了日志的切分方式——把每一天的日志歸檔到一個檔案中,
<maxHistory>30</maxHistory>
表示隻保留最近30天的日志,以防止日志填滿整個磁盤空間。同理,可以使用%d{yyyy-MM-dd_HH-mm}來定義精确到分的日志切分方式。
<totalSizeCap>1GB</totalSizeCap>
用來指定日志檔案的上限大小,例如設定為1GB的話,那麼到了這個值,就會删除舊的日志。
子節點二 <root>
<root>
root節點是必選節點,用來指定最基礎的日志輸出級别,隻有一個level屬性。
level:用來設定列印級别,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能設定為INHERITED或者同義詞NULL,預設是DEBUG。
可以包含零個或多個元素,辨別這個appender将會添加到這個loger。
"info">
<appender-ref ref="console" />
<appender-ref ref="file"
子節點三 <loger>
<loger>
<loger>
用來設定某一個包或者具體的某一個類的日志列印級别、以及指定
<appender>
。
<loger>
僅有一個name屬性,一個可選的level和一個可選的addtivity屬性。
- name:用來指定受此loger限制的某一個包或者具體的某一個類。
- level:用來設定列印級别,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,還有一個特俗值INHERITED或者同義詞NULL,代表強制執行上級的級别。如果未設定此屬性,那麼目前loger将會繼承上級的級别。
第一種:帶有loger的配置,不指定級别,不指定appender
<logger name="com.ahut.action"/>
将控制action包下的所有類的日志的列印,但是并沒用設定列印級别,是以繼承他的上級
<root>
的日志級别“info”;
沒有設定addtivity,預設為true,将此loger的列印資訊向上級傳遞;
沒有設定appender,此loger本身不列印任何資訊。
<root level="info">
将root的列印級别設定為“info”,指定了名字為“console”的appender。
當執行com.ahur.action.DemoAction類的demo方法時,DemoAction 在包com.ahur.actionr中,是以首先執行
<logger name="com.ahut.action"/>
,将級别為“info”及大于“info”的日志資訊傳遞給root,本身并不列印;
root接到下級傳遞的資訊,交給已經配置好的名為“console”的appender處理,“console”appender将資訊列印到控制台;
第二種:帶有多個loger的配置,指定級别,指定appender
<logger name="com.ahut.action" level="INFO" additivity="false">
<appender-ref ref="console"
</logger>
控制com.ahut.action.DemoAction類的日志列印,列印級别為“WARN”
additivity屬性為false,表示此loger的列印資訊不再向上級傳遞
指定了名字為“console”的appender
這時候執行com.ahut.action.DemoAction類的login方法時,先執行
<logger name="com.dudu.controller.LearnController" level="WARN" additivity="false">
,将級别為“WARN”及大于“WARN”的日志資訊交給此loger指定的名為“console”的appender處理,在控制台中打出日志,不再向上級root傳遞列印資訊。
當然如果你把additivity=”false”改成additivity=”true”的話,就會列印兩次,因為列印資訊向上級傳遞,logger本身列印一次,root接到後又列印一次。
多環境日志輸出
據不同環境(prod:生産環境,test:測試環境,dev:開發環境)來定義不同的日志輸出,在 logback-spring.xml中使用 springProfile 節點來定義,方法如下:
檔案名稱不是logback.xml,想使用spring擴充profile支援,要以logback-spring.xml命名
<!-- 測試環境+開發環境. 多個使用逗号隔開. -->
<springProfile name="test,dev">
<logger name="com.ahut.action" level="info"
</springProfile>
<!-- 生産環境. -->
<springProfile name="prod">
<logger name="com.ahut.action" level="ERROR"
</springProfile>
可以啟動服務的時候指定 profile (如不指定使用預設),如指定prod 的方式為:
java -jar xxx.jar –spring.profiles.active=prod
列印sql
<!-- 列印執行的sql name指定mapper所在的包,additivity設定為true時,父級也會列印相應的資訊,相當于列印多次 -->
<logger name="com.ahut.mapper" level="DEBUG" additivity="false">
<appender-ref ref="console"
<appender-ref ref="file"
</logger>
總結
private Logger logger = LoggerFactory.getLogger(this.getClass());