简单总结日志管理

系统梳理一下 Spring Boot 中的日志体系,包括涉及到的组件、它们之间的区别、优势、以及使用上的一些关键知识点。


一、Spring Boot 默认用到的日志组件

  1. Commons Logging (Jakarta Commons Logging, JCL)

    • Spring 框架本身最早使用的日志门面(facade)。
    • Spring Boot 会把它桥接到 SLF4J。
  2. SLF4J (Simple Logging Facade for Java)

    • 日志门面:只定义接口,不负责日志的具体实现。
    • 常用的接口方法:logger.info(), logger.debug(), logger.error() 等。
    • 优点:屏蔽底层实现差异,支持灵活替换。
  3. Logback

    • Spring Boot 默认的日志实现(在 spring-boot-starter-logging 里)。
    • 高性能,支持异步日志,支持灵活的配置(logback-spring.xml)。
    • 提供分级别日志、滚动日志、异步输出等。
  4. Log4j2

    • 新一代的 Log4j,性能比 Logback 更强,支持异步日志(基于 LMAX Disruptor)。
    • 配置文件灵活(XML、JSON、YAML)。
    • 需要替换默认依赖:排除 spring-boot-starter-logging,引入 spring-boot-starter-log4j2
  5. Java Util Logging (JUL)

    • JDK 自带的日志框架,功能较弱,扩展性差。
    • 一般只作为兼容层使用。

二、它们之间的区别和优势

组件 类型 优势 劣势
Commons Logging 门面 早期 Spring 框架支持 已被 SLF4J 替代
SLF4J 门面 统一日志 API,桥接能力强 需要绑定实现
Logback 实现 默认,性能好,配置强大 启动速度比 Log4j2 慢一点
Log4j2 实现 性能极佳,异步日志领先 需要手动替换
JUL 实现 自带,零依赖 功能弱,扩展性差

三、日志等级与生效配置

日志级别从高到低(优先级):

ERROR > WARN > INFO > DEBUG > TRACE

  • 如果配置了 INFO,则 INFO、WARN、ERROR 会输出,DEBUG、TRACE 不会。
  • Spring Boot 默认等级是 INFO

配置方式:

1
2
3
4
5
logging:
level:
root: INFO
com.example.demo: DEBUG # 指定包
org.springframework.web: WARN # Spring Web 模块

也可以在 application.properties 中:

1
2
logging.level.root=INFO
logging.level.com.example.demo=DEBUG

例子:如果只想在控制台打印执行的sql,但是不打印结果,可以设置相关包路径DEBUG,

四、日志分层管理的原理

日志框架是怎么做到“分层管理”,以及日志等级是怎么注册、生效的。我分几个步骤来讲清楚整个原理(以 SLF4J + Logback 为例,Log4j2 原理类似)。


1. 日志体系的分层模型

日志的“分层管理”来自 Logger 的层级树结构,对应 包名/类名的层次

  • 每一个类通常会定义自己的 Logger,如:

    1
    private static final Logger logger = LoggerFactory.getLogger(MyService.class);
  • Logger 的名字一般是 类的全限定名com.example.service.MyService)。

  • Logger 是树状结构:

    1
    2
    3
    4
    5
    6
    root
    └── com
    └── example
    ├── service
    │ └── MyService
    └── repository

👉 父子关系规则

  • com.examplecom.example.service.MyService 的父 logger。
  • 如果子 logger 没有单独配置等级,就会继承父 logger 的等级。

2. Logger 注册过程

  1. 获取 Logger
    • 调用 LoggerFactory.getLogger(clazz)
    • SLF4J 只是 facade,最终会调用底层实现(比如 Logback 的 LoggerContext)。
  2. LoggerContext 管理所有 Logger
    • LoggerContext 维护一张 logger name → Logger 对象 的 Map。
    • 如果请求的 logger 不存在,就新建一个,并挂在对应父 logger 下。
    • 默认情况下,所有 Logger 最终都继承自 root logger
  3. root logger 特殊性
    • 必须存在,默认等级是 DEBUG(Logback)或 INFO(Spring Boot 默认配置覆盖)。
    • 所有没有明确配置的 logger 最终都会走 root 的等级。

