整合Logback日志框架

整合 Logback 日志框架

概述

日志是排查问题的眼睛。接口报错了、数据不对了、性能慢了,第一反应就是去看日志。Spring Boot 默认集成了 Logback,你要做的不是"引入",而是"配好"。


需要引入依赖吗?

不需要。spring-boot-starter-web 里面已经自带了 spring-boot-starter-logging,而 spring-boot-starter-logging 底层就是 Logback。只要你用了 Spring Boot Web,Logback 就已经在 classpath 里了。

所以直接进入正题:写配置文件。


配置文件放哪?

Spring Boot 会自动在 classpath 下查找这几个文件:

文件名 优先级
logback-spring.xml ✅ 推荐,可以用 Spring 的 <springProfile> 标签按环境切换
logback.xml 能用,但不支持 <springProfile>,比 Spring 更早加载

命名加 -spring 后缀的原因是:logback.xml 先于 Spring 容器加载,那时候还不知道激活的是哪个 profile,所以 <springProfile> 标签不生效。logback-spring.xml 则交给 Spring 来控制加载时机,profile 功能就能用了。

所以我们统一放在 src/main/resources/logback-spring.xml


从零开始搭

第一步:定义变量

先定义几个变量,后面反复用到,改一处全生效:

xml 复制代码
<configuration>
    <!-- 引用 Spring Boot 自带的默认变量(CONSOLE_LOG_PATTERN 等) -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />

    <!-- 应用名称,区分不同服务的日志 -->
    <property scope="context" name="appName" value="auth"/>

    <!-- 日志文件路径和名称 -->
    <property name="LOG_FILE" value="./logs/${appName}.%d{yyyy-MM-dd}"/>

    <!-- 每行日志的输出格式 -->
    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
</configuration>

LOG_PATTERN 里每个占位符的含义:

占位符 含义 输出示例
%d{yyyy-MM-dd HH:mm:ss.SSS} 时间 2026-07-06 14:30:00.123
[%thread] 线程名 [http-nio-8080-exec-1]
%-5level 日志级别,左对齐占 5 位 INFO
%logger{50} 输出日志的类名,最多 50 个字符 c.l.i.a.controller.TestController
%msg%n 日志正文 + 换行 ---

第二步:配置文件输出(RollingFileAppender)

日志必须落地到文件,不然服务一重启控制台的就没了。

xml 复制代码
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <!-- 日志文件命名:auth.2026-07-06-0.log、auth.2026-07-06-1.log ... -->
        <fileNamePattern>${LOG_FILE}-%i.log</fileNamePattern>
        <!-- 保留 30 天 -->
        <maxHistory>30</maxHistory>
        <!-- 单个文件超过 10MB 就滚动到下一个 -->
        <maxFileSize>10MB</maxFileSize>
        <!-- 总大小不限制 -->
        <totalSizeCap>0</totalSizeCap>
        <!-- 重启不清历史日志 -->
        <cleanHistoryOnStart>false</cleanHistoryOnStart>
    </rollingPolicy>
    <encoder>
        <pattern>${LOG_PATTERN}</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>

SizeAndTimeBasedRollingPolicy 是一个复合滚动策略,同时按"时间"和"大小"来切分文件。普通策略只能二选一,这个可以兼顾:

  • 每天生成新文件:auth.2026-07-06-0.log
  • 单文件超过 10MB 也会切:auth.2026-07-06-1.logauth.2026-07-06-2.log......
  • 超过 30 天的旧文件自动删除
属性 作用
fileNamePattern 日志文件的命名模板
maxFileSize 单个文件超过多大就滚动切分
maxHistory 最多保留多少天
totalSizeCap 总大小上限,0 表示不限制
cleanHistoryOnStart 启动时是否清空历史,生产环境务必设为 false

第三步:异步写入(AsyncAppender)

上一步的 FILE appender 是同步写 的:每次 log.info() 都直接写磁盘,I/O 阻塞当前线程。高并发下,日志写入会成为性能瓶颈。

所以我们需要异步:日志先扔到一个内存队列里,由另一个线程负责批量刷盘。

xml 复制代码
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
    <!-- 队列满时是否丢弃日志。0 表示永不丢弃 -->
    <discardingThreshold>0</discardingThreshold>
    <!-- 队列容量,默认 256 -->
    <queueSize>256</queueSize>
    <!-- 套在哪个真实 appender 外面 -->
    <appender-ref ref="FILE"/>
</appender>
配置项 含义
queueSize 队列大小。日志量大的服务可以调到 512 或 1024
discardingThreshold 队列满到多少比例开始丢弃。默认 20,即队列满 80% 时丢弃 TRACE/DEBUG/INFO 级别的日志。设为 0 表示永不丢弃,宁可堵着也不丢

