SpringBoot——logging


根據 SpringBoot v2.2.1.RELEASE 的官方文檔

日誌

日誌框架包括兩種:

  • 日誌門面——日誌的一個抽象層
  • 日誌的實現
日誌的抽象層 日誌的實現
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-logging Log4j 、JUL(java.util.logging) Log4j2 Logback

在使用時應該從左邊選取一個抽象層,右邊選取一個實現框架。

SpringBoot使用 Commons Logging 作爲內部日誌記錄,但保留了底層的日誌實現。提供了對於java util loggingLog4j2Logback的默認配置。logger都預先配置爲使用控制檯輸出,但可以選擇使用文件輸出。

默認情況下,使用Logback 進行日誌記錄。

1、日誌格式

SpringBoot的默認日誌輸出類似於:

2020-03-04 13:52:20.301  INFO 7169 --- [           main] s.Springboot01HelloworldApplicationTests : No active profile set, falling back to default profiles: default
2020-03-04 13:52:21.097  INFO 7169 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-03-04 13:52:21.312  INFO 7169 --- [           main] s.Springboot01HelloworldApplicationTests : Started Springboot01HelloworldApplicationTests in 1.317 seconds (JVM running for 2.174)

輸出以下項:

  • 日期和時間:精度爲毫秒,易於排序
  • 日誌級別: ERROR, WARN, INFO, DEBUG, or TRACE
  • 進程ID
  • --- 標誌日誌信息的開始
  • 線程名稱:用方括號擴起來(在控制檯輸出時可以會被截斷)
  • 記錄器名稱:通常是類名(通常縮寫)
  • 日誌消息

Logback沒有 FATAL 級別,歸於了 ERROR

2、控制檯輸出

默認情況下,日誌會輸出到控制檯上。默認ERRORWRANINFO 級別的日誌會被記錄。能夠通過--dubug來啓動應用程序開啓“debug”模式。

$ java -jar myapp.jar --debug

也能夠在 application.properties 中指定debug=true

開啓“debug”模式後,一些核心的logger(內置的容器, Hibernate, 並且 Spring Boot)會被配置來輸出更多的信息。啓用 debug 模式不會將應用程序配置爲以debug級別記錄所有消息。

當然也可以通過同樣的方式開啓 trace 模式。

2.1 彩色輸出

如果你的 terminal 支持 ANSI ,彩色輸出能夠提高可讀性。可以通過設置 spring.output.ansi.enabled支持的值 來改變默認的自動檢測(detect)。

通過使用 %clr 轉化字符來配置彩色編碼。如下示例:

%clr(%5p)
Level Color
FATAL Red
ERROR Red
WARN Yellow
INFO Green
DEBUG Green
TRACE Green

另外,你可以通過將顏色或樣式作爲轉換選項來指定應該使用的顏色或樣式。在下面的例子中,會使文本變成黃色:

%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}

支持的顏色和樣式:

  • blue
  • cyan
  • faint
  • green
  • magenta
  • red
  • yellow

3、文件輸出

SpringBoot的日誌默認只會輸出在控制檯中,如果想要記錄日誌到文件中,需要設置logging.file.namelogging.file.path 屬性(可以在application.properties文件)。

下面的表格顯示了 logging.* 如果配合使用:

logging.file.name logging.file.path Example Description
(無) (無) 僅僅在控制檯輸出
Specific file (無) my.log 寫入指定的目錄文件。名稱可以是絕對位置或相對位置
(無) Specific directory /var/log spring.log文件寫入 指定的目錄。名稱可以是絕對位置或相對位置

當日志文件達到10 MB時,就會循環保存(意味着1個文件的大小隻能是10MB,達到後就會換一個文件存放),並且與控制檯輸出一樣,默認情況下會記錄 ERROR/WRAN/INFO 日誌 。

可以通過 logging.file.max-size 屬性改變文件大小限制。

除非 logging.file.max-history 已經被設置,否則默認情況下保存最近7天的循環日誌文件。

日誌檔案的總大小能夠通過 logging.file.total-size-cap 設置上限,當總大小超過該閥值,就會刪除備份。

