前言

在将 Spring Boot 项目升级至 3.3.4 版本后,遇到 Logback 配置的兼容性问题。本文将详细描述该问题的错误信息、原因分析,并提供调整日志回滚策略的解决方案。

错误描述

这是SpringBoot 3.3.3版本之前的回滚策略的配置

    <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
        <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <maxFileSize>10MB</maxFileSize>
        </timeBasedFileNamingAndTriggeringPolicy>
        <!--日志文档保留天数-->
        <maxHistory>30</maxHistory>
    </rollingPolicy>

当 升级至 Spring Boot 3.3.4 版本后,启动时出现以下报错:

Exception in thread "main" java.lang.IllegalStateException: java.lang.IllegalStateException: Logback configuration error detected: 
ERROR in ch.qos.logback.core.model.processor.ImplicitModelHandler - Could not create component [timeBasedFileNamingAndTriggeringPolicy] of type [ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP] java.lang.ClassNotFoundException: ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP
ERROR in c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy - Filename pattern [/logs/app/%d{yyyy-MM-dd}.%i.log] contains an integer token converter, i.e. %i, INCOMPATIBLE with this configuration. Remove it.

主要问题出现在 logback 日志配置的 SizeAndTimeBasedFNATP 类以及日志文件命名中的 %i 令牌使用上。

关键错误信息:

  1. java.lang.ClassNotFoundException: ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP
  2. Filename pattern contains an integer token converter, i.e. %i, INCOMPATIBLE with this configuration

原因分析

在升级 Spring Boot 版本至 3.3.4 后,底层的 Logback 版本也随之更新。在较新的 Logback 版本中,以下变化引发了兼容性问题:

  1. SizeAndTimeBasedFNATP 类弃用

    • 在新的 Logback 版本中,SizeAndTimeBasedFNATP 类已经被移除或不再使用。之前用来支持基于大小和时间的日志滚动的策略必须替换为新的策略类。
    • 此类需要被 SizeAndTimeBasedRollingPolicy 替代,它能够同时支持按文件大小和时间进行日志滚动。
  2. 日志文件命名中的 %i 令牌不兼容

    • 日志文件命名模式中使用的 %i 令牌,用于在日志滚动时生成多个文件(如 log.1, log.2 等),但这与 TimeBasedRollingPolicy 不兼容。TimeBasedRollingPolicy 仅基于时间滚动日志,不支持 %i 分片。

解决方案

调整日志回滚策略

为了解决以上问题,我们需要将原有的 TimeBasedRollingPolicy 替换为新的 SizeAndTimeBasedRollingPolicy,并调整日志文件的命名模式以去除不兼容的 %i 令牌。

配置修改

以下是修改后的 logback-spring.xml 配置:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!-- SpringBoot默认logback的配置 -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
    <property name="LOG_HOME" value="/logs/${APP_NAME}"/>

    <!-- 1. 输出到控制台 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 2. 输出到文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/log.log</file>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} -%5level ---[%15.15thread] %-40.40logger{39} : %msg%n%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 使用SizeAndTimeBasedRollingPolicy替代旧的策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 滚动后的日志文件命名模式 -->
            <fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <!-- 日志文件的最大大小 -->
            <maxFileSize>10MB</maxFileSize>
            <!-- 最大保留30天的日志 -->
            <maxHistory>30</maxHistory>
            <!-- 总日志文件大小不超过3GB -->
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
    </appender>

    <!-- 开发环境输出至控制台 -->
    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="CONSOLE"/>
        </root>
    </springProfile>

    <!-- 生产环境输出至文件 -->
    <springProfile name="prod">
        <root level="INFO">
            <appender-ref ref="CONSOLE"/>
            <appender-ref ref="FILE"/>
        </root>
    </springProfile>

</configuration>

修改内容说明:

  1. 使用 SizeAndTimeBasedRollingPolicy

    • 该策略同时支持按时间和文件大小滚动日志。与旧的 TimeBasedRollingPolicy 类相比,它是更推荐的滚动策略。
  2. 文件命名模式调整

    • fileNamePattern 中,使用 %d{yyyy-MM-dd}-%i.log 作为文件名格式,这允许日志按照日期命名,并在同一天滚动日志时通过 %i 生成分片文件(如 2024-10-01-1.log, 2024-10-01-2.log 等)。
  3. 限制日志大小和保留时间

    • maxFileSize 设置为 10MB,表示单个日志文件的最大大小。
    • maxHistory 设置为 30,表示最多保留30天的日志文件。
    • totalSizeCap 设置为 3GB,表示日志总大小不能超过 3GB。达到该限制时,将删除最早的日志文件。

总结

在 Spring Boot 升级至 3.3.4 后,由于底层 Logback 版本的更新,原先使用的 TimeBasedRollingPolicy 类和日志文件名中的 %i 令牌会引发兼容性问题。通过调整日志回滚策略,使用新的 SizeAndTimeBasedRollingPolicy 并去除不兼容的文件命名模式,可以顺利解决这些问题,使日志系统恢复正常运行。

10-19 07:29