默認(rèn)情況下,SpringBoot會(huì)用Logback來記錄日志,并用INFO級(jí)別輸出到控制臺(tái)。
1. 引入日志依賴
<!-- 引入web依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
在Spring Boot中,Logback是默認(rèn)的日志記錄框架,只需添加spring-boot-starter-web,它就能引入logback依賴項(xiàng)。
2. 日志輸出
日志級(jí)別從低到高分為TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果設(shè)置為WARN,則低于WARN的信息都不會(huì)輸出。 Spring Boot中默認(rèn)配置ERROR、WARN和INFO級(jí)別的日志輸出到控制臺(tái)。
開啟調(diào)試模式:
- 在運(yùn)行命令后加入–debug標(biāo)志;
- 在application.properties/yml中配置debug=true,該屬性置為true的時(shí)候,核心Logger(包含嵌入式容器、hibernate、spring)會(huì)輸出更多內(nèi)容,但是你自己應(yīng)用的日志并不會(huì)輸出為DEBUG級(jí)別。
彩虹色輸出日志:
通過在application.properties/yml中設(shè)置spring.output.ansi.enabled參數(shù)來支持。
- NEVER:禁用ANSI-colored輸出(默認(rèn)項(xiàng))
- DETECT:會(huì)檢查終端是否支持ANSI,是的話就采用彩色輸出(推薦項(xiàng))
- ALWAYS:總是使用ANSI-colored格式輸出,若終端不支持的時(shí)候,會(huì)有很多干擾信息,不推薦使用
當(dāng)有多處指定了要記錄的日志的最下日志級(jí)別時(shí),走優(yōu)先級(jí)最高的,優(yōu)先級(jí): logback-spring.xml中 > 啟動(dòng)jar包時(shí) > xxx.properties/xxx.yml中
3. 自定義日志配置
根據(jù)不同的日志系統(tǒng),你可以按如下規(guī)則組織配置文件名,就能被正確加載:
- 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
SpringBoot官方推薦優(yōu)先使用帶有-spring的文件名作為你的日志配置(如使用logback-spring.xml,而不是logback.xml)。
4. spring對(duì)日志的配置文件屬性支持
#LOGGING
#日志配置文件的位置。例如,Logback的classpath:logback.xml
logging.config = classpath:logging-config.xml
#記錄異常時(shí)使用的轉(zhuǎn)換字。
logging.exception-conversion-word =%wEx
#日志文件名(例如`myapp.log`)。名稱可以是確切的位置或相對(duì)于當(dāng)前目錄。
logging.file =
#要保留的歸檔日志文件的最大數(shù)量。僅支持默認(rèn)的登錄設(shè)置。
logging.file.max-history = 0
#最大日志文件大小。僅支持默認(rèn)的登錄設(shè)置。
logging.file.max-size = 10MB
#日志級(jí)別嚴(yán)重性映射。例如`logging.level.org.springframework = DEBUG`。
logging.level。* =
#日志文件的位置。例如,`/ var / log`。
logging.path =
#輸出到控制臺(tái)的Appender模式。僅使用默認(rèn)的Logback設(shè)置支持。
logging.pattern.console =
#日志格式的Appender模式。僅使用默認(rèn)的Logback設(shè)置支持。
logging.pattern.dateformat = yyyy-MM-dd HH:mm:ss.SSS
#輸出到文件的Appender模式。僅使用默認(rèn)的Logback設(shè)置支持。
logging.pattern.file =
#日志級(jí)別的Appender模式。僅使用默認(rèn)的Logback設(shè)置支持。
logging.pattern.level =%5p
#為日志記錄系統(tǒng)初始化時(shí)注冊(cè)一個(gè)關(guān)閉鉤子。
logging.register-shutdown-hook = false
5. 整合Logback
5.1 logback-spring.xml
在resources目錄下新建一個(gè)logback-spring.xml文件。
配置示例:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>RabbitsInTheGrass_XJ</contextName>
<!-- 通過property標(biāo)簽,來存放key-value數(shù)據(jù),便于后面的動(dòng)態(tài)獲取,提高程序的靈活性 -->
<property name="log.path" value="E:\myLog" />
<!-- 彩色日志 -->
<!-- 彩色日志依賴的渲染類 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 文件輸出日志格式 -->
<property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n" />
<!-- 輸出到控制臺(tái) -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36}:%L- %msg%n</pattern>-->
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 設(shè)置日志編碼字符集 -->
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
<!--此日志appender是為開發(fā)使用,只配置最底級(jí)別,控制臺(tái)輸出的日志級(jí)別是大于或等于此級(jí)別的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<!--輸出到文件-->
<!-- 時(shí)間滾動(dòng)輸出 level為 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件輸出格式-->
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
<!-- 正在記錄的日志文件的路徑及文件名 -->
<file>${log.path}/log_debug.log</file>
<!-- 此日志文件只記錄debug級(jí)別的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志歸檔 -->
<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天數(shù)-->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>
<!-- 時(shí)間滾動(dòng)輸出 level為 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件輸出格式-->
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
<!-- 正在記錄的日志文件的路徑及文件名 -->
<file>${log.path}/log_info.log</file>
<!-- 此日志文件只記錄info級(jí)別的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志歸檔路徑以及格式 -->
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天數(shù)-->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>
<!-- 時(shí)間滾動(dòng)輸出 level為 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件輸出格式-->
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
<!-- 正在記錄的日志文件的路徑及文件名 -->
<file>${log.path}/log_warn.log</file>
<!-- 此日志文件只記錄warn級(jí)別的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天數(shù)-->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>
<!-- 時(shí)間滾動(dòng)輸出 level為 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件輸出格式-->
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
<!-- 正在記錄的日志文件的路徑及文件名 -->
<file>${log.path}/log_error.log</file>
<!-- 此日志文件只記錄ERROR級(jí)別的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 日志記錄器的滾動(dòng)策略,按日期,按大小記錄 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天數(shù)-->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>
<!--
注:日志級(jí)別有: trace|debug|info|warn|error|fatal
注:當(dāng)有多處指定了要記錄的日志的最下日志級(jí)別時(shí),走優(yōu)先級(jí)最高的,優(yōu)先級(jí):
logback-spring.xml中 > 啟動(dòng)jar包時(shí) > xxx.properties/xxx.yml中
-->
<!-- 開發(fā)環(huán)境 -->
<springProfile name="dev">
<logger name="com" level="debug" />
<root level="info">
<appender-ref ref="CONSOLE" />
</root>
</springProfile>
<!-- 測(cè)試環(huán)境+生產(chǎn)環(huán)境 -->
<springProfile name="test,prod">
<logger name="com" level="info" />
<root level="info">
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
</configuration>
詳解:
5.1.1 根節(jié)點(diǎn)configuration標(biāo)簽
- scan:默認(rèn)值為true,開啟對(duì)配置信息的自動(dòng)掃描(默認(rèn)時(shí)間為60秒掃描一次) 。配置文件如果發(fā)生改變,將會(huì)被重新加載。
- scanPeriod: 設(shè)置監(jiān)測(cè)配置文件是否有修改的時(shí)間間隔,如果沒有給出時(shí)間單位,默認(rèn)單位是毫秒。當(dāng)scan為true時(shí),此屬性生效。默認(rèn)的時(shí)間間隔為1分鐘。
- debug: 當(dāng)此屬性設(shè)置為true時(shí),將打印出logback內(nèi)部日志信息,實(shí)時(shí)查看logback運(yùn)行狀態(tài)。默認(rèn)值為false。
5.1.2 屬性一:contextName 設(shè)置上下文名稱
每個(gè)logger都關(guān)聯(lián)到logger上下文,默認(rèn)上下文名稱為“default”。但可以使用設(shè)置成其他名字,用于區(qū)分不同應(yīng)用程序的記錄。一旦設(shè)置,不能修改,可以通過%contextName來打印日志上下文名稱
5.1.3 屬性二:property 設(shè)置變量
用來定義變量值的標(biāo)簽, 有兩個(gè)屬性,name和value;其中name的值是變量的名稱,value的值時(shí)變量定義的值。通過定義的值會(huì)被插入到logger上下文中。定義變量后,可以使“${}”來使用變量。
5.1.4 子節(jié)點(diǎn)一:appender 標(biāo)簽
appender用來格式化日志輸出節(jié)點(diǎn),有倆個(gè)屬性name和class,name自定義,class用來指定哪種輸出策略,常用就是控制臺(tái)輸出策略和文件輸出策略。
5.1.4.1 控制臺(tái)輸出ConsoleAppender
encoder表示對(duì)日志進(jìn)行編碼:
- %d{HH: mm:ss.SSS}——日志輸出時(shí)間。
- %thread——輸出日志的進(jìn)程名字,這在Web應(yīng)用以及異步任務(wù)處理中很有用。
- %-5level——日志級(jí)別,并且使用5個(gè)字符靠左對(duì)齊。
- %logger{36}——日志輸出者的名字。
- %msg——日志消息。
- %n——平臺(tái)的換行符。
ThresholdFilter為系統(tǒng)定義的攔截器,可以過濾某個(gè)級(jí)別以下的日志不輸出到文件中。
5.1.4.2 輸出到文件RollingFileAppender
其中重要的是rollingPolicy的定義:
- < file>${log.path}</ file> 正在記錄的日志文件的路徑及文件名;
- < fileNamePattern>${log.path}/logback.%d{yyyy-MM-dd}.log </ fileNamePattern>定義了日志的切分方式——把每一天的日志歸檔到一個(gè)文件中;
- < maxHistory>30</ maxHistory>表示只保留最近30天的日志,以防止日志填滿整個(gè)磁盤空間。同理,可以使用%d{yyyy-MM-dd_HH-mm}來定義精確到分的日志切分方式;
- < totalSizeCap>1GB</ totalSizeCap>用來指定日志文件的上限大小,例如設(shè)置為1GB的話,那么到了這個(gè)值,就會(huì)刪除舊的日志。
- 可以在rollingPolicy中嵌套滾動(dòng)策略:
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
SizeAndTimeBasedFNATP策略是: 在每天都會(huì)拆分日志的前提下,當(dāng)該天的日志大于規(guī)定大小時(shí)進(jìn)行拆分并以【%i】進(jìn)行區(qū)分,i從0開始。
5.1.5 子節(jié)點(diǎn)二:loger 標(biāo)簽
loger標(biāo)簽用來設(shè)置某一個(gè)包或者具體的某一個(gè)類的日志打印級(jí)別、以及指定appender。loger標(biāo)簽僅有一個(gè)name屬性,一個(gè)可選的level和一個(gè)可選的addtivity屬性。
- name:用來指定受此loger約束的某一個(gè)包或者具體的某一個(gè)類。
- level:用來設(shè)置打印級(jí)別,大小寫無關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,還有一個(gè)特俗值INHERITED或者同義詞NULL,代表強(qiáng)制執(zhí)行上級(jí)的級(jí)別。如果未設(shè)置此屬性,那么當(dāng)前l(fā)oger將會(huì)繼承上級(jí)的級(jí)別。
- addtivity:是否向上級(jí)loger傳遞打印信息。默認(rèn)是true。
- < appender-ref ref="console"/> 指定了名字為“console”的appender。
5.1.6 子節(jié)點(diǎn)三:root 標(biāo)簽
root節(jié)點(diǎn)是必須配置的節(jié)點(diǎn),用來指定最基礎(chǔ)的日志輸出級(jí)別,只有一個(gè)level屬性。
- level:設(shè)置打印級(jí)別,跟大小寫無關(guān):TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能設(shè)置為INHERITED或者同義詞NULL。
- 一般都默認(rèn)是DEBUG。
可以包含零個(gè)或多個(gè)元素,標(biāo)識(shí)這個(gè)appender將會(huì)添加到這個(gè)loger。
5.2 多環(huán)境日志配置
根據(jù)不同的環(huán)境(prod:生產(chǎn)環(huán)境,test:測(cè)試環(huán)境,dev:開發(fā)環(huán)境)來定義不同的日志輸出,在 logback-spring.xml中使用 springProfile 節(jié)點(diǎn)來定義,方法如下:
<!-- 開發(fā)環(huán)境 -->
<springProfile name="dev">
<logger name="com" level="debug" />
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
<!-- 測(cè)試環(huán)境+生產(chǎn)環(huán)境 -->
<springProfile name="test,prod">
<logger name="com" level="info" />
<root level="info">
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
多個(gè)環(huán)境使用同一個(gè)在name中用逗號(hào)隔開。springProfile 標(biāo)簽的 name 屬性對(duì)應(yīng) application.properties 中的 spring.profiles.active 的配置。即 spring.profiles.active 的值可以看作是日志配置文件中對(duì)應(yīng)的 springProfile 是否生效的開關(guān)。
使用中的問題
- 建議使用占位符的方式參數(shù)化記錄日志
- logback 內(nèi)部機(jī)制保證 logger 在記錄日志時(shí),不必每一次都去遍歷它的父輩以獲得關(guān)于日志級(jí)別、Appender 的信息
- 在 logback 中,將日志信息格式化,以及輸出到目的地,是最損耗性能的操作