日志框架:Logback
前言
Logback 是一个由 Log4j 创始人 Ceki Gülcü 设计的 Java 开源日志框架 ,作为 Log4j 的继任者,它以其 高性能、灵活配置 和 原生实现 SLF4J API 等特性,成为 Spring Boot 的默认日志框架,并广泛应用于企业级开发
Logback 由三个模块构成,形成清晰的分层架构:
logback-core:基础模块,提供底层支持,不依赖 SLF4J。logback-classic:实现 SLF4J API ,是 log4j 的增强版,最常用模块。-
logback-access:与 Servlet 容器(如 Tomcat )集成,记录 HTTP 访问日志。
其核心三组件为:
- Logger:接收日志请求,决定是否处理(基于日志级别)。
- Appender:定义日志输出目的地,如控制台、文件、数据库。
- Encoder :负责将日志事件格式化为字符串(替代旧版 Layout),支持二进制输出。
主流日志框架对比
| 特性 | Logback | Log4j2 | java.util.logging (JUL) |
|---|---|---|---|
| 性能 | 高,异步支持良好 | 极高(Disruptor 异步引擎) | 低 |
| SLF4J 集成 | 原生支持 | 需桥接 | 不支持 |
| 配置灵活性 | 高(XML/Groovy) | 极高(XML/JSON/YAML) | 低(属性文件) |
| 自动重载 | 支持 | 支持 | 不支持 |
| 社区活跃度 | 高(稳定维护) | 高(活跃更新) | 低(JDK 内置,无独立更新) |
| 适用场景 | 企业级 Java 项目首选,SpringBoot 默认 | 高并发、极致性能场景 | 小型工具、无依赖需求 |
Spring Boot 选择 Logback 作为默认日志,是因为它在兼容性、性能、功能、生态、稳定性、易用性上取得了最佳平衡,完美支撑 "开箱即用" 与生产级需求。
再SpringBoot中使用
Spring Boot 选择 Logback 作为默认日志,提供了两种方式,我们从从简单到复杂、从全局到精细进行讲解。
最简方式:文件配置
特点 :不用写 XML ,纯配置项,适合简单项目。
可配置:日志级别、日志文件、包级别日志、格式等。
- 全局默认日志级别 :控制所有日志的默认级别,是日志继承的根节点(默认值为
INFO)。根日志记录器是所有日志记录器的父级,当一个日志记录器没有显式设置级别时,它会继承根记录器的级别。
yml
logging:
level:
root: info
日志级别优先级:TRACE < DEBUG < INFO < WARN < ERROR,仅当请求级别 ≥ Logger 级别时才输出。
假设你将某个 Logger 的级别设置为
INFO,那么INFO、WARN和ERROR级别的日志会被打印;而TRACE和DEBUG级别的日志则会被忽略,不会输出。
- 自定义包 / 类日志级别:设置指定包(或类)的日志记录器级别,用于对特定包或类的输出进行更精细的日志控制,优先级高于根日志记录器。
yml
logging:
level:
com.baomidou.mybatisplus: DEBUG
- 直接指定文件名:可以同时指定日志文件的路径和文件名。
yml
logging:
file:
name: ./logs/app.log
项目启动后,如果指定了完整路径(包括文件名),日志将输出到该路径下的指定文件中。若仅指定文件名,则默认在项目根目录下创建该文件。
例如:logging.file.name=/var/log/myapp/app.log 会将日志写入 /var/log/myapp/ 目录下的 app.log 文件中。
- 只指定目录,自动生成
spring.log:仅用于指定日志文件的存储路径。
yml
logging:
file:
path: logs
项目启动后,日志文件的名称默认为 spring.log。
例如:logging.file.path=/var/log/myapp 会在 /var/log/myapp/ 目录下生成名为 spring.log 的日志文件。
此外,如果两个属性同时配置,则
logging.file.name的优先级更高,会覆盖logging.file.path的设置,推荐使用logging.file.name以避免混淆并提高可读性。
- 日志格式:用于定义日志输出格式的属性,自定义日志在控制台或文件中的显示方式。
(1)logging.pattern.console:定义日志输出到控制台的格式。
yml
logging:
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%wEx%n"

