diff --git a/src/NLog/Targets/FileTarget.cs b/src/NLog/Targets/FileTarget.cs
index db46c5d440..bffef3a1c7 100644
--- a/src/NLog/Targets/FileTarget.cs
+++ b/src/NLog/Targets/FileTarget.cs
@@ -486,6 +486,13 @@ public bool ArchiveOldFileOnStartup
set => _archiveOldFileOnStartup = value;
}
private bool? _archiveOldFileOnStartup;
+
+ ///
+ /// Gets or sets whether to write the Header on initial creation of file appender.
+ /// Independent of file is empty or not.
+ /// Alternative use to ensure each application session has its own individual log-file.
+ ///
+ public bool WriteHeaderOnInitialFileOpen { get; set; }
///
/// Gets or sets a value of the file size threshold to archive old log file on startup.
@@ -2493,25 +2500,24 @@ private void WriteHeaderAndBom(BaseFileAppender appender)
if (Header is null && !WriteBom) return;
var length = appender.GetFileLength();
- // Write header and BOM only on empty files or if file info cannot be obtained.
- if (length is null || length == 0)
+ // File is empty or file info cannot be obtained
+ var isNewOrEmptyFile = length is null || length == 0;
+
+ if (isNewOrEmptyFile && WriteBom)
{
- if (WriteBom)
- {
- InternalLogger.Trace("{0}: Write byte order mark from encoding={1}", this, Encoding);
- var preamble = Encoding.GetPreamble();
- if (preamble.Length > 0)
- appender.Write(preamble, 0, preamble.Length);
- }
-
- if (Header != null)
+ InternalLogger.Trace("{0}: Write byte order mark from encoding={1}", this, Encoding);
+ var preamble = Encoding.GetPreamble();
+ if (preamble.Length > 0)
+ appender.Write(preamble, 0, preamble.Length);
+ }
+
+ if (Header != null && (isNewOrEmptyFile || WriteHeaderOnInitialFileOpen))
+ {
+ InternalLogger.Trace("{0}: Write header", this);
+ ArraySegment headerBytes = GetLayoutBytes(Header);
+ if (headerBytes.Count > 0)
{
- InternalLogger.Trace("{0}: Write header", this);
- ArraySegment headerBytes = GetLayoutBytes(Header);
- if (headerBytes.Count > 0)
- {
- appender.Write(headerBytes.Array, headerBytes.Offset, headerBytes.Count);
- }
+ appender.Write(headerBytes.Array, headerBytes.Offset, headerBytes.Count);
}
}
}
diff --git a/tests/NLog.UnitTests/Targets/FileTargetTests.cs b/tests/NLog.UnitTests/Targets/FileTargetTests.cs
index f90379cb84..f44a658fa4 100644
--- a/tests/NLog.UnitTests/Targets/FileTargetTests.cs
+++ b/tests/NLog.UnitTests/Targets/FileTargetTests.cs
@@ -2237,6 +2237,71 @@ public void RepeatingFooterTest(bool writeFooterOnArchivingOnly)
Directory.Delete(tempDir, true);
}
}
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void WriteHeaderOnStartupTest(bool writeHeaderOnInitialFileOpen)
+ {
+ var logFile = Path.GetTempFileName() + ".txt";
+ try
+ {
+ const string header = "Headerline";
+
+ // Configure first time
+ var fileTarget = new FileTarget
+ {
+ FileName = SimpleLayout.Escape(logFile),
+ LineEnding = LineEndingMode.LF,
+ Layout = "${message}",
+ Header = header,
+ WriteBom = true,
+ WriteHeaderOnInitialFileOpen = true
+ };
+
+ LogManager.Setup().LoadConfiguration(c => c.ForLogger().WriteTo(fileTarget));
+
+ logger.Debug("aaa");
+ logger.Info("bbb");
+ logger.Warn("ccc");
+
+ LogManager.Configuration = null;
+
+ string headerPart = header + LineEndingMode.LF.NewLineCharacters;
+ string logPart = "aaa\nbbb\nccc\n";
+ AssertFileContents(logFile, headerPart + logPart, Encoding.UTF8, addBom: true);
+
+ // Configure second time
+ fileTarget = new FileTarget
+ {
+ FileName = SimpleLayout.Escape(logFile),
+ LineEnding = LineEndingMode.LF,
+ Layout = "${message}",
+ Header = header,
+ WriteBom = true,
+ WriteHeaderOnInitialFileOpen = writeHeaderOnInitialFileOpen
+ };
+
+ LogManager.Setup().LoadConfiguration(c => c.ForLogger().WriteTo(fileTarget));
+
+ logger.Debug("aaa");
+ logger.Info("bbb");
+ logger.Warn("ccc");
+
+ LogManager.Configuration = null; // Flush
+
+ if (writeHeaderOnInitialFileOpen)
+ AssertFileContents(logFile, headerPart + logPart + headerPart + logPart, Encoding.UTF8, addBom: true);
+ else
+ AssertFileContents(logFile, headerPart + logPart + logPart, Encoding.UTF8, addBom: true);
+ }
+ finally
+ {
+ LogManager.Configuration = null;
+ if (File.Exists(logFile))
+ File.Delete(logFile);
+ }
+ }
[Theory]
[InlineData(false)]