Skip to content

GZipFile - Support Header / Footer / WriteBom#6129

Merged
snakefoot merged 1 commit intoNLog:devfrom
snakefoot:GzipFileHeader
Mar 28, 2026
Merged

GZipFile - Support Header / Footer / WriteBom#6129
snakefoot merged 1 commit intoNLog:devfrom
snakefoot:GzipFileHeader

Conversation

@snakefoot
Copy link
Copy Markdown
Contributor

Trying to resolve #6128

@snakefoot snakefoot added bug Bug report / Bug fix file-target labels Mar 28, 2026
@snakefoot snakefoot changed the title GZipFIle - Support Header / Footer / WriteBom GZipFile - Support Header / Footer / WriteBom Mar 28, 2026
@snakefoot snakefoot requested a review from Copilot March 28, 2026 09:20
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Consolidated "new/empty file" detection into IsNewFileEmpty(initialFileOpen, fileStream) and applied it for BOM and header writing in FileTarget. Added GZip and AtomicFile unit tests validating Header/Footer with WriteBom and set tests to throw on logging exceptions.

Changes

Cohort / File(s) Summary
FileTarget logic
src/NLog/Targets/FileTarget.cs
Extracted empty-file check into IsNewFileEmpty(initialFileOpen, fileStream); BOM and header branches now use it, preserving special-case when ReplaceFileContentsOnEachWrite or ArchiveOldFileOnStartup && !fileStream.CanSeek.
GZip file tests
tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs
Added constructor setting LogManager.ThrowExceptions = true and new [Fact] SimpleFileGZipStream_HeaderFooterBom to verify Header → logged message → Footer → EOF when WriteBom=true.
AtomicFile tests
tests/NLog.Targets.AtomicFile.Tests/AtomFileTests.cs
New test class AtomFileTests (constructor sets LogManager.ThrowExceptions = true) with SimpleAtomicFileStream_HeaderFooterBom validating Header, message, Footer and EOF for AtomicFileTarget with WriteBom=true; includes temp-dir cleanup.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I checked each stream with a careful hop,
Ensured BOM and headers lined up on the top.
GZip and Atomic files now dance in tune,
Small hops, big smiles beneath the moon. 🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for Header, Footer, and WriteBom features to GZipFileTarget.
Description check ✅ Passed The description references issue #6128, which directly relates to the changeset addressing GZipFileTarget's NotSupportedException problem.
Linked Issues check ✅ Passed The PR addresses issue #6128 by extracting the 'is file empty' logic into a helper method that avoids calling GZipStream.get_Length() inappropriately, and adds tests demonstrating the fix works with Header/Footer/WriteBom.
Out of Scope Changes check ✅ Passed All changes are directly related to supporting Header/Footer/WriteBom in GZipFileTarget and resolving the NotSupportedException, with comprehensive test coverage added.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adjusts FileTarget stream-initialization logic to avoid calling Stream.Length for GZipStream (which throws NotSupportedException), enabling GZipFileTarget to support Header, Footer, and WriteBom scenarios and adding test coverage for the behavior.

Changes:

  • Updated FileTarget.OpenNewFileStream to treat files as “empty” on initial open when ArchiveOldFileOnStartup is enabled, avoiding Stream.Length in those cases.
  • Updated header-writing condition to also short-circuit when ArchiveOldFileOnStartup is enabled on initial open.
  • Added a new xUnit test verifying gzip output includes Header, message, and Footer with BOM enabled.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/NLog/Targets/FileTarget.cs Avoids Stream.Length access for initial-open + archive-on-startup scenarios (intended to prevent GZipStream.Length exceptions during open).
tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs Adds a test validating gzip output when using Header/Footer and BOM.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (2)
tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs (1)

43-46: Global static setting may affect test isolation.

