文章目錄
爲什麼需要日誌框架
通過日誌的方式記錄系統運行的過程或錯誤以便定位問題。
日誌框架的設計思想
1、System.out.println("");將關鍵數據打印在控制檯;去掉?寫在一個文件?
2、框架來記錄系統的一些運行時信息
3、高大上的幾個功能?異步模式?自動歸檔?
4、將以前框架卸下來?換上新的框架,重新修改之前相關的API;
5、JDBC—數據庫驅動;
寫了一個統一的接口層 給項目中導入具體的日誌實現就行了;我們之前的日誌框架都是實現的抽象層;
市面上常見的日誌框架
JUL,JCL,Jboss-logging,logback,log4j,log4j2,slf4j等等
日誌門面(抽象層) | 日誌實現 |
---|---|
JCL,SLF4j,jboss-logging | Log4j JUL Log4j2, logback |
Springboot:底層是Spring框架 Spring框架默認是用JCL
Springboot選用的是SLF4j和logback
SLF4j的使用
以後開發的時候,日誌記錄方法的調用,不應該來直接調用日誌的實現類,而是調用日誌抽象層裏面的方法
導入slf4j的jar和 logback的實現jar
使用手冊
如何在系統中使用log4j
每一個日誌的實現框架都有自己的配置文件。使用slf4j以後,配置文件還是做成日誌實現框架自己本身的配置文件
遺留問題
統一日誌記錄,即使是別的框架和我一起統一使用slf4j進行輸出?
這裏官方給出瞭解決辦法
翻譯出來就是:如果您所依賴的外部維護的組件使用的是SLF4J以外的日誌API,比如commons logging、log4j或java.util。日誌記錄,看看SLF4J對遺留api的支持
如何讓系統中所有的日誌都統一到slf4j
- 將系統中其他日誌框架先排除出去
- 用中間包來替換原有的日誌框架
- 我們導入slf4j其他的實現
當項目是使用多種日誌API時,可以統一適配到SLF4J,中間使用SLF4J或者第三方提供的日誌適配器適配到SLF4J,SLF4J再底層用開發者想用的一個日誌框架來進行日誌系統的實現,從而達到了多種日誌的統一實現。其中的技術實現大體有一下兩種方式
- 重寫上游類的實現。比如jcl-over-slf4j和log4j-over-slf4j,爲了承接log4j 1,重寫了log4j 1 的Logger和LogFactory類。
- 對接上游類的擴展方案。比如jul-to-slf4j和log4j-to-slf4j,爲了承接JUL,實現了繼承java.util.logging.Handler的SLF4JBridgeHandler
Springboot日誌關係
底層依賴
- SpringBoot底層也是使用slf4j+logback的方式進行日誌記錄
- SpringBoot也把其他的日誌都替換成了slf4j
- 中間替換包
- 如果我們要引入其他框架 一定要把這個框架的默認日誌依賴移除掉
- Spring框架用的是commons-logging
- Spring框架用的是commons-logging
說明 :SpringBoot能自動適配所有的日誌,而且底層使用slf4j+logback的方式記錄日誌,引入其他框架的時候,只需要把這個框架依賴的日誌框架排除掉即可
logback日誌使用
默認配置
日誌的級別:
由低到高:trace<debug<info<warn<error
簡單理解 級別越低 就越容易輸出
springboot的默認級別就是info,比他級別高的會打印,級別低的不會打印
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)//通過指定入口類,就知道要從哪兒去掃描包
public class MainTest {
//slf4j+logback
@Test
public void testLogging() throws Exception{
Logger logger = LoggerFactory.getLogger(getClass());
logger.trace("這是trace級別的日誌..............");
logger.debug("這是debug級別的日誌..............");
logger.info("這是info級別的日誌..............");
logger.warn("這是warn級別的日誌..............");
logger.error("這是error級別的日誌..............");
}
}
輸出:
如果要修改輸出的日誌級別:
可以再配置文件application.yml中添加
注意!!記得添加包的名字不然會報錯
輸出到文本:
輸出到指定目錄
path: /spring/log
在當前磁盤的根路徑下創建spring文件夾和裏面的log文件夾;使用 spring.log 作爲默認文件
日誌輸出格式:
%d表示日期時間,
%thread表示線程名,
%-5level:級別從左顯示5個字符寬度
%logger{50} 表示logger名字最長50個字符,否則按照句點分割。
%msg:日誌消息,
%n是換行符
注意加引號!!!因爲當中有一些字符會被轉義
輸出:
輸出文件:
默認配置的位置
defaults.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
Default logback configuration provided for import, equivalent to the programmatic
initialization performed by Boot
-->
<included>
<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{${LOG_DATEFORMAT_PATTERN:-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="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/>
<logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/>
<logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/>
<logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/>
<logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/>
<logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/>
<logger name="org.hibernate.validator.internal.util.Version" level="WARN"/>
</included>
自定義配置
如果上面的日誌還滿足不了 就可以使用自定義的配置 給類路徑下放上每個日誌框架自己的配置文件即可;SpringBoot就不使用他默認配置的
logback.xml:直接就被日誌框架識別了;
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:當此屬性設置爲true時,配置文件如果發生改變,將會被重新加載,默認值爲true。
scanPeriod:設置監測配置文件是否有修改的時間間隔,如果沒有給出時間單位,默認單位是毫秒當scan爲true時,此屬性生效。默認的時間間隔爲1分鐘。
debug:當此屬性設置爲true時,將打印出logback內部日誌信息,實時查看logback運行狀態。默認值爲false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
<!-- 定義日誌的根目錄 -->
<property name="LOG_HOME" value="/leryoo/log" />
<!-- 定義日誌文件名稱 -->
<property name="appName" value="spring_logback"></property>
<!-- ch.qos.logback.core.ConsoleAppender 表示控制檯輸出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!--
日誌輸出格式:
%d表示日期時間,
%thread表示線程名,
%-5level:級別從左顯示5個字符寬度
%logger{50} 表示logger名字最長50個字符,否則按照句點分割。
%msg:日誌消息,
%n是換行符
-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</layout>
</appender>
<!-- 滾動記錄文件,先將日誌記錄到指定文件,當符合某個條件時,將日誌記錄到其他文件 -->
<appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定日誌文件的名稱 -->
<file>${LOG_HOME}/${appName}.log</file>
<!--
當發生滾動時,決定 RollingFileAppender 的行爲,涉及文件移動和重命名
TimeBasedRollingPolicy: 最常用的滾動策略,它根據時間來制定滾動策略,既負責滾動也負責出發滾動。
-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
滾動時產生的文件的存放位置及文件名稱 %d{yyyy-MM-dd}:按天進行日誌滾動
%i:當文件大小超過maxFileSize時,按照i進行文件滾動
-->
<fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!--
可選節點,控制保留的歸檔文件的最大數量,超出數量就刪除舊文件。假設設置每天滾動,
且maxHistory是365,則只保存最近365天的文件,刪除之前的舊文件。注意,刪除舊文件是,
那些爲了歸檔而創建的目錄也會被刪除。
-->
<MaxHistory>365</MaxHistory>
<!--
當日志文件超過maxFileSize指定的大小是,根據上面提到的%i進行日誌文件滾動 注意此處配置SizeBasedTriggeringPolicy是無法實現按文件大小進行滾動的,必須配置timeBasedFileNamingAndTriggeringPolicy
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 日誌輸出格式: -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
</layout>
</appender>
<!--
logger主要用於存放日誌對象,也可以定義日誌類型、級別
name:表示匹配的logger類型前綴,也就是包的前半部分
level:要記錄的日誌級別,包括 TRACE < DEBUG < INFO < WARN < ERROR
additivity:作用在於children-logger是否使用 rootLogger配置的appender進行輸出,
false:表示只用當前logger的appender-ref,true:
表示當前logger的appender-ref和rootLogger的appender-ref都有效
-->
<!-- hibernate logger -->
<logger name="org.leryoo" level="debug" />
<!-- Spring framework logger -->
<logger name="org.springframework" level="debug" additivity="false"></logger>
<!--
root與logger是父子關係,沒有特別定義則默認爲root,任何一個類只會和一個logger對應,
要麼是定義的logger,要麼是root,判斷的關鍵在於找到這個logger,然後判斷這個logger的appender和level。
-->
<root level="info">
<appender-ref ref="stdout" />
<appender-ref ref="appLogAppender" />
</root>
</configuration>
logback-spring.xml:日誌框架就不直接加載日誌的配置項,由SpringBoot解析日誌配置,可以使用SpringBoot的高級Profile功能
判斷是否爲開發環境
<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>
切換日誌框架
如果要切換爲log4j2
先要排除原來logback配置 然後在加上log4j2
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!--排除原來logback配置-->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--加入log4j2配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!--導入springboot測試場景-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>