Skip to content

Conversation

@snakefoot
Copy link
Contributor

@snakefoot snakefoot commented Oct 19, 2025

Fixed bug in archive-cleanup where it skipped cleanup when wildcard only finds single file. Fixed resetting of Windows Tunneling File-Timestamp when recycling old FileName.

Adding support for:

    <target xsi:type="File" name="fileTarget" fileName="app_${date:format=ddd}.log" maxArchiveDays="6" />

@snakefoot snakefoot added enhancement Improvement on existing feature file-target file-archiving Issues with archiving with the file target labels Oct 19, 2025
@coderabbitai
Copy link

coderabbitai bot commented Oct 19, 2025

Walkthrough

Introduces ResolveMaxArchiveFiles(bool) in BaseFileArchiveHandler and replaces inline max-archive resolution with it; adds a guard path when resolved max ≥ matched files and MaxArchiveDays ≤ 0 in DeleteOldFilesBeforeArchive; tightens CleanupFiles single-file/exclusion behavior; adds an extra FixWindowsFileSystemTunneling call in RollingArchiveFileHandler when the initial target file exists and old files were deleted; adds a new unit test and removes a couple of access-time updates in tests.

Changes

Cohort / File(s) Summary
Base archive handler
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs
Added private int ResolveMaxArchiveFiles(bool initialFileOpen) and replaced prior inline max-archive resolution with this helper. DeleteOldFilesBeforeArchive uses the helper and returns early when resolved max ≥ matched files and MaxArchiveDays <= 0. CleanupFiles single-file handling changed to fileInfos.Length == 1, excludes matching files, yields the sole file only when maxArchiveFiles == 0, and removed the prior early-break condition. Minor log message changed: "Archive contains old file" → "Archive cleanup found old file".
Rolling archive handler
src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs
Added local initialFileExists = initialFileOpen && File.Exists(newFilePath) and an additional guarded call FixWindowsFileSystemTunneling(newFilePath) when initialFileExists && deletedOldFiles, preserving existing tunneling calls and return flow. No public API changes.
Unit tests
tests/NLog.UnitTests/Targets/FileTargetTests.cs
Added test FileTarget_MaxArchiveDays_NewStyle_RollWhenOld(bool reloadConfig) (Theory with InlineData true/false) that creates dated archives with controlled timestamps, triggers rolling to exercise MaxArchiveDays behavior, asserts archive/current file contents and counts, and cleans up. Also removed some File.SetLastAccessTime(...) calls in other tests to align with behavior changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller
  participant BaseHandler
  participant FileSystem

  Note over BaseHandler: BaseFileArchiveHandler — deletion resolution
  Caller->>BaseHandler: DeleteOldFilesBeforeArchive(fileInfos, initialFileOpen)
  BaseHandler->>BaseHandler: max = ResolveMaxArchiveFiles(initialFileOpen)
  BaseHandler->>FileSystem: match & sort candidate files
  alt max >= matchedCount and MaxArchiveDays <= 0
    BaseHandler-->>Caller: return (no deletions)
  else
    BaseHandler->>BaseHandler: CleanupFiles(candidates, max, MaxArchiveDays)
    BaseHandler->>FileSystem: evaluate exclusions & ages, yield deletions
    BaseHandler-->>Caller: return deletions
  end
Loading
sequenceDiagram
  autonumber
  participant Caller
  participant RollingHandler
  participant BaseHandler
  participant FileSystem

  Note over RollingHandler: RollingArchiveFileHandler — tunneling invocation for existing target
  Caller->>RollingHandler: ArchiveBeforeOpenFile(oldPath, newPath, initialFileOpen)
  RollingHandler->>RollingHandler: initialFileExists = initialFileOpen && File.Exists(newFilePath)
  RollingHandler->>BaseHandler: DeleteOldFilesBeforeArchive(..., initialFileOpen)
  BaseHandler-->>RollingHandler: deletedOldFiles (true/false)
  alt initialFileExists and deletedOldFiles
    RollingHandler->>FileSystem: FixWindowsFileSystemTunneling(newFilePath)  %% added call %%
  end
  Note over RollingHandler: existing tunneling calls remain unchanged
  RollingHandler->>RollingHandler: continue archive flow
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through folders, counted every file,

