Springboot 日誌應用使用入門

 

目錄

日誌框架背景

主流日誌框架

SLF4J詳解

SLF4J 原理

slf4j 與實現框架圖總覽

slf4j 與 logback 入門

slf4j 與 log4j 入門

添加 Maven 依賴

添加配置文件

日誌記錄

Springboot使用logback


日誌框架背景

1)程序媛小張,開發了一個大型系統;

2)最開始系統中使用 System.out.println("");將關鍵數據打印在控制檯

3)後面發現這樣不容易查看之前的日誌信息,於是小張開發了一個小框架來記錄系統的一些運行時信息,將所有運行信息統一保存到了文件中,最原始的日誌框架就叫“zhanglogging.jar”

4)在不斷的開發實踐中,小張覺得之前的框架需要改進,決定再加幾個功能:如異步模式、自動分類歸檔等, 改進版的框架名字叫“zhanglogging-good.jar”

5)因爲日誌框架升級,以前的項目如果要使用新的日誌框架,那就不得不修改源碼,假設哪一天又升級了日誌框架叫“zhanglogging-prefect.jar”,這樣反覆修改項目源碼仍然不太合適

6)後面發現數據庫 JDBC 的 數據庫驅動的模式,由Java 提供統一的JDBC 接口,不同的數據庫供應商提供實現,切換數據庫的時候,只需要直接更新數據庫驅動即可,並不需要修改源碼

7)於是小張也寫了一個統一的日誌接口層,叫 “日誌門面”(日誌的一個抽象層),名字叫 logging-abstract.jar;給項目中導入具體的日誌實現就行了;


主流日誌框架

1、市面上的日誌框架;JUL、JCL(Apache 基金會的)、Jboss-logging、logback、log4j、log4j2、slf4j....


2、其中 SLF4j 與 Log4j 、 Logback 出自同一人之手,Logback 是 Log4j 的升級版;而 Log4j2 只是借用了 Log4j 的名號而已

3、SpringBoot 底層是 Spring 框架,而 Spring 框架默認是用 JCL,但是 SpringBoot 選用的是 SLF4j 和 logback,所以Spring Boot 的日誌框架重點是學習使用 SLF4j 和 logback

4、所以爲了開發日誌系統擴展性更好的應用,就得從上表中左右兩邊各選擇一個進行日誌接口和實現進行開發,而且編碼的時候應該調用左邊的接口,而不是右邊的實現,這樣利於將來擴展。

SLF4J詳解

SLF4J 原理

1、官網地址:https://www.slf4j.org/,官網有非常詳細的使用文檔以及 Jar 包下載和 Maven 依賴配置 等

2、SLF4J Maven 依賴獲取網址:https://mvnrepository.com/artifact/org.slf4j/slf4j-api

3、開發的時候,爲了應用日誌系統的將來的擴展,日誌記錄方法的調用,不應該直接調用日誌的實現類,而是調用日誌抽象層裏面的方法;這樣以後即使更換了實現類也沒有關係。

4、通俗的說就是系統裏面導入 slf4j 和 logback 的 jar 包之後,記錄日誌時應該調用的是 slf4j 的API 而不是 logback,官方 "Hello Wolrd" 例子代碼如下:
 

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");
  }
}

5、每一個日誌的實現框架都有自己的配置文件,使用 slf4j 日誌門面以後,配置文件還是要用日誌實現框架自己本身的配置文件,如果使用的是 logback 實現,同理也要用 logback 的配置文件。

slf4j 與實現框架圖總覽

 

1、第一列“SLF4J unbound”:意思是如果應用中只導入“slf4j-api.jar日誌門面”,沒有導入slf4j實現時,則所有調用日誌記錄的方法都會無效,即不會有記錄

2、第二列“SLF4J bound to logback-classic”:意思是如果導入了“slf4j-api.jar日誌門面”及實現“logback-classic”的jar包,則調用SLF4J之後底層會以logback進行記錄

3、第三列“SLF4J bound to log4j”:意思是導入了“slf4j-api.jar日誌門面”及實現“log4j.jar”包之後,中間還要導入一個適配包“slf4j-log412.jar”,所以當應用中調用SLF4J記錄日誌的時候,會先經過適配包,最後調用實現包

