From 47d9811bdb38aa3546aa609bc0c5859e1ca1811c Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Tue, 27 Oct 2026 03:06:27 +0800 Subject: [PATCH 1/2] Fix size-only backup scan for #338 --- ...RollingFileAppenderShortDatePatternTest.cs | 30 +++++++++++++++++++ src/log4net/Appender/RollingFileAppender.cs | 7 +++++ 2 files changed, 37 insertions(+) diff --git a/src/log4net.Tests/Appender/RollingFileAppenderShortDatePatternTest.cs b/src/log4net.Tests/Appender/RollingFileAppenderShortDatePatternTest.cs index 5e24b001..35c48d64 100644 --- a/src/log4net.Tests/Appender/RollingFileAppenderShortDatePatternTest.cs +++ b/src/log4net.Tests/Appender/RollingFileAppenderShortDatePatternTest.cs @@ -38,6 +38,12 @@ namespace log4net.Tests.Appender; [TestFixture] public sealed class RollingFileAppenderShortDatePatternTest { + private sealed class RollingFileAppenderForTest : RollingFileAppender + { + internal new List GetExistingFiles(string baseFilePath) + => base.GetExistingFiles(baseFilePath); + } + /// /// With a static name, .dd names the file of the 10th like backup 10, so the appender is /// reported and uses the dated name instead, with its backups numbered after the date. @@ -153,6 +159,30 @@ public void DatedNameCountsOnlyItsOwnBackups() Assert.That(appender.CurrentSizeRollBackups, Is.EqualTo(2)); } + /// + /// An unrelated sibling whose name starts with the base file must not set the size-roll index. + /// + [Test] + public void SizeOnlyRollingIgnoresPrefixSibling() + { + using AutoTempFolder folder = new(); + string file = Path.Combine(folder.Path, "log.txt"); + File.WriteAllText(file + ".unrelated.5", "synthetic fixture"); + RollingFileAppenderForTest appender = new() + { + File = file, + RollingStyle = RollingFileAppender.RollingMode.Size, + StaticLogFileName = false, + MaxSizeRollBackups = -1, + CountDirection = 1 + }; + + List files = appender.GetExistingFiles(file); + appender.InitializeRollBackups(Path.GetFileName(file), files); + + Assert.That(appender.CurrentSizeRollBackups, Is.Zero); + } + private static readonly DateTime _mockedNow = new(2026, 10, 4, 9, 0, 0); private static RollingFileAppender CreateShortDatePatternAppender(string file, diff --git a/src/log4net/Appender/RollingFileAppender.cs b/src/log4net/Appender/RollingFileAppender.cs index 15dc84a7..54b758e0 100644 --- a/src/log4net/Appender/RollingFileAppender.cs +++ b/src/log4net/Appender/RollingFileAppender.cs @@ -971,6 +971,13 @@ private int GetBackupIndex(string baseFile, string curFileName) int index = fileName.LastIndexOf(".", StringComparison.Ordinal); if (index > 0) { + // Non-static size-only backups must have the base name immediately before the index. + if (!StaticLogFileName && !_rollDate + && !string.Equals(fileName.Substring(0, index), baseFile, StringComparison.Ordinal)) + { + return -1; + } + // with a static name, log.txt.20261003.1 is a backup of an earlier date if (StaticLogFileName && (!string.Equals(fileName.Substring(0, index), baseFile, StringComparison.Ordinal) From 2fbda3d484d2cca5ef249fea479c0aae61108548 Mon Sep 17 00:00:00 2001 From: Jan Friedrich Date: Mon, 26 Oct 2026 21:01:11 +0100 Subject: [PATCH 2/2] count only the base name's backups without date rolling #338 - size and once rolling no longer count log.txt.errors.3 as backup 3 - the static name guard from #334 now covers names without dates --- ...338-size-backup-ignores-prefix-sibling.xml | 12 ++++++++ ...RollingFileAppenderShortDatePatternTest.cs | 30 ------------------- .../Appender/RollingFileAppenderTest.cs | 24 +++++++++++++++ src/log4net/Appender/RollingFileAppender.cs | 11 ++----- 4 files changed, 38 insertions(+), 39 deletions(-) create mode 100644 src/changelog/3.5.1/338-size-backup-ignores-prefix-sibling.xml diff --git a/src/changelog/3.5.1/338-size-backup-ignores-prefix-sibling.xml b/src/changelog/3.5.1/338-size-backup-ignores-prefix-sibling.xml new file mode 100644 index 00000000..3b7cbcb8 --- /dev/null +++ b/src/changelog/3.5.1/338-size-backup-ignores-prefix-sibling.xml @@ -0,0 +1,12 @@ + + + + + Without date rolling, a `RollingFileAppender` with `StaticLogFileName` + false counted a file such as `log.txt.errors.3` as backup 3 of `log.txt` when it started. Only + files whose name is the base name followed by the index count as backups now (reported by + @dajiaohuang, fixed by @dajiaohuang) + diff --git a/src/log4net.Tests/Appender/RollingFileAppenderShortDatePatternTest.cs b/src/log4net.Tests/Appender/RollingFileAppenderShortDatePatternTest.cs index 35c48d64..5e24b001 100644 --- a/src/log4net.Tests/Appender/RollingFileAppenderShortDatePatternTest.cs +++ b/src/log4net.Tests/Appender/RollingFileAppenderShortDatePatternTest.cs @@ -38,12 +38,6 @@ namespace log4net.Tests.Appender; [TestFixture] public sealed class RollingFileAppenderShortDatePatternTest { - private sealed class RollingFileAppenderForTest : RollingFileAppender - { - internal new List GetExistingFiles(string baseFilePath) - => base.GetExistingFiles(baseFilePath); - } - /// /// With a static name, .dd names the file of the 10th like backup 10, so the appender is /// reported and uses the dated name instead, with its backups numbered after the date. @@ -159,30 +153,6 @@ public void DatedNameCountsOnlyItsOwnBackups() Assert.That(appender.CurrentSizeRollBackups, Is.EqualTo(2)); } - /// - /// An unrelated sibling whose name starts with the base file must not set the size-roll index. - /// - [Test] - public void SizeOnlyRollingIgnoresPrefixSibling() - { - using AutoTempFolder folder = new(); - string file = Path.Combine(folder.Path, "log.txt"); - File.WriteAllText(file + ".unrelated.5", "synthetic fixture"); - RollingFileAppenderForTest appender = new() - { - File = file, - RollingStyle = RollingFileAppender.RollingMode.Size, - StaticLogFileName = false, - MaxSizeRollBackups = -1, - CountDirection = 1 - }; - - List files = appender.GetExistingFiles(file); - appender.InitializeRollBackups(Path.GetFileName(file), files); - - Assert.That(appender.CurrentSizeRollBackups, Is.Zero); - } - private static readonly DateTime _mockedNow = new(2026, 10, 4, 9, 0, 0); private static RollingFileAppender CreateShortDatePatternAppender(string file, diff --git a/src/log4net.Tests/Appender/RollingFileAppenderTest.cs b/src/log4net.Tests/Appender/RollingFileAppenderTest.cs index 8ef01257..588436c9 100644 --- a/src/log4net.Tests/Appender/RollingFileAppenderTest.cs +++ b/src/log4net.Tests/Appender/RollingFileAppenderTest.cs @@ -1799,6 +1799,30 @@ public void TestInitializeRollBackupsNotStaticDateWithoutDashes(string baseFile, Assert.That(rfa.CurrentSizeRollBackups, Is.EqualTo(1)); } + /// + /// Tests that without date rolling a sibling such as log.txt.errors.3 is not counted as a backup + /// of a non-static name + /// + [TestCase(true, "log.5.txt", 5)] + [TestCase(false, "log.txt.5", 5)] + [TestCase(true, "log.errors.3.txt", 0)] + [TestCase(false, "log.txt.errors.3", 0)] + public void TestInitializeRollBackupsSizeIgnoresPrefixSibling(bool preserveExtension, + string file, int expected) + { + RollingFileAppender rfa = new() + { + RollingStyle = RollingFileAppender.RollingMode.Size, + StaticLogFileName = false, + PreserveLogFileNameExtension = preserveExtension, + MaxSizeRollBackups = -1, + CurrentSizeRollBackups = 0 + }; + rfa.InitializeRollBackups("log.txt", [file]); + + Assert.That(rfa.CurrentSizeRollBackups, Is.EqualTo(expected)); + } + /// /// Tests that with a short date pattern the suffixes of a static file name count as backup /// indexes, as a date like .10 cannot be told apart from backup 10 diff --git a/src/log4net/Appender/RollingFileAppender.cs b/src/log4net/Appender/RollingFileAppender.cs index 54b758e0..c6b17a31 100644 --- a/src/log4net/Appender/RollingFileAppender.cs +++ b/src/log4net/Appender/RollingFileAppender.cs @@ -971,15 +971,8 @@ private int GetBackupIndex(string baseFile, string curFileName) int index = fileName.LastIndexOf(".", StringComparison.Ordinal); if (index > 0) { - // Non-static size-only backups must have the base name immediately before the index. - if (!StaticLogFileName && !_rollDate - && !string.Equals(fileName.Substring(0, index), baseFile, StringComparison.Ordinal)) - { - return -1; - } - - // with a static name, log.txt.20261003.1 is a backup of an earlier date - if (StaticLogFileName + // without dates log.txt.errors.3 is another file (#338) + if ((StaticLogFileName || !_rollDate) && (!string.Equals(fileName.Substring(0, index), baseFile, StringComparison.Ordinal) || IsDateSuffix(fileName.Substring(index)))) {