A helper whispered "which ones stay awhile",
I nudged a tunnel where the old path lay,
Tests chased the sprites of dates and rolls today,
Carrots, logs, and tidy piles — hooray!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "FileTarget - Archive-cleanup should support weekday-format ddd" directly corresponds to the main objective stated in the PR: adding support for using the weekday-format "ddd" in File target filenames so archive-cleanup works correctly with filenames like app_${date:format=ddd}.log. The title is specific, mentions the key feature being added (weekday-format ddd), and clearly distinguishes this change from other potential improvements. A developer scanning the commit history would immediately understand that this PR is about enabling archive cleanup functionality with weekday-formatted filenames.
Description Check ✅ Passed The PR description is directly related to the changeset and provides a concrete example of the configuration that is being enabled by these changes. It specifies that support is being added for the "ddd" weekday format and demonstrates the exact use case with XML configuration. While the description is brief, it is sufficiently informative and clearly explains what is being added without being vague or generic. The description aligns with the modifications across all three modified files, which collectively implement the infrastructure needed to support archive cleanup with weekday-formatted filenames.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56727c0 and 3ab45e0.

📒 Files selected for processing (1)
  • src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (2 hunks)
🔇 Additional comments (2)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (2)

90-91: LGTM: Valid optimization for early exit.

The early exit correctly avoids unnecessary processing when there's sufficient capacity for all files and no days-based constraint is active.


52-117: PR title mentions "weekday-format ddd" but changes appear optimization-focused.

The PR title suggests adding support for weekday format "ddd", but the visible changes only add early-exit optimizations. Are there additional changes in other files that implement the weekday format feature, or should the PR title be updated to reflect the optimization focus?

@snakefoot snakefoot force-pushed the filetarget_weekday2 branch 8 times, most recently from a36ad85 to 7673576 Compare October 19, 2025 14:02
@pull-request-size pull-request-size bot added size/M and removed size/S labels Oct 19, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9bc18a6 and 7673576.

📒 Files selected for processing (1)
  • src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (3 hunks)
🔇 Additional comments (2)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (2)

84-86: LGTM: Clean refactoring with sound optimization.

Extracting maxArchiveFiles calculation to a dedicated helper improves readability. The early-return condition correctly skips cleanup when we have file-count capacity and no time-based constraints are configured.


114-122: Rewrite: Original concern is unfounded after code analysis.

The maxArchiveFiles=0 behavior in ResolveMaxArchiveFiles only applies during the initial file open (initialFileOpen=true). After startup, normal MaxArchiveFiles rules resume. Additionally, ShouldDeleteFile applies maxArchiveDays independently via OR logic—files are deleted if either the count threshold or age threshold is exceeded. The two settings don't conflict; they're independent filters. No issue to address.

@snakefoot snakefoot closed this Oct 19, 2025
@snakefoot snakefoot reopened this Oct 19, 2025
@snakefoot snakefoot force-pushed the filetarget_weekday2 branch from 7673576 to 837d3be Compare October 19, 2025 15:09
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)

198-210: Critical: maxArchiveFiles == 0 logic still contradicts NLog specification.

The condition at line 205 (maxArchiveFiles == 0) yields the file for deletion, but according to NLog specification, MaxArchiveFiles=0 means "infinite archives" (do not delete based on count). The current logic is inverted:

  1. Incorrect semantic: When users set MaxArchiveFiles=0, they expect infinite archives, but the code deletes the file
  2. Age constraint bypass: The code yields without checking MaxArchiveDays (line 207), so even files newer than the configured age threshold are deleted

This issue was identified in the previous review and remains unaddressed.

Apply this fix to respect both the specification and age constraints:

-                else if (maxArchiveFiles == 0)
+                else if (maxArchiveFiles == 0 && _fileTarget.MaxArchiveDays > 0)
                 {
-                    yield return fileInfos[0];
-                    yield break;
+                    // Single file: check age constraint before yielding
+                    var fileCreatedTimeUtc = FileInfoHelper.LookupValidFileCreationTimeUtc(fileInfos[0]);
+                    var fileInfoDate = new FileInfoDateTime(fileInfos[0], fileCreatedTimeUtc);
+                    if (ShouldDeleteFile(fileInfoDate, 1, maxArchiveFiles, _fileTarget.MaxArchiveDays))
+                    {
+                        yield return fileInfos[0];
+                    }
+                    yield break;
                 }

Note: This fix handles the maxArchiveFiles == 0 case when MaxArchiveDays > 0. You should also verify the overall logic: if maxArchiveFiles == 0 is intended as a sentinel for "delete all" (via DeleteOldFileOnStartup), the relationship between user-configured MaxArchiveFiles values and the resolved maxArchiveFiles needs clearer separation to avoid conflating "infinite archives" with "delete all".

