日志的選取需要考慮以下幾個(gè)因素:
1)性能和易用性
2)容錯(cuò)性:日志的運(yùn)行應(yīng)該不影響系統(tǒng)的正常運(yùn)行
3)規(guī)范化:日志是否能分級(jí)別打印、日志打印信息是否完善
一、常見日志框架
抽象框架
SLF4J--Simple Logging Facade For Java,定義了統(tǒng)一的日志抽象接口,真正的日志實(shí)現(xiàn)是在運(yùn)行時(shí)決定的。
實(shí)現(xiàn)框架
Log4j,Log4j2,Logback,JCL(Jakarta Commons Logging API)。其中SLF4J、Log4j、Logback都是由一個(gè)人所寫,Logback是Log4j的升級(jí)版,而Log4j2則是Apache借用Log4j的名出的日志框架。Spring框架默認(rèn)使用JCL。
二、Spring Boot默認(rèn)日志框架
??Spring Boot默認(rèn)使用Logback來記錄日志,并用INFO級(jí)別輸出到控制臺(tái)。程序啟動(dòng)時(shí)即可看到打印的信息:
上圖可看出日志的組成結(jié)構(gòu):
- 時(shí)間日期:精確到毫秒
- 日志級(jí)別:ERROR、WARN、INFO、DEBUG、TRACE
- 進(jìn)程ID
- 分隔符: ---標(biāo)識(shí)實(shí)際日志的開始
- 線程名
- Logger名:通常使用源代碼的類名
-
日志內(nèi)容
再看類關(guān)系圖:
因?yàn)閟pring-boo-starter中包含了spring-boot-starter-logging,所以不需要特別引入日志包。
三、簡(jiǎn)單用法
??在類中要使用Logback只需調(diào)用以下代碼:
private Logger logger = LoggerFactory.getLogger(getClass());//注意引入的是SLF4J的包
通過在xx.application文件中直接配置即可實(shí)現(xiàn)的功能
1.控制臺(tái)輸出
debug=true//核心Logger(嵌入器、spring等)會(huì)輸出更多內(nèi)容,但是你自己應(yīng)用的日志并不會(huì)輸出DEBUG級(jí)別
2.文件輸出
logging.file
:設(shè)置日志文件,可以是相對(duì)路徑,也可以是絕對(duì)路徑。如logging.file=my.log
logging.path
:設(shè)置日志目錄,會(huì)在該目錄下創(chuàng)建spring.log文件。如logging.path=/app/logs
??二者同時(shí)使用時(shí),只有l(wèi)ogging.file生效。默認(rèn)情況下,日志文件大小達(dá)到10MB時(shí)會(huì)切分一次,產(chǎn)生新的日志文件。
3.級(jí)別控制
使用格式為:logging.level.=LEVEL
logging.level:日志級(jí)別控制前綴,為包名或Logger名
LEVEL:選型有TRACE,DEBUG,INFO,WARN,ERROR等
示例:
logging.level.oracle=INFO //oracle日志以warn級(jí)別輸出
logging.level.com.mytest=DEBUG //com.mytest包下所有class以DEBUG級(jí)別輸出
四、自定義日志配置文件
1.配置文件詳解
以logback-spring為例
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>wcintegrate</contextName>
<property name="log.path" value="d:/my_logs/wcintegrate" />
<!--<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)的換行符-->
<!--輸出到控制臺(tái)-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- ThresholdFilter為系統(tǒng)定義的攔截器,例如我們用ThresholdFilter來過濾掉ERROR
級(jí)別以下的日志不輸出到文件中。如果不用記得注釋掉,不然你控制臺(tái)會(huì)發(fā)現(xiàn)沒日志-->
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>-->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--輸出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/logback.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<!--RollingFileAppender用于切分文件日志:
<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ì)刪除舊的日志。
補(bǔ):如果你想把日志直接放到當(dāng)前項(xiàng)目下,把${log.path}/去掉即可。-->
<encoder>
<pattern>%d{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>
<!-- logback為java中的包 -->
<logger name="com.app.controller"/>
<!--logback.LogbackDemo:類的全路徑 -->
<logger name="com.app.controller.testController" level="WARN" additivity="false">
<appender-ref ref="console"/>
</logger>
</configuration>
1)根節(jié)點(diǎn)<configuration>的屬性
- scan:當(dāng)此屬性設(shè)置為true時(shí),配置文件如果發(fā)生改變,將會(huì)被重新加載,默認(rèn)值為true。
- 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。
根節(jié)點(diǎn)<configuration>下共有兩個(gè)屬性,三個(gè)子節(jié)點(diǎn)。
2)屬性一:上下文名稱<contextName>
??主要作用是打印時(shí)顯示,用于區(qū)分是用哪個(gè)logger打印的,可不設(shè)置。
3)屬性二:變量<property>
??用來定義變量值的標(biāo)簽, 有兩個(gè)屬性,name和value;其中name的值是變量的名稱,value的值時(shí)變量定義的值。通過定義的值會(huì)被插入到logger上下文中。定義變量后,可以使“${}”來使用變量。
4)子節(jié)點(diǎn)一:<appender>
??appender用來格式化日志輸出節(jié)點(diǎn),有倆個(gè)屬性name和class,class用來指定哪種輸出策略,常用就是控制臺(tái)輸出策略和文件輸出策略。
5)子節(jié)點(diǎn)二:<root>
??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è)logger。
6)子節(jié)點(diǎn)三:<logger>
??<logger>用來設(shè)置某一個(gè)包或者具體的某一個(gè)類的日志打印級(jí)別、以及指定<appender>。<logger>僅有一個(gè)name屬性,一個(gè)可選的level和一個(gè)可選的addtivity屬性。
- name:用來指定受此logger約束的某一個(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ā)ogger將會(huì)繼承上級(jí)的級(jí)別。
- addtivity:是否向上級(jí)logger傳遞打印信息。默認(rèn)是true。
root與logger是父子關(guān)系,沒有特別定義則默認(rèn)為root,任何一個(gè)類只會(huì)和一個(gè)logger對(duì)應(yīng),要么是定義的logger,要么是root,判斷的關(guān)鍵在于找到這個(gè)logger,然后判斷這個(gè)logger的appender和level。
2.配置文件區(qū)別
logback.xml和logback-spring.xml都可作為日志框架配置文件正常使用。區(qū)別如下:
- logback.xml:直接就被日志框架識(shí)別了;
- logback-spring.xml:日志框架不直接加載日志的配置項(xiàng),由SpringBoot解析日志配置,可以使用SpringBoot的高級(jí)Profile功能。
3.多環(huán)境配置
??如下所示,在不同環(huán)境下使用不同的日志輸出格式:
<!-- 測(cè)試環(huán)境+開發(fā)環(huán)境. 多個(gè)使用逗號(hào)隔開. -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<springProfile name="dev">
<pattern>%d{yyyy‐MM‐dd HH:mm:ss.SSS} ‐‐‐‐> [%thread] ‐‐‐> %‐5level%logger{50} ‐ %msg%n</pattern>
</springProfile>
<springProfile name="!dev">
<pattern>%d{yyyy‐MM‐dd HH:mm:ss.SSS} ==== [%thread] ==== %‐5level
%logger{50} ‐ %msg%n</pattern>
</springProfile>
</layout>
</appender>
五、常見問題
1.一個(gè)項(xiàng)目中多日志框架
??Spring Boot能自動(dòng)適配所有的日志,底層使用sl4j+logback的方式記錄日志,如果引入其他框架時(shí),一定要把這個(gè)框架的默認(rèn)日志實(shí)現(xiàn)依賴移除掉。如Spring默認(rèn)使用java.commons.logging。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
六、文獻(xiàn)
https://blog.csdn.net/J080624/article/details/80632121
http://tengj.top/2017/04/05/springboot7/
https://blog.csdn.net/wujianmin577/article/details/68922545