为什么写这个呢?

因为我遇到了一个问题多个%d的问题,日志文件要么不按照日期文件目录划分,要么日志文件名字不变,结果处理了好久

原来是因为logback只会根据第一个%d去划分,所以需要忽略前面的%d,添加一个

,aux

很关键,这样他就会忽略前面的按照后面的来滚动划分,具体看实战案例

以下是 基于Logback 1.5.12logback.xml 完整配置详解,涵盖核心组件、常用场景和该版本的注意事项。

实战案例

及其简略的案例,可以生产直接使用

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <contextName>com.cmit</contextName>
    <property name="pattern"
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L -[%X{TRACE_ID}] - %msg %n"/>

    <property name="LOG_HOME" value="logs"/>
    <property name="PROJECT_NAME" value="project-name"/>
    <property name="MAX_FILE_SIZE" value="10MB" />
    <property name="MAX_HISTORY" value="200" />

    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <!-- 文件输出 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/${PROJECT_NAME}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/%d{yyyy-MM,aux}/${PROJECT_NAME}/${PROJECT_NAME}-%d{yyyy-MM-dd}-%i.log.gz</fileNamePattern>
            <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
            <maxHistory>${MAX_HISTORY}</maxHistory>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>

</configuration>

文件基础结构

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 属性定义 -->
    <property name="LOG_HOME" value="./logs"/>
    <property name="APP_NAME" value="myapp"/>
    
    <!-- Appender 定义 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        ...
    </appender>
    
    <!-- Logger 定义 -->
    <logger name="com.example" level="DEBUG"/>
    
    <!-- 根 Logger -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>

核心组件详解

<configuration> 根标签属性

属性 说明 示例
scan 是否自动扫描配置文件变更 scan="true"
scanPeriod 扫描间隔,默认 60 秒 scanPeriod="30 seconds"
debug 是否打印 logback 内部状态 debug="false"
<configuration scan="true" scanPeriod="30 seconds" debug="false">

<property> 属性定义

<!-- 直接定义 -->
<property name="LOG_PATH" value="/var/log/myapp"/>

<!-- 引用系统属性 -->
<property name="LOG_PATH" value="${user.home}/logs"/>

<!-- 默认值语法(属性不存在时使用默认值) -->
<property name="LOG_LEVEL" value="${LOG_LEVEL:-INFO}"/>

Appender 详解

ConsoleAppender(控制台输出)

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <!-- 日志立即刷新,性能会略降但确保不丢失 -->
    <immediateFlush>true</immediateFlush>
    
    <!-- 编码器 -->
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
    
    <!-- 过滤器:只输出 INFO 及以上 -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>INFO</level>
    </filter>
</appender>

常用 Pattern 符号:

