1. 程式人生 > >[SpringBoot之一入門] 04-Springboot的日誌

[SpringBoot之一入門] 04-Springboot的日誌

1、日誌框架的選擇

SpringBoot 選用 SLF4j(Simple Logging Facade for Java)抽象層 和 logback實現類

開發時,日誌記錄方法的呼叫,不應該來直接呼叫日誌的實現類,而是呼叫日誌抽象層裡面的方法;

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以後,配置檔案還是做成日誌實現框架自己本身的配置檔案;

遺留問題

a(slf4j+logback): Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis、xxxx,各個日誌包衝突

這裡寫圖片描述

如何讓系統中所有的日誌都統一到slf4j;
1、將系統中其他日誌框架先排除出去;
2、用中間包來替換原有的日誌框架;
3、我們匯入slf4j其他的實現;

這裡寫圖片描述

總結:
​ 1)、SpringBoot底層也是使用slf4j+logback的方式進行日誌記錄
​ 2)、SpringBoot也把其他的日誌都替換成了slf4j;
​ 3)、中間替換包,底層被slf4j替換了方法
這裡寫圖片描述


4)、如果我們要引入其他框架?一定要把這個框架的預設日誌依賴移除掉?
Spring框架用的是commons-logging;

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <exclusions>
        <exclusion>
            <groupId>commons-logging</groupId
>
<artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency>

SpringBoot能自動適配所有的日誌,而且底層使用slf4j+logback的方式記錄日誌,
引入其他框架的時候,只需要把這個框架依賴的日誌框架排除掉即可;

3.日誌級別

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot03LoggerApplicationTests {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Test
    public void contextLoads() {
        //日誌的級別;
        //由低到高   trace<debug<info<warn<error
        //可以調整輸出的日誌級別;日誌就只會在這個級別以以後的高級別生效
        logger.trace("這是trace日誌...");
        logger.debug("這是debug日誌...");
        logger.info("這是info日誌...");
        logger.warn("這是warn日誌...");
        logger.error("這是error日誌...");
    }
}

執行結果:

c.s.SpringBoot03LoggerApplicationTests   : 這是info日誌...
c.s.SpringBoot03LoggerApplicationTests   : 這是warn日誌...
c.s.SpringBoot03LoggerApplicationTests   : 這是error日誌...

SpringBoot預設給我們使用的是info級別的,沒有指定級別的就用SpringBoot預設規定的級別;root級別

日誌輸出格式:
    %d表示日期時間,
    %thread表示執行緒名,
    %-5level:級別從左顯示5個字元寬度
    %logger{50} 表示logger名字最長50個字元,否則按照句點分割。 
    %msg:日誌訊息,
    %n是換行符

 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n

4.指定配置

給類路徑下放上每個日誌框架自己的配置檔案即可;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:日誌框架就不直接載入日誌的配置項,由SpringBoot解析日誌配置,可以使用SpringBoot的高階Profile功能

<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
    可以指定某段配置只在某個環境下生效
</springProfile>

如:

<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    <layout class="ch.qos.logback.classic.PatternLayout">
        <springProfile name="dev">  //dev環境下使用使用如下格式(前提:命名為logback-spring.xml)
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern>
        </springProfile>
        <springProfile name="!dev"> //非dev環境下使用如下格式(前提:命名為logback-spring.xml)
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
        </springProfile>
    </layout>
</appender>

完整案例:

<?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="/app/log" />
    <!-- 定義日誌檔名稱 -->
    <property name="appName" value="日誌檔名稱name"></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="com.atguigu" 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>