常用占位符 :
%d:时间
%thread:线程名
%-5level:级别(左对齐 5 字符宽度,后面自动补空格,全部占满 5 个字符宽度),比如:[INFO ]
%logger{36}:类名(最多 36 字符)
%msg:日志内容
%n:换行
%wEx:异常信息
(2)logging.pattern.file:定义日志输出到文件的格式。
yml
logging:
pattern:
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
(3)logging.pattern.dateformat:统一控制日志时间戳格式。
yml
logging:
# 全局统一时间格式(覆盖默认)
pattern:
dateformat: yyyy-MM-dd HH:mm:ss.SSS
logging.pattern.console和logging.pattern.file都能自定义日期格式,再dateformat中配置统一格式,避免混乱,减少重复代码:
yml
logging:
pattern:
dateformat: yyyy-MM-dd HH:mm:ss.SSS
console: "%d [%thread] %-5level %logger{36} - %msg%wEx%n"
file: "%d [%thread] %-5level %logger{36} - %msg%wEx%n"
(4)logging.pattern.level :定义日志级别(INFO、WARN、ERROR)的显示格式。
常用占位符 :
%p输出日志级别(INFO/WARN/ERROR)
%5p固定占 5 个字符宽度,对齐美观
%clr()Spring 提供的颜色渲染
{bold}加粗
{red}{yellow} 颜色
yml
logging:
pattern:
level: "%clr(%5p){faint}%clr(%5p){bold}" # Spring 自带
- 日志文件滚动切割:用来控制日志文件什么时候切分、保留多久、占用多少空间。
(1)clean-history-on-start :启动时是否清除已归档的历史日志文件。默认 false,一般不用配置,留空即可。
yml
logging:
logback:
rollingpolicy:
clean-history-on-start: true
(2)file-name-pattern:当日志文件达到滚动条件(如时间或大小)时,旧日志文件被重命名的格式。它通常包含时间戳和索引占位符,例如:
yml
logging:
logback:
rollingpolicy:
file-name-pattern: logs/%d{yyyy-MM}/info.%d{yyyy-MM-dd}.%i.gz
常用占位符 :
logs/%d{yyyy-MM}:日志存在项目下的logs文件夹里,按月创建文件。
%d{yyyy-MM-dd}:按天切割。
%i:同一天内,文件超过大小就递增序号(1、2、3...)。
.log:后缀。
.gz:表示压缩归档文件
(3)max-file-size :单个日志文件最大大小,默认:100MB,超过 100MB 自动切分,生成新文件:
yml
logging:
logback:
rollingpolicy:
max-file-size: 500MB
支持单位:KB、MB、GB。
(4)max-history :最多保留最近多少天的日志,默认情况下,max-history 的值通常为 7 天,意味着只保留最近一周的归档日志。当 max-history 设置为 0 时,Spring Boot 不会自动删除旧的日志文件
yml
logging:
logback:
rollingpolicy:
max-history: 7
(5)total-size-cap:所有日志文件总大小上限,默认不限制。
yml
logging:
logback:
rollingpolicy:
total-size-cap: 3GB # 所有日志文件总大小不超过3GB
完整配置如下:
yml
logging:
logback:
rollingpolicy:
file-name-pattern: logs/%d{yyyy-MM}/info.%d{yyyy-MM-dd}.%i.gz
max-file-size: 500MB
max-history: 7
total-size-cap: 3GB
日志存到 logs 目录,按月归类、按日命名,单文件 500MB 拆分、旧日志自动压缩;最多存 7 天 日志,所有日志加起来绝不超过 3GB。
- 编码格式 :默认使用系统默认编码,这可能导致日志文件中出现乱码,特别是当系统默认编码不是 UTF-8 时。
(1)logging.charset.console:设置控制台输出的日志编码格式。
yml
logging:
charset:
console: UTF-8
(2)logging.charset.file:设置写入文件的日志编码格式。
yml
logging:
charset:
file: UTF-8
- 日志分组(批量设置级别):把一堆包归为一组,统一设级别。
yml
logging:
group:
web: org.springframework.controller,org.springframework.web
sql: org.mybatis,java.sql
level:
web: info
sql: warn
- 异常堆栈输出 :默认:
%wEx,会在异常信息的开始和结束处添加空行。这有助于在日志中更清晰地分隔异常信息,提高可读性。它会输出完整的异常堆栈跟踪,并在前后添加空行。
yml
logging:
exception-conversion-word: "%wEx"
10:30:45.123 [main] ERROR com.example.MyClass - 业务处理失败
java.lang.RuntimeException: 业务处理失败
at com.example.MyClass.main(MyClass.java:10)
Caused by: java.sql.SQLException: 数据库连接失败
at com.example.MyClass.main(MyClass.java:6)
Process finished with exit code 1
除了%wEx外,还有%ex、%rEx、%xEx ,这 3 个都是打印异常堆栈的格式:
(1)%ex:这是最基本的异常信息转换符。它会输出异常的类型、消息以及完整的堆栈跟踪信息。这是最常用的异常输出格式。
10:30:45.123 [main] ERROR com.example.MyClass - 业务处理失败
java.lang.RuntimeException: 业务处理失败
at com.example.MyClass.main(MyClass.java:10)
Caused by: java.sql.SQLException: 数据库连接失败
at com.example.MyClass.main(MyClass.java:6)
(2)%rEx:与 %ex 类似,但会输出异常的根原因(root cause)信息。它会显示异常的完整堆栈跟踪,但更侧重于异常链的根部原因,这对于理解问题的根本原因很有帮助。
10:30:45.123 [main] ERROR com.example.MyClass - 业务处理失败
java.lang.RuntimeException: 业务处理失败
at com.example.MyClass.main(MyClass.java:10)
Caused by: java.sql.SQLException: 数据库连接失败
at com.example.MyClass.main(MyClass.java:6)
(3)%xEx:这个转换符不仅输出异常信息,还会在每一行异常信息后面追加 JAR 包的信息。这对于调试时确定具体是哪个 JAR 包中的类抛出了异常非常有用。它会输出完整的堆栈跟踪,并包含 JAR 包的详细信息。
10:30:45.123 [main] ERROR com.example.MyClass - 业务处理失败
java.lang.RuntimeException: 业务处理失败
at com.example.MyClass.main(MyClass.java:10) [myapp.jar]
Caused by: java.sql.SQLException: 数据库连接失败
at com.example.MyClass.main(MyClass.java:6) [myapp.jar]
- 指定日志配置文件 :你不想用默认的
logback-spring.xml,想自己改名字、放别的目录,就必须用logging.config指定。
一般情况,默认寻找:src/main/resources/logback-spring.xml文件
如果,你想将文件名改成:my-log.xml 或者放到:resources/config/my-log.xml:
yml
logging:
config: classpath:config/my-log.xml
- 日志写入完整性 :关闭时,保证日志能写完、不丢失,默认:
true。
程序要立刻退出,但日志可能还在缓冲区里,没来得及写入文件,如果直接退出,最后几条日志就丢了。
yml
logging:
register-shutdown-hook: true # 开启安全关闭钩子
常用配置
完整且常用的 yml 日志模板:
yml
# 日志核心配置
logging:
# 日志文件路径(自动创建文件夹+文件)
file:
name: logs/app.log
# 日志级别
level:
root: info # 全局默认级别
com.example.demo: debug # 你的包路径(按需改)
# 日志格式
pattern:
# 控制台格式(SpringBoot 官方默认标准格式)
console: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p){bold} %clr(${PID:- }){magenta} %clr(---){faint} %clr([%5.50t]){faint} %clr(%-40.40logger{39} %line){cyan} %clr(:){faint} %m%n%wEx"
# 文件格式(和控制台 100% 一模一样,统一整齐)
file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %-40logger{39} [%line] - %msg%n"
# 日志文件滚动切割
logback:
rollingpolicy:
file-name-pattern: logs/%d{yyyy-MM}/info.%d{yyyy-MM-dd}.%i.gz
max-file-size: 500MB
max-history: 7
total-size-cap: 10GB
# 日志编码格式
charset:
console: UTF-8
file: UTF-8
简单项目、只想改日志级别,推荐用yml方式,快、省事,不需要额外文件;复杂日志规则、多环境、自定义格式,必须用 xml,功能强大、标准。
默认框架配置:XML配置
SpringBoot 加载日志配置的顺序:
logback-spring.xml -> logback.xml -> application.yml / application.properties
yml 配置优先级低于 xml方式,读到 logback.xml 或 logback-spring.xml后,日志系统已经初始化完成,yml 里的相关配置会失效。
SpringBoot推荐使用logback-spring.xml。
logback.xml属于原生 Logback 配置,被 Logback 自己加载,比SpringBoot 容器加载要早,拿不到 SpringBoot 的配置信息;
logback-spring.xml由SpringBoot 接管,SpringBoot 启动后能通过占位符拿到所有配置信息。
logback-spring.xml 默认存放位置(SpringBoot 会自动找的默认文件名):
src/main/resources/logback-spring.xml
如果,你想将文件名改成:my-log.xml 或者 放到:resources/config/my-log.xml(不推荐):
yml
logging:
config: classpath:config/my-log.xml
先在resources目录下创建logback-spring.xml文件,填充Logback基础模板
顶层根标签
<configuration>标签:顶层根标签,所有日志配置都必须写在它里面,相当于日志配置的 "总容器"。
xml
<!--XML 声明-->
<?xml version="1.0" encoding="UTF-8" ?>
<!--根标签-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
</configuration>
(1)scan :是否自动扫描配置文件变化,修改 logback.xml 后不用重启项目就能生效。默认值:false。
(2)scanPeriod :自动扫描配置文件的间隔时间,只有 scan="true" 时才生效。默认值:60 seconds(1 分钟),单位支持:milliseconds / seconds / minutes / hours。
(3)debug :是否打印 logback 自身的内部调试日志。默认值:false。
变量 / 属性标签
<property>标签 :定义全局变量,方便复用,通过${变量名}引用。
xml
<property name="LOG_PATH" value="logs/app" />
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %-40logger{39} [%line] - %msg%n" />
(1)name:变量名。必填,用于引用的键。
(2)value:变量值。变量的具体内容。
输出器
<appender>标签:日志输出目的地:控制台、文件、滚动文件、Socket 等。
xml
<!--控制台输出-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
</appender>
(1)name:唯一名称,给 logger 引用。
(2)class :输出器实现类。常用Class :ch.qos.logback.core.ConsoleAppender(控制台)、ch.qos.logback.core.FileAppender(文件)、ch.qos.logback.core.rolling.RollingFileAppender(滚动文件)、ch.qos.logback.classic.AsyncAppender(异步输出)。
ch.qos.logback.core.ConsoleAppender:这是用于将日志输出到控制台的 Appender 。它通常与<encoder>配合使用来格式化日志输出。
xml
<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>
这个配置会将日志输出到控制台,并按照指定的格式进行格式化。
ch.qos.logback.core.FileAppender:将日志输出到文件的 Appender。它会将所有日志写入到指定的文件中。
xml
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>logs/app.log</file>
<append>true</append> <!-- 追加写入 -->
<charset>UTF-8</charset>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %-40logger{39} [%line] - %msg%wEx%n</pattern>
</encoder>
</appender>
这个配置会一直将日志写入到名为 logs/app.log的文件中,一般不用。
ch.qos.logback.core.rolling.RollingFileAppender:这是用于将日志输出到文件,并支持日志滚动(例如按日期或文件大小滚动 )的 Appender 。它通常与<rollingPolicy>和<triggeringPolicy>配合使用。
xml
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<append>true</append>
<charset>UTF-8</charset>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 切割后的文件路径 -->
<fileNamePattern>logs/%d{yyyy-MM}/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<!-- 单个文件最大大小 -->
<maxFileSize>500MB</maxFileSize>
<!-- 保留30天 -->
<maxHistory>30</maxHistory>
<!-- 总大小限制 -->
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %-40logger{39} [%line] - %msg%wEx%n</pattern>
</encoder>
</appender>
特点:按天 / 按大小切割、自动压缩 .gz、自动删除旧日志、控制总占用空间、不占满磁盘。
ch.qos.logback.classic.AsyncAppender:用于异步输出日志的 Appender 。它会将日志事件放入一个阻塞队列中,然后由一个或多个后台线程处理这些事件,从而提高日志记录的性能(它自己不写文件,只是包装别的appender!)。
xml
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>logs/app.log</file>
<append>true</append> <!-- 追加写入 -->
<charset>UTF-8</charset>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %-40logger{39} [%line] - %msg%wEx%n</pattern>
</encoder>
</appender>
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE"/>
<queueSize>1024</queueSize>
<discardingThreshold>0</discardingThreshold>
<neverBlock>true</neverBlock>
<includeCallerData>false</includeCallerData>
<maxFlushTime>1000</maxFlushTime>
</appender>
(1)<appender-ref>标签 :引用一个已定义好的 appender。
(2)<queueSize>标签 :异步日志队列大小,最多能缓存 1024 条日志。默认 256。
(3)<discardingThreshold>标签 :队列剩余空间低于多少时,开始丢弃低级日志,默认值是 20,你写0表示永远不主动丢弃。
(4)<neverBlock>标签:队列满了,也绝不阻塞业务代码。
(5)<includeCallerData>标签 :是否获取类名、方法名、行号等调用者信息,建议设置false,获取这些信息非常耗性能。
(6)<maxFlushTime>标签:服务关闭时,最多等 1000 毫秒,把队列里剩余日志刷入文件。
日志文件路径
<file>标签:设置日志文件路径。
xml
<file>${LOG_PATH}/app.log</file>
滚动策略
<rollingPolicy>标签:定义日志文件滚动策略,决定何时以及如何滚动日志文件。
常见的滚动策略包括:TimeBasedRollingPolicy (按时间)、SizeAndTimeBasedRollingPolicy (按大小 + 时间)、FixedWindowRollingPolicy(固定窗口滚动,几乎不用)。
TimeBasedRollingPolicy :基于时间进行滚动,例如每天、每小时或每月生成一个新的日志文件app.2026-04-01.log、app.2026-04-02.log。
xml
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
(1)<fileNamePattern>标签:指定滚动日志文件的命名模式,通常包含日期或索引等信息。
%d 转换符用于表示日期,可以指定日期格式。
(2)<maxHistory>标签:指定保留多少天。
SizeAndTimeBasedRollingPolicy:既按天切分,单个文件超过指定大小也会立即切分。
xml
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
%i 转换符用于表示文件索引(当按大小滚动时)。
(1)<maxFileSize>标签:指定单个日志文件的最大大小。
(2)<totalSizeCap>标签 :指定所有历史日志文件的总大小上限。当总大小超过此值时,将删除最旧的日志文件,默认值为 0(表示无总大小限制)。
FixedWindowRollingPolicy :基于文件数量进行滚动,通过文件索引(如 %i)来管理归档文件(几乎不用)。
xml
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>logs/app.%i.log.gz</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
(1)<minIndex>标签:指定滚动文件的最小索引值。
(2)<maxIndex>标签:指定滚动文件的最大索引值。
在实际应用中,SizeAndTimeBasedRollingPolicy 更为常用,因为它更符合现代日志管理的需求。
日志格式编码
<encoder>标签:用于对日志事件进行格式化,将日志信息转换为可输出的字符串格式。
xml
<encoder>
<!--日志格式-->
<pattern>${LOG_PATTERN}</pattern>
<!--编码格式-->
<charset>UTF-8</charset>
</encoder>
日志过滤器
<filter>标签:过滤器日志事件,只输出符合条件的日志。
xml
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
<evaluator>
<expression>message.contains("login")</expression>
</evaluator>
</filter>
<onMatch>标签:配置符合过滤条件时的操作,值:ACCEPT (放行)、NEUTRAL (不处理)、DENY(拒绝)。
<onMismatch>标签:配置不符合过滤条件时的操作,值:ACCEPT (放行)、NEUTRAL (不处理)、DENY(拒绝)。
最常用过滤器:
(1)ThresholdFilter :阈值过滤器,只输出指定级别的日志(>=Level)。
xml
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
(2) LevelFilter:精确级别过滤器,只输出 / 只拒绝 某一个精确级别的日志。
xml
<!--只输出 ERROR-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level> <!-- 精确匹配 -->
<onMatch>ACCEPT</onMatch> <!-- 匹配就放行 -->
<onMismatch>DENY</onMismatch><!-- 不匹配就拒绝 -->
</filter>
(3)EvaluatorFilter:自定义表达式 / 条件过滤器。
xml
<!--包含 login 才输出-->
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<expression>message.contains("login")</expression>
</evaluator>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
其它不常用标签
<append>标签:控制日志是否追加到文件末尾,而不是覆盖文件内容。 默认:true,表示追加日志。
xml
<append>true</append>
<target>标签:指定日志输出到System.out或System.err,通常用于 ConsoleAppender (控制台输出)。默认值为System.out。
xml
<target>System.err</target>
<prudent>标签:控制日志文件的写入方式,确保在多线程或多进程环境中安全地写入日志,默认值:false。
xml
<prudent>true</prudent>
开启后性能下降 5--10 倍。
<triggeringPolicy>标签:定义何时触发日志滚动,即什么条件满足时会触发滚动操作。
滚动策略有:TimeBasedRollingPolicy (时间触发)到时间就切、SizeBasedTriggeringPolicy(大小触发)文件超过指定大小就切。
xml
<!-- 旧式写法(现在基本不用) -->
<rollingPolicy class="FixedWindowRollingPolicy">
<fileNamePattern>logs/app.%i.log</fileNamePattern>
</rollingPolicy>
<!-- 旧式必须写这个 -->
<triggeringPolicy class="SizeBasedTriggeringPolicy">
<maxFileSize>100MB</maxFileSize>
</triggeringPolicy>
在新版 Logback 中,<triggeringPolicy> 已经不需要手动写了!TimeBasedRollingPolicy 内部自带时间触发和SizeAndTimeBasedRollingPolicy 内部自带大小 + 时间触发。
常用清单
<appender>标签比较详细且常用的配置示例:
xml
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<file>logs/server.log</file>
<!-- 追加写入 -->
<append>true</append>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
<!-- 过滤器:只输出 INFO 及以上 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<!-- 日志格式 -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
除了上述介绍的,还有很多,有兴趣的可以自行研究。
日志器标签
<logger>标签 :定义特定包或类的日志行为。它允许你为不同的包或类设置不同的日志级别,从而实现对日志输出的精细化控制。
xml
<logger name="包名/类全名" level="日志级别" additivity="true/false">
<appender-ref ref="输出到哪里" />
</logger>
name:必填,要控制的包名或类全名,例如,name="com.example.myapp"。level:可选属性,用于设置日志级别,输出什么级别以上的日志。默认继承父<logger>的日志级别。可选值包括TRACE<DEBUG<INFO<WARN<ERRORadditivity:可选属性,控制日志是否向上传播到父级 Logger 。默认值为true。
xml
<!-- 让 controller 包输出 DEBUG 日志,其他包保持 INFO -->
<logger name="com.example.controller" level="DEBUG" />
<!-- 打印 MyBatis SQL -->
<logger name="com.example.mapper" level="DEBUG" />
引用一个已定义好的 appender。
xml
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 为特定包设置日志级别和 Appender -->
<logger name="com.example.myapp" level="INFO">
<appender-ref ref="STDOUT" />
</logger>
根日志器
<root>标签 :默认全局日志配置,所有 logger 最终都会走到这里。整个应用所有日志的最终接收者、最终输出者,整个配置文件只能出现一个<root>标签。
如果你没有给某个包配置 <logger>,所有类的日志级别默认使用 root 的级别。
xml
<root level="INFO">
你配置的控制台、文件输出,最终都要在 root 里绑定才会生效。
xml
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
<logger>标签是局部配置,<root>标签是全局兜底。
<logger name="xxx">只对 name 指定的包 / 类生效;<root>对整个项目所有类生效,是全局默认规则。
所以如果你这样配:
xml
<logger name="com.example" level="DEBUG">
<appender-ref ref="FILE"/>
</logger>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
那么 com.example 包的日志:会输出到 FILE (自己 logger ),同时也会输出到 CONSOLE (传给 root)。
如果不想向上传递:
xml
<logger name="com.example" level="DEBUG" additivity="false">
<appender-ref ref="FILE"/>
</logger>
这样就不会再CONSOLE输出。
上下文标签
<contextName>标签 :设置日志上下文名称,用于区分不同应用的日志,可通过%contextName在日志格式中输出。
xml
<!-- 设置上下文名称 -->
<contextName>spring-boot-app</contextName>
<!-- 控制台输出 appender -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg (%contextName)%n</pattern>
</encoder>
</appender>
如果只是配置了 <contextName> 而没有在 <pattern> 中使用 %contextName,那么该名称不会出现在日志输出中。
读取Spring配置
<springProperty> 标签主要用于在 Logback 配置文件中引用 Spring 应用程序的属性值。它允许你在 Logback 的配置中使用 Spring 环境中的属性,从而实现日志配置与应用程序配置的一致性。
xml
<springProperty scope="context" name="property_name" source="property_source" [defaultValue="default_value"] />
scope:指定从 Spring 上下文中读取属性值,通常设置为context。name:在 Logback 配置中定义的属性名称。source:指定从 Spring 应用程序配置文件中读取的属性源。defaultValue:可选属性,如果 Spring 上下文中找不到指定的属性,则使用默认值。
假设你的 Spring Boot 应用程序的 application.properties 文件中包含如下配置:
perl
spring.application.name=my-app
server.port=8080
logging.path=/var/logs/myapp
在 Logback 的配置文件 logback-spring.xml 中,你可以使用 <springProperty> 标签来动态引用这些属性值:
xml
<configuration scan="false" debug="false">
<!-- 从 Spring 上下文中读取属性值 -->
<springProperty scope="context" name="spring_application_name" source="spring.application.name"/>
<springProperty scope="context" name="server_port" source="server.port"/>
<springProperty scope="context" name="LOG_HOME" source="logging.path" defaultValue="../logs"/>
<!-- 定义日志输出格式 -->
<property name="CONSOLE_LOG_PATTERN" value="%clr(${spring_application_name}){cyan}||%clr(%d{ISO8601}){faint}|%clr(%p)|%X{requestId}|%X{X-B3-TraceId:-}|%X{requestIp}|%X{userIp}|%ip|${server_port}|${PID}|%clr(%t){faint}|%clr(%.40logger{39}){cyan}.%clr(%method){cyan}:%L|%m|%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 定义控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
</configuration>
除此之外,还可以使用<springProperty> 标签进行多环境切换,示例如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 读取 SpringBoot yml 中的服务名(可选) -->
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="app"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %-40logger{39} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/${APP_NAME}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/%d{yyyy-MM}/%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>500MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %-40logger{39} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
</appender>
<!-- 开发环境 dev -->
<springProfile name="dev">
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<!-- 测试环境、生产环境共用 -->
<springProfile name="test,prod">
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</springProfile>
</configuration>
大多数情况下,用一套配置就行。
MDC
Logback 的 MDC (Mapped Diagnostic Context ,映射诊断上下文)是 SLF4J 提供的一种方便在多线程条件下记录日志的功能。它本质上是一个与当前线程绑定的哈希表,可以往其中添加键值对。
在分布式系统或多线程场景中,一个请求可能会经过多个线程、多个服务处理。MDC 可以统一标记同一请求的所有日志,通过在 MDC 中设置全局唯一的 traceId,让该请求触发的所有日志都携带这个 ID。
代码里放入值:
java
import org.slf4j.MDC;
// 在请求入口处设置
MDC.put("traceId", UUID.randomUUID().toString());
MDC.put("userId", userId);
在 xml 中通过%X{traceId}、 %X{userId}追加:
xml
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d [%thread] %-5level %-40logger{39} [%line] [traceId=%X{traceId}] [userId=%X{userId}] - %msg%n</pattern>
</encoder>
</appender>
</configuration>
请求结束后清除:
java
MDC.clear();
输出效果:
bash
2026-04-05 22:50:00.123 [http-nio-8080-exec-1] INFO com.example.controller [25] [traceId=a1b2c3d4] [userId=10086] - 查询订单成功
MDC 为在复杂的分布式系统中追踪日志提供了有效的解决方案,使得日志能够携带上下文信息,便于问题排查和系统监控。
注解使用
@Slf4j 是 Lombok 提供的一个注解,用于在 Java 类中快速集成日志功能。
传统方式定义 Logger:
java
public class UserService {
private static final Logger log = LoggerFactory.getLogger(UserService.class);
public void login(String username) {
log.info("用户 {} 登录成功", username);
}
}
使用 @Slf4j 注解方式:
java
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class UserService {
public void login(String username) {
log.info("用户 {} 登录成功", username);
}
}
编译后,class 文件里自动变成:
java
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
}
使用 @Slf4j 需要:添加 Lombok 依赖、在 IDE 中安装 Lombok 插件:
xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
@Slf4j 就是帮你偷懒的,少写一行代码。
常用配置
完整且常用的 xml 日志模板:
xml
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="false" debug="false">
<!-- 1. 引入Spring默认配置(解决clr) -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<property name="LOG_PATH" value="logs/app"/>
<property name="LOG_PATTERN"
value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p){bold} %clr(${PID:- }){magenta} %clr(---){faint} %clr([%5.50t]){faint} %clr(%-40.40logger{39} %line){cyan} %clr(:){faint} %m%n"/>
<property name="FILE_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %-40logger{39}:%line - %msg%n"/>
<property name="ENCODING" value="UTF-8"/>
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!-- 滚动文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/info.log</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/%d{yyyy-MM}/info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>500MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 错误日志文件输出 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/error.log</file>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>500MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>
<!-- 包级别日志控制 -->
<logger name="org.springframework" level="WARN"/>
<logger name="com.baomidou.mybatisplus" level="WARN"/>
<logger name="com.yourpackage" level="INFO"/>
<!-- 根日志(全局生效) -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>
</configuration>