符号 含义
%d{...} 日期时间
%thread 线程名
%-5level 日志级别,左对齐占5字符
%logger{36} Logger 名,最长36字符
%msg / %m 日志消息
%n 换行
%line / %L 输出代码行号(性能开销大,生产慎用
%M 方法名(性能开销大

FileAppender(单文件输出)

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${LOG_HOME}/app.log</file>
    <append>true</append>  <!-- true=追加,false=覆盖 -->
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %level %logger - %msg%n</pattern>
    </encoder>
</appender>

RollingFileAppender(滚动日志)⭐最常用

<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 当前正在写入的文件 -->
    <file>${LOG_HOME}/app.log</file>
    
    <!-- 滚动策略 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- 归档文件名格式,%d 触发按天滚动 -->
        <fileNamePattern>${LOG_HOME}/app.%d{yyyy-MM-dd}.log</fileNamePattern>
        <!-- 保留最近 30 天的归档日志 -->
        <maxHistory>30</maxHistory>
        <!-- 启动时清理超期日志 -->
        <cleanHistoryOnStart>true</cleanHistoryOnStart>
        <!-- 单个归档文件最大 100MB(TimeBasedRollingPolicy 不支持,需用 SizeAndTimeBasedRollingPolicy) -->
    </rollingPolicy>
    
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

SizeAndTimeBasedRollingPolicy(按时间和大小双重滚动)⭐推荐

<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_HOME}/app.log</file>
    
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <!-- %i 是序号,同一天内超过大小则递增 -->
        <fileNamePattern>${LOG_HOME}/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
        <!-- 单个文件最大 100MB -->
        <maxFileSize>100MB</maxFileSize>
        <!-- 保留 30 天的日志 -->
        <maxHistory>30</maxHistory>
        <!-- 所有日志总大小上限(防止磁盘满) -->
        <totalSizeCap>10GB</totalSizeCap>
        <!-- 启动时清理 -->
        <cleanHistoryOnStart>true</cleanHistoryOnStart>
    </rollingPolicy>
    
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

注意SizeAndTimeBasedRollingPolicyTimeBasedRollingPolicy 的子类,功能更强大,生产环境建议直接使用这个

Logger 层级配置

<!-- 设置特定包的日志级别 -->
<logger name="com.example.dao" level="DEBUG" additivity="false">
    <appender-ref ref="CONSOLE"/>
    <appender-ref ref="ROLLING_FILE"/>
</logger>

<!-- Spring 框架日志 -->
<logger name="org.springframework" level="WARN"/>
<logger name="org.springframework.jdbc" level="DEBUG"/>

<!-- MyBatis 日志 -->
<logger name="com.ibatis" level="DEBUG"/>
<logger name="java.sql" level="DEBUG"/>

<!-- 根 Logger,所有日志的默认配置 -->
<root level="INFO">
    <appender-ref ref="CONSOLE"/>
    <appender-ref ref="ROLLING_FILE"/>
</root>

additivity="false" 的重要性:

  • true(默认):日志会同时输出到当前 logger 的 appender 和父 logger(root)的 appender,导致重复打印

  • false:只输出到当前 logger 配置的 appender

过滤器(Filter)

<!-- 级别过滤器:精确匹配级别 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>ERROR</level>
    <onMatch>ACCEPT</onMatch>
    <onMismatch>DENY</onMismatch>
</filter>

<!-- 阈值过滤器:该级别及以上通过 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
    <level>WARN</level>
</filter>

高级配置

异步日志(AsyncAppender)

<!-- 先定义同步 appender -->
<appender name="FILE_SYNC" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_HOME}/app.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>${LOG_HOME}/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
        <maxFileSize>100MB</maxFileSize>
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

<!-- 包装为异步 appender -->
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
    <!-- 队列大小,默认 256 -->
    <queueSize>512</queueSize>
    <!-- 队列满时的策略:false=丢弃,true=阻塞 -->
    <discardingThreshold>0</discardingThreshold>
    <!-- 不丢失日志事件 -->
    <neverBlock>false</neverBlock>
    <!-- 引用同步 appender -->
    <appender-ref ref="FILE_SYNC"/>
</appender>

<root level="INFO">
    <appender-ref ref="ASYNC_FILE"/>
</root>

按日志级别分离文件

<!-- INFO 及以上 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_HOME}/info.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${LOG_HOME}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>INFO</level>
    </filter>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} %level %logger - %msg%n</pattern>
    </encoder>
</appender>

<!-- 仅 ERROR -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_HOME}/error.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
        <maxHistory>90</maxHistory>
    </rollingPolicy>
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>ERROR</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %logger{36} - %msg%n%ex{full}</pattern>
    </encoder>
</appender>

彩色控制台输出(Logback 1.5.x 支持)

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
    </encoder>
</appender>

高亮颜色:

  • %highlight():根据级别自动着色(ERROR=红,WARN=黄,INFO=绿等)

  • %cyan()%magenta()%yellow()

Logback 1.5.x 版本注意事项

安全性增强

  • 1.5.x 修复了 CVE-2023-6378(序列化漏洞)等安全问题

  • 建议确保 logback.xml不要配置从 JNDI / 远程加载配置,避免被利用

maxHistory 和 cleanHistoryOnStart 的行为

  • maxHistory归档文件时间戳计算,不是按文件创建时间

  • cleanHistoryOnStart=true 只在应用启动时执行一次清理

  • 如果应用长期不重启,超期文件不会被自动清理(需依赖定时任务或确保会重启)

推荐的最小完整配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    
    <property name="LOG_HOME" value="${user.home}/logs/myapp"/>
    <property name="LOG_PATTERN" 
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>
    
    <!-- 控制台 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <!-- 文件滚动 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/app.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>5GB</totalSizeCap>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <!-- 第三方框架降噪 -->
    <logger name="org.springframework" level="WARN"/>
    <logger name="org.apache.http" level="WARN"/>
    <logger name="com.zaxxer.hikari" level="INFO"/>
    
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

更多推荐