Logback 配置
约 1563 字大约 5 分钟
布欧-Lewyon
2026-05-15
首页 › Spring Boot › 日志 › Logback 配置
Spring Boot 在 classpath 上找到 Logback(默认存在)时自动使用它。你可以在 application.yml 中完成大部分日志配置,高级场景使用 logback-spring.xml。
application.yml 中的日志配置
设置日志级别
logging:
level:
root: INFO # 全局级别
com.example.demo: DEBUG # 某包级别
org.springframework.web: WARN # 框架包级别
org.hibernate.SQL: DEBUG # Hibernate SQL输出到文件
logging:
file:
name: logs/app.log # 日志文件路径
max-size: 10MB # 每个文件最大
max-history: 7 # 保留天数
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"分组控制
为自定义的多个包设置别名:
logging:
group:
business: com.example.order,com.example.payment
level:
business: DEBUGlogback-spring.xml
当 application.yml 无法满足需求时(如按天滚动、条件过滤),在 src/main/resources/ 下创建 logback-spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按天滚动文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按大小同时按天滚动 -->
<appender name="SIZED_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>7</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- Profile 隔离 -->
<springProfile name="dev">
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="SIZED_FILE"/>
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
</configuration>文件名使用
logback-spring.xml而非logback.xml,这样可以使用<springProfile>标签按 Profile 切换日志配置。
MDC(Mapped Diagnostic Context)
在日志中附加请求级别的上下文信息,如 TraceId、用户 ID:
@RestController
public class OrderController {
@GetMapping("/orders/{id}")
public Result<Order> getOrder(@PathVariable Long id) {
MDC.put("userId", SecurityContextHolder.getContext()
.getAuthentication().getName());
MDC.put("traceId", UUID.randomUUID().toString().substring(0, 8));
try {
return Result.success(orderService.findById(id));
} finally {
MDC.clear(); // 请求结束必须清理
}
}
}<pattern>%d{HH:mm:ss} [%thread] %-5level [%X{traceId}] %logger{36} - %msg%n</pattern>输出示例:
14:30:22 [http-nio-8080-exec-3] INFO [a1b2c3d4] c.e.d.service.OrderService - 查询订单 1001使用 Micrometer Tracing 可自动生成并传播 TraceId(非 Spring Cloud Sleuth,后者已迁至 Micrometer),手动 MDC 仅适合简单场景。
源码与架构:SLF4J 绑定机制与 Logback 上下文
SLF4J 门面原理
SLF4J(Simple Logging Facade for Java)本身不实现日志功能,它在运行期动态绑定具体的日志框架。绑定机制的核心在 LoggerFactory.getLogger() 的第一次调用:
LoggerFactory.getLogger(UserService.class)
│
├── ① performInitialization()
│ └── bind()
│ ├── findPossibleStaticLoggerBinderPathSet()
│ │ └── 扫描 classpath 中 org/slf4j/impl/StaticLoggerBinder.class
│ │
│ ├── 找到 0 个 → 打印 "No SLF4J providers were found."
│ ├── 找到 1 个 → 唯一绑定成功
│ └── 找到 2+ 个 → 打印 "Multiple bindings were found on classpath for SLF4J"
│
└── ② 返回 Logger 实例
├── Logback → LogbackLoggerContext.getLogger(name)
└── Log4j2 → Log4j2LoggerFactory.getLogger(name)这就是为什么永远不要同时引入 logback-classic 和 log4j-slf4j-impl——运行时 SLF4J 会发现多个 StaticLoggerBinder,虽然仍会选择一个继续工作,但控制台会打印烦人的绑定冲突警告。Spring Boot 的 spring-boot-starter-logging 已经排除了其他日志实现,确保唯一绑定。
Logback Logger 层级
Logback 的 Logger 对象有父子层级关系,基于包名点号分隔:
Logger Hierarchy(部分)
│
├── ROOT Logger(根)
│ └── Level = INFO(默认)
│
├── com ← root 的子 Logger
│ └── com.example ← 继承 root 级别
│ └── com.example.demo ← 可独立设置级别
│
└── org.springframework
└── org.springframework.web ← 可独立设置级别日志级别查询规则:向上追溯——如果 com.example.demo.service.UserService 没有显式设置级别,Logback 会向上检查 com.example.demo → com.example → com → ROOT,直到找到有级别配置的祖先。logging.level.com.example.demo=DEBUG 实际是在 com.example.demo Logger 上设置级别,其子 Logger 在没有自定义级别时会继承。
LoggingSystem 初始化时序
在 Spring Boot 启动过程中,日志系统通过 LoggingApplicationListener 初始化:
SpringApplication 启动 → ApplicationStartingEvent 发布
│
└── LoggingApplicationListener.onApplicationStartingEvent()
├── ① 确定 LoggingSystem 实现
│ └── 检查 classpath 中存在的日志框架
│ ├── Logback → LogbackLoggingSystem
│ ├── Log4j2 → Log4J2LoggingSystem
│ └── Java Util → JavaLoggingSystem
│
├── ② 读取配置文件
│ └── 查找 `logging.config` 指定 → 否则按约定查找
│ ├── classpath:logback-spring.xml → LogbackLoggingSystem
│ └── classpath:logback.xml → 也可,但无法使用 <springProfile>
│
├── ③ 应用 logging.level.* 设置
│ └── 在 LoggingSystem 上调用 setLogLevel("com.example", DEBUG)
│
└── ④ 发布 ApplicationEnvironmentPreparedEvent
└── LoggingSystem 已初始化完成,后续日志可正常输出生产意识:日志系统的初始化时机晚于
ApplicationStartingEvent但早于ApplicationEnvironmentPreparedEvent。这意味着在SpringApplication构造函数中注册的ApplicationListener在初始化阶段如果打印日志,此时 Logback 尚未配置完成,会使用 SLF4J 的 NOP(无操作)实现——日志静默丢失。解决方法:不在构造函数中打印日志,或在监听器中推迟打印到日志系统就绪之后。另外,logback-spring.xml中<springProperty>标签可用于读取application.yml中的配置属性(如日志路径、应用名),这比硬编码路径更灵活。
生产意识:托管环境中(Kubernetes + 日志采集系统,如 ELK / Loki),日志输出到标准输出(stdout)而非文件更为常见——容器平台自动收集 stdout 做集中管理。此时
logback-spring.xml中只需保留 CONSOLE appender,FILE appender 可以省略。日志格式建议统一为 JSON(使用net.logstash.logback:logstash-logback-encoder),便于日志系统结构化解析。MDC 中的 TraceId 建议由 Micrometer Tracing 自动生成,而非手动 UUID——后者在跨服务调用时无法串联。
Log4j2 替代(简述)
如需使用 Log4j2,需排除 Logback 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>建议在需要异步日志或 Log4j2 特定功能时再做切换,大多数场景 Logback 完全够用。
小结
logging.level.*在application.yml中控制级别,最简便。- 自定义配置用
logback-spring.xml(支持springProfile标签)。 - 按天/按大小滚动日志文件,定期清理避免磁盘写满。
- MDC 在日志中注入请求上下文(TraceId、用户 ID),便于问题追踪。
- 易错:直接放
logback.xml无法使用springProfile标签。MDC 值在请求结束后必须清理(MDC.clear()),否则线程池复用时上下文污染。生产环境避免 DEBUG 级别日志大量输出影响性能。 - 思考任务:配置
logback-spring.xml实现 dev 环境控制台 DEBUG、prod 环境按天滚动 INFO 到文件,添加 MDC 注入 TraceId,验证日志输出格式。
上一节:定时任务与异步
下一节:安全入门