4、因爲 log4j 使用的時間很久了,之前並沒有考慮到後來的星星之火 slf4j 可以燎原,所以導致現在使用時需要藉助適配包。而logback 本身就是專門爲 slf4 寫的實現包,所以不需要任何適配 。後面的 JUL 也是同理,不再累述。

slf4j 與 logback 入門

 

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

slf4j 與 log4j 入門

添加 Maven 依賴

1、在應用中的 pom.xml 中導入依賴

2、所有的依賴配置都可以從 Maven 中央倉庫中找到:“https://mvnrepository.com/”

    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.25</version>
    </dependency>
 
    <!--https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.25</version>
    </dependency>
  </dependencies>

添加配置文件

#指定輸出信息的級別--以及輸出的位置
log4j.rootLogger=DEBUG,console,logFile
#表示Logger不會在父Logger的appender裏輸出,默認爲true
log4j.additivity.org.apache=true
 
#控制檯
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout.ConversionPattern=%5p [%t] (%c:%L) %d{yyyy-MM-dd HH:mm:ss,SSS} ---- %m%n
 
#日誌文件
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=E:/logs_wmx/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n

日誌記錄

package www.wmx.com;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
 * Hello world!
 */
public class App {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(App.class);
        logger.info("Hello World");
        logger.warn("嚴重警告.....");
    }
}

控制檯輸出如下:

 INFO [main] (www.wmx.com.App:12) 2018-07-14 13:40:28,643 ---- Hello World
 WARN [main] (www.wmx.com.App:13) 2018-07-14 13:40:28,646 ---- 嚴重警告.....
 
Process finished with exit code 0

Springboot使用logback

SpringBoot底層默認使用slf4j+logback的方式進行日誌記錄 ,這裏簡單介紹一下logback的使用。

logbac日誌級別從低到高分別爲TRACE, DEBUG, INFO, WARN, ERROR

我們一般是在類路徑下建立一個logback.xml,也可命名爲(logback-spring.xml , logback-spring.groovy , logback.xml ,logback.groovy)

<?xml version="1.0" encoding="UTF-8"?>
<configuration  scan="true" scanPeriod="60 seconds" debug="false">
    <contextName>spring-boot-logging</contextName>
    <property name="log.path" value="log" />
    <!--輸出到控制檯-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 級別過濾 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </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">
        <file>${log.path}/spring-boot-logging.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
            <!-- 日誌保存週期 -->
            <maxHistory>30</maxHistory>
            <!-- 總大小 -->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <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.baiding"/>

</configuration>

1.根節點包含的屬性

<configuration></configuration>
  • scan:當此屬性設置爲true時,配置文件如果發生改變,將會被重新加載,默認值爲true
  • scanPeriod:設置監測配置文件是否有修改的時間間隔,如果沒有給出時間單位,默認單位是毫秒。當scan爲true時,此屬性生效。默認的時間間隔爲1分鐘
  • debug:當此屬性設置爲true時,將打印出logback內部日誌信息,實時查看logback運行狀態。默認值爲false

2. 設置上下文名稱

<contextName>spring-boot-logging</contextName>

每個logger都關聯到logger上下文,默認上下文名稱爲“default”。但可以使用設置成其他名字,用於區分不同應用程序的記錄。一旦設置,不能修改,可以通過%contextName來打印日誌上下文名稱。

3.設置變量
用來定義變量值的標籤, 有兩個屬性,name和value;其中name的值是變量的名稱,value的值時變量定義的值。通過定義的值會被插入到logger上下文中。定義變量後,可以使“${}”來使用變量

<property name="log.path" value="log" />

####4.子節點appender

appender用來格式化日誌輸出節點,有倆個屬性name和class,class用來指定哪種輸出策略,常用就是控制檯輸出策略和文件輸出策略。

控制檯輸出ConsoleAppender

<!--輸出到控制檯-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <!-- 級別過濾 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>ERROR</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

filter是一個過濾器,表示對輸出到控制檯的日記進行過濾。有兩種過濾器,分別爲LevelFilter 和ThresholdFilter。執行一個過濾器會有返回個枚舉值,即DENY,NEUTRAL,ACCEPT其中之一。返回DENY,日誌將立即被拋棄不再經過其他過濾器;返回NEUTRAL,有序列表裏的下個過濾器接着處理日誌;返回ACCEPT,日誌會被立即處理,不再經過剩餘過濾器。

