一、日誌概述
1. 日誌的級別
Java應用中,日誌一般分爲以下5個級別:
- ERROR 錯誤信息
- WARN 警告信息
- INFO 一般信息
- DEBUG 調試信息
- TRACE 跟蹤信息
Spring Boot使用Apache的Commons Logging
作爲內部的日誌框架,其僅僅是一個日誌接口,在實際應用中需要爲該接口來指定相應的日誌實現。Spring Boot默認的日誌實現是Java Util Logging
,是JDK自帶的日誌包,此外Spring Boot當然也支持Log4J、Logback
這類很流行的日誌框架。
2. 日誌框架的作用
日誌框架能控制什麼?需要打印的日誌都能滿足什麼樣的需求?
1、能夠控制日誌信息想往哪裏打就往哪裏打,比如:控制檯、文件、郵箱、數據庫等等;
2、能夠控制日誌信息想怎麼打就怎麼打,比如:想要打印時間、程序的名稱、程序的方法名、程序的行號、線程的名稱等等;
3、能夠控制日誌信息想打什麼打什麼,不想打的就不打,日誌信息是分級別的,有時候只想看錯誤的信息或者警告的信息,有時候想看到所有的信息調試程序等等。
記錄日誌信息的作用:
- 監視代碼中變量的變化情況,週期性的記錄到文件中供其它應用進行統計分析;
- 跟蹤代碼運行時軌跡,作爲日後審計的依據;
- 擔當集成開發環境中的調試器的作用,向文件或控制檯打印代碼的調試信息。
二、Spring Boot使用日誌
使用slf4j-api
接口,Java Util Logging
作爲默認的日誌實現
1. 設置level爲INFO
application.properties配置:
logging.level.root=INFO
控制器代碼如下:
package com.example.loggingdemo.controller;
import com.example.loggingdemo.LoggingdemoApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/logging")
public class TestLogging {
private static Logger logger = LoggerFactory.getLogger(LoggingdemoApplication.class);
@GetMapping("/hello")
public String sayHello() {
logger.info("say hello...");
return "hello";
}
}
運行結果(由於將日誌等級設置爲INFO,因此包含INFO及以上級別的日誌信息都會打印出來):
圖片可以看出,很多大部分的INFO日誌均來自於Spring Boot框架本身,如果我們想屏蔽它們,可以將日誌級別統一先全部設置爲ERROR,這樣框架自身的INFO信息不會被打印。然後再將應用中特定的包設置爲DEBUG級別的日誌,這樣就可以只看到所關心的包中的DEBUG及以上級別的日誌了。
2. 控制特定包的日誌級別
application.properties配置:
logging.level.root=error
logging.level.com.example.loggingdemo.controller:debug
將root日誌級別設置爲ERROR,然後再將com.example.loggingdemo.controller
包的日誌級別設爲DEBUG,即先禁止所有再允許個別包的設置方法。
控制器部分代碼:
private Logger logger = LoggerFactory.getLogger(this.getClass());
運行結果:
可見框架自身的INFO級別日誌全部藏匿,而指定包中的日誌按級別順利打印。
3. 將日誌輸出到某個文件中
application.properties配置:
logging.file=E:/logs/hello.log
運行結果:
使用Spring Boot Logging日誌框架,發現雖然日誌文件已生成並輸出,但控制檯中依舊會打印日誌,使用Spring Boot Logging無法解決這個問題。
三、Spring Boot集成Log4J2日誌框架
1. pom.xml中添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
2. 在resources目錄下新建log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appenders>
<File name="file" fileName="E:/logs/hello2.log">
<PatternLayout pattern="%d{HH:mm:ss,SSS} %p %c (%L) - %m%n"/>
</File>
</appenders>
<loggers>
<root level="ERROR">
<appender-ref ref="file"/>
</root>
<logger name="com.example.loggingdemo.controller" level="DEBUG"/>
</loggers>
</configuration>
3. 控制器代碼
package com.example.loggingdemo.controller;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/logging")
public class TestLogging {
private final Logger logger = LogManager.getLogger(this.getClass());
@GetMapping("/hello")
public String sayHello() {
for (int i = 0; i < 1000; i++) {
logger.info("info execute index method");
logger.warn("warn execute index method");
logger.error("error execute index method");
}
return "say hello";
}
}
運行結果:
運行程序發現控制檯沒有日誌輸出,而hello2.log文件中有內容,即符合我們的要求。
四、Log4J詳細配置
1. log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="warn">
<properties>
<Property name="app_name">springboot-web</Property>
<Property name="log_path">logs/${app_name}</Property>
</properties>
<appenders>
<console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%d][%t][%p][%l] %m%n"/>
</console>
<RollingFile name="RollingFileInfo" fileName="${log_path}/info.log"
filePattern="${log_path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="INFO"/>
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n"/>
<Policies>
<!-- 歸檔每天的文件 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!-- 限制單個文件大小 -->
<SizeBasedTriggeringPolicy size="2 MB"/>
</Policies>
<!-- 限制每天文件個數 -->
<DefaultRolloverStrategy compressionLevel="0" max="10"/>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="${log_path}/warn.log"
filePattern="${log_path}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="WARN"/>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n"/>
<Policies>
<!-- 歸檔每天的文件 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!-- 限制單個文件大小 -->
<SizeBasedTriggeringPolicy size="2 MB"/>
</Policies>
<!-- 限制每天文件個數 -->
<DefaultRolloverStrategy compressionLevel="0" max="10"/>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${log_path}/error.log"
filePattern="${log_path}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
<ThresholdFilter level="ERROR"/>
<PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n"/>
<Policies>
<!-- 歸檔每天的文件 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!-- 限制單個文件大小 -->
<SizeBasedTriggeringPolicy size="2 MB"/>
</Policies>
<!-- 限制每天文件個數 -->
<DefaultRolloverStrategy compressionLevel="0" max="10"/>
</RollingFile>
</appenders>
<loggers>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>
控制器及其他代碼不變,運行結果如下:
日誌會根據不同的級別存儲在不同的文件,當日志文件大小超過2M以後會分多個文件壓縮存儲,生產環境的日誌文件大小建議調整爲20-50MB。
2. SSM框架下Log4j配置(補充)
- 控制器代碼
private static Logger logger = Logger.getLogger(Test.class);
public static void main(String[] args) {
// 記錄debug級別的信息
logger.debug("This is debug message.");
// 記錄info級別的信息
logger.info("This is info message.");
// 記錄error級別的信息
logger.error("This is error message.");
}
}
- Log4j.properties
### org.apache.log4j.ConsoleAppender (控制檯)
### org.apache.log4j.FileAppender (文件)
### org.apache.log4j.DailyRollingFileAppender (每天產生一個日誌文件)
### org.apache.log4j.RollingFileAppender (文件大小到達指定尺寸的時候產生一個新的文件)
### org.apache.log4j.WriterAppender (將日誌信息以流格式發送到任意指定的地方)
### ERROR、WARN、INFO、DEBUG 優先級從高到低
### 設置日誌輸出的等級爲DEBUG,低於DEBUG不會輸出
### 設置輸出到控制檯 (stdout)、D、E 三個地方
log4j.rootLogger = debug,stdout,D,E
### 輸出信息到控制擡 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 輸出DEBUG 級別以上的日誌到=E://logs/error.log ###
### 第二個地方D, 以滾動的方式輸出到文件,文件名是log.log
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 輸出ERROR 級別以上的日誌到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n