日志處理是一個正式項目必備的功能,日志要能夠根據時間、類型等要素,根據指定格式來保存指定的日志,方便我們觀察程序運行情況、定位程序bug。
SpringBoot中推薦使用Logback日志框架。
本節示例項目在https://github.com/laolunsi/spring-boot-examples
slf4j:一個針對各類Java日志框架的統一facade抽象。
java常見日志框架:java.util.logging, log4j, logback, commons-logging
logback是log4j的作者開發的新一代日志框架,目前應用最廣泛。SpringBoot默認使用logback,默認INFO級別
Logback:
日志加載順序:logback.xml -> application.properties -> logback-spring.xml
一、日志級別
log4j定義的日志級別:debug/info/warn/error/fatal
warn,潛在錯誤;error,錯誤,可能導致程序退出;fatal,嚴重錯誤,程序會退出
還有兩個特殊的級別:OFF-最高級別,ALL-最低級別
log4j建議僅使用debug/info/warn/error四個級別
日志級別:ERROR -> WARN -> INFO -> DEBUG
如配置日志級別為INFO,則INFO及以上級別的日志會輸出,而比INFO級別低的日志(debug日志)不會被輸出。
二、SpringBoot引入logger
直接引入:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>2.1.11.RELEASE</version>
<scope>compile</scope>
</dependency>
間接引入:
引入spring-boot-starter,會自動引入spring-boot-starter-logging
引入spring-boot-starter-web,會自動引入spring-boot-starter
三、通過springboot配置文件配置logback
配置輸出日志到文件:
logging:
file: logback-demo.log # 輸出到項目目錄下
默認是疊加輸出,即每次啟動項目不會刪除之前的日志文件,也不會將當前使用的日志文件清空,而是在下面另起一行。
日志級別:logging.level.*: level-name
*指包名或日志名,日志名如root,表示系統日志
level-name指日志級別,常用debug/info/warn/error
比如:
logging:
level:
com.example.logbackdemo: debug # 指定包下日志以debug級別輸出
#root: warn # root日志以warn級別輸出,不要用debug級別!!---會卡的!
四、通過XMl文件自定義logback配置
上面的配置確實將日志保存到文件中,但是對於實際項目來說用處不大。
比如:日志文件非常龐大,每天產生的日志大小在數百MB,單個文件能處理么?日志需要分類型進行保存怎么辦呢?定制日志格式怎么辦呢?
這些都是問題。
幸好,包括logback在內的日志框架大多提供了配置文件功能,最常見的是使用xml文件進行配置。
日志框架默認配置文件:
- 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
日志加載順序:logback.xml -> application.properties -> logback-spring.xml
logback框架下:
建議使用logback-spring.xml,也可以在application中通過logging.config=classpath:xxx.xml來指定配置文件。
示例:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<contextName>logback-spring-demo-dev</contextName>
<property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n"/>
<property name="pattern-color" value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{50}) - %highlight(%msg) %n"/>
<property name="LOG_HOME" value="logs"/>
<!-- 控制台輸出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- 控制台輸出-帶顏色 -->
<appender name="CONSOLE-WITH-COLOR" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern-color}</pattern>
</encoder>
</appender>
<!-- 文件輸出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/all.%d.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE-WITH-COLOR"/>
<appender-ref ref="FILE"/>
</root>
<logger name="com.example.logbackdemo.IndexAction" level="info" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
</configuration>
下面具體描述一下logback.xml中的配置項:
共有兩種屬性和三個節點:
- 兩種屬性:contextName和property
- 三個節點:appender、root、logger
4.1 contextName屬性
contextName:日志名,可以使用%contextName來引用
如果同時存在logback.xml和logback-spring.xml,或者同時存在logback.xml和自定義的配置文件,則會先加載logback.xml,再根據application配置加載指定配置文件,或加載logback-spring,xml。如果這兩個配置文件的contextName不同,就會報錯:
ERROR in ch.qos.logback.classic.joran.action.ContextNameAction - Failed to rename context [logback-demo] as [logback-spring-demo-dev] java.lang.IllegalStateException: Context has been already given a name
4.2 property屬性
property標簽可用於自定義屬性,比如定義一個
4.3 appender節點
appender的意思是追加器,在這里可以理解為一個日志的渲染器。比如渲染console日志為某種格式,渲染文件日志為另一種格式。
appender中有name和class兩個屬性,有rollingPolicy和encoder兩個子節點。
name表示該渲染器的名字,class表示使用的輸出策略,常見的有控制台輸出策略和文件輸出策略。
4.3.1 控制台輸出appender
<property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
encoder表示輸出格式,具體說明如下:
%d表示時間
%thread表示線程名
%-5level 表示日志級別,允許以五個字符長度輸出
%logger{50}表示具體的日志輸出者,比如類名,括號內表示長度
%msg表示具體的日志消息,就是logger.info("xxx")中的xxx
%n表示換行
還可以定義顏色高亮,比如講pattern定義為如下:
<property name="pattern-color" value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{50}) - %highlight(%msg) %n"/>
即使用%color(xxx)來指定對應列的輸出顏色,可以實現控制台輸出的顏色高亮。
4.3.2 文件輸入appender
文件輸出主要包括配置:以指定格式將日志輸出到指定文件夾下的文件中,可以配置該文件的名稱、最大大小、保存時間
例如:
<property name="LOG_HOME" value="logs"/>
<property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/all.%d.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
上述配置的主要內容是:以指定的格式向logs文件下的文件輸出日志,文件名稱格式被指定為logs/all.日期.索引號.log,日志文件最大大小為10MB,超出則創建新文件,日志文件保留三十天
索引從0開始遞增
rollingPolicy指滾動粗略,具體配置如上。
關於日志文件大小限制也可以使用
4.4 root節點-啟用配置
root節點實際上是配置啟用哪種appender,可以添加多個appender。
比如:
<root level="INFO">
<appender-ref ref="CONSOLE-WITH-COLOR"/>
<appender-ref ref="FILE"/>
</root>
表示level為info級別,啟用渲染器CONSOLE-WITH-COLOR和FILE。
按照這樣配置,輸出日志時,控制台會按照CONSOLE定義的格式輸出,而日志文件會按照CONSOLE-WITH-COLOR的配置去輸出。
4.5 logger節點
對單個包或類添加配置:
<!-- logger節點可以指定具體包或類的日志配置 -->
<!-- name屬性為必選,指定要配置的包或類,level和additivity為可選,有缺省值 -->
<!-- level表示日志級別,這里配置info級別,表示info及以上級別的日志被輸出 -->
<!-- additivity表示日志是否傳遞到上一級,默認為true -->
<logger name="com.example.logbackdemo.IndexAction" level="info" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
這里我們添加了一個測試接口類:
@RestController
@RequestMapping(value = "log")
public class IndexAction {
private Logger logger = LoggerFactory.getLogger(IndexAction.class);
@GetMapping(value = "")
public String testLoggerTag() {
logger.debug("測試logger標簽");
logger.info("測試logger標簽");
logger.warn("測試logger標簽");
logger.error("測試logger標簽");
return "this is spring-boot-logback-demo projects.";
}
}
啟動項目,調用接口測試一下:
發現IndexAction類的控制台日志輸出是無顏色的,即logger配置生效。additivity設為true后,發現控制台輸出了兩遍相同的內容。
此外,還有一個用於指定springboot配置文件對應日志配置的springProfile標簽,在下面會講到其應用。
4.6 指定啟用那些日志配置
-
springboot指定啟用哪個xml
我們可以在springboot的配置文件中指明使用哪個xml作為logger的配置,比如:logging.config=classpath:logback-spring-dev.xml。
如果不指定,則會按照logback.xml->application.yml->logback-spring.xml的順序去查找是否存在默認的配置。
-
xml中使用springProfile標簽指定哪些環境下應該使用哪些配置
我們也可以在具體的日志配置xml文件中指定在哪些環境下使用哪些配置,比如:
<springProfile name="local,dev"> <root level="INFO"> <appender-ref ref="CONSOLE-WITH-COLOR"/> <appender-ref ref="FILE"/> </root> </springProfile> <springProfile name="prod"> <root level="INFO"> <appender-ref ref="CONSOLE-WITH-COLOR"/> <appender-ref ref="FILE"/> </root> </springProfile>
這樣的話,就不需要建議多個xml文件了,使用一個默認的logback-spring.xml即可。
參考:
https://mrbird.cc/Spring-Boot-logback.html
https://www.jianshu.com/p/b3dedb8fb61e