🧹 Nitpick comments (2)
src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (1)

60-61: Refactor for clarity: variable name and logic flow are confusing.

The variable deletedOldFiles is first assigned File.Exists(newFilePath) (line 60), then updated with an AND operation (line 61). This is logically correct but confusing because:

  1. The name "deletedOldFiles" suggests it tracks whether files were deleted, but it initially tracks whether the target file exists
  2. The AND operation DeleteOldFilesBeforeArchive(...) && deletedOldFiles is backwards for readability

Consider this clearer alternative:

-                bool deletedOldFiles = File.Exists(newFilePath);
-                deletedOldFiles = DeleteOldFilesBeforeArchive(newFilePath, initialFileOpen, parseArchiveSequenceNo) && deletedOldFiles;
+                bool targetFileExists = File.Exists(newFilePath);
+                bool deletedOldFiles = DeleteOldFilesBeforeArchive(newFilePath, initialFileOpen, parseArchiveSequenceNo);
-                if (deletedOldFiles && initialFileOpen)
+                if (deletedOldFiles && targetFileExists && initialFileOpen)
                 {
                     FixWindowsFileSystemTunneling(newFilePath);
                 }
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)

114-122: Simplify ResolveMaxArchiveFiles for readability.

The conditional logic at lines 117-118 is difficult to parse:

  1. Line 117: The condition (!_fileTarget.ArchiveOldFileOnStartup || _fileTarget.DeleteOldFileOnStartup) requires careful boolean logic analysis
  2. Line 118: The ternary _fileTarget.DeleteOldFileOnStartup ? 0 : maxArchiveFiles may assign maxArchiveFiles to itself (no-op) when DeleteOldFileOnStartup is false

Consider restructuring for clarity:

 private int ResolveMaxArchiveFiles(bool initialFileOpen)
 {
     var maxArchiveFiles = _fileTarget.MaxArchiveFiles;
-    if (initialFileOpen && (!_fileTarget.ArchiveOldFileOnStartup || _fileTarget.DeleteOldFileOnStartup))
-        maxArchiveFiles = _fileTarget.DeleteOldFileOnStartup ? 0 : maxArchiveFiles;
+    if (initialFileOpen && _fileTarget.DeleteOldFileOnStartup)
+    {
+        maxArchiveFiles = 0; // Delete all files on startup
+    }
+    else if (initialFileOpen && !_fileTarget.ArchiveOldFileOnStartup)
+    {
+        // Keep maxArchiveFiles as-is, don't decrement
+    }
     else if (maxArchiveFiles > 0)
+    {
         maxArchiveFiles -= 1;
+    }
     return maxArchiveFiles;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7673576 and 837d3be.

📒 Files selected for processing (2)
  • src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (3 hunks)
  • src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (1)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (3)
  • DeleteOldFilesBeforeArchive (52-60)
  • DeleteOldFilesBeforeArchive (62-112)
  • FixWindowsFileSystemTunneling (406-421)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: task-list-completed
🔇 Additional comments (1)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)

84-86: No issues found with early-exit logic.

The early-exit at lines 84-86 handles all scenarios correctly:

  • DeleteOldFileOnStartup case: ResolveMaxArchiveFiles returns 0 (line 118). The condition 0 >= fileInfos.Length is false if files exist (caught by line 82), so no early-exit occurs—cleanup proceeds as intended.
  • Normal cleanup case: Early-exit skips unnecessary cleanup when we have room for all files and no age-based constraint.

The code distinguishes between two "zero" semantics: MaxArchiveFiles=0 (property, triggers ZeroFileArchiveHandler) versus maxArchiveFiles=0 (local variable, signals "delete all files" during DeleteOldFileOnStartup). The logic correctly navigates both scenarios.

@snakefoot snakefoot force-pushed the filetarget_weekday2 branch 3 times, most recently from d602d5a to d5f7a55 Compare October 19, 2025 15:24
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (1)

60-60: LGTM - Correctly handles edge case for weekday-format archive cleanup.

The new initialFileExists check and subsequent FixWindowsFileSystemTunneling call correctly address scenarios where files with weekday patterns (e.g., "app_Mon.log") might be both the current file and an old archive requiring cleanup. Since FixWindowsFileSystemTunneling internally checks !File.Exists(newFilePath) before acting, this is safe even when the file wasn't actually deleted.

