Log4j2滚动日志无法自动按日期创建目录存入指定文件夹解决方案
问题描述
日志配置文件如下:
<?xml version="1.0" encoding="utf-8"?> <!--status:log4j包内部日志等级 600s刷新一次配置 --> <Configuration status="WARN" monitorInterval="600"> <!-- 参数声明 --> <Properties> <!-- 日志文件存放根路径 --> <property name="DEFAULT_LOG_ROOT_PATH" value="./run"/> <!-- 日志格式1 --> <property name="LOG_PATTERN" value="[ %X{traceId} ] %d{yyyy-MM-dd HH:mm:ss.SSS} -- %style{[%t]}{bright,magenta} %highlight{%-5level}{ERROR=Bright RED, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Cyan, TRACE=Bright White} %logger{36}.%M - %msg%n"/> <!-- 日志格式2 完全自定义--> <property name="INIT_INFO_PATTERN" value="%msg%n"/> <!-- 日志文件最大文件大小全局配置,单位可以为KB、MB或GB,一天之内最大文件产生数量全局配置 --> <property name="MAX_FILE_SIZE" value="10KB"/> <property name="MAX_FILE_NUM" value="2"/> <!-- debug 日志文件位置及名称,在rollFile的时候老文件的生成规则 --> <property name="DEBUG_FILE_PATH_ING" value="${DEFAULT_LOG_ROOT_PATH}/logs/current/debug.log"/> <!-- filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd}-%i.log.gz"> 备份时使用gz格式压缩--> <property name="DEBUG_FILE_PATH_ED" value="${DEFAULT_LOG_ROOT_PATH}/logs/history/$${date:yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log"/> <!-- info 日志文件位置及名称,在rollFile的时候老文件的生成规则 --> <property name="INFO_FILE_PATH_ING" value="${DEFAULT_LOG_ROOT_PATH}/logs/current/info.log"/> <property name="INFO_FILE_PATH_ED" value="${DEFAULT_LOG_ROOT_PATH}/logs/history/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log"/> <!-- error 日志文件位置及名称,在rollFile的时候老文件的生成规则 --> <property name="ERROR_FILE_PATH_ING" value="${DEFAULT_LOG_ROOT_PATH}/logs/current/error.log"/> <property name="ERROR_FILE_PATH_ED" value="${DEFAULT_LOG_ROOT_PATH}/logs/history/$${date:yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log"/> <!-- warn 日志文件位置及名称,在rollFile的时候老文件的生成规则 --> <property name="WARN_FILE_PATH_ING" value="${DEFAULT_LOG_ROOT_PATH}/logs/current/warn_error.log"/> <property name="WARN_FILE_PATH_ED" value="${DEFAULT_LOG_ROOT_PATH}/logs/history/$${date:yyyy-MM-dd}/warn_error-%d{yyyy-MM-dd}.%i.log"/> <!-- init 日志文件位置及名称,在rollFile的时候老文件的生成规则 --> <property name="pathNow_Init" value="./init.log"/> </Properties> <!--输出终端--> <appenders> <!-- 控制台 --> <console name="Console_Log" target="SYSTEM_OUT"> <PatternLayout pattern="${LOG_PATTERN}"/> </console> <!-- 加载信息文件打印,由append属性:每次运行程序会自动清空 --> <File name="initInfoAppender" fileName="${pathNow_Init}" append="false"> <PatternLayout pattern="${INIT_INFO_PATTERN}"/> </File> <!-- info日志文件输出日志信息 --> <RollingFile name="Info_File" fileName="INFO_FILE_PATH_ING" filePattern="${INFO_FILE_PATH_ED}"> <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/> <!--日志 行样式--> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <SizeBasedTriggeringPolicy size="${MAX_FILE_SIZE}" /> </Policies> <DefaultRolloverStrategy max="${MAX_FILE_NUM}"/> </RollingFile> </appenders> <!--配置总的日志监听级别--> <loggers> <root level="INFO"> <appender-ref ref="Console_Log"/> <!-- <appender-ref ref="Debug_File"/>--> <appender-ref ref="Info_File"/> <appender-ref ref="Error_File"/> </root> <!-- 自定义logger,additivity=false标识不走root模式输出日志--> <logger name="init" level="INFO" additivity="false"> <appender-ref ref="initInfoAppender"/> </logger> </loggers> </Configuration>
以info级别日志为例,预期配置效果为:当日写入的日志存放在current目录,历史日志按日期存放在history目录下对应yyyy-MM-dd格式命名的文件夹中。但项目实际运行后生成的目录结构如下:
-- current ---- info.log -- history ---- 2022-06-29 ------ info-2022-06-29.1.log ------ info-2022-06-29.2.log ------ info-2022-06-30.1.log ------ info-2022-06-30.2.log ------ info-2022-07-01.1.log
跨天后系统未自动创建对应日期的新文件夹,所有历史日志均存入首次生成的2022-06-29目录,无法存入预期的指定日期文件夹。
问题原因
问题出在两处配置:
- 配置存在笔误:
Info_File的fileName属性直接写了变量名INFO_FILE_PATH_ING,没有用${}包裹,会导致当前活动日志文件的路径解析异常。 - 历史日志路径的日期变量写法错误:
filePattern中目录层级使用的$${date:yyyy-MM-dd}是双美元符的延迟Lookup变量,Log4j2初始化RollingFile appender时,只会解析一次该变量生成父目录,后续触发日志滚动时,只会替换文件名部分的日期、序号占位符,不会重新解析目录层级的Lookup变量,因此所有滚动生成的历史日志都会被存入第一次启动时解析出的日期文件夹中,不会按日期创建新目录。
解决方案
按以下步骤修改配置即可修复:
- 修正笔误:所有RollingFile的
fileName属性引用配置变量时,必须用${}包裹,将info日志配置里的fileName="INFO_FILE_PATH_ING"改为fileName="${INFO_FILE_PATH_ING}",debug、error、warn等级别的对应配置也做相同检查修正。 - 调整历史日志路径的日期占位符写法:将所有
filePattern中目录部分的$${date:yyyy-MM-dd}替换为%d{yyyy-MM-dd},和文件名部分的日期占位符格式保持一致。以info级别日志为例,修改后的历史路径配置为:
debug、error、warn级别的<property name="INFO_FILE_PATH_ED" value="${DEFAULT_LOG_ROOT_PATH}/logs/history/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log"/>filePattern按相同规则替换即可。
补充说明:如果需要开启历史日志压缩,直接在
filePattern的日志文件名后缀加.gz即可,比如配置为info-%d{yyyy-MM-dd}.%i.log.gz,滚动时Log4j2会自动将历史日志压缩为gz包,无需额外配置。
内容的提问来源于stack exchange,提问作者yang37
相关产品推荐
相关产品推荐