其中LevelFilter 爲級別過濾器,根據日誌級別進行過濾。其下有三個子節點,level表示過濾的級別,用於配置符合過濾條件的操作,ACCEPT符合級別的輸出到控制檯,用於配置不符合過濾條件的操作,DENY不符合的拒絕輸出到控制檯。

ThresholdFilter爲臨界值過濾器,過濾掉低於指定臨界值的日誌。當日志級別等於或高於臨界值時,過濾器返回NEUTRAL;當日志級別低於臨界值時,日誌會被拒絕。

表示對日誌進行格式化

%d{HH:mm:ss.SSS} :日誌的輸出時間
%contextName : 上下文名稱
%thread : 輸出日誌的進程名字,這在Web應用以及異步任務處理中很有用
%-5level : 日誌級別,並且使用5個字符靠左對齊
%logger{36} : 日誌輸出者的名字(一般爲類名),名字最長36個字符,否則按照句點分割
%msg : 具體的日誌消息
%n :換行符


輸出到文件RollingFileAppender

<!--輸出到文件-->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/spring-boot-logging.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
            <!-- 日誌保存週期 -->
            <maxHistory>30</maxHistory>
            <!-- 總大小 -->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

常見的日誌輸出到文件,隨着應用的運行時間越來越長,日誌也會增長的越來越多,將他們輸出到同一個文件並非一個好辦法。RollingFileAppender用於切分文件日誌。

其中file屬性定義文件的帶全路徑的文件名,重要的是rollingPolicy的定義。

class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"是最常用的滾動策略,它根據時間來制定滾動策略,既負責滾動也負責觸發滾動

<fileNamePattern>${log.path}/spring-boot-logging.%d{yyyy-MMdd}.log.zip</fileNamePattern>定義了日誌的切分方式——把每一天的日誌歸檔到一個文件中,同理,可以使用%d{yyyy-MM-dd HH-mm}來定義精確到分的日誌切分方式。

<maxHistory>30</maxHistory>表示只保留最近30天的日誌

<totalSizeCap>1GB</totalSizeCap>用來指定日誌文件的上限大小,例如設置爲1GB的話,那麼到了這個值,就會刪除舊的日誌

####5. 子節點root

<root level="info">
    <appender-ref ref="console" />
    <appender-ref ref="file" />
</root>

root節點是必選節點,用來指定最基礎的日誌輸出級別,只有一個level屬性,默認是DEBUG。

其中可以包含零個或多個元素,表示我們定義的appender將會添加到我們定義的loger子節點中。

6. 子節點loger
<loger>用來設置某一個包或者具體的某一個類的日誌打印級別、以及指定<appender>

<loger>僅有一個name屬性,一個可選的level和一個可選的addtivity屬性

name:用來指定受此loger約束的某一個包或者具體的某一個類。
level:用來設置打印級別,如果未設置此屬性,那麼當前loger將會繼承上級的級別。
addtivity:是否向上級loger傳遞打印信息。默認是true。
<loger> 的實際使用有兩種情況

第一種是不指定level,不指定appender

<root level="info">
    <appender-ref ref="console" />
    <appender-ref ref="file" />
</root>
<logger name="com.baiding.logging.SpringBootLoggingApplicationTests"/>

此logger指定了level爲warn,addtivity爲false,不在向上級傳遞打印信息,若設置了<appender-ref>屬性,但沒有設置addtivity爲false,則com.baiding包下的日誌會先在名爲console的appender記錄一次,之後傳遞給上級,root又會在名爲console和file的appender記錄一次,這樣就打印了兩次了。

Spring Boot在使用logback記錄日誌時,推薦使用logback-spring.xml的格式,這樣的話,日誌框架就不直接加載日誌的配置項,而是由SpringBoot解析日誌配置,就可以使用SpringBoot 的高級Profile功能

如下logback-spring.xml

<springProfile name="dev">
    <logger name="com.baiding" level="info"/>
</springProfile>

<springProfile name="prod">
    <logger name="com.baiding" level="warn"/>
</springProfile>

可以在不同的節點中使用springProfile功能,用於指定某段配置只在某個環境下生效 。當然使用前,要激活profile。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章