Optional micro-optimization: If profiling shows this matters, you could check File.Exists(newFilePath) again before calling FixWindowsFileSystemTunneling to avoid the method call overhead when the file still exists after cleanup:

 if (initialFileExists && deletedOldFiles)
 {
-    FixWindowsFileSystemTunneling(newFilePath);
+    if (!File.Exists(newFilePath))
+    {
+        FixWindowsFileSystemTunneling(newFilePath);
+    }
 }

However, since FixWindowsFileSystemTunneling already performs this check and the method is lightweight, the current implementation prioritizes code simplicity.

Also applies to: 72-75

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 837d3be and d5f7a55.

📒 Files selected for processing (2)
  • src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (3 hunks)
  • src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs
🧰 Additional context used
🧬 Code graph analysis (1)
src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (1)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)
  • FixWindowsFileSystemTunneling (406-421)

@snakefoot snakefoot force-pushed the filetarget_weekday2 branch from d5f7a55 to b1fb06d Compare October 19, 2025 18:28
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)

198-210: Single-file fast‑path still bypasses MaxArchiveDays; guard or drop the special‑case.

With maxArchiveFiles == 0 the file is yielded unconditionally, ignoring MaxArchiveDays. If the intent is that age should still gate deletion, either guard by days or let the general path handle it. This mirrors prior feedback on this block.

Option A (keep fast‑path but respect days):

-else if (maxArchiveFiles == 0)
+else if (maxArchiveFiles == 0)
 {
-    yield return fileInfos[0];
-    yield break;
+    if (maxArchiveDays <= 0)
+    {
+        yield return fileInfos[0];
+    }
+    else
+    {
+        var createdUtc = FileInfoHelper.LookupValidFileCreationTimeUtc(fileInfos[0]);
+        var candidate = new FileInfoDateTime(fileInfos[0], createdUtc);
+        // Disable count-based deletion here so age decides
+        if (ShouldDeleteFile(candidate, 1, -1, maxArchiveDays))
+            yield return fileInfos[0];
+    }
+    yield break;
 }

Option B (simpler, rely on common logic and avoid surprises):

-else if (maxArchiveFiles == 0)
-{
-    yield return fileInfos[0];
-    yield break;
-}
+// No single-file shortcut; let common path apply count/age rules uniformly
🧹 Nitpick comments (1)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)

84-87: Add missing fast-path for “unlimited archives and no age policy”.

If MaxArchiveFiles < 0 and MaxArchiveDays ≤ 0 there’s nothing to delete; skip enumeration to reduce I/O and log noise.

 int maxArchiveFiles = ResolveMaxArchiveFiles(initialFileOpen);
-if (maxArchiveFiles >= fileInfos.Length && _fileTarget.MaxArchiveDays <= 0)
+// Nothing to delete when count already within limit and no age policy
+if (maxArchiveFiles >= fileInfos.Length && _fileTarget.MaxArchiveDays <= 0)
     return false;
+// Also nothing to delete when unlimited archives and no age policy
+if (maxArchiveFiles < 0 && _fileTarget.MaxArchiveDays <= 0)
+    return false;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d5f7a55 and b1fb06d.

📒 Files selected for processing (2)
  • src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (4 hunks)
  • src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs
🧰 Additional context used
🧬 Code graph analysis (1)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)
src/NLog/Common/InternalLogger.cs (1)
  • InternalLogger (51-511)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: task-list-completed
🔇 Additional comments (2)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (2)

268-268: LGTM: clearer internal log line.


114-122: ResolveMaxArchiveFiles logic needs clarification; confirm behavioral intent before refactoring.

The review comment raises a valid semantic concern. Your current code unconditionally coerces the resolved max to 0 whenever DeleteOldFileOnStartup = true on initial file open—even if MaxArchiveFiles is configured as negative (infinite). Web search and test results confirm:

  • MaxArchiveFiles < 0 means "disabled/unlimited"; positive values keep at most N archive files
  • DeleteOldFileOnStartup applies to the active log file at startup and is separate from periodic archive cleanup

The ambiguity: The existing tests do not cover the edge case of MaxArchiveFiles < 0 combined with DeleteOldFileOnStartup = true. The code at line 118 forces cleanup to 0, but it's unclear whether this is intentional (e.g., "DeleteOldFileOnStartup means clean all archives at startup") or an unintended side-effect.

