当前位置: 首页 > news >正文

整合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


从零开始搭

第一步:定义变量

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

<configuration><!-- 引用 Spring Boot 自带的默认变量(CONSOLE_LOG_PATTERN 等) --><includeresource="org/springframework/boot/logging/logback/defaults.xml"/><!-- 应用名称,区分不同服务的日志 --><propertyscope="context"name="appName"value="auth"/><!-- 日志文件路径和名称 --><propertyname="LOG_FILE"value="./logs/${appName}.%d{yyyy-MM-dd}"/><!-- 每行日志的输出格式 --><propertyname="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)

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

<appendername="FILE"class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicyclass="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)

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

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

<appendername="ASYNC_FILE"class="ch.qos.logback.classic.AsyncAppender"><!-- 队列满时是否丢弃日志。0 表示永不丢弃 --><discardingThreshold>0</discardingThreshold><!-- 队列容量,默认 256 --><queueSize>256</queueSize><!-- 套在哪个真实 appender 外面 --><appender-refref="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,不需要手写,直接引用就行:

<includeresource="org/springframework/boot/logging/logback/console-appender.xml"/>

第五步:按环境组装

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

<springProfile>按环境分别配置:

<!-- 开发环境:控制台 + 文件 --><springProfilename="dev"><includeresource="org/springframework/boot/logging/logback/console-appender.xml"/><rootlevel="INFO"><appender-refref="CONSOLE"/><appender-refref="ASYNC_FILE"/></root></springProfile><!-- 生产环境:只看文件,不打控制台 --><springProfilename="prod"><rootlevel="INFO"><appender-refref="ASYNC_FILE"/></root></springProfile>

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


完整配置

把上面的步骤拼起来:

<configuration><includeresource="org/springframework/boot/logging/logback/defaults.xml"/><!-- 变量 --><propertyscope="context"name="appName"value="auth"/><propertyname="LOG_FILE"value="./logs/${appName}.%d{yyyy-MM-dd}"/><propertyname="LOG_PATTERN"value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/><!-- 文件输出(同步) --><appendername="FILE"class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicyclass="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><!-- 异步包装 --><appendername="ASYNC_FILE"class="ch.qos.logback.classic.AsyncAppender"><discardingThreshold>0</discardingThreshold><queueSize>256</queueSize><appender-refref="FILE"/></appender><!-- 开发环境 --><springProfilename="dev"><includeresource="org/springframework/boot/logging/logback/console-appender.xml"/><rootlevel="INFO"><appender-refref="CONSOLE"/><appender-refref="ASYNC_FILE"/></root></springProfile><!-- 生产环境 --><springProfilename="prod"><rootlevel="INFO"><appender-refref="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里加上:

spring.profiles.active=dev

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

<!-- 兜底:当没有任何 profile 激活时,默认输出到控制台 --><rootlevel="INFO"><appender-refref="CONSOLE"/></root>
http://www.jsqmd.com/news/1138896/

相关文章:

  • 轻量化部署,小空间也能实现智能升级
  • [Android] AccumuPDF-全能工具箱+视图文转换,合并分割
  • 抖店订单API 与微信小店API 对比:3 个关键差异与数据同步策略
  • 儿童古诗启蒙App哪个好用?适趣古诗词适合孩子系统入门
  • 去中心化刚性编队:大规模无人机集群抗毁协同控制框架
  • 2026呼和浩特传媒营销公司实力横评 爱笑文化传媒深度解析
  • 建筑施工企业临时设施与周转材料固定资产动态管理平台开发
  • 主流WMS仓库管理系统选型对比:特性解析与适用场景分析
  • STM32F071VB与MC6470 IMU硬件设计及姿态解算实践
  • GEO推广合法吗?标准答案来了
  • RPLIDAR C1 激光雷达 + ROS2 Humble:从驱动编译到 SLAM 建图全流程
  • AMD Ryzen硬件级调试技术揭秘:SMUDebugTool深度解析与实战应用
  • TPS5450 降压变换器 PCB 布局实战:3 个关键回路面积控制与 20% 纹波优化
  • 创新驱动 智能采样 - Smart WQS2000Pro水质智能采样器
  • n8n + MCP + CLI 自动化选品教程:5 步跑通
  • 灰度重心法
  • 全球谐波减速器行业规划建议与发展趋势预判报告2026年版
  • 震惊!铝单板掉色变形,这些低价陷阱你躲过了吗?
  • 单VLA模型驱动多品牌机械臂协同控制
  • 星元素甄选的“逆势逻辑”:越是经费紧张,越该选靠谱的平台
  • 员工花8万美元做游戏为公司带回1亿美元AUM?竟是不到200美元的营销骗局!
  • Kylin V10 ARM64 上编译 Ambari 3.0 + BigTop 3.3 实战指南
  • DBeaver安装与JDBC驱动协同部署实操指南
  • 等保二级升三级,巡检量翻3倍,人手不增怎么过测评?
  • OpenClaw 2.6.4 本地Agent环境避坑指南:Skill注册与路径兼容性问题
  • 连续空间POMDP在线规划:参考策略与快速采样的工程实践
  • OpenClaw:从对话到实操,重新定义自主 AI 智能体
  • 大模型到底是什么
  • 以可恢复性为约束的机器人物理域能力扩展方法
  • 为什么我们建议医学生使用openevidence