3. 日志等级的生效机制

日志有 5 个常用等级(Logback/Log4j2 都一样):
TRACE < DEBUG < INFO < WARN < ERROR

生效过程

  1. 设置等级

    • 可以针对 root 或某个具体包/类配置等级:

      1
      2
      logging.level.root=INFO
      logging.level.com.example.service=DEBUG
  2. 日志调用时判断

    • 调用 logger.debug("...") → Logger 会先检查自己的 有效等级(effective level)
    • 有效等级的计算方式:
      • 当前 logger 有配置 → 使用当前等级
      • 没有配置 → 继承父 logger 的等级(逐层向上找,直到 root)
  3. 等级比较

    • 如果 调用等级 >= 有效等级 → 允许打印
    • 否则丢弃,不进入 appender。

例如:

1
2
logging.level.root=INFO
logging.level.com.example=DEBUG
  • logger.debug()com.example.MyClass → 会输出(因为生效等级 DEBUG ≤ 调用等级 DEBUG)。
  • logger.debug()org.springframework.web → 不输出(继承 root,生效等级 INFO,DEBUG < INFO)。

4. Appender 与 Filter 生效

  • 日志被判断“允许输出”后,会传给 Appender(输出器,比如 console/file)。
  • Appender 可以再挂 Filter(比如只允许 WARN+)。
  • 最终决定是否写入日志目标。

5. 小结(原理串起来)

  • 注册
    LoggerFactory.getLogger() → LoggerContext 查找/创建 Logger → 挂到层级树上。
  • 生效等级
    每个 Logger 都有一个“有效等级”,优先取自己的配置,否则继承父级,一直回退到 root。
  • 调用时判断
    logger.debug() → 判断调用等级和有效等级 → 通过则进入 Appender。
  • Appender 输出
    日志事件传递到 Appender → 可能经过 Filter → 最终写到控制台/文件。

📌 一句话总结
日志分层管理的原理就是:Logger 以包/类为树状结构组织,等级自顶向下继承,调用时逐级比较有效等级,满足条件才会进入输出器


五、SLF4J 是怎么管理多个实现的

SLF4J 本身不做日志输出,它通过 绑定(binding jar) 来决定最终使用哪个实现:

  • 常见的绑定包:

    • slf4j-logback → 绑定 Logback
    • slf4j-log4j2 → 绑定 Log4j2
    • jul-to-slf4j → 把 JUL 桥接到 SLF4J
  • 桥接机制
    如果系统中混用多个日志框架,SLF4J 提供桥接器来把其他日志统一路由到一个实现:

    • jcl-over-slf4j → 把 Commons Logging 转发到 SLF4J
    • log4j-over-slf4j → 把 Log4j 转发到 SLF4J
    • jul-to-slf4j → 把 JUL 转发到 SLF4J

最终,所有日志都会统一到 SLF4J,再交给某个具体实现(比如 Logback)来打印。


六、Spring Boot 使用日志的常见知识点

  1. 默认配置文件

    • logback-spring.xml → 推荐 Spring Boot 扩展标签(如 profile 分组)。
    • logback.xml → 标准 logback 配置文件。
  2. 日志输出位置

    • 默认输出到 控制台

    • 配置输出到文件:

      1
      2
      3
      4
      5
      6
      7
      8
      logging:
      file:
      name: app.log
      logback:
      rollingpolicy:
      file-name-pattern: logs/app-%d{yyyy-MM-dd}.%i.log
      max-file-size: 10MB
      max-history: 30
  3. 异步日志

    • Logback 支持 AsyncAppender
    • Log4j2 支持原生异步日志,性能更强。
  4. 占位符写法(避免字符串拼接浪费性能)

    1
    logger.debug("User id: {}, name: {}", userId, userName);

🔑 总结一句话
Spring Boot 默认使用 SLF4J + Logback。SLF4J 负责统一 API,桥接不同实现;Logback 则负责具体日志输出。如果要追求极致性能,可以切换到 Log4j2。日志等级、输出位置和异步化是使用时的核心关注点。