Spring中如何優雅地配置日誌

背景

spring對logback提供了良好的支持,大部分情況下,不需要自定義logback配置文件 而很多項目對logback在spring中的使用,很多都做了不必要的定製:

  1. 通過logback.xml自定義配置:這種方式繞過了spring的生命週期管理,對熱部署、失去了通過spring參數在線調節日誌級別等能力;
  2. 通過logback-spring.xml自定義配置,但並未繼承或參考spring的配置,這種方式雖然日誌的生命週期被spring所管理,但是仍然失去了部分動態修改日誌配置的能力

儘量使用spring屬性

spring通過屬性配置,提供了靈活的配置功能,來支撐我們做詳細的配置。 spring配置已經爲我們提供了以下諸多能力:

指定日誌文件

spring可以通過屬性logging.file.namelogging.file.path來配置日誌文件或路徑。 由於開發、測試環境的差別,往往本地調試時,並不需要也不推薦配置日誌文件 當服務部署到服務器上時,有三種方式,可以指定日誌文件路徑:

方式一:通過特定profile的配置文件指定日誌文件路徑

比如通過application-docker.properties,指定在docker中部署時的日誌路徑:

logging.file.name=logs/${spring.application.name}.log

方式二:通過啓動參數指定日誌路徑

java -jar -Dlogging.file.name=logs/app.log app.jar

方式三:通過環境變量指定日誌路徑

如果使用tomcat,可以通過bin/setenv.sh文件指定環境變量

JAVA_OPTS="${JAVA_OPTS} -Dlogging.file=logs/sso.log"

參考:features.html#features.logging.file-output

指定日誌級別

可以通過spring的屬性機制,指定特定包的日誌級別

# 指定全局日誌級別爲警告
logging.level.root=warn
# 指定 org.springframework.web 包的日誌級別爲調試
logging.level.org.springframework.web=debug
# 指定 org.hibernate 包的日誌級別爲錯誤
logging.level.org.hibernate=error

使用分組批量指定日誌級別

spring支持將數個包組合成一個日誌組,然後按組指定日誌級別

# 定義名爲tomcat的日誌組
logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
# 定義tomcat日誌組的日誌級別爲調試
logging.level.tomcat=debug

spring已經內置了兩個日誌組,用來快速開放web日誌和sql日誌 | Name | Loggers| | ----------- | ----------- | |web| org.springframework.core.codec,<br>org.springframework.http,<br>org.springframework.web,<br>org.springframework.boot.actuate.endpoint.web,<br>org.springframework.boot.web.servlet.ServletContextInitializerBeans| |sql|org.springframework.jdbc.core,org.hibernate.SQL,<br>org.jooq.tools.LoggerListener|

指定其它屬性

spring-boot也提供了更多屬性,來定製logback日誌配置,如:

使用好logback-spring.xml

絕大部分情況下,在spring-boot工程中,通過屬性就能完成日誌的個性化配置。

當屬性配置不夠用時,可以通過logback-spring.xml文件來擴展logback配置,但是要注意繼承spring本身的日誌配置,保持靈活配置的能力

下面我們以使用logstash採集日誌爲例,一起看看如何使用logback-spring.xml擴展日誌

引入base.xml文件

要繼承spring-boot的日誌配置能力,首先要在自己的logback-spring.xml中引入spring日誌基礎配置

<!-- logback-spring.xml -->
<include resource="org/springframework/boot/logging/logback/base.xml"/>

使用spring屬性

在logback-spring.xml中可以使用Spring屬性,從而繼承了spring的配置,並保留通過spring配置機制來擴展自定義日誌的

<!-- logback-spring.xml -->
    <springProperty scope="context" name="LOGSTASH_DEST" source="logging.logstash.destination" defaultValue=""/>
    <springProperty scope="context" name="PROJECT_NAME" source="spring.application.name" defaultValue="my_app"/>
    <if condition='!property("LOGSTASH_DEST").isEmpty()'>
        <then>
            <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
                <!-- logstash服務地址 -->
                <destination>${LOGSTASH_DEST}</destination>
                <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
                    <!-- 日誌自定義字段,隨日誌內容一起進行存儲,方便在日誌查看端kibana中按此字段進行檢索 -->
                    <customFields>{"projectName":"${PROJECT_NAME}"}</customFields>
                </encoder>
            </appender>
        </then>
    </if>

以上spring.application.name屬性,爲spring標準屬性 而logging.logstash.destination則爲自定義屬性,我們可以通過spring配置機制覆蓋其值,從而提供了配置logstash服務地址的能力。

使用條件判斷

上述示例中,在logback配置中使用了條件判斷,需要在pom.xml中添加額外的依賴

<!-- pom.xml -->
<dependency>
  <groupId>org.codehaus.janino</groupId>
  <artifactId>janino</artifactId>
</dependency>

添加依賴後,就可以在logback-spring.xml中使用條件判斷

<!-- logback-spring.xml -->
<root level="INFO">
  <appender-ref ref="CONSOLE"/>
  <appender-ref ref="FILE"/>
  <if condition='!property("LOGSTASH_DEST").isEmpty()'>
    <then>
      <appender-ref ref="LOGSTASH"/>
    </then>
  </if>
</root>

將日誌發送給logstash

爲了將日誌發送給logstash,還需要添加額外的依賴

<!-- pom.xml -->
<dependency>
  <groupId>net.logstash.logback</groupId>
  <artifactId>logstash-logback-encoder</artifactId>
  <version>5.2</version>
</dependency>

完成所有上述配置後,在屬性中配置logging.logstash.destination=[ip:port]即可實現日誌發送到logstash中

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