要在應用程序啓動時強制清除日誌存檔,需要使用 logging.file.clean-history-on-start 屬性。

每一個日誌的實現框架都有自己的配置文件。不論使用哪個日誌接口框架,配置文件還是做成日誌實現框架自己本身的配置文件;

4、日誌級別

日誌的輸出級別可以在Spring Environment 配置(例如:application.properties ,環境變量)。

配置方法:

  • logging.level.<logger-name>=<level> ,其中的level 可選爲:TRACEDEBUGINFOWRANERRORFATALOFF

    #root的logger能夠通過 `loggin.level.root` 配置
    logging.level.root=warn	
    logging.level.org.springframework.web=debug
    logging.level.org.hibernate=error
    logging.level.com.springboot=trace
    
  • 環境變量配置:LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG 將設置org.springframework.web 的輸出爲DEBUG 級別。

5、日誌分組

能夠把相關的logger放到一個組統一管理。

例如,定一個“tomcat”組:

logging.group.tomcat=org.apache.catalina, org.apache.coyote, org.apache.tomcat

統一管理“tomcat”組中的所有logger:

logging.level.tomcat=TRACE

SpringBoot包含了一些預定義的日誌記錄組,它們可以直接使用:

Name Loggers
web org.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans
sql org.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener

6、自定義log配置

springBoot的自動配置會檢測類路徑的類庫來自動激活相應的日誌系統,可以提供一個合適的配置來進一步的自定義配置。這個配置應該在 classpath 的根目錄或者被屬性logging.config 指定的目錄。

你可以使用 org.springframework.boot.logging.LoggingSystem 系統屬性來強制Spring boot使用一個特指的日誌系統。這個值應該是日誌系統具體實現的全限定類名。你也可以將這個值設置爲none,表示完全關閉日誌配置。

因爲loggin是在 ApplicationContext 創建之前初始化的,所以不能在 @Configuration 配置的文件中控制日誌。自定義日誌系統或者關閉它的唯一方式是通過系統屬性(system properties)。

依賴於你的日誌系統,以下的文件會被加載:

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

官方推薦我們使用 -spring 變體作爲日誌的配置名(例如:使用logback-spring.xml而不是logback.xml)->原因:可以使用 logback 的擴展功能,詳見7。如果你使用標準的配置位置,Spring將不能完全控制日誌的初始化。

爲了方便自定義log配置,以下是Spring Environment 轉爲系統屬性(System properties)的一些屬性:

