springboot系列文章之日誌配置

前言

下面的總結基本上來自網絡與官方文檔,這裏做一個記錄,方便以後查看

SpringBoot 內部採用的是 Commons Logging進行日誌記錄,但是默認配置也提供了對常用日誌的支持,如: Java Util LoggingLog4j,Log4j2Logback。每種Logger 都可以通過配置使用控制檯或者文件輸出日誌內容。

slf4j

Simple Logging Facade For Java ,它是一個針對於各類Java日誌框架的統一 Facade抽象。Java日誌框架衆多————常用的有Java Util LoggingLog4j,Log4j2Logback,Spring框架使用的是 Jakarta Commons Logging API(JCL)。而 slf4j定義了統一的日誌抽象接口,而真正的日誌實現則是在運行時決定的–它提供了各類日誌框架的binding

Logback

Logback是log4j框架的作者開發的新一代日誌框架,它效率更高,能夠適應諸多的運行環境,同時天然支持 slf4j

默認情況下SpringBoot的日誌框架是 logback,在建立SpringBoot項目時自動導入的 spring-boot-starter 依賴包含了 spring-boot-starter-logging,該依賴內容就是 Spring Boot默認的日誌框架。

日誌格式

默認的日誌輸出如下:

2018-09-05 16:49:46.985  INFO 17416 --- [           main] com.pjmike.logger.LoggerApplication      : Started LoggerApplication in 7.555 seconds (JVM running for 8.677)

輸出內容元素具體如下:
- 時間日期 —— 精確到毫秒
- 日誌級別 —— ERROR,WARN,INFO,DEBUG,TRACE
- 進程ID
- 分割符 —— --- 標識實際日誌的開始
- 線程名 —— 方括號括起來(可能會截斷控制檯輸出)
- Logger名 —— 通常使用源代碼的類名
- 日誌內容

注 Logback沒有FATAL級別,它會映射到ERROR

日誌輸出

SpringBoot 默認爲我們輸出的日誌級別爲 INFO,WARN,ERROR。如需要輸出更多日誌的時候,可以通過以下方法開啓
- 命令模式配置: java -jar app.jar --debug=true,這種命令會被 SpringBoot解析,且優先級最高。
- 資源文件配置: application.properties 配置 debug=true即可。該配置只對嵌入式容器,Spring,Hibernate生效,我們自己的項目想要輸出 DEBUG需要額外配置(配置規則:logging.level.<logger-name>=<level>)

日誌輸出級別配置

logging.level.root = WARN
logging.level.org.springframework.web = DEBUG
logging.level.org.hibernate = ERROR

# 比如 mybatis sql日誌
loggging.level.org.mybatis = DEBUG
logging.level.com.pjmike.mybatis.dao = DEBUG

日誌輸出格式配置

  • logging.pattern.console: 定義輸出到控制檯的格式(不支持 JDK Logger)
  • logging.pattern.file:定義輸出到文件的格式(不支持 JDK Logger)

顏色編碼

如果終端支持 ANSI,默認情況下會給日誌上個色,提高可讀性,可以在配置文件中設置spring.output.ansi.enabled 來改變默認值:
- ALWAYS:啓用 ANSI顏色的輸出
- DETECT: 嘗試檢測 ANSI 着色功能是否可用
- NEVER: 禁用 ANSI 顏色的輸出

編碼對照表

Level Color
WARN Yellow
FATAL,ERROR red
INFO,DEBUG,TRACE Green

文件輸出

默認情況下,SpringBoot僅將日誌輸出到控制檯,不會寫入到日誌文件中,如果除了控制檯輸出之外還想寫日誌文件,則需要在 application.properties 設置 loggging.filelogging.path屬性。
- logging.file: 將日誌寫入到指定的文件中,默認爲相對路徑。可以設置成絕對路徑

logging.file = spring-logger.log
  • logging.path: 將名爲 spring.log寫入到指定的文件夾中,如(/var/log)

一般情況下設置其中一個屬性就足夠了。

日誌文件在達到 10MB時進行分割,產生一個新的日誌文件(如: spring.1.log,spring.2.log)。新的日誌依舊輸出到 spring.log中去,默認情況下會記錄 ERROR,WARN,INFO級別消息
- logging.file.max-size: 限制日誌文件的大小
- logging.file.max-history: 限制日誌保留天數