LogManager.ThrowExceptions is a global static property. Setting it in the constructor affects all tests in this class, but may also bleed into other test classes if tests run in parallel within the same process. Consider resetting it in a Dispose method (implementing IDisposable) or using IClassFixture to manage the setting's lifecycle.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs` around lines 43 - 46, The
constructor for GZipFileTests sets the global static LogManager.ThrowExceptions
which can leak across tests; modify GZipFileTests to capture the previous value,
implement IDisposable (or use an IClassFixture) and in Dispose restore
LogManager.ThrowExceptions to the saved previousValue so the global state is
reset after the test class finishes; reference the GZipFileTests constructor,
LogManager.ThrowExceptions and Dispose/IDisposable (or IClassFixture) when
making the change.
src/NLog/Targets/FileTarget.cs (1)

1313-1313: Consider extracting conditions to reduce cognitive complexity.

This line now has 5 conditional operators, exceeding SonarCloud's maximum of 4. While functionally correct, extracting to named locals would improve readability and satisfy the static analysis rule.

♻️ Proposed refactor to reduce complexity
                 if (Header != null)
                 {
-                    bool writeHeader = (initialFileOpen && WriteHeaderWhenInitialFileNotEmpty) || ReplaceFileContentsOnEachWrite || (initialFileOpen && ArchiveOldFileOnStartup) || (fileWasEmpty ?? fileStream.Length == 0);
+                    bool treatAsNewFile = ReplaceFileContentsOnEachWrite || (initialFileOpen && ArchiveOldFileOnStartup);
+                    bool forceHeaderOnStart = initialFileOpen && WriteHeaderWhenInitialFileNotEmpty;
+                    bool writeHeader = forceHeaderOnStart || treatAsNewFile || (fileWasEmpty ?? fileStream.Length == 0);
                     if (writeHeader)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Targets/FileTarget.cs` at line 1313, The complex boolean for
writeHeader should be split into named local booleans to reduce cognitive
complexity: compute separate locals such as bool isInitialOpen =
initialFileOpen, bool initialNotEmptyHeader = isInitialOpen &&
WriteHeaderWhenInitialFileNotEmpty, bool replaceOnEachWrite =
ReplaceFileContentsOnEachWrite, bool archiveOnStartup = isInitialOpen &&
ArchiveOldFileOnStartup, and bool isFileEmpty = fileWasEmpty ??
fileStream.Length == 0, then set writeHeader = initialNotEmptyHeader ||
replaceOnEachWrite || archiveOnStartup || isFileEmpty; update the assignment
site (writeHeader and the referenced symbols initialFileOpen,
WriteHeaderWhenInitialFileNotEmpty, ReplaceFileContentsOnEachWrite,
ArchiveOldFileOnStartup, fileWasEmpty, fileStream.Length) accordingly to improve
readability and satisfy SonarCloud.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/NLog/Targets/FileTarget.cs`:
- Line 1313: The complex boolean for writeHeader should be split into named
local booleans to reduce cognitive complexity: compute separate locals such as
bool isInitialOpen = initialFileOpen, bool initialNotEmptyHeader = isInitialOpen
&& WriteHeaderWhenInitialFileNotEmpty, bool replaceOnEachWrite =
ReplaceFileContentsOnEachWrite, bool archiveOnStartup = isInitialOpen &&
ArchiveOldFileOnStartup, and bool isFileEmpty = fileWasEmpty ??
fileStream.Length == 0, then set writeHeader = initialNotEmptyHeader ||
replaceOnEachWrite || archiveOnStartup || isFileEmpty; update the assignment
site (writeHeader and the referenced symbols initialFileOpen,
WriteHeaderWhenInitialFileNotEmpty, ReplaceFileContentsOnEachWrite,
ArchiveOldFileOnStartup, fileWasEmpty, fileStream.Length) accordingly to improve
readability and satisfy SonarCloud.

In `@tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs`:
- Around line 43-46: The constructor for GZipFileTests sets the global static
LogManager.ThrowExceptions which can leak across tests; modify GZipFileTests to
capture the previous value, implement IDisposable (or use an IClassFixture) and
in Dispose restore LogManager.ThrowExceptions to the saved previousValue so the
global state is reset after the test class finishes; reference the GZipFileTests
constructor, LogManager.ThrowExceptions and Dispose/IDisposable (or
IClassFixture) when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e2b1205d-6a9d-4f67-8921-a6b8d42621f5

📥 Commits

Reviewing files that changed from the base of the PR and between 19b3146 and 30fd39d.

📒 Files selected for processing (2)
  • src/NLog/Targets/FileTarget.cs
  • tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs

@snakefoot snakefoot added this to the 6.1.2 milestone Mar 28, 2026
Copy link
Copy Markdown

@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.

🧹 Nitpick comments (2)
tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs (1)

120-128: Make regression preconditions explicit in target setup.

To avoid this test silently drifting with future default changes, set the key preconditions explicitly (especially the startup/archive/open mode that exercises this path).

🧪 Suggested test setup hardening
                     cfg.ForLogger().WriteTo(new GZipFileTarget()
                     {
                         FileName = logFileName,
                         Layout = "${message}",
                         LineEnding = LineEndingMode.LF,
+                        KeepFileOpen = true,
+                        ArchiveOldFileOnStartup = true,
+                        CompressionLevel = CompressionLevel.Optimal,
                         Header = "Hello World",
                         Footer = "Goodbye World",
                         WriteBom = true,
                     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs` around lines 120 - 128,
The test relies on specific target startup/archive/open behavior but doesn't
lock those preconditions; update the GZipFileTarget setup (the new
GZipFileTarget instance used in the test where FileName, Layout, LineEnding,
Header, Footer, WriteBom are set) to explicitly set the startup/archive/open
mode properties so the exercised path can't change with defaults—for example set
StartMode (or equivalent startup property), ArchiveMode (or archive rotation
property), and file-open behavior properties such as KeepFileOpen and
ConcurrentWrite (or OpenFileShare/OpenFileCache settings) to the values required
by the test; ensure those properties are set on the same GZipFileTarget instance
so the test remains deterministic.
src/NLog/Targets/FileTarget.cs (1)

1331-1338: Harden IsNewFileEmpty against non-seekable streams.

Line 1335's exact-type matching with GetType() is brittle for wrapped streams. More critically, line 1337's unconditional access to fileStream.Length can throw NotSupportedException for non-seekable streams (e.g., GZipStream from GZipFileTarget) when initialFileOpen=false during file reopens, since the type guard at line 1335 only applies when initialFileOpen=true. Use capability checks (CanSeek) instead of runtime type matching.

♻️ Proposed refactor
 private bool IsNewFileEmpty(bool initialFileOpen, Stream fileStream)
 {
     if (ReplaceFileContentsOnEachWrite)
         return true;
-    if (initialFileOpen && ArchiveOldFileOnStartup && !typeof(FileStream).Equals(fileStream.GetType()))
+    if (initialFileOpen && ArchiveOldFileOnStartup && !fileStream.CanSeek)
         return true;
+    if (!fileStream.CanSeek)
+        return false;
     return fileStream.Length == 0;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Targets/FileTarget.cs` around lines 1331 - 1338, The IsNewFileEmpty
method currently uses exact type comparison and unguarded access to
fileStream.Length which can throw for non-seekable or wrapped streams; update
IsNewFileEmpty to return true when ReplaceFileContentsOnEachWrite is set, and
when initialFileOpen is true and ArchiveOldFileOnStartup is set but the provided
stream cannot seek (use fileStream.CanSeek instead of
typeof(FileStream).Equals(fileStream.GetType())), and before reading Length
ensure fileStream.CanSeek is true (otherwise treat as non-empty/return true as
appropriate for your logic) to avoid NotSupportedException on streams like
GZipStream.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/NLog/Targets/FileTarget.cs`:
- Around line 1331-1338: The IsNewFileEmpty method currently uses exact type
comparison and unguarded access to fileStream.Length which can throw for
non-seekable or wrapped streams; update IsNewFileEmpty to return true when
ReplaceFileContentsOnEachWrite is set, and when initialFileOpen is true and
ArchiveOldFileOnStartup is set but the provided stream cannot seek (use
fileStream.CanSeek instead of typeof(FileStream).Equals(fileStream.GetType())),
and before reading Length ensure fileStream.CanSeek is true (otherwise treat as
non-empty/return true as appropriate for your logic) to avoid
NotSupportedException on streams like GZipStream.

In `@tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs`:
- Around line 120-128: The test relies on specific target startup/archive/open
behavior but doesn't lock those preconditions; update the GZipFileTarget setup
(the new GZipFileTarget instance used in the test where FileName, Layout,
LineEnding, Header, Footer, WriteBom are set) to explicitly set the
startup/archive/open mode properties so the exercised path can't change with
defaults—for example set StartMode (or equivalent startup property), ArchiveMode
(or archive rotation property), and file-open behavior properties such as
KeepFileOpen and ConcurrentWrite (or OpenFileShare/OpenFileCache settings) to
the values required by the test; ensure those properties are set on the same
GZipFileTarget instance so the test remains deterministic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4b55ca34-461e-4568-9ae7-a7ba5e2123c2

📥 Commits

Reviewing files that changed from the base of the PR and between 30fd39d and e9422fc.

📒 Files selected for processing (2)
  • src/NLog/Targets/FileTarget.cs
  • tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs

@snakefoot snakefoot force-pushed the GzipFileHeader branch 2 times, most recently from a545d0e to 336d209 Compare March 28, 2026 09:46
Copy link
Copy Markdown

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/NLog/Targets/FileTarget.cs`:
- Around line 1331-1337: The IsNewFileEmpty method currently accesses
fileStream.Length without verifying seekability; update IsNewFileEmpty to first
check fileStream.CanSeek and handle non-seekable streams (e.g., if
(!fileStream.CanSeek) return true) before reading Length so you don't throw
NotSupportedException for streams like GZipStream; keep the existing
special-case logic (ReplaceFileContentsOnEachWrite, initialFileOpen &&
ArchiveOldFileOnStartup) and then only use fileStream.Length when
fileStream.CanSeek is true.

In `@tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs`:
- Around line 43-46: The constructor GZipFileTests currently mutates global
state by setting LogManager.ThrowExceptions = true and never restores it; modify
the GZipFileTests class to implement IDisposable, add a private bool field (e.g.
originalThrowExceptions) to capture the prior LogManager.ThrowExceptions value
in the constructor, and implement Dispose() to restore
LogManager.ThrowExceptions back to originalThrowExceptions after each test;
ensure the constructor still sets ThrowExceptions = true and Dispose restores
the saved value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fe9d954d-b224-4d57-aa66-d7822c7cf7df

📥 Commits

Reviewing files that changed from the base of the PR and between e9422fc and 336d209.

📒 Files selected for processing (2)
  • src/NLog/Targets/FileTarget.cs
  • tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs

@snakefoot snakefoot force-pushed the GzipFileHeader branch 2 times, most recently from 51730ef to 3929f86 Compare March 28, 2026 10:50
@pull-request-size pull-request-size bot added size/L and removed size/M labels Mar 28, 2026
Copy link
Copy Markdown

@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.

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

1331-1338: Consider a more defensive check for non-seekable streams.

The current logic only avoids fileStream.Length when both ArchiveOldFileOnStartup is true AND the stream is non-seekable. If a future subclass overrides CreateFileStream to return a non-seekable stream without setting ArchiveOldFileOnStartup=true, this would throw NotSupportedException.

The implementation works correctly for GZipFileTarget since it falls back to a regular FileStream when ArchiveOldFileOnStartup=false. However, a more defensive approach would check CanSeek first:

🛡️ Optional defensive refactor
 private bool IsNewFileEmpty(bool initialFileOpen, Stream fileStream)
 {
     if (ReplaceFileContentsOnEachWrite)
         return true;
-    if (ArchiveOldFileOnStartup && !fileStream.CanSeek)
-        return initialFileOpen;    // NLog.Targets.GZipFile expects newly opened files to be empty
+    if (!fileStream.CanSeek)
+        return initialFileOpen && ArchiveOldFileOnStartup;    // NLog.Targets.GZipFile expects newly opened files to be empty
     return fileStream.Length == 0;
 }

This ensures fileStream.Length is never accessed on non-seekable streams, returning false (non-empty) as a safe fallback when conditions aren't met.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Targets/FileTarget.cs` around lines 1331 - 1338, The IsNewFileEmpty
method must avoid accessing fileStream.Length on non-seekable streams; update
the logic in IsNewFileEmpty to first check ReplaceFileContentsOnEachWrite
(return true), then check fileStream.CanSeek and if false return
ArchiveOldFileOnStartup ? initialFileOpen : false, and only if the stream is
seekable evaluate ArchiveOldFileOnStartup or fileStream.Length == 0; this
ensures fileStream.Length is never called for non-seekable streams (refer to
method IsNewFileEmpty and flags ReplaceFileContentsOnEachWrite and
ArchiveOldFileOnStartup).
tests/NLog.Targets.AtomicFile.Tests/AtomFileTests.cs (1)

42-45: Global state mutation may affect test isolation.

Setting LogManager.ThrowExceptions = true in the constructor modifies global state, which could interfere with parallel test execution. Since the test creates its own LogFactory instance (line 55), consider setting ThrowExceptions on that specific factory instead:

♻️ Preferred: Configure the specific LogFactory instance
 public AtomFileTests()
 {
-    LogManager.ThrowExceptions = true;
 }

 [Fact]
 public void SimpleAtomicFileStream_HeaderFooterBom()
 {
     // ...
     try
     {
-        var logFactory = new LogFactory().Setup().LoadConfiguration(cfg =>
+        var logFactory = new LogFactory();
+        logFactory.ThrowExceptions = true;
+        logFactory.Setup().LoadConfiguration(cfg =>

Alternatively, if LogManager.ThrowExceptions is intentional for all tests, consider implementing IDisposable to restore the original value after tests complete.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/NLog.Targets.AtomicFile.Tests/AtomFileTests.cs` around lines 42 - 45,
The test constructor currently sets the global LogManager.ThrowExceptions = true
which mutates global state; instead, remove that global assignment in
AtomFileTests() and set the ThrowExceptions flag on the specific LogFactory
instance you create for the tests (the LogFactory created in the test setup) by
assigning factory.ThrowExceptions = true right after constructing the
LogFactory; if the global change was intentional for all tests, implement
IDisposable on AtomFileTests to save the original LogManager.ThrowExceptions
value in the constructor and restore it in Dispose() to avoid leaking global
state across tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/NLog/Targets/FileTarget.cs`:
- Around line 1331-1338: The IsNewFileEmpty method must avoid accessing
fileStream.Length on non-seekable streams; update the logic in IsNewFileEmpty to
first check ReplaceFileContentsOnEachWrite (return true), then check
fileStream.CanSeek and if false return ArchiveOldFileOnStartup ? initialFileOpen
: false, and only if the stream is seekable evaluate ArchiveOldFileOnStartup or
fileStream.Length == 0; this ensures fileStream.Length is never called for
non-seekable streams (refer to method IsNewFileEmpty and flags
ReplaceFileContentsOnEachWrite and ArchiveOldFileOnStartup).

In `@tests/NLog.Targets.AtomicFile.Tests/AtomFileTests.cs`:
- Around line 42-45: The test constructor currently sets the global
LogManager.ThrowExceptions = true which mutates global state; instead, remove
that global assignment in AtomFileTests() and set the ThrowExceptions flag on
the specific LogFactory instance you create for the tests (the LogFactory
created in the test setup) by assigning factory.ThrowExceptions = true right
after constructing the LogFactory; if the global change was intentional for all
tests, implement IDisposable on AtomFileTests to save the original
LogManager.ThrowExceptions value in the constructor and restore it in Dispose()
to avoid leaking global state across tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5842a025-1254-4b7a-b71e-5bca4ba095a4

📥 Commits

Reviewing files that changed from the base of the PR and between 51730ef and 65e15c7.

📒 Files selected for processing (3)
  • src/NLog/Targets/FileTarget.cs
  • tests/NLog.Targets.AtomicFile.Tests/AtomFileTests.cs
  • tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/NLog.Targets.GZipFile.Tests/GZipFileTests.cs

@sonarqubecloud
Copy link
Copy Markdown

@sonarqubecloud
Copy link
Copy Markdown

This was referenced Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug report / Bug fix file-target size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

System.NotSupportedException: GZipStream.get_Length() still occurring in NLog 6.1.1 with GZipFileTarget during file open

2 participants