tupelo-schneck opened a new pull request, #4227:
URL: https://github.com/apache/logging-log4j2/pull/4227

   **This changes the names of direct write files for cron based appenders.** 
That is the point of the change, but it is user visible on upgrade, so it 
deserves a decision rather than a rubber stamp. Details below.
   
   An appender configured without a `fileName` writes directly to the file its 
pattern resolves to. That file covers a whole rollover period, but it is 
currently named after the moment the appender started rather than after the 
period it covers.
   
   With a weekly schedule and a day-granularity pattern:
   
   ```xml
   <RollingFile name="errorLogAppender" 
filePattern="${LOG_DIR}/error.log-%d{yyyyMMdd}">
       <PatternLayout pattern="%m%n"/>
       <CronTriggeringPolicy schedule="0 0 0 ? * SUN" evaluateOnStartup="true"/>
   </RollingFile>
   ```
   
   starting on Tuesday 2026-07-28 writes to `error.log-20260728`. The period 
began on Sunday 2026-07-26, so a restart on Wednesday opens 
`error.log-20260729` instead of continuing the same file. A week with daily 
restarts leaves seven files where the schedule implies one, and rollover only 
ever closes out whichever fragment happens to be current.
   
   ## Cause
   
   `CronTriggeringPolicy.initialize()` computes the period start and records it 
correctly:
   
   ```java
   final Date lastRegularRoll = cronExpression.getPrevFireTime(new Date());
   aManager.getPatternProcessor().setCurrentFileTime(lastRegularRoll.getTime());
   ```
   
   `DirectWriteRolloverStrategy.getCurrentFileName()` then discards it:
   
   ```java
   // LOG4J2-3339 - Always use the current time for new direct write files.
   manager.getPatternProcessor().setCurrentFileTime(System.currentTimeMillis());
   ```
   
   That override compensates for a different problem. 
`CronTriggeringPolicy.rollover()` passes `lastRollDate`, the *previous* 
period's start, as the new file's time:
   
   ```java
   manager.rollover(cronExpression.getPrevFireTime(rollTime), lastRollDate);
   ```
   
   and `RollingFileManager.rollover(prevFileTime, prevRollTime)` assigns that 
to the current file time, so each replacement file was named after the file 
just rolled. Substituting the current time hid this, and works only because at 
the instant of a rollover "now" is approximately the new period's start. At 
startup "now" is an arbitrary point inside the period, which is where it breaks.
   
   ## Fix
   
   Pass the roll time rather than the previous roll date, so the replacement 
file is named after the period it opens, and let `getCurrentFileName()` use the 
period start the policy already recorded.
   
   Blast radius is limited to policies that track a period. 
`PatternProcessor.formatFileName()` already falls back to the current time when 
the current file time is 0:
   
   ```java
   final long time = useCurrentTime
           ? currentFileTime != 0 ? currentFileTime : System.currentTimeMillis()
           : prevFileTime != 0 ? prevFileTime : System.currentTimeMillis();
   ```
   
   and `PatternProcessor.updateTime()` resets it to 0, so 
`TimeBasedTriggeringPolicy`, which never sets it, keeps its existing behaviour 
unchanged. Only cron, which knows its period start, behaves differently.
   
   ## Compatibility
   
   Direct write files for cron based appenders change name, from the start time 
of the process to the start of the rollover period. For the example above that 
is `error.log-20260726` rather than `error.log-20260728`. Existing files are 
untouched and are neither read nor renamed; a restart after upgrading simply 
begins writing to the period's file. The changelog entry calls this out.
   
   Appenders configured *with* a `fileName` are unaffected, since 
`getCurrentFileName()` is only consulted on the direct write path.
   
   ## Testing
   
   `CronTriggeringPolicyTest#testDirectWriteFileNameUsesPeriodStart` asserts 
the manager's file name matches the period start computed independently from 
the same cron expression. Against `2.x` without the fix it fails with:
   
   ```
   expected: <target/testcmd5.log-20260726> but was: 
<target/testcmd5.log-20260728>
   ```
   
   `RollingAppenderDirectCronTest`, the regression test added with LOG4J2-3339, 
still passes; it asserts that a rolled file's name matches the timestamp of its 
first line, which this change preserves.
   
   `./mvnw verify` passes across all 41 modules: 11088 tests, 0 failures, 0 
errors, 40 pre-existing environment-conditional skips.
   
   ## Relationship to the other PR
   
   Independent of the startup-delay fix in the companion PR; the two touch 
different code paths and can merge in either order. They surfaced from the same 
investigation, which is why both concern `CronTriggeringPolicy`.
   
   ## Checklist
   
   * [x] Based on `2.x`
   * [x] `./mvnw verify` succeeds
   * [x] Changelog entry in `src/changelog/.2.x.x`
   * [x] Tests are provided
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to