自定義日誌配置

在官網中有如下一段描述:

Since logging is initialized before the ApplicationContext is created, it is not possible to control logging from @PropertySources in Spring @Configuration files. The only way to change the logging system or disable it entirely is via System properties.

由於創建 ApplicationContext 之前就已經初始化日誌記錄了,因此無法在Spring @Configuration文件中控制來自@PropertySources的日誌記錄。它並不是必須通過 Spring 的配置文件控制,因此通過系統屬性 logging.config和傳統的Spring Boot外部配置文件依然可以很好的支持日誌控制和管理。

根據不同的日誌系統,你可以按如下規則組織配置文件名,就能被正確加載:
- Logback: logback-spring.xml,logback-spring.groovy,logback.xml,logback.groovy
- Log4j: log4j-spring.properties,log4j-spring.xml,log4j.properties,log4j.xml
- Log4j2: log4j2-spring.xml,log4j2.xml
- JDK(Java Util Logging): logging.properties

SpringBoot官方推薦優先使用帶有 -spring的文件名爲你的日誌配置 (比如使用 logback-spring.xml,而不是 logback.xmllogback.xml配置加載過早,比application.properties還早,不適合進行擴展)

Logback配置

SpringBoot 默認的日誌框架是 logback,下面我們來一個簡單的 logback-spring.xml的例子:

<?xml version="1.0" encoding="UTF-8"?>
<configuration  scan="true" scanPeriod="60 seconds" debug="false">
    <contextName>logback</contextName>
    <!--輸出到控制檯-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <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>logback.%d{yyyy-MM-dd}.log</fileNamePattern>
        </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>
</configuration>

根節點 <configuration>包含的屬性:
- scan: 當此屬性設置爲 true時,配置文件如果發生改變,將會被重新加載,默認值爲 true
- scanPeriod: 設置監測配置文件是否有修改的時間間隔,如果沒
- debug: 當屬性設置爲true時,將打印出 logback內部日誌信息,實時查看 logback運行狀態,默認值爲 false.

根節點<configuration>:下面的兩個屬性,三個子節點

  • 屬性一:設置上下文名稱 <contextName>
    每個logger都關聯到logger上下文,默認上下文名稱爲“default”。但可以使用設置成其他名字,用於區分不同應用程序的記錄。一旦設置,不能修改,可以通過%contextName來打印日誌上下文名稱
<contextName>logback</contextName>
  • 屬性二: 設置變量<property>
    用來定義變量值的標籤, 有兩個屬性,name和value;其中name的值是變量的名稱,value的值時變量定義的值。通過定義的值會被插入到logger上下文中。定義變量後,可以使“${}”來使用變量
<property name="log.path" value="/Documents/log" />
  • 子節點 <appender>

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


控制檯輸出 ConsoleAppender:
<!--輸出到控制檯-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <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>
``表示對日誌進行編碼: - %d{HH: mm:ss.SSS}——日誌輸出時間 - %thread——輸出日誌的進程名字,這在Web應用以及異步任務處理中很有用 - %-5level——日誌級別,並且使用5個字符靠左對齊 - %logger{36}——日誌輸出者的名字 - %msg——日誌消息 - %n——平臺的換行符 `ThresholdFilter`爲系統定義的攔截器,例如我們用 `ThresholdFilter`來過濾 ERROR 級別以下的日誌不輸出到文件中。如果不用記得註釋掉,不然你控制檯發現沒日誌 **輸出到文件 RollingFileAppender**: 另一種常見的日誌輸出到文件,隨着應用的運行時間越來越長,日誌也會增長的越來越多,將他們輸出到同一個文件並非一個好辦法. `RolliingFileAppender`用於切分文件日誌:
    <!--輸出到文件-->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logback.%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
