一、配置文件入口:选对文件,支持 Spring 特性
Logback 支持 XML/Groovy 配置,SpringBoot 项目优先选logback-spring.xml(放在 resources 目录下):
- 优势 1:支持springProfile(按环境配置,比如开发 / 生产不同日志级别)
- 优势 2:支持springProperty(读取 Spring 配置,比如应用名、端口)
配置文件对比
| 配置文件 | 加载方式 | 优势 | 适用场景 |
|---|---|---|---|
| logback.xml | Logback直接加载 | 简单直接 | 非Spring项目 |
| logback-spring.xml | Spring Boot处理 | 支持Spring特性 | Spring Boot项目(推荐) |
二、核心配置标签:一步步配置,不迷路
以logback-spring.xml为例,核心标签按 "定义变量→输出规则→日志级别" 的顺序配置:
1. 定义变量(property/springProperty)
先定义常用变量(比如日志路径、日志格式),后续复用:
bash
<!-- 读取Spring配置的应用名(spring.application.name) -->
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
<springProperty scope="context" name="PROFILE" source="spring.profiles.active" defaultValue="default"/>
<!-- 定义日志路径(存在用户目录下的应用名文件夹) -->
<property name="LOG_PATH" value="${user.home}/logs/${APP_NAME}/logs"/>
<!-- 定义日志文件名称 -->
<property name="APP_LOG_FILE" value="${LOG_PATH}/application.log"/>
<!-- 定义日志格式(包含时间、级别、traceId、线程、日志名、内容、异常) -->
<property name="LOG_PATTERN" value="%date{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%X{traceId}|%thread|%logger{20}|%message%n%exception"/>
<property name="SIMPLE_PATTERN"
value="%d{HH:mm:ss.SSS} | %-5level | %logger{20} | %msg%n"/>
2. 输出规则(appender):控制日志往哪写、怎么写
常用 2 种 Appender:滚动文件输出(避免日志文件过大)、异步输出(不阻塞业务)。
控制台输出器(开发环境)
bash
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${SIMPLE_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 开发环境过滤掉低级别日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
(1)滚动文件输出(RollingFileAppender,生产环境)
按时间 + 大小分割日志,比如每天一个文件,单个文件最大 200MB:
bash
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志文件路径 -->
<file>${APP_LOG_FILE}</file>
<!-- 日志格式(引用上面定义的变量) -->
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 滚动策略:时间+大小 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 分割后的日志文件名(比如application.log.2024-10-01.1) -->
<fileNamePattern>${APP_LOG_FILE}.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxHistory>30</maxHistory> <!-- 保留30天的日志 -->
<maxFileSize>200MB</maxFileSize> <!-- 单个文件最大200MB -->
<totalSizeCap>10GB</totalSizeCap> <!-- 所有日志文件总大小不超过10GB -->
</rollingPolicy>
<!-- 日志级别过滤 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
</appender>
=====错误日志单独输出=====
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/error.log</file>
<encoder>
<pattern>${DETAILED_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>15</maxHistory>
<totalSizeCap>2GB</totalSizeCap>
</rollingPolicy>
<!-- 只记录ERROR级别 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
(2)异步输出(AsyncAppender,性能优化)
日志打印不阻塞业务线程,提升性能:
bash
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 队列大小,根据业务量调整 -->
<queueSize>1024</queueSize>
<!-- 队列剩余容量低于此阈值时,丢弃DEBUG/INFO/TRACE日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 队列满时是否阻塞 -->
<neverBlock>false</neverBlock>
<!-- 包含调用者信息(影响性能) -->
<includeCallerData>false</includeCallerData>
<appender-ref ref="FILE"/>
</appender>
<appender name="ASYNC_ERROR" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>512</queueSize>
<discardingThreshold>0</discardingThreshold>
<neverBlock>true</neverBlock>
<appender-ref ref="ERROR_FILE"/>
</appender>
3. 日志级别配置(logger/root)
控制不同日志的输出级别,不用每个类都配置:
Root Logger配置
bash
<root level="INFO">
<appender-ref ref="ASYNC_FILE"/>
<appender-ref ref="ASYNC_ERROR"/>
</root>
包级别日志控制
bash
<!-- 应用代码:DEBUG级别 -->
<logger name="com.yourcompany.yourapp" level="DEBUG" additivity="false">
<appender-ref ref="ASYNC_FILE"/>
</logger>
<!-- 框架日志:WARN级别,减少噪音 -->
<logger name="org.springframework" level="WARN"/>
<logger name="org.hibernate" level="WARN"/>
<logger name="org.apache" level="WARN"/>
<logger name="com.zaxxer.hikari" level="INFO"/>
<!-- SQL日志:单独控制 -->
<logger name="org.hibernate.SQL" level="DEBUG" additivity="false">
<appender-ref ref="ASYNC_FILE"/>
</logger>
<logger name="org.hibernate.type.descriptor.sql" level="TRACE" additivity="false">
<appender-ref ref="ASYNC_FILE"/>
</logger>
4. 多环境配置
bash
<!-- 开发环境 -->
<springProfile name="dev">
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
<!-- 开发环境开启SQL日志 -->
<logger name="org.hibernate.SQL" level="DEBUG"/>
<logger name="org.hibernate.type.descriptor.sql" level="TRACE"/>
</springProfile>
<!-- 测试环境 -->
<springProfile name="test">
<root level="INFO">
<appender-ref ref="ASYNC_FILE"/>
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<!-- 生产环境 -->
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="ASYNC_FILE"/>
<appender-ref ref="ASYNC_ERROR"/>
</root>
<!-- 生产环境关闭调试日志 -->
<logger name="org.hibernate.SQL" level="WARN"/>
<logger name="org.hibernate.type.descriptor.sql" level="WARN"/>
</springProfile>
三、高级配置特性
3.1 日志格式占位符详解
常用占位符
bash
<property name="ADVANCED_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | %X{traceId:-N/A} | %X{userId:-} | %thread | %logger{30} | %msg | %exception{10}%n"/>
| 占位符 | 说明 | 示例输出 |
|---|---|---|
| %d{pattern} | 日期时间 | 2024-01-15 14:30:25.123 |
| %-5level | 日志级别(左对齐) | INFO |
| %X{traceId} | MDC中的traceId | abc-123-def-456 |
| %X{key:-default} | MDC值,带默认值 | userId:-(无值时显示-) |
| %thread | 线程名 | http-nio-8080-exec-1 |
| %logger{length} | Logger名称(智能缩写) | c.y.s.UserService |
| %msg | 日志消息 | 用户登录成功 |
| %exception{length} | 异常堆栈(限制行数) | 显示前10行堆栈 |
| %n | 换行符 |
Logger名称智能缩写示例
bash
<!-- 原始Logger名称: com.yourcompany.yourapp.service.UserService -->
<pattern>%logger{20}</pattern>
<!-- 输出: c.y.y.s.UserService -->
<pattern>%logger{10}</pattern>
<!-- 输出: c.y.y.UserService -->
<pattern>%logger{0}</pattern>
<!-- 输出: UserService -->
3.2 格式修饰符(Format Modifiers)
bash
<property name="FORMATTED_PATTERN"
value="%d{HH:mm:ss.SSS} | %-5.5level | %-20.20thread | %-30.30logger | %msg%n"/>
| 配置 | 含义 | 输入 | 输出 |
|---|---|---|---|
| %-5level | 最小5字符,左对齐 | INFO INFO | |
| %5level | 最小5字符,右对齐 | INFO INFO | |
| %.5level | 最大5字符,保留左侧 | DEBUG DEBUG | |
| %.-3level | 最大3字符,保留左侧 | DEBUG DEB | |
| %-10.10thread | 最小10最大10字符 | main main |
3.3 动态日志级别控制
bash
<!-- 开启JMX支持,支持运行时调整日志级别 -->
<jmxConfigurator/>
<!-- 开启自动扫描,配置文件变化时自动重载 -->
<configuration scan="true" scanPeriod="30 seconds">
四、生产环境最佳实践
4.1 完整的生产环境配置
bash
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
<!-- 变量定义 -->
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
<springProperty scope="context" name="LOG_LEVEL" source="logging.level.root" defaultValue="INFO"/>
<property name="LOG_HOME" value="/app/logs/${APP_NAME}"/>
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | %X{traceId:-} | %thread | %logger{30} | %msg%n"/>
<property name="ERROR_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | %X{traceId:-} | %thread | %logger{30} | %msg | %exception{20}%n"/>
<!-- 控制台输出(用于K8s环境) -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 应用日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/app.log</file>
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>50GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
</appender>
<!-- 错误日志文件 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/error.log</file>
<encoder>
<pattern>${ERROR_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>15</maxHistory>
<totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
<!-- 异步输出器 -->
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>2048</queueSize>
<discardingThreshold>0</discardingThreshold>
<neverBlock>false</neverBlock>
<appender-ref ref="FILE"/>
</appender>
<appender name="ASYNC_ERROR" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>1024</queueSize>
<discardingThreshold>0</discardingThreshold>
<neverBlock>true</neverBlock>
<appender-ref ref="ERROR_FILE"/>
</appender>
<!-- 日志级别控制 -->
<root level="${LOG_LEVEL}">
<appender-ref ref="ASYNC_FILE"/>
<appender-ref ref="ASYNC_ERROR"/>
<appender-ref ref="CONSOLE"/>
</root>
<!-- 业务代码详细日志 -->
<logger name="com.yourcompany" level="DEBUG" additivity="false">
<appender-ref ref="ASYNC_FILE"/>
</logger>
<!-- 框架日志降级 -->
<logger name="org.springframework" level="WARN"/>
<logger name="org.hibernate" level="WARN"/>
<!-- JMX支持 -->
<jmxConfigurator/>
</configuration>
4.2 日志脱敏配置
自定义脱敏转换器
bash
@Component
public class SensitiveDataConverter extends MessageConverter {
private static final Pattern PHONE_PATTERN = Pattern.compile("(\\d{3})\\d{4}(\\d{4})");
private static final Pattern ID_CARD_PATTERN = Pattern.compile("(\\d{6})\\d{8}(\\w{4})");
private static final Pattern EMAIL_PATTERN = Pattern.compile("(\\w{3})(\\w+)(@\\w+\\.[a-z]+)");
@Override
public String convert(ILoggingEvent event) {
String message = event.getFormattedMessage();
// 手机号脱敏
message = PHONE_PATTERN.matcher(message).replaceAll("$1****$2");
// 身份证脱敏
message = ID_CARD_PATTERN.matcher(message).replaceAll("$1********$2");
// 邮箱脱敏
message = EMAIL_PATTERN.matcher(message).replaceAll("$1***$3");
return message;
}
}
注册脱敏转换器
bash
<!-- 注册自定义转换器 -->
<conversionRule conversionWord="msg" converterClass="com.yourcompany.logging.SensitiveDataConverter"/>
<!-- 在encoder中使用 -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | %msg%n</pattern>
</encoder>
4.3 监控和告警集成
错误日志监控配置
bash
<!-- 错误日志统计 -->
<appender name="ERROR_METRICS" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/metrics/error_metrics.log</file>
<encoder>
<pattern>%msg</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/metrics/error_metrics.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 慢查询日志 -->
<appender name="SLOW_QUERY" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/metrics/slow_query.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/metrics/slow_query.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>3</maxHistory>
</rollingPolicy>
</appender>
<logger name="SLOW_QUERY_LOGGER" level="INFO" additivity="false">
<appender-ref ref="SLOW_QUERY"/>
</logger>
五、故障排查和调试
5.1 Logback内部日志
bash
<!-- 开启Logback内部状态输出 -->
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<!-- 或者输出到文件 -->
<configuration>
<timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
<appender name="LOGBACK_STATUS" class="ch.qos.logback.core.FileAppender">
<file>logback-status-${bySecond}.log</file>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="ch.qos.logback" level="DEBUG">
<appender-ref ref="LOGBACK_STATUS"/>
</logger>
</configuration>
5.2 常见问题解决
问题1:日志文件不生成
bash
<!-- 检查文件权限和路径 -->
<property name="LOG_HOME" value="/app/logs"/>
<!-- 确保目录存在 -->
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${LOG_HOME}/app.log</file>
<prudent>true</prudent> <!-- 多进程写同一个文件 -->
</appender>
问题2:日志重复打印
bash
<!-- 设置 additivity="false" 避免重复 -->
<logger name="com.yourcompany" level="DEBUG" additivity="false">
<appender-ref ref="FILE"/>
</logger>
问题3:内存溢出
bash
<!-- 调整异步队列大小 -->
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>1024</queueSize> <!-- 根据内存调整 -->
<discardingThreshold>20</discardingThreshold> <!-- 队列80%满时丢弃低级别日志 -->
</appender>
本篇小结
Logback 配置的核心是 "按需定制":先定义变量,再配置输出规则(文件 + 异步),最后设置日志级别。
通过合理的Logback配置,你可以构建一个高性能、可维护的生产级日志系统:
- 环境适配:使用logback-spring.xml和支持多环境
- 性能优化:合理配置异步日志和滚动策略
- 可观测性:集成traceId、结构化日志格式
- 安全合规:实现敏感数据脱敏
- 运维友好:配置监控、告警和故障排查机制
记住:好的日志配置不是一成不变的,需要根据业务发展和运维需求持续优化调整。