springboot日誌集成:
日誌實現: logback、log4j、log4j2、 JUL(java.util.longging)
日誌抽象層:JCL(jakarta Commons Logging) 、 SLF4J(Simple Logging Facade for java) 、jboss-logging
也就是 抽象層選一個,實現類選一個就成了一個日誌框架。
JCL(jakarta Commons Logging): 最後更新 2014年,過時。
jboss-logging:應用場景太少。
SLF4J、Log4J、Logback:出自同一個人編寫,就在這裏面選了。
Log4j沒有Logback 的功能多。
Log4J2:apche小組重新研發的 ,有兼容性問題。
所以我們選擇:
日誌門面(抽象層):SLF4J
日誌實現:LogBack
調用方式:
官方說明:http://www.slf4j.org/manual.html
代碼調用示例:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
SLF4J+Logback原理:
application(應用) 調用SLF4J(抽象層),再調用LogBack實現。
SLF4J+Log4J原理:
application(應用) 調用SLF4J(抽象層),不能直接調用Log4j實現類(原因:Log4j最初根本沒想到有slf4j抽象層,所以不兼容),需要加入適配器Adaptation layer,
這個適配器相當於SLF4J調用了他的方法,然後更具他的方法去調用log4j的實現類。
**SLF4J+JUL(java.Uilt.logging)原理: **
application(應用) 調用SLF4J(抽象層),不能直接調用JUL實現類(原因:JUL是臨時加入搶佔市場的,並沒有考慮兼容slf4j抽象層,所以不兼容),和調用log4j一樣,需要加入適配器Adaptation layer,適配器再調用JUL的實現類。
SLF4J本身就有簡單的實現類:
包名:slf4j-api.jar
加入slf4j-simple.jar: 只有一些簡單的實現類,可以直接使用。
加入slf4j-nop.jar: 沒有什麼實現,但是也可以使用,直接輸出到空的文件。
每一個日誌的實現框架都有自己的配置文件,使用哪個日誌的實現類就配置哪個實現類的配置文件。
比如:我們用了slf4j,實現類是logback,所以我們要配置log back的文件。
遺留問題:日誌統一
比如: 系統太大了,使用了多個框架,spring自帶的Commons logging、hibernate的jboss-logging、mybatis、XXX 等一系列日誌。
太雜,而我們現在想用slf4j+logback來作爲統一日誌。
方法:
看官方說明(http://www.slf4j.org/legacy.html),給出了張圖:
這個圖第一部分的意思就是:
原理:
先去掉系統自帶的框架Commons-logging,使用中間包(作用:替換原有的日誌jar包)jcl-over-slf4j.jar來替換Commons-logging,jcl-over-slf4j再調用SLF4J,SLF4J再調用Logback實現類。
用idea工具在pom.xml右擊鼠標,選擇Diagrams–>ShowDependencies…可以清楚的看到依賴結構圖
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uOo8REoE-1571111198385)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\1571039872501.png)]
springboot與日誌的底層關係:
springboot-logging官方手冊說明:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html
導入maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
底層依賴關係圖:
spring boot 底層也用的slf4j+logback的方式進行日誌記錄。
spring boot 把底層的日誌都替換成了slf4j
中間包:比如jcl-over-slf4j.jar 裏面有org.Commons-logging的包,但它的實現卻是slf4j的初始化,也就是調用的還是slf4j。
如果spring boot要引入其他框架比如說Log4J,那麼一定要先排除原有的默認日誌依賴logback,
spring框架用的是Commons-logging;
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QA3PMiLg-1571111198387)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\1571041405599.png)]
2.0版本以前的springboot底層也是這樣做的,但是在spring boot 2.0就沒有排除了,應該說是沒有依賴Commons-logging了能找到的也就只有log4j-to-slf4j、 jul-to-slf4以及logback-classic的jar.
但是統一方法還是一樣的,如果要更換其他日誌,還是得先排除。在添加自己要集成得日誌jar.
springboot默認日誌配置:
//logger 爲日誌記錄器
private static final Logger log=LoggerFactory.getLogger(Test.class);
用法:
//trace 追蹤
log.trace("這是一個trace日誌記錄");
log.debug("這是一個Debug的測試日誌記錄");
log.info("這是一個info日誌記錄");
log.warn("這是一個warn日誌記錄");
log.error("這是一個error日誌記錄");
日誌級別:
由低到高分別爲:trace–>debug–>info–>warn–>error
作用:可以調整日誌級別的輸出,比如說項目不想看到Debug和info這一類日誌信息,那麼我們就寫成warn,那麼就只會輸出warn以及warn以上級別的信息。
spring boot 默認日誌輸出級別爲Info,也就是控制檯只輸出info及info以上的信息。
指定級別:
logging:
level.logdemo: //logdemo 爲項目的包名,該包下的所有日誌都輸出trace級別及以上級別的信息,沒有指定的包輸出級別的爲springboot默認級別Info
root: trace
Logging properties:
logging.file |
logging.path |
Example | 描述(Description) |
---|---|---|---|
(沒有) | (沒有) | 僅控制檯記錄。 | |
特定檔案 | (沒有) | my.log |
寫入指定的日誌文件。名稱可以是確切位置,也可以是相對於當前目錄的位置。 |
(沒有) | 具體目錄 | /var/log |
寫入spring.log 指定的目錄。名稱可以是確切位置,也可以是相對於當前目錄的位置 |
日誌文件達到10 MB時會旋轉,並且與控制檯輸出一樣,默認情況下會記錄ERROR
-level,WARN
-level和INFO
-level消息。可以使用該logging.file.max-size
屬性更改大小限制。除非logging.file.max-history
已設置屬性,否則以前旋轉的文件將無限期存檔。
指定日誌文件存放路徑:
logging.file:
logging:
level.logdemo:
root: trace
file: E:\\IDEA_project\\logdemo\\logs\\info.log
logging.path:
logging:
level.logdemo:
root: trace
path:/spring/log
//這裏"/"是Linux下的絕對路徑, 表示在當前磁盤路徑下創建spring文件夾 ,在spring文件夾下創建log文件夾,默認文件的是spring.log
logging.file和logging.path:二者不能同時使用,如若同時使用,則只有logging.file生效
logging:
level.logdemo:
root: INFO
# org:
# springframework:
# hibernate: ERROR
# web: DEBUG
#logging.file和logging.path二者不能同時使用,如若同時使用,則只有logging.file生效
file: E:\\IDEA_project\\logdemo\\logs\\info.log
pattern:
#在控制檯輸出的格式
console:
#指定文件中的輸出格式:
file:
日誌輸出格式:
%d: 日期時間
%thread或%t: 線程名
%-5level或%5p: 級別從左顯示5個字符寬
%logger{50}: logger名字最長50個字符,否在按照句點分割
%msg : 日誌消息
%n: 換行
自定義日誌配置:
給類路徑下放上每個日誌框架自己的配置文件,springboot就不會啓動默認的配置了。
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml , or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
logback.xml: 直接就被日誌框架識別
logback-spring.xml: 日誌框架不自動識別並加載,spring boot2.0好像可以自動識別並加載,
注意:由於xml文件配置的加載要優先於application.yml,logback-spring.xml會找不到配置的文件存放地址,所以不能在yml裏面配置日誌存放的位置。
Logback擴展:
在使用logback-spring.xml
作爲配置文件,可以使用log back的高級功能。
由於標準logback.xml
配置文件加載太早,因此不能在其中使用擴展名。您需要使用logback-spring.xml
或定義一個logging.config
屬性。
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]
使用logback-spring.xml作爲配置文件則我們可以使用高級功能:springProfile 這個配置
<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
<!-當“staging(臨時或者測試環境)”配置文件處於活動狀態時要啓用的配置->
</springProfile>
<springProfile name = " dev | staging" >
<!-要在激活“dev(開發環境)”或“staging”配置文件時啓用配置->
</ springProfile>
<springProfile name = "!production" >
<!-當“poduction(生產環境)”配置文件未激活時要啓用的配置->
</ springProfile>
當然先要設置開發環境:
server:
port: 8080
servlet:
context-path: /logdemo
#logging:
# pattern:
# level.com: Info
# console: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){blue} %clr(%-5level) %clr([%t]){magenta} %clr(----){faint} %clr(%-40.40logger{39}){cyan} %clr(:){blue} %m%n"
# file: "%d{yyyy-MM-dd HH:mm:ss.SSS}{faint} %-5level [%t] ---- %-40.40logger{39} : %m%n"
# file: E:\\IDEA_project\\logdemo\\logs\\info.log
spring:
profiles.:
active: dev #設置爲開發環境dev,或者 是生產環境production
個人自定義完整配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定義日誌文件的存儲地址 勿在 LogBack 的配置中使用相對路徑-->
<property name="LOG_HOME" value="E:\\IDEA_project\\logdemo\\logs\\" />
<!-- 彩色日誌 -->
<!-- 彩色日誌依賴的渲染類 -->
<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" />
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){blue} %clr(%-5level) %clr([%t]){magenta} %clr(----){faint} %clr(%-40.40logger{39}){cyan} %clr(:){blue} %m%n</pattern>
</encoder>
</appender>
<appender name="stdout" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件輸出的文件名-->
<FileNamePattern>${LOG_HOME}Info-%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日誌文件保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}{faint} %-5level [%t] ---- %-40.40logger{39} : %m%n</pattern>
</encoder>
<!--日誌文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
<maxHistory>${LOG_FILE_MAX_HISTORY:-0}</maxHistory>
</rollingPolicy>
</appender>-->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="stdout" />
<!--<appender-ref ref="FILE" />-->
</root>
</configuration>
分級日誌文件存放配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定義日誌文件的存儲地址 勿在 LogBack 的配置中使用相對路徑-->
<property name="LOG_HOME" value="E:\\IDEA_project\\logdemo\\logs\\" />
<springProfile name = "!dev">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%t] ---- %-40.40logger{39}: %m%n</pattern>
</encoder>
</appender>
</springProfile>
<springProfile name = "dev" >
<!--要在激活“dev(開發環境)”或“staging”配置文件時啓用配置-->
<!-- 彩色日誌 -->
<!-- 彩色日誌依賴的渲染類 -->
<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" />
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){blue} %clr(%-5level) %clr([%t]){magenta} %clr(----){faint} %clr(%-40.40logger{39}){cyan} %clr(:){blue} %m%n</pattern>
</encoder>
</appender>
</springProfile>
<!-- Console 輸出設置 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- 不用彩色控制檯輸出 -->
<!-- 控制檯輸出 -->
<!--<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">-->
<!--<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">-->
<!--<!–格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符–>-->
<!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>-->
<!--</encoder>-->
<!--</appender>-->
<!-- 按照每天生成日誌文件 -->
<!--info-->
<appender name="DAYINFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件輸出的文件名-->
<FileNamePattern>${LOG_HOME}/Info-%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日誌文件保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日誌文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--error appender-->
<appender name="DAYERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件輸出的文件名-->
<FileNamePattern>${LOG_HOME}/Error-%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日誌文件保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<!--這裏設置日誌級別爲error-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日誌文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--warning appender-->
<appender name="DAYWARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件輸出的文件名-->
<FileNamePattern>${LOG_HOME}/Warning-%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日誌文件保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<!--這裏設置日誌級別爲error-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日誌文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 日誌輸出級別 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="DAYINFO" />
<appender-ref ref="DAYERROR" />
<appender-ref ref="DAYWARN" />
</root>
</configuration>