Before accepting the refactor:

  1. Confirm with maintainers whether infinite archives should be coerced to 0 during DeleteOldFileOnStartup
  2. If yes, the refactoring improves clarity—add a comment explaining why: DeleteOldFileOnStartup = true forces maxArchiveFiles = 0 to trigger full cleanup, regardless of configured limit
  3. If no (infinite should stay infinite), adjust the logic: if (DeleteOldFileOnStartup) return initialFileOpen ? 0 : maxArchiveFiles; or similar

The suggested refactor does improve readability, but the behavior change (or confirmation) is the key decision point.

@snakefoot snakefoot force-pushed the filetarget_weekday2 branch 2 times, most recently from 781c236 to 28bbbcd Compare October 20, 2025 18:23
@snakefoot snakefoot force-pushed the filetarget_weekday2 branch from 28bbbcd to 9b8561f Compare October 20, 2025 18:24
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (1)

72-75: Avoid duplicate FixWindowsFileSystemTunneling call paths.

You now call FixWindowsFileSystemTunneling both inside the early-return branch (Lines 65–68) and here. Consider consolidating into a single post-cleanup condition to reduce duplication, e.g., invoke once when deletedOldFiles is true and initialFileOpen is true; the method itself safely no-ops if the file still exists.

src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)

114-122: Clarify ResolveMaxArchiveFiles semantics.

Helper improves readability. Add a brief comment summarizing the adjustments for initialFileOpen, ArchiveOldFileOnStartup, DeleteOldFileOnStartup, and the “-1/0/>0” cases to prevent regressions and future confusion.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 781c236 and 9b8561f.

📒 Files selected for processing (3)
  • src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (4 hunks)
  • src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (2 hunks)
  • tests/NLog.UnitTests/Targets/FileTargetTests.cs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
tests/NLog.UnitTests/Targets/FileTargetTests.cs (2)
tests/NLog.UnitTests/NLogTestBase.cs (3)
  • IsLinux (369-372)
  • AssertFileContents (121-124)
  • AssertFileContents (126-170)
src/NLog/Internal/FileInfoHelper.cs (2)
  • DateTime (43-46)
  • DateTime (48-62)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)
src/NLog/Common/InternalLogger.cs (1)
  • InternalLogger (51-511)
src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (1)
src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (1)
  • FixWindowsFileSystemTunneling (407-422)
🔇 Additional comments (5)
src/NLog/Targets/FileArchiveHandlers/RollingArchiveFileHandler.cs (1)

60-61: Good pre-check for initial existence.

Capturing initialFileExists before cleanup correctly detects whether the active file may have been removed by DeleteOldFilesBeforeArchive. LGTM.

tests/NLog.UnitTests/Targets/FileTargetTests.cs (1)

2714-2784: Solid coverage for weekday “ddd” with MaxArchiveDays + size rolling.

Test reliably seeds 8 prior days, exercises cleanup and rolling, and validates expected sequences and counts. LGTM.

src/NLog/Targets/FileArchiveHandlers/BaseFileArchiveHandler.cs (3)

84-87: Early-exit guard is correct and reduces I/O.

Skipping cleanup when maxArchiveFiles ≥ file count and no MaxArchiveDays avoids unnecessary enumeration. LGTM.


198-210: Single-file path: early-yield with yield break is correct.

The yield + yield break prevents duplicate enumeration and keeps behavior deterministic. LGTM.


265-269: Use of TimeSource.Current for age checks is appropriate.

Converting from system creation time via FromSystemTime keeps tests and production in sync with custom time sources. LGTM.

@sonarqubecloud
Copy link

@snakefoot snakefoot merged commit 09b0821 into NLog:dev Oct 21, 2025
5 of 6 checks passed
@snakefoot snakefoot changed the title FileTarget - Archive-cleanup should support weekday-format ddd FileTarget - Fix cleanup when only single old archive file and using MaxArchiveDays Oct 24, 2025
@snakefoot snakefoot changed the title FileTarget - Fix cleanup when only single old archive file and using MaxArchiveDays FileTarget - Fix archive cleanup when only single old archive file and using MaxArchiveDays Oct 24, 2025
@snakefoot snakefoot changed the title FileTarget - Fix archive cleanup when only single old archive file and using MaxArchiveDays FileTarget - Fix archive cleanup when only single old file and using MaxArchiveDays Oct 24, 2025
@snakefoot snakefoot added this to the 6.0.6 milestone Oct 24, 2025
@coderabbitai coderabbitai bot mentioned this pull request Nov 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement on existing feature file-archiving Issues with archiving with the file target file-target size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant