Skip to content
NoGTNoHappy edited this page Dec 12, 2023 · 141 revisions

Writes log messages to one or more files.

Platforms Supported: All

Configuration Syntax

<targets>
  <target xsi:type="File"
          name="String"
          layout="Layout"
          header="Layout"
          footer="Layout"
          encoding="Encoding"
          lineEnding="Enum"
          archiveAboveSize="Long"
          maxArchiveFiles="Integer"
          maxArchiveDays="Integer"
          archiveFileName="Layout"
          archiveNumbering="Enum"
          archiveDateFormat="String"
          archiveEvery="Enum"          
          archiveOldFileOnStartup="Boolean"
          archiveOldFileOnStartupAboveSize="Long"
          replaceFileContentsOnEachWrite="Boolean"
          fileAttributes="Enum"
          fileName="Layout"
          deleteOldFileOnStartup="Boolean"
          enableFileDelete="Boolean"
          createDirs="Boolean"
          concurrentWrites="Boolean"
          openFileFlushTimeout="Integer"
          openFileCacheTimeout="Integer"
          openFileCacheSize="Integer"
          networkWrites="Boolean"
          concurrentWriteAttemptDelay="Integer"
          concurrentWriteAttempts="Integer"
          bufferSize="Integer"
          autoFlush="Boolean"
          keepFileOpen="Boolean"
          forceManaged="Boolean"
          enableArchiveFileCompression="Boolean"
          cleanupFileName="Boolean"
          writeFooterOnArchivingOnly="Boolean"
          writeHeaderWhenInitialFileNotEmpty="Boolean"
          writeBom="Boolean" />
</targets>

Read more about using the Configuration File.

Parameters

General Options

  • name - Name of the target.

  • forceManaged - Indicates that the file target should only use managed methods. This disables some of the options.

Layout Options

  • layout - Text to be rendered. Layout Required. Default: ${longdate}|${level:uppercase=true}|${logger}|${message:withexception=true}

  • header - Header. Layout

  • footer - Footer. Layout

  • encoding - File encoding name like "utf-8", "ascii" or "utf-16". See Encoding class on MSDN. Default: Utf-8 (Before NLog 5.0 the default was Encoding.Default)

  • writeBom - Indicates whether to write BOM (byte order mark) in created files. Boolean Default: false.

    Introduced with NLog 4.5. Before NLog 5.0 it would not enabled automatically when encoding UTF16 or UTF32.

  • lineEnding - Line ending mode.
    Possible values:

    • CR - Insert CR character (ASCII 13) after each line.
    • CRLF - Insert CR LF sequence (ASCII 13, ASCII 10) after each line.
    • Default - Insert platform-dependent end-of-line sequence after each line.
    • LF - Insert LF character (ASCII 10) after each line.
    • NULL - Null terminator (ASCII 0) after each line.
    • None - Don't insert any line ending.

Output Options

  • fileName - Name of the file to write to. Layout Required.
    This FileName string is a layout which may include instances of layout renderers. This lets you use a single target to write to multiple files.
    The following value makes NLog write logging events to files based on the log level in the directory where the application runs. ${basedir}/${level}.log All Debug messages will go to Debug.log, all Info messages will go to Info.log and so on. You can combine as many of the layout renderers as you want to produce an arbitrary log file name. See also Filename Directory

  • enableFileDelete - Indicates whether to enable log file(s) to be deleted. The FileTarget will periodically verify if the file has been deleted and must be recreated. When using ConcurrentWrites=true, then FileSystem watchers are activated for monitoring. Boolean Default: True

  • createDirs - Indicates whether to create directories if they don't exist. Boolean Default: True
    Setting this to false may improve performance a bit, but you'll receive an error when attempting to write to a directory that's not present.

  • replaceFileContentsOnEachWrite - Indicates whether to replace file contents on each write instead of appending log message at the end. Boolean Default: False

  • writeHeaderWhenInitialFileNotEmpty - Indicates whether to write the Header on initial creation of file appender, independent of file is empty or not. Boolean Default: False (Alternative one can use archiveOldFileOnStartup to ensure each application-session has its own individual log-file)

    Introduced with NLog v5.2.6

  • fileAttributes - File attributes (Windows only).
    Possible values:

    • Archive - File should be archived.
    • Compressed - Compress won't work due to .Net restrictions. You can use enableArchiveFileCompression.
    • DeleteOnClose - Delete file after it is closed.
    • Device - Device file.
    • Encrypted - Encrypted file.
    • Hidden - Hidden file.
    • NoBuffering - The system opens a file with no system caching.
    • Normal - Normal file.
    • NotContentIndexed - File should not be indexed by the content indexing service.
    • PosixSemantics - A file is accessed according to POSIX rules.
    • Readonly - Read-only
    • ReadOnly - Read-only file.
    • ReparsePoint - Reparse point.
    • SparseFile - Sparse file.
    • System - System file.
    • Temporary - File is temporary (should be kept in cache and not written to disk if possible).
    • WriteThrough - The system writes through any intermediate cache and goes directly to disk.

Archival Options

  • deleteOldFileOnStartup - Indicates whether to delete old log file on startup. Boolean Default: False. This option works only when the "FileName" parameter denotes a single file.

  • archiveAboveSize - Size in bytes above which log files will be automatically archived. Long

    Before NLog ver. 4.5.7 then this would not work together with archiveNumbering=Date. Newer version will correctly merge into the existing file on archive.

  • maxArchiveFiles - Maximum number of archive files that should be kept. If maxArchiveFiles is less or equal to 0, old files aren't deleted Integer Default: 0

  • maxArchiveDays - Maximum age of archive files that should be kept. Has no effect when archiveNumbering is Rolling. If maxArchiveDays is less or equal to 0, old files aren't deleted Integer Default: 0

    Introduced with NLog 4.7 but not supporting archiveNumbering="Rolling", or archiveNumbering="Sequence" with custom archiveFileName-path

    NLog 5.0 added support for archiveNumbering="Sequence" with custom archiveFileName-path

  • archiveFileName - Name of the file to be used for an archive. Layout
    It may contain a special placeholder {###} that will be replaced with a sequence of numbers depending on the archiving strategy. The number of hash characters used determines the number of numerical digits to be used for numbering files.

    • Warning: Before NLog 4.5 then it would lead to very aggressive cleanup if having configured maxArchiveFiles without having specified the special placeholder {###}. NLog 4.4 would delete any file from the archive folder (not just log files), so make sure specify an isolated folder. This has been fixed in NLog 4.5 (and newer) where cleanup wildcard is not as dangerous, and allows same folder archives.
  • archiveNumbering - Way file archives are numbered. See also Archive Numbering Examples
    Possible values:

    • Rolling - Rolling style numbering (the most recent is always #0 then #1, ..., #N).
    • Sequence - Sequence style numbering. The most recent archive has the highest number.
    • Date - Date style numbering. The date is formatted according to the value of archiveDateFormat.
      • Warning: Before NLog ver. 4.5.7 then this would not work together with archiveAboveSize. Newer version will correctly merge into the existing file on archive.
    • DateAndSequence - Combination of Date and Sequence .Archives will be stamped with the prior period (Year, Month, Day) datetime. The most recent archive has the highest number (in combination with the date). The date is formatted according to the value of archiveDateFormat.
  • archiveEvery - Indicates whether to automatically archive log files every time the specified time passes.
    Possible values:

    • Day - Archive daily.
    • Hour - Archive every hour.
    • Minute - Archive every minute.
    • Month - Archive every month.
    • None - Don't archive based on time.
    • Year - Archive every year.
    • Sunday - Archive every Sunday. Introduced in NLog 4.4.4.
    • Monday - Archive every Monday. Introduced in NLog 4.4.4.
    • Tuesday - Archive every Tuesday. Introduced in NLog 4.4.4.
    • Wednesday - Archive every Wednesday. Introduced in NLog 4.4.4.
    • Thursday - Archive every Thursday. Introduced in NLog 4.4.4.
    • Friday - Archive every Friday. Introduced in NLog 4.4.4.
    • Saturday - Archive every Saturday. Introduced in NLog 4.4.4.

    Files are moved to the archive as part of the write operation if the current period of time changes. For example if the current hour changes from 10 to 11, the first write that will occur on or after 11:00 will trigger the archiving.

  • archiveDateFormat - Specifies the date format used for archive numbering. Default format depends on the archive period. This option works only when the "ArchiveNumbering" parameter is set to Date or DateAndSequence

    • Default: yyyyMMdd
    • Default when ArchiveEvery = Minute: yyyyMMddHHmm
    • Default when ArchiveEvery = Hour: yyyyMMddHH
    • Default when ArchiveEvery = Month: yyyyMM
    • Default when ArchiveEvery = Year: yyyy
  • archiveOldFileOnStartup - Archive old log file on startup. Default: False

  • archiveOldFileOnStartupAboveSize - File size threshold to archive old log file on startup. Default value is 0 which means that the file is archived as soon as archiveOldFileOnStartup is enabled. Introduced in NLog 4.7

  • enableArchiveFileCompression - Indicates whether to compress the archive files into the zip files. Boolean Default: False

    Introduced in NLog ver. 4.0. Not supported for .Net35 + .Net40 and only works with static filename Before NLog ver. 5.0 then the filename inside the zip-file would be original filename, instead of archive-filename.

  • writeFooterOnArchivingOnly - Indicates whether the footer should be written only when the file is archived. If False, the footer will also be written when starting to write to a different file and when the target is closed Boolean Default: False

Performance Tuning Options

  • keepFileOpen - Indicates whether to keep log file open instead of opening and closing it on each logging event. When set to false it will allow other applications to "take over" the filehandle, and NLog will fail logging to file. When set to false then it will give a major performance hit because it is expensive to open/close file-handle. If the FileName points to a network-path, then it is recommended to use keepFileOpen="false" in combination with <targets async="true">. Boolean Default: True (Before NLog 5.0 the default was false)

  • concurrentWrites - Enables support for optimized concurrent writes to same log file from multiple processes on the same machine-host, when using keepFileOpen = true. By using a special synchronization techniques that lets it keep the files open from multiple processes. The special synchronization cost performance and not compatible with platforms like UWP / Xamarin. Default: False (Before NLog 5.0 the default was true)

  • openFileCacheTimeout - Maximum number of seconds that files are kept open. If this number is negative the files are not automatically closed after a period of inactivity. Integer Default: -1

  • openFileCacheSize - Number of files to be kept open. Setting this to a higher value may improve performance in a situation where a single File target is writing to many files (such as splitting by level or by logger). Integer Default: 5
    The files are managed on a LRU (least recently used) basis, which flushes the files that have not been used for the longest period of time should the cache become full. As a rule of thumb, you shouldn't set this parameter to a very high value. A number like 10-15 shouldn't be exceeded, because you'd be keeping a large number of files open which consumes system resources.

  • networkWrites - Indicates whether concurrent writes to the log file by multiple processes on different network hosts. This effectively prevents files from being kept open, so behaves just like KeepFileOpen="false". Boolean Default: False

  • concurrentWriteAttemptDelay - Delay in milliseconds to wait before attempting to write to the file again. Integer Default: 1
    The actual delay is a random value between 0 and the value specified in this parameter. On each failed attempt the delay base is doubled up to ConcurrentWriteAttempts times.
    Assuming that ConcurrentWriteAttemptDelay is 10 the time to wait will be: a random value between 0 and 10 milliseconds - 1st attempt a random value between 0 and 20 milliseconds - 2nd attempt a random value between 0 and 40 milliseconds - 3rd attempt a random value between 0 and 80 milliseconds - 4th attempt ... and so on.

  • concurrentWriteAttempts - Number of times the write is attempted on the file before NLog discards the log message. Integer Default: 10

  • cleanupFileName - before writing to a file, the name of the file get checked for illegal characters (OS dependent). This can be costly if a lot of messages are written. The cleanup is cached for fixed names (no layout renderers). Set this to false for optimal performance (but beware of the file name, if it's wrong, nothing gets written). Default: true. Introduced in NLog 4.2.3.

  • bufferSize - Log file buffer size in bytes. Notice Large-Object-Heap will be used when size 85000 or above. Integer Default: 32768

  • autoFlush - Ensures file buffers are flushed after each log message, thus avoiding loss of critical log-messages during unexpected application-crash or -exit. The operating system will ensure that flushed data will be written to disk, even if application has left the planet. But if the operating system also crashes or computer-power-failure, then flushed data might still be lost, as it is not flush with write-through. If log-messages are not super critical for troubleshooting, or not having issues with unexptected application crashes, then one can improve performance with AutoFlush = false (See also openFileFlushTimeout). Boolean Default: True

  • openFileFlushTimeout - Number of seconds between explicit flush of file buffers. Helps to ensure file buffers are eventually flushed when autoFlush = false. Integer Default: 0 (Disabled)

    Introduced with NLog v4.5.7

Examples

Simple logging

The simplest use of File target is to produce single log file. In order to do this, put the following code in the configuration file such as NLog.config. Logs wil be written to logfile.txt in logs directory.

<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 
    <targets>
        <target name="file" xsi:type="File"
            layout="${longdate} ${logger} ${message}${exception:format=ToString}" 
            fileName="${basedir}/logs/logfile.txt" 
            keepFileOpen="true"
            encoding="utf-8" />
    </targets>
 
    <rules>
        <logger name="*" minlevel="Debug" writeTo="file" />
    </rules>
</nlog>

Filename Directory

File Target supports relative paths since NLog 4.3, where it will implicitly use ${BaseDir} (AppDomain.BaseDirectory). It is also possible to specify an absolute path or make use of these helpers:

Example using CommonApplicationData which is good when running as Windows Service:

  • fileName="${specialfolder:folder=CommonApplicationData:cached=true}/AppName/logfile.txt"
    • Windows-Path - C:/ProgramData/AppName/logfile.txt

To remove all doubt, then one can also use absolute-paths. And by using NLog config variables then one can reuse the absolute path for multiple file targets:

<variable name="logDirectory" value="C:/AppDir/" />
<targets>
<target type="file" name="logfile" filename="${logDirectory}App.log" />
</targets>

It is also possible to override the directory at runtime using GDC:

<targets>
<target type="file" name="logfile" filename="${gdc:logDirectory:whenEmpty=${baseDir}}/App.log" />
</targets>
NLog.GlobalDiagnosticsContext.Set("logDirectory", "C:/Temp/");

Batch write and asynchronous logging

The file target has support for batch writing, where multiple log messages are written in one file-operation. Batch write will improve performance, especially when using KeepFileOpen=false. Batch writing is enabled automatically when using the AsyncWrapper. This can be done by adding the attribute async="true" to the <targets>-element.

Asynchronous logging is recommended for multi-threaded server applications, but might not be worth it for quick-finishing command line application. Make sure to remember to flush at application shutdown, or else output can be dropped.

<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 
    <targets async="true">
        <target type="File" name="logfile" fileName="${basedir}/logs/${level}.txt" keepFileOpen="true" />
    </targets>
 
    <rules>
        <logger name="*" minlevel="Debug" writeTo="logfile" />
    </rules>
</nlog>

Multi processes writing same file

The file target supports that multiple applications are concurrently writing to the same file. This mode is activated with concurrentWrites=true. The IIS-application can run multiple AppDomains, and each AppDomain operates like a child process. When multiple processes are concurrently writing to the same file, then some locking for coordination is needed. NLog has support for the following locking-modes:

  • Operating System File Locks - Default mode that is supported on most platforms. This mode is enabled with KeepFileOpen=false and ConcurrentWrites=true. File locking from operating system are not fair and doesn't scale when having more than 2 processes writing to the same file. Exceptions will be thrown when one process tries to open a file, that is currently in use by another process. NLog tries to handle these exception by retrying on error (concurrentWriteAttempts=10) together with randomizing how long to wait before retry (concurrentWriteAttemptDelay=1). When you start to increase the number of processes, then the chance of failing 10 times in row increases, and so log messages are lost.

  • Global Mutex Locks - NLog can use global mutex for inter-process communication, which is supported on many platforms. This mode is enabled with KeepFileOpen=True and ConcurrentWrites=true. The performance is better than file locks and with much less memory allocations. It works great on Windows, and most Linux platforms using NetCore2 or newer versions of MONO. But seldom works for platforms for mobile devices like UWP / Xamarin Android / Xamarin iOS as these platforms runs in restricted sandbox without access to global mutex.

  • Atomic File Append - .NET Framework on Windows has support for atomic file append mode. This mode is enabled with KeepFileOpen=True and ConcurrentWrites=true. This mode is only supported for .NET Framework on Windows platform. The lock synchronization is fair, and happens at the operating system level. It is the fastest concurrent mode available with minimum overhead.

It is recommended to enable asynchronous logging as it will reduce the overhead from file locking coordination (Especially when using KeepFileOpen=false and ConcurrentWrites=true).

Archive old log files

NLog 4.5 makes it easy to setup archive logic to cleanup old files when using dynamic fileName-Layout. You just need to configure maxArchiveFiles and it will automatically perform cleanup.

<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 
    <targets>
        <target name="file" xsi:type="File"
            layout="${longdate} ${logger} ${message}${exception:format=ToString}" 
            fileName="${basedir}/logs/AppLog.${shortdate}.txt" 
            maxArchiveFiles="4"
            archiveAboveSize="10240" />
    </targets>
 
    <rules>
        <logger name="*" minlevel="Debug" writeTo="file" />
    </rules>
</nlog>

NLog 4.7 (and newer) adds support for the option MaxArchiveDays. It works like MaxArchiveFiles but instead inspect the timestamp of the files in the archive. They can be combined. Ex. maxArchiveDays="30" maxArchiveFiles="90" (Deletes files older than 30 days or if more than 90 files in archive).

Dynamic vs. Static Archive Logic

Do not mix "Dynamic FileName Archive Logic" together with "Static FileName Archive Logic" as one will get unexpected archive behavior.

  • Dynamic FileName Archive Logic - Enabled by using fileName="${basedir}/AppLog.${shortdate}.log". This means it will roll / archive dynamically because of the layout-renderer-logic in ${date} (Changes on day-change). Never use it together with archiveFileName="..." or archiveEvery="Day".

  • Static FileName Archive Logic - Enabled by using archiveEvery="Day" and archiveFileName="...". This means it will expect the FileName to be static (Ex. fileName="${basedir}/AppLog.txt"). Never use dynamic layout (Ex. ${date}) in archiveFileName="..." or fileName="...". Instead use archiveDateFormat together with {#}.

Static-filename-archive-logic are well suited for being used with tail-applications, that monitors a single static-filename. But there might be issues when NLog tries to rename/move the old file to create new file (Ex. when locked by external file-viewer). There are certain features that only works together with static-filename-archive-logic:

  • archiveFileName - Can move old files into other folder and also rename with datetime/seq-no
  • archiveNumbering - Can control how old files are renamed on archive. Ex DateAndSequence
  • enableArchiveFileCompression - Can compress old files

There are several FileTarget-Archive-Examples of how to use Static FileName with ArchiveEvery.

Per-level log files

Single File target can be used to write to multiple files at once. The following configuration will cause log entries for each log level to be written to a separate file, so you will get:

  • Trace.log
  • Debug.log
  • Info.log
  • Warn.log
  • Error.log
  • Fatal.log
<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 
    <targets>
        <target name="file" xsi:type="File"
            layout="${longdate} ${logger} ${message}${exception:format=ToString}" 
            fileName="${basedir}/${level}.log" />
    </targets>
 
    <rules>
        <logger name="*" minlevel="Debug" writeTo="file" />
    </rules>
</nlog>

JSON Log-file

The NLog FileTarget can be combined with the JsonLayout to create Json-LogFile:

<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets>
        <target name="jsonfile" xsi:type="File" fileName="${basedir}/file.json">
            <layout xsi:type="JsonLayout">
                <attribute name="time" layout="${date:format=O}" />
                <attribute name="message" layout="${message}" />
                <attribute name="logger" layout="${logger}"/>
                <attribute name="level" layout="${level}"/>
            </layout>
        </target>
    </targets>
 
    <rules>
        <logger name="*" minlevel="Debug" writeTo="jsonfile" />
    </rules>
</nlog>

CSV Log-file

The NLog FileTarget can be combined with the CsvLayout to create comma-separated CSV-LogFile. Here is an example of a file with 4 columns:

<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets>
        <target name="csvfile" xsi:type="File" fileName="${basedir}/file.csv">
            <layout xsi:type="CSVLayout">
                <column name="time" layout="${longdate}" />
                <column name="message" layout="${message}" />
                <column name="logger" layout="${logger}"/>
                <column name="level" layout="${level}"/>
            </layout>
        </target>
    </targets>
 
    <rules>
        <logger name="*" minlevel="Debug" writeTo="csvfile" />
    </rules>
</nlog>
Clone this wiki locally