我们的log4j2配置有问题,我们几乎是直接从 https:/www.baeldung.comjava-logging-rolling-file-appenders 4.4节。
<RollingFile name="roll-by-time-and-size"
fileName="target/log4j2/roll-by-time-and-size/app.log"
filePattern="target/log4j2/roll-by-time-and-size/app.%d{MM-dd-yyyy-HH-mm-ss.SSS}.%i.log.gz"
ignoreExceptions="false">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %p %m%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="5 KB" />
<TimeBasedTriggeringPolicy interval="5000000" />
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="." maxDepth="2">
<IfFileName glob="target/log4j2/roll-by-time-and-size/app.*.log.gz" />
<IfLastModified age="20d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
如果我减少时间间隔以确保它是基于时间的滚动, 这将在文件名中放入正确的当前时间。 但如果我把间隔时间增加到5000或其他什么,并让SizeBasedTriggeringPolicy被击中,时间戳总是相同的,唯一改变的是文件末尾的索引。
这对我们来说是个问题,因为我们有一个cron作业,会把滚过的文件移动到一个远程挂载点。 这意味着下一次log4j触发基于大小的触发策略时,索引将被重置为1,文件名中的时间戳将是相同的,尽管它不应该是相同的(为什么?),我们的cron作业将尝试移动文件,但它将与另一个已经移动过的文件是相同的文件名。
使用最新的spring boot starter log4j2 (截至目前)
是一个bug还是有意行为。 作为一个预期行为,它没有太大意义,但如果是,我们应该如何解决这个问题?
似乎策略的工作原理和文档中的一样。我在一个Spring Boot 2.2.6.RELEASE应用上进行了测试。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
然后,我使用了以下依赖项来代替启动项,以确保我使用的是最新版本。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jcl</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.13.2</version>
</dependency>
在这两种情况下,基于大小的触发策略仅在使用时改变文件名中的时间戳。橆 基于时间的触发策略。
从 文件:
当与基于时间的触发策略相结合时,文件模式必须包含%i,否则目标文件将在每次翻转时被覆盖,因为基于大小的触发策略不会导致文件名中的时间戳值发生变化。 当没有使用基于时间的触发策略时,基于大小的触发策略将导致时间戳值发生变化。
每次基于时间的触发策略触发翻转时,都会创建一个名称中带有新时间戳的文件。下一次击中基于大小的触发策略时,它会使用最新文件中的时间戳,并且只改变%i部分。
由于你不能改变SizeBasedTriggerin策略确定索引的方式。唯一明显的解决方案似乎是改变cron作业,不移动带有最新时间戳和索引的文件。. 这应该足以解决你的问题。