日志是應用程序不可或缺的組成部分,它不僅能幫助我們調試問題,還能監控系統運行狀態。在 Spring Boot 生態中,Logback 憑借其高性能和靈活性成為首選的日志框架。本文將通過一個實際的 Logback 配置文件,詳細解析其各個組件的功能和配置技巧。
什么是 Logback?
Logback 是由 Log4j 創始人設計的開源日志組件,是 Log4j 的繼任者。它分為三個模塊:
- logback-core:核心組件,提供基礎功能
- logback-classic:實現了 SLF4J API,可直接替換 Log4j
- logback-access:與 Servlet 容器集成,提供 HTTP 訪問日志功能
在 Spring Boot 中,Logback 是默認的日志框架,無需額外依賴即可使用。
完整配置文件解析
<?xml version="1.0" encoding="UTF-8"?>
<!--Copyright 2010-2011 The myBatis TeamLicensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.
-->
<configuration debug="false"><!--定義日志文件的存儲地址 勿在 LogBack 的配置中使用相對路徑--><springProperty scope="context" name="LOG_HOME" source="HuiChen.log.directory"/><springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="huichen-device-sms-manager"/><springProperty scope="context" name="LOG_LEVEL" source="HuiChen.log.level" defaultValue="debug"/><!-- 彩色日志 --><!-- 彩色日志依賴的渲染類 --><conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/><conversionRule conversionWord="wex"converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/><conversionRule conversionWord="wEx"converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/><!-- 彩色日志格式 --><property name="CONSOLE_LOG_PATTERN"value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/><!-- Console 輸出設置 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- <encoder>-->
<!-- <pattern> ${CONSOLE_LOG_PATTERN}</pattern>-->
<!-- <charset>utf8</charset>-->
<!-- </encoder>--><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"><pattern>[%tid] ${CONSOLE_LOG_PATTERN}</pattern></layout><charset>utf-8</charset></encoder></appender><!-- 按照每天生成INFO日志文件 --><appender name="FILEINFO" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--日志文件輸出的文件名--><FileNamePattern>${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.info.%i.log</FileNamePattern><!--日志文件保留天數--><MaxHistory>30</MaxHistory><!--日志文件最大的大小--><MaxFileSize>10MB</MaxFileSize></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!-- 按照每天生成ERROR日志文件 --><appender name="FILEERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--日志文件輸出的文件名--><FileNamePattern>${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.error.%i.log</FileNamePattern><!--日志文件保留天數--><MaxHistory>30</MaxHistory><!--日志文件最大的大小--><MaxFileSize>10MB</MaxFileSize></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder><!-- 此日志文件只記錄info級別的 --><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>error</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter></appender><!-- skywalking 采集日志 --><appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout"><Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern></layout></encoder></appender><!--myibatis mongodb log configure--><logger name="com.apache.ibatis" level="TRACE"/><logger name="java.sql.Connection" level="DEBUG"/><logger name="java.sql.Statement" level="DEBUG"/><logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- <logger name="org.springframework.data.mongodb.core" level="DEBUG"/><logger name="org.springframework.data.redis.core" level="DEBUG"/><logger name="org.springframework.data.elasticsearch" level="DEBUG"/><logger name="org.springframework.data.neo4j" level="DEBUG"/>--><logger name="com.sms.manager" level="DEBUG"/><!-- 日志輸出級別 INFO--><root level="${LOG_LEVEL}"><appender-ref ref="STDOUT"/><appender-ref ref="grpc-log"/><appender-ref ref="FILEINFO"/><appender-ref ref="FILEERROR"/></root><!--日志異步到數據庫 --><!--<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">--><!--<!–日志異步到數據庫 –>--><!--<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">--><!--<!–連接池 –>--><!--<dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">--><!--<driverClass>com.mysql.jdbc.Driver</driverClass>--><!--<url>jdbc:mysql://baas.ievent.cn:3306/ievent</url>--><!--<user>live</user>--><!--<password>novacloudlive</password>--><!--</dataSource>--><!--</connectionSource>--><!--</appender>-->
</configuration>
下面我們將逐部分解析一個生產級別的 Logback 配置文件,理解其各個組件的作用。
1. 配置文件基本結構
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false"><!-- 配置內容 -->
</configuration>
debug="false"
:關閉 Logback 自身的調試日志,生產環境建議關閉
2. 動態屬性定義
<springProperty scope="context" name="LOG_HOME" source="HuiChen.log.directory"/>
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="huichen-device-sms-manager"/>
<springProperty scope="context" name="LOG_LEVEL" source="HuiChen.log.level" defaultValue="debug"/>
這部分配置通過?<springProperty>
?標簽將 Spring 環境中的配置注入到 Logback 中,實現了配置的動態化和外部化:
LOG_HOME
:日志文件存儲目錄,值來自 Spring 配置的?HuiChen.log.directory
APP_NAME
:應用名稱,默認值為?huichen-device-sms-manager
,可通過?spring.application.name
?覆蓋LOG_LEVEL
:全局日志級別,默認?debug
,可通過?HuiChen.log.level
?配置
這種方式的優勢在于:
- 可以在不同環境(開發、測試、生產)使用不同的配置
- 無需修改 Logback 配置文件即可調整日志行為
- 符合 Spring Boot 外部化配置的理念
3. 彩色日志配置
<!-- 彩色日志依賴的渲染類 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/><!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
這段配置實現了控制臺彩色日志輸出:
<conversionRule>
:定義了三個轉換規則,用于日志的彩色渲染和異常信息格式化CONSOLE_LOG_PATTERN
:定義了控制臺日志的輸出格式,其中:%clr(...)
:用于指定日志元素的顏色%d{...}
:日期時間,格式為 yyyy-MM-dd HH:mm:ss.SSS%5p
:日志級別,占 5 個字符寬度${PID:- }
:進程 ID%15.15t
:線程名,最長 15 個字符%-40.40logger{39}
:日志器名稱,最長 40 個字符%m%n
:日志消息和換行符
彩色日志的優勢在于:
- 不同級別日志用不同顏色顯示,便于快速識別
- 關鍵信息(如線程名、類名)有顏色區分,提高可讀性
- 異常堆棧信息格式化顯示,便于調試
4. 日志輸出目的地(Appender)
Appender 定義了日志的輸出方式和位置,一個配置文件中可以有多個 Appender。
4.1 控制臺輸出(STDOUT)
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"><pattern>[%tid] ${CONSOLE_LOG_PATTERN}</pattern></layout><charset>utf-8</charset></encoder>
</appender>
這是一個輸出到控制臺的 Appender:
name="STDOUT"
:Appender 的名稱,用于后續引用class="ch.qos.logback.core.ConsoleAppender"
:指定這是控制臺輸出的 Appender<encoder>
:編碼器,負責將日志事件轉換為字符串LayoutWrappingEncoder
:使用自定義布局的編碼器TraceIdPatternLogbackLayout
:集成了 SkyWalking 的布局,用于添加分布式追蹤 ID[%tid]
:SkyWalking 追蹤 ID,在分布式系統中非常有用charset="utf-8"
:日志編碼格式
4.2 INFO 級別日志文件(FILEINFO)
<appender name="FILEINFO" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 日志文件輸出的文件名 --><FileNamePattern>${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.info.%i.log</FileNamePattern><!-- 日志文件保留天數 --><MaxHistory>30</MaxHistory><!-- 日志文件最大的大小 --><MaxFileSize>10MB</MaxFileSize></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder>
</appender>
這是一個滾動輸出 INFO 級別日志到文件的 Appender:
class="ch.qos.logback.core.rolling.RollingFileAppender"
:滾動文件輸出 Appender,支持日志文件分割<rollingPolicy>
:滾動策略,這里使用?SizeAndTimeBasedRollingPolicy
,結合了時間和大小的滾動策略FileNamePattern
:日志文件命名規則,包含日期和序號MaxHistory
:日志文件保留 30 天MaxFileSize
:單個日志文件最大 10MB,超過則創建新文件
<encoder>
:定義了文件日志的格式,包含日期、線程、級別、日志器和消息
4.3 ERROR 級別日志文件(FILEERROR)
<appender name="FILEERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><FileNamePattern>${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.error.%i.log</FileNamePattern><MaxHistory>30</MaxHistory><MaxFileSize>10MB</MaxFileSize></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>error</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter>
</appender>
這個 Appender 專門用于記錄 ERROR 級別日志:
- 與 FILEINFO 類似,但增加了?
<filter>
?配置 LevelFilter
:級別過濾器,只接受 ERROR 級別的日志onMatch>ACCEPT</onMatch>
:匹配 ERROR 級別則接受onMismatch>DENY</onMismatch>
:不匹配則拒絕
將 ERROR 日志單獨存儲的好處:
- 便于快速定位錯誤,無需在大量日志中篩選
- 可以設置更長的保留時間,便于問題追溯
- 不同級別的日志可以有不同的處理策略
4.4 SkyWalking 日志采集(grpc-log)
<appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout"><Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern></layout></encoder>
</appender>
這個 Appender 用于將日志發送到 SkyWalking APM 系統:
GRPCLogClientAppender
:通過 gRPC 協議將日志發送到 SkyWalking 服務器TraceIdMDCPatternLogbackLayout
:將追蹤 ID 放入日志,實現分布式追蹤[%X{tid}]
:從 MDC(Mapped Diagnostic Context)中獲取追蹤 ID
集成 SkyWalking 的優勢:
- 實現日志與分布式追蹤的關聯,便于微服務架構下的問題排查
- 可以在 SkyWalking 控制臺查看全鏈路日志
- 追蹤 ID 貫穿整個調用鏈,方便定位跨服務問題
5. 日志級別控制
<!-- myibatis mongodb log configure -->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!--
<logger name="org.springframework.data.mongodb.core" level="DEBUG"/>
<logger name="org.springframework.data.redis.core" level="DEBUG"/>
<logger name="org.springframework.data.elasticsearch" level="DEBUG"/>
<logger name="org.springframework.data.neo4j" level="DEBUG"/>
--><logger name="com.sms.manager" level="DEBUG"/><!-- 日志輸出級別 -->
<root level="${LOG_LEVEL}"><appender-ref ref="STDOUT"/><appender-ref ref="grpc-log"/><appender-ref ref="FILEINFO"/><appender-ref ref="FILEERROR"/>
</root>
這部分配置控制不同包或類的日志級別:
<logger>
:針對特定包或類設置日志級別name
:指定包或類的全限定名level
:日志級別,從低到高為 TRACE < DEBUG < INFO < WARN < ERROR- 例如?
com.sms.manager
?包下的日志被設置為 DEBUG 級別
<root>
:根日志配置,所有未被特定 logger 配置的類都繼承此配置level="${LOG_LEVEL}"
:使用之前定義的動態屬性作為全局日志級別<appender-ref>
:引用前面定義的 Appender,表示日志會輸出到這些目的地
日志級別的作用:
- 控制日志輸出的詳細程度,生產環境通常使用 INFO 級別減少日志量
- 特定包可以設置更詳細的日志級別,便于調試
- 避免不必要的日志輸出,提高系統性能
6. 數據庫日志(注釋部分)
配置文件中還有一個注釋掉的數據庫日志 Appender:
<!--
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender"><connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource"><dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource"><driverClass>com.mysql.jdbc.Driver</driverClass><url>jdbc:mysql://baas.ievent.cn:3306/ievent</url><user>live</user><password>novacloudlive</password></dataSource></connectionSource>
</appender>
-->
這個 Appender 用于將日志存儲到數據庫中,適用于需要對日志進行復雜查詢和分析的場景。但由于性能影響和配置復雜性,通常在生產環境中不推薦使用,除非有特殊需求。
實際應用中的最佳實踐
環境隔離:
- 開發環境:使用 DEBUG 級別,輸出到控制臺
- 生產環境:使用 INFO 級別,輸出到文件,限制日志大小和保留時間
性能考慮:
- 避免在循環中輸出大量日志
- 生產環境避免使用 DEBUG 級別
- 適當設置日志文件大小和保留時間,避免磁盤空間耗盡
安全考慮:
- 日志中避免包含敏感信息(密碼、令牌等)
- 確保日志文件有適當的權限控制
- 敏感操作的日志應特別關注
分布式系統:
- 集成分布式追蹤系統(如 SkyWalking)
- 確保日志中包含追蹤 ID,便于跨服務追蹤
- 統一日志收集和分析(如使用 ELK 棧)
總結
本文詳細解析了一個生產級別的 Logback 配置文件,涵蓋了動態屬性、彩色日志、多目的地輸出、日志級別控制和分布式追蹤集成等方面。合理配置 Logback 不僅能幫助我們更好地理解系統運行狀態,還能在出現問題時快速定位和解決。
Logback 的配置靈活多變,應根據實際需求進行調整。在開發和生產環境中使用不同的配置,既能保證開發效率,又能確保生產系統的穩定運行。
希望本文能幫助你更好地理解和使用 Logback,構建更健壯的日志系統。