Spring Environment 系統屬性 註釋
logging.exception-conversion-word LOG_EXCEPTION_CONVERSION_WORD 記錄異常時使用的轉換字。
logging.file.clean-history-on-start LOG_FILE_CLEAN_HISTORY_ON_START 是否在啓動時清除存檔日誌文件(如果啓用了LOG_FILE)。(僅默認登錄設置支持。)
logging.file.name LOG_FILE 如果定義,它將在默認日誌配置中使用。
logging.file.max-size LOG_FILE_MAX_SIZE 日誌文件的最大大小(如果啓用了LOG_FILE)。(僅默認登錄設置支持。)
logging.file.max-history LOG_FILE_MAX_HISTORY 要保留的最大歸檔日誌文件數(如果啓用了LOG_FILE)。(僅默認登錄設置支持。)
logging.file.path LOG_PATH 如果定義,它將在默認日誌配置中使用。
logging.file.total-size-cap LOG_FILE_TOTAL_SIZE_CAP 要保留的日誌備份的總大小(如果啓用了LOG_FILE)。(僅默認登錄設置支持。)
logging.pattern.console CONSOLE_LOG_PATTERN 控制檯上要使用的日誌模式(stdout)。(僅默認登錄設置支持。)
logging.pattern.dateformat LOG_DATEFORMAT_PATTERN 記錄日期格式的附加模式。(僅默認登錄設置支持。)
logging.pattern.file FILE_LOG_PATTERN 文件中使用的日誌模式(如果LOG_FILE已啓用)。(僅默認登錄設置支持。)
logging.pattern.level LOG_LEVEL_PATTERN 呈現日誌級別時使用的格式(默認%5p)。(僅默認登錄設置支持。)
logging.pattern.rolling-file-name ROLLING_FILE_NAME_PATTERN 過渡日誌文件名的模式(默認${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz)。(僅默認登錄設置支持。)
PID PID 當前進程ID(如果可能,並且尚未將其定義爲OS環境變量,則發現)。

當解析配置文件時,所有支持的日誌系統都能夠查詢系統屬性。可以看看spring-boot.jar中的配置樣例:

如果你想要在一個日誌屬性中使用佔位符,應該使用Spring Boot 的語法而不是日誌框架的語法。特別地,如果使用Logback ,你應該使用 : 作爲屬性名和默認值的分隔符,而不是使用 -

7、Logback擴展

SpringBoot包含了許多對 Logback 日誌框架的擴展,可以幫助我們進行高級的配置。需要注意的是這些擴展功能只能在 logback-spring.xml 配置文件中使用。

因爲 logback.xml 配置文件加載時間過早,所以不能在其中使用擴展功能。只能在 logback-spring.xml 中使用或者定義 logging.config 屬性。

這些擴展不能和Logbackconfiguration scanning 一起使用。

7.1 Profile配置

使用 <springProfile> 標籤,你可以根據需要不同的環境需要包括或排除某些配置。

使用 name 屬性指定使用哪個配置文件。name 屬性可以是一個簡單的profile名稱,也可以是複雜的表達式。如下例:

<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev | staging">
    <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="!production">
    <!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>

7.2 Environment屬性

<springProperty> 標籤讓你可以將Spring environment 中的屬性暴露給 Logback 使用。如果你想要在Logback 的配置中訪問 application.properties 文件中的值,這是十分方便的。

該標籤的工作方式與 Logback 的標準標籤 <property> 類似。不同的是,你不需要指定一個直接的 value ,只需要指定 source 屬性(這個屬性來自於Environment)。

如果你需要將屬性存儲在 local 範圍以外的地方,可以使用 scope 屬性。

如果需要一個默認值(以防該屬性沒有在 environment 中設置),可以使用 defaultValue 屬性。

下面的例子顯示瞭如何在 Logback 中使用這些屬性:

<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
        defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
    <remoteHost>${fluentHost}</remoteHost>
    ...
</appender>

source 必須以短橫線命名的方式指定(例如:my.property-name)。雖然屬性可能是以鬆散規則添加到 Environment

8、SLF4j的使用

8.1 如何在系統中使用SLF4j

官方文檔

在開發的時候,日誌記錄方法的調用,不應該來直接調用日誌的實現類,而是調用日誌抽象層裏面的方法

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

在這裏插入圖片描述

如上圖所示,如果要使用 logback 作爲日誌實現類,需要導入slf4-api.jarlogback-classic.jarlogback-core.jar 。如果需要使用 log4j 作爲日誌實現類,需要導入slf4-api.jarlog4j.jar 和一個適配器slf4j-log412.jar 。其餘類似。

每一個日誌的實現框架都有自己的配置文件。使用slf4j以後,配置文件還是做成日誌實現框架自己本身的配置文件;

8.2 其餘問題

框架都有着默認的日誌使用框架,比如Hibernate默認使用jboss-logging作爲日誌抽象層,那如果現在在項目中統一都要使用 SLF4jlogback ,該如何呢?

在這裏插入圖片描述

如上圖所示,如果使用Commons logging Api 的框架要改成使用SLF4j作爲日誌抽象層,則需要:

  1. 移除commons-logging 的jar包
  2. 導入中間包 jcl-cover-slf4j.jar (該包和commons-logging 包的類名、方法全部一樣,只是實現不同)
  3. 導入slf4-api.jarlogback-classic.jarlogback-core.jar

9、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="/Users/yanjundong/Desktop/log" />
    <!-- 定義日誌文件名稱 -->
    <property name="appName" value="atguigu-springboot"></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> 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章