Details
-
Bug
-
Resolution: Unresolved
-
Major
-
1.2.3
-
Intellij / JDK 11 / Spring Boot 2.2.4 using logback 1.2.3
<appender name="TechFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
{yyyy-MM-dd_HH}
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/test-app.%d.log</fileNamePattern>
{yyyyMMdd.HHmmss}
<maxHistory>10</maxHistory>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder>
<pattern>%d.%p.%t.%logger
{35}%-5level - %msg %n</pattern>
</encoder>
</appender>Intellij / JDK 11 / Spring Boot 2.2.4 using logback 1.2.3 <appender name="TechFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_DIR}/test-app.%d {yyyy-MM-dd_HH} .log</fileNamePattern> <maxHistory>10</maxHistory> <cleanHistoryOnStart>true</cleanHistoryOnStart> </rollingPolicy> <encoder> <pattern>%d {yyyyMMdd.HHmmss} .%p.%t.%logger {35} %-5level - %msg %n</pattern> </encoder> </appender>
Description
Hello,
Figured out a bug inside class RollingCalendar in method "periodBarriersCrossed" when applying periodicityType = TOP_OF_HOUR.
The "int cast" is applied to "diff" value making the resulting long value negative and not properly applying period calculation for the kind of periodicity.
Fix is to delete the int cast.
Workaround is creating all set of classes allowing us to override the default implementation of this RollingCalendar.
<appender name="TechFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="CustomTimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/test-app.%d
.log</fileNamePattern>
<maxHistory>10</maxHistory>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder>
<pattern>%d
.%p.%t.%logger
{35} %-5level - %msg %n</pattern>
</encoder>
</appender>
public class CustomTimeBasedRollingPolicy<E> extends TimeBasedRollingPolicy<E> { @Override public void start() { setTimeBasedFileNamingAndTriggeringPolicy(new CustomTimeBasedFileNamingAndTriggeringPolicy<>()); super.start(); } } class CustomTimeBasedFileNamingAndTriggeringPolicy<E> extends TimeBasedFileNamingAndTriggeringPolicyBase<E> { private static final String COLLIDING_DATE_FORMAT_URL = CODES_URL + "#rfa_collision_in_dateFormat"; private FileNamePattern fileNamePatternWithoutCompSuffix; @Override public void start() { super.start(); if (!super.isErrorFree()) return; final var fileNamePatternStr = tbrp.getFileNamePattern(); final var fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context); fileNamePatternWithoutCompSuffix = new FileNamePattern(Compressor.computeFileNameStrWithoutCompSuffix(fileNamePatternStr, tbrp.getCompressionMode()), this.context); DateTokenConverter<Object> dtc = fileNamePattern.getPrimaryDateTokenConverter(); if (dtc == null) { throw new IllegalStateException("FileNamePattern [" + fileNamePattern.getPattern() + "] does not contain a valid DateToken"); } if (dtc.getTimeZone() != null) { rc = new CustomTopOfHourRollingCalendar(dtc.getDatePattern(), dtc.getTimeZone(), Locale.getDefault()); } else { rc = new CustomTopOfHourRollingCalendar(dtc.getDatePattern()); } addInfo("The date pattern is '" + dtc.getDatePattern() + "' from file name pattern '" + fileNamePattern.getPattern() + "'."); rc.printPeriodicity(this); if (!rc.isCollisionFree()) { addError("The date format in FileNamePattern will result in collisions in the names of archived log files."); addError(CoreConstants.MORE_INFO_PREFIX + COLLIDING_DATE_FORMAT_URL); withErrors(); return; } if(fileNamePattern.hasIntegerTokenCOnverter()) { addError("Filename pattern ["+fileNamePattern+"] contains an integer token converter, i.e. %i, INCOMPATIBLE with this configuration. Remove it."); return; } archiveRemover = new TimeBasedArchiveRemover(fileNamePattern, rc); archiveRemover.setContext(context); started = true; } @Override public boolean isTriggeringEvent(File activeFile, final E event) { long time = getCurrentTime(); if (time >= nextCheck) { Date dateOfElapsedPeriod = dateInCurrentPeriod; addInfo("Elapsed period: " + dateOfElapsedPeriod); elapsedPeriodsFileName = fileNamePatternWithoutCompSuffix.convert(dateOfElapsedPeriod); setDateInCurrentPeriod(time); computeNextCheck(); return true; } else { return false; } } } class CustomTopOfHourRollingCalendar extends RollingCalendar { private final PeriodicityType calculatedPeriodicityType; CustomTopOfHourRollingCalendar(String datePattern) { super(datePattern); this.calculatedPeriodicityType = computePeriodicityType(); } CustomTopOfHourRollingCalendar(String datePattern, TimeZone tz, Locale locale) { super(datePattern, tz, locale); this.calculatedPeriodicityType = computePeriodicityType(); } @Override public long periodBarriersCrossed(long start, long end) { if(TOP_OF_HOUR == calculatedPeriodicityType) { if (start > end) throw new IllegalArgumentException("Start cannot come before end"); long startFloored = getStartOfCurrentPeriodWithGMTOffsetCorrection(start, getTimeZone()); long endFloored = getStartOfCurrentPeriodWithGMTOffsetCorrection(end, getTimeZone()); long diff = endFloored - startFloored; return diff / MILLIS_IN_ONE_HOUR; } return super.periodBarriersCrossed(start, end); } }
Attachments
Issue Links
- duplicates
-
LOGBACK-1344 RollingCalendar invalid "period barrier crossed" computation
- Open