discardingThreshold = 0 为什么重要?

默认值是 20。意味着:队列满了 80%,新来的 INFO 日志直接扔掉。排查线上问题的时候,你翻半天日志发现关键那条"刚好"被丢了,抓瞎。设成 0 之后,如果队列满了会阻塞一小会儿等队列腾出空间,但不会丢日志。

如果你对性能有极致要求、允许偶尔丢日志,可以把 discardingThreshold 调成默认值,并且打开 neverBlock


第四步:控制台输出(CONSOLE appender)

不会有人把所有的日志都写在文件里,控制台也要一份。毕竟 DevOps 看的是控制台。

不过 Spring Boot 已经自带了 console-appender.xml,不需要手写,直接引用就行:

xml 复制代码
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />

第五步:按环境组装

开发环境我希望控制台 + 文件 都有,生产环境只保留文件,别在线上打控制台日志,浪费 I/O。

<springProfile> 按环境分别配置:

xml 复制代码
<!-- 开发环境:控制台 + 文件 -->
<springProfile name="dev">
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="ASYNC_FILE"/>
    </root>
</springProfile>

<!-- 生产环境:只看文件,不打控制台 -->
<springProfile name="prod">
    <root level="INFO">
        <appender-ref ref="ASYNC_FILE"/>
    </root>
</springProfile>

<root level="INFO"> 的含义:默认日志级别为 INFODEBUGTRACE 的日志不打印(除非单独给某个包开了 DEBUG)。


完整配置

把上面的步骤拼起来:

xml 复制代码
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />

    <!-- 变量 -->
    <property scope="context" name="appName" value="auth"/>
    <property name="LOG_FILE" value="./logs/${appName}.%d{yyyy-MM-dd}"/>
    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>

    <!-- 文件输出(同步) -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}-%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <maxFileSize>10MB</maxFileSize>
            <totalSizeCap>0</totalSizeCap>
            <cleanHistoryOnStart>false</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 异步包装 -->
    <appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
        <discardingThreshold>0</discardingThreshold>
        <queueSize>256</queueSize>
        <appender-ref ref="FILE"/>
    </appender>

    <!-- 开发环境 -->
    <springProfile name="dev">
        <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
        <root level="INFO">
            <appender-ref ref="CONSOLE"/>
            <appender-ref ref="ASYNC_FILE"/>
        </root>
    </springProfile>

    <!-- 生产环境 -->
    <springProfile name="prod">
        <root level="INFO">
            <appender-ref ref="ASYNC_FILE"/>
        </root>
    </springProfile>
</configuration>

常见踩坑:No appenders present

如果你启动后看到这个警告:

复制代码
WARN - No appenders present in context [default] for logger [xxx]

意思是 Logback 找不到任何 <root> 配置------没有一个 appender 生效,日志不知道该往哪儿输出。

回头检查你的 <springProfile>:你的 application.properties 里是否配置了 spring.profiles.active?如果没有激活任何 profile(比如没设 dev),那么所有的 <springProfile> 都不会生效,<root> 也就没了。

修法 :在 application.properties 里加上:

properties 复制代码
spring.profiles.active=dev

或者写一个 default 配置 ,在所有 <springProfile> 之外补一段 root 作为兜底:

xml 复制代码
<!-- 兜底:当没有任何 profile 激活时,默认输出到控制台 -->
<root level="INFO">
    <appender-ref ref="CONSOLE"/>
</root>
相关推荐
逆光的July1 个月前
Logback 学习笔记
笔记·学习·logback
大大杰哥1 个月前
Java 日志框架详解:SLF4J + Logback 从入门到实战
java·开发语言·logback
RemainderTime2 个月前
(十二)Spring Cloud Alibaba 2023.x:基于 Filebeat 构建轻量级 ELK日志追踪体系
分布式·elk·elasticsearch·微服务·架构·logback
ideal-cs2 个月前
总结:生产环境Logback日志配置模板与pattern格式案例
java·log4j·logback·pattern·后端日志
非情剑2 个月前
logback日志脱敏、FASTJSON日志脱敏
logback
雨辰AI2 个月前
SpringBoot3 + 人大金仓 V9 全栈日志实战:Logback + Loki + Filebeat 构建统一日志平台
java·数据库·后端·云原生·eureka·logback·政务
NEGl DRYN2 个月前
Spring Boot 3.3.4 升级导致 Logback 之前回滚策略配置不兼容问题解决
java·spring boot·logback
eSsO KERF3 个月前
使用 Logback 的最佳实践:`logback.xml` 与 `logback-spring.xml` 的区别与用法
xml·spring·logback
色空大师3 个月前
【日志文件配置详解】
java·logback·log4j2·日志