logback实战详解fileNamePattern配置问题%d多级日期文件夹
为什么写这个呢?
因为我遇到了一个问题多个%d的问题,日志文件要么不按照日期文件目录划分,要么日志文件名字不变,结果处理了好久
原来是因为logback只会根据第一个%d去划分,所以需要忽略前面的%d,添加一个
,aux很关键,这样他就会忽略前面的按照后面的来滚动划分,具体看实战案例
以下是 基于Logback 1.5.12的
logback.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>注意:
SizeAndTimeBasedRollingPolicy是TimeBasedRollingPolicy的子类,功能更强大,生产环境建议直接使用这个。
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>