From 42caff87ae6eb553dcbf77e25ba87a9d340357ee Mon Sep 17 00:00:00 2001 From: Carl Mai Date: Sat, 21 Sep 2024 20:48:03 +0200 Subject: [PATCH] fix writing the header for RollingFileAppender (#862) this fixes issue #857 `encoderInit` will write the header once the `OutputStreamAppender` is started. Since the outputStream is set before starting, the other `encoderInit` inside the `start`-method is still needed. Signed-off-by: Carl Mai --- .../logback/core/OutputStreamAppender.java | 2 + .../core/rolling/RollingFileAppenderTest.java | 66 ++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java b/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java index b7a02feedf..114d310f52 100755 --- a/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java +++ b/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java @@ -174,6 +174,8 @@ public void setOutputStream(OutputStream outputStream) { closeOutputStream(); this.outputStream = outputStream; + // after opening we have to output the header + encoderInit(); } finally { streamWriteLock.unlock(); } diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/RollingFileAppenderTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/RollingFileAppenderTest.java index 0db36262bf..6f5d0849b6 100755 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/RollingFileAppenderTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/RollingFileAppenderTest.java @@ -13,9 +13,12 @@ */ package ch.qos.logback.core.rolling; +import ch.qos.logback.core.util.Duration; +import ch.qos.logback.core.util.FileSize; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import ch.qos.logback.core.Appender; @@ -27,6 +30,14 @@ import ch.qos.logback.core.testUtil.CoreTestConstants; import ch.qos.logback.core.testUtil.RandomUtil; import ch.qos.logback.core.status.testUtil.StatusChecker; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Collections; +import java.util.List; //import ch.qos.logback.core.util.StatusPrinter; public class RollingFileAppenderTest extends AbstractAppenderTest { @@ -37,13 +48,14 @@ public class RollingFileAppenderTest extends AbstractAppenderTest { TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy(); int diff = RandomUtil.getPositiveInt(); String randomOutputDir = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "/"; + DummyEncoder encoder; @BeforeEach public void setUp() throws Exception { // noStartTest fails if the context is set in setUp // rfa.setContext(context); - - rfa.setEncoder(new DummyEncoder()); + encoder = new DummyEncoder<>(); + rfa.setEncoder(encoder); rfa.setName("test"); tbrp.setContext(context); tbrp.setParent(rfa); @@ -260,4 +272,54 @@ public void collidingFileNamePattern() { checker.assertContainsMatch(Status.ERROR, "'FileNamePattern' option has the same value"); } + @Test + @DisplayName("Checks header and footer are written when the files are rolled") + public void testHeaderFooterWritten() throws IOException, InterruptedException { + for (int i = 0; i < 8; i++) { + File file = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + "header-" + i + ".log"); + file.deleteOnExit(); + } + encoder.setFileHeader("HEADER"); + encoder.setFileFooter("FOOTER"); + rfa.setContext(context); + FixedWindowRollingPolicy fixedWindowRollingPolicy = new FixedWindowRollingPolicy(); + fixedWindowRollingPolicy.setContext(context); + fixedWindowRollingPolicy.setParent(rfa); + fixedWindowRollingPolicy.setMaxIndex(3); + String fileNamePattern = CoreTestConstants.OUTPUT_DIR_PREFIX + "header-%i.log"; + fixedWindowRollingPolicy.setFileNamePattern(fileNamePattern); + rfa.setRollingPolicy(fixedWindowRollingPolicy); + rfa.setFile(CoreTestConstants.OUTPUT_DIR_PREFIX + "header-0.log"); + fixedWindowRollingPolicy.start(); + rfa.setImmediateFlush(true); + SizeBasedTriggeringPolicy sbtp = new SizeBasedTriggeringPolicy<>(); + sbtp.setMaxFileSize(new FileSize(10)); + sbtp.setCheckIncrement(Duration.buildByMilliseconds(10)); + + rfa.setTriggeringPolicy(sbtp); + rfa.getTriggeringPolicy().start(); + rfa.start(); + + for (int i = 0; i < 100; i++) { + rfa.doAppend("data" + i); + File file = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + "header-" + fixedWindowRollingPolicy.getMaxIndex() + ".log"); + if (file.exists()) { + break; + } + Thread.sleep(5); + } + rfa.stop(); + + for (int i = 0; i < fixedWindowRollingPolicy.getMaxIndex(); i++) { + File file = new File(CoreTestConstants.OUTPUT_DIR_PREFIX + "header-" + i + ".log"); + Assertions.assertTrue(file.exists()); + List lines = Files.readAllLines(file.toPath()); + Assertions.assertTrue(lines.size() > 2, "At least 2 lines per file are expected in " + file); + Assertions.assertEquals("HEADER", lines.get(0)); + Assertions.assertEquals("FOOTER", lines.get(lines.size() - 1)); + Assertions.assertEquals(1, Collections.frequency(lines, "HEADER")); + Assertions.assertEquals(1, Collections.frequency(lines, "FOOTER")); + } + } + }