其中重要的是rollingPolicy的定義,上例中logback.%d{yyyy-MM-dd}.log定義了日誌的切分方式——把每一天的日誌歸檔到一個文件中,30表示只保留最近30天的日誌,以防止日誌填滿整個磁盤空間。同理,可以使用%d{yyyy-MM-dd_HH-mm}來定義精確到分的日誌切分方式。1GB用來指定日誌文件的上限大小,例如設置爲1GB的話,那麼到了這個值,就會刪除舊的日誌
  • 子節點二<root>

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


level:用來設置打印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能設置爲INHERITED或者同義詞NULL。
默認是DEBUG。 可以包含零個或多個元素,標識這個appender將會添加到這個logger。
<root level="debug">
    <appender-ref ref="console" />
    <appender-ref ref="file" />
</root>
  • 子節點三 <logger>

用來設置某一個包或者具體的某一個類的日誌打印級別,以及指定。僅有一個name屬性,一個可選的level和一個可選的 addtivity屬性

  • name: 用來指定受此 logger 約束的某一個包或者具體的某一個類
  • level: 用來設置打印級別,大小寫無關: TRACE,DEBUG,INFO,WARN,ERROR,ALL和OFF。,還有一個特俗值INHERITED或者同義詞NULL,代表強制執行上級的級別。如果未設置此屬性,那麼當前logger將會繼承上級的級別。(這裏的上級就是上面提到的 root)
  • additivity: 是否向上級logger傳遞打印信息,默認爲true。

logger在實際使用的時候有兩種情況

  1. 在代碼中使用:
@RestController
public class HelloController {
    private Logger logger = LoggerFactory.getLogger(HelloController.class);
    @RequestMapping("/index")
    public String index() {
        logger.trace("日誌輸出 trace");
        logger.debug("日誌輸出 debug");
        logger.info("日誌輸出 info");
        logger.warn("日誌輸出 warn");
        logger.error("日誌輸出 error");
        return "index";
    }
}
  1. 在xml文件中使用,例子如下:
<logger name="com.pjmike.controller.HelloController" level="WARN" additivity="false">
    <appender-ref ref="console"/>
</logger>

多環境日誌輸出

有時候我們需要在不同的環境(prod:生產環境,test: 測試環境,dev: 開發環境)來定義不同的日誌輸出,這類情況一般有兩種做法:
- 第一種就是爲每一種環境都創建一個對應日誌配置文件,然後再其對應環境的application.properties指定 logging.cofig屬性
- 第二種就是使用擴展屬性 springProfilespringProperty

springProfile

<springProfile>標籤使我們讓配置文件更加靈活,它可以選擇性的包含或排除部分配置

<!--注意以下這種情況必須配置spring.profiles.active屬性-->
<springProfile name="dev">
    <!-- 開發環境時激活 -->
</springProfile>

<springProfile name="dev,test">
    <!-- 開發,測試的時候激活-->
</springProfile>

<springProfile name="!prod">
    <!-- 當 "生產" 環境時,該配置不激活-->
</springProfile>

例子

<springProfile name="dev">
        <!--開發環境時激活-->
        <root level="debug">
            <appender-ref ref="console"/>
        </root>
</springProfile>
<springProfile name="test">
        <root level="info">
            <appender-ref ref="file"/>
            <appender-ref ref="console"/>
        </root>
</springProfile>

springProperty

<springProperty>標籤可以讓我們在 Logback中使用 Spring Environment中的屬性。如果想在 logback-spring.xml中回讀 application.properties配置的值時,這是一個非常好的解決方案

<!-- 讀取 spring.application.name 屬性來生成日誌文件名
    scope:作用域
    name:在 logback-spring.xml 使用的鍵
    source:application.properties 文件中的鍵
    defaultValue:默認值
 -->
<springProperty scope="context" name="logName" source="spring.application.name" defaultValue="myapp.log"/>

<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/${logName}.log</file>
</appender>

小結

以上總結也參考了一些大佬的教程,關於日誌配置更多的細節可以參閱 官方文檔: https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/htmlsingle/#boot-features-custom-log-configuration

PS: 有時候我們會覺得在每個類中寫Logger會很繁瑣,這裏推薦一款插件叫做 Lombok ,它裏面有一個註解 @Slf4j 能夠實現Logger的功能,非常好用,關於Lombok的詳細介紹參照文章: http://t.cn/RS0UdrX

參考資料 & 鳴謝

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