-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Configuration file
NLog will only produce output if having configured one (or more) NLog targets. NLog can be configured using XML by adding a NLog.config, that will be described in the page.
Everything that can be configured from XML file, can be also be configured in code. See also How to configure from code.
Notice instead of using XML configuration file, then it is also possible to load NLog LoggingConfiguration from the appsettings.json
file with help from NLog.Extensions.Logging.
NLog config XML
File locations
Top-level elements
Targets
Log levels
Rules
Variables
Layouts and layout renderers
Asynchronous processing and wrapper targets
Default wrappers
Default target parameters
Extensions
Automatic reconfiguration
Include files
Content escaping
Troubleshooting logging
Example XML for a stand-alone NLog.config
that can be added to Visual Studio Project (Remember to configure File Properties: Copy If newer
):
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="logfile" xsi:type="File" fileName="file.txt" />
<target name="logconsole" xsi:type="Console" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logconsole" />
<logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>
</nlog>
The NLog configuration can also be embedded into the .NET Framework application configuration file (app.config or web.config). This is done by adding an nlog section
element under configSections
and then use the nlog
element. For example:
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
</configSections>
...
<nlog>
<targets>
<target name="logconsole" xsi:type="Console" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logconsole" />
</rules>
</nlog>
</configuration>
The use of an XML namespace is optional, but enables Intellisense in Visual Studio.
NLog config XML is case-insensitive for Xml-Nodes and Xml-Attributes, when not using a namespace and is case-sensitive when using a namespace.
At startup, NLog searches for its configuration in various files as described below. It loads the first nlog configuration found. Search ends when the first nlog configuration is found. NLog will not perform any logging if configuration is not found.
For a stand-alone *.exe application, files are searched as follows:
- standard application configuration file app.config (Ex. applicationname.exe.config)
- applicationname.exe.nlog in application’s directory
- NLog.config in application’s directory
- NLog.dll.nlog in a directory where NLog.dll is located (only if NLog isn't installed in the GAC)
For an ASP.NET application, files are searched as follows:
- standard web application configuration file web.config
- web.nlog located in the same directory as web.config
- NLog.config in application’s directory
- NLog.dll.nlog in a directory where NLog.dll is located (only if NLog isn't installed in the GAC)
See also Explicit NLog configuration loading (Includes details about assets
-folder for Xamarin Android).
You can use the following elements as children to nlog
. targets
and rules
are required in any configuration The others are optional and can be useful in advanced scenarios.
-
targets
– defines log targets/outputs -
rules
– defines log routing rules -
extensions
– loads NLog extensions from the *.dll file -
include
– includes external configuration file -
variable
– sets the value of a configuration variable
The simplest configuration consists of one target
and one rule (logger
) that routes messages to the target.
The targets
section defines log Targets. Each target is represented by a target
element. There are two attributes required for each target:
-
name
– target name -
type
– target type – such as "File", "Database", "Mail". When using namespaces this attribute is namedxsi:type
.
In addition to these attributes, targets usually accept other parameters, which impact the way diagnostic traces are written. Each target has a different set of parameters, they are described in detail on project’s homepage and they are context-sensitive. Intellisense is also available in Visual Studio.
For example – the File target accepts the fileName
parameter which defines output file name and the Console target has the error
parameter which determines whether the diagnostic traces are written to standard error (stderr) instead of standard output (stdout) of the process.
This example demonstrates a targets
section which defines multiple targets: two files, one network target and OutputDebugString target:
<targets>
<target name="f1" xsi:type="File" fileName="file1.txt"/>
<target name="f2" xsi:type="File" fileName="file2.txt"/>
<target name="n1" xsi:type="Network" address="tcp://localhost:4001"/>
<target name="ds" xsi:type="OutputDebugString"/>
</targets>
NLog provides many predefined Targets. It’s actually very easy to create your own target - see How to write a custom Target.
Each log entry has a level. And each logger is configured to include or ignore certain levels. A common configuration is to specify the minimum level where that level and higher levels are included. For example, if the minimum level is Info, then Info, Warn, Error and Fatal are logged, but Debug and Trace are ignored.
The log levels ordered by severity:
LogLevel | Ordinal | Severity | Typical Use |
---|---|---|---|
Trace | 0 | Most verbose level. Used for development and seldom enabled in production. | Ex. Request-payload, Response-payload, Begin-method-X or End-method-X |
Debug | 1 | Debugging the application behavior from internal events of interest. | Ex. Executed query, User authenticated, Session expired |
Info | 2 | Information that highlights progress or application lifetime events. | |
Warn | 3 | Warnings about validation issues or temporary failures that can be recovered. | |
Error | 4 | Errors where functionality has failed or Exception have been caught. | |
Fatal | 5 | Most critical level. Application is about to abort. | |
Off | 6 | Artificial level for disabling logger output |
The special loglevel Off
has the highest ordinal value. It is not used for LogEvents, but can be used for filtering in logging rules.
The rules
section controls how LogEvents from the Logger-objects are redirected to output targets. Where logger-name and log levels can be used for filtering.
When creating a NLog Logger-object then one must provide a logger-name like NLog.LogManager.GetLogger("my logger name")
. The logger-name can also be extracted from class-context by using NLog.LogManager.GetCurrentClassLogger()
where logger-name becomes "NameSpace.ClassName".
A single rule is defined with a logger
element that filters what Logger-objects to match:
-
name
– Match logger-name of the Logger-object - may include wildcard characters (* and ?) -
minlevel
– minimum level to log (matches the specified level and levels above) -
maxlevel
– maximum level to log (matches the specified level and levels below) -
level
– single level to log -
levels
- comma separated list of levels to log -
writeTo
– comma separated list of targets to write to -
final
– no rules are processed after a final rule matches -
enabled
- set tofalse
to disable the rule without deleting it -
ruleName
- rule identifier to allow rule lookup withConfiguration.FindRuleByName
andConfiguration.RemoveRuleByName
. Introduced in NLog 4.6.4 - finalMinLevel - Loggers matching will be restricted to specified minimum level for following rules. Introduced in NLog 5.0
The example below shows a single rule that will match ALL Logger-objects independent of their logger-name because of name="*"
. At the same time it will only match LogEvents with minimum LogLevel = Info (or more severe). LogEvents matching these criterias will be written to the console-target.
<targets>
<target name="logconsole" xsi:type="Console" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logconsole" />
</rules>
Rules are processed in sequential order. Multiple rules may apply to a logger. Use final
to stop processing rules after a match is found.
Note: Although a rule is named logger
, it does not define a logger. It references one or more loggers based on the name-pattern.
A rule is mapped to a logger by matching the rule name
pattern to a logger name. A rule name
attribute may include wildcard characters (* and ?) to match logger names by wildcard matching.
-
*
- matches 0 or more characters -
?
- matches exactly 1 character
When using NLog.LogManager.GetCurrentClassLogger()
then the logger name will have the format "NameSpace.ClassName". This makes it very convenient to setup filtering for all classes within a namespace:
<logger name="Name.Space.*" writeTo="target1" />
By using logger-name filtering then one can also redirect output for a single ClassName-logger:
<logger name="Name.Space.Class1" writeTo="target2" /> <!-- Add final=true to stop output to target1 -->
<logger name="Name.Space.*" writeTo="target1" />
One can also reduce the logging from a single ClassName-logger:
<logger name="Name.Space.Class2" maxlevel="Warn" final="true" /> <!-- Blackhole that stops all but Error + Fatal -->
<logger name="Name.Space.*" writeTo="target1" />
One can also completely block a single ClassName-logger:
<logger name="Name.Space.Class3" maxlevel="Off" final="true" /> <!-- Blackhole that stops everything -->
<logger name="Name.Space.*" writeTo="target1" />
Before NLog 4.6 then one could only use wildcards (*) at the beginning and/or at the end of the pattern:
<rules>
<logger name="*" minlevel="Info" writeTo="logconsole" />
<logger name="Name.Space.*" minlevel="Debug" writeTo="f1" />
<logger name="*.Class1" minlevel="Trace" writeTo="f2" />
<logger name="*.Library.*" minlevel="Warn" writeTo="f3" />
</rules>
Since NLog 4.6, wildcards (* and ?) are allowed in any position.
<rules>
<logger name="*TcpTestServer[*].Connection[07].*" minlevel="Trace" writeTo="logconsole" final="true" />
<logger name="*TcpTestServer[*].Connection[??].*" minlevel="Debug" writeTo="logconsole" final="true" />
<logger name="*" minlevel="Info" writeTo="logconsole" />
</rules>
A rule defines which log entry level(s) are matched. Entries with other levels will not match this rule. A commonly used specifier is minlevel
. The other specifiers allow for more advanced configuration.
If a rule contains more than one level-declaring attribute (level
, levels
, minlevel
and maxlevel
) only the first level-declaring attribute or set is used and the rest are ignored.
The level-declaring attributes are processed in the following order:
level
levels
-
minlevel
andmaxlevel
(these have the same priority) - none (all levels are logged)
For example: if minlevel="Warn" level="Info"
is used, the rule will only use Info
In case a rule is marked as final
and contains any level-declaring attributes, the final
attribute applies only to the specified levels.
The logging rules provides high performance because of their static nature. The options for configuration has been very limited. But recent changes has now been made to improve this:
- NLog 4.6 added support for using NLog Config Variables to configure level attributes. (
level
,minlevel
etc):
<variable name='globalLevel' value='debug'/>
<rules>
<logger minlevel='${globalLevel}'/>
</rules>
-
NLog 4.6.4 added support for lookup of Logging Rules using
RuleName
using Configuration API -
NLog 4.6.7 added support for using NLog Layout like
${gdc:globalLevel}
to dynamically change level attributes at runtime. See also Semi Dynamic Routing Rules
NLog Config Variables allows you to simplify configuration by reducing repeated text. Variable can be used to give a human name to a NLog Layout that is commonly used (or is long and complex). This makes it easier to organize and structure the NLog config.
Define a custom variable as follows:
<variable name="varname" value="xxx" />
The value of a variable can be inserted into an attribute value via the ${varname}
syntax. A variable value can even be used to define the value of another variable. The following example shows using a pre-defined variable shortdate
and defining and using a custom variable logDirectory
.
<nlog>
<variable name="logDirectory" value="logs/${shortdate}"/>
<targets>
<target name="file1" xsi:type="File" fileName="${logDirectory}/file1.txt"/>
<target name="file2" xsi:type="File" fileName="${logDirectory}/file2.txt"/>
</targets>
</nlog>
With this syntax, a variable must be defined before use. Otherwise configuration initialization will fail. Note ${gdc} can be used used as an alternative to configuration variables, as they work independent of loading / unloading / reloading different NLog configurations.
NLog Config variables can operate in two modes:
- Constant mode -
${varName}
- Dynamic mode -
${var:varName}
(Introduced with NLog 4.1)
Constant mode (or static mode) works for all types of properties independent of their type, but they will not react to runtime changes.
Dynamic mode only works for properties of the type NLog Layout
, and provides the following abilities:
- Variables can be changed, deleted and created from the Configuration API
- A default value can be configured for a variable, e.g.
${var:password:default=unknown}
- By default all variables assigned at runtime are kept even after configuration reloads. Unless having configured
keepVariablesOnReload="false"
.NLog 4.4 introduced
keepVariablesOnReload
and before NLog 5.0 the default value wasfalse
NLog 5.0 extends NLog config variables to also handle complex Layout types like JsonLayout + CsvLayout. Ex:
<nlog>
<variable name="myJsonLayout">
<layout type="JsonLayout">
<attribute name="message" value="${messsage}">
</layout>
</variable>
<targets>
<target name="debug" type="Debug" layout="${myJsonLayout}" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="debug" />
</rules>
</nlog>
One of NLog’s strongest assets is the ability to use layouts. In the simplest form, layouts are texts with embedded tags delimited by ${
and }
. The tags are called Layout Renderers and can be used to insert pieces of contextual information into the text.
Layouts can be used in many places, for example they can control the format of information written on the screen or sent to a file, but also to control the file names themselves. This is very powerful, which we’ll see in a moment.
Let’s assume, that we want to annotate each message written to the console with:
- current date and time
- name of the class and method that emitted the log message
- log level
- message text
This is very easy:
<target name="c" xsi:type="Console" layout="${longdate} ${callsite} ${level} ${message}"/>
We can make each messages for each logger go to a separate file, as in the following example:
<target name="f" xsi:type="File" fileName="${logger}.txt"/>
As you can see, the ${logger} layout renderer was used in the fileName attribute, which causes each log message to be written to the file whose name includes the logger name. The above example will create the following files:
- Name.Space.Class1.txt
- Name.Space.Class2.txt
- Name.Space.Class3.txt
- Other.Name.Space.Class1.txt
- Other.Name.Space.Class2.txt
- Other.Name.Space.Class3.txt
NLog provides wrapper and compound targets which modify other targets’ behavior by adding features like:
- asynchronous processing (wrapped target runs in a separate thread)
- retry-on-error
- load balancing
- buffering
- filtering
- failover (failover)
To define a wrapper in the configuration file, simply nest a target node within another target node. You can even wrap a wrapper target - there are no limits on depth. For example, to add asynchronous logging with retry-on-error functionality add this to your configuration file:
<targets>
<target name="n" xsi:type="AsyncWrapper">
<target xsi:type="RetryingWrapper">
<target xsi:type="File" fileName="${file}.txt" />
</target>
</target>
</targets>
Because asynchronous processing is a common scenario, NLog supports a shorthand notation to enable it for all targets without the need to specify explicit wrappers. You can simply set async="true"
on targets element and all your targets within that element will be wrapped with the AsyncWrapper target.
<nlog>
<targets async="true">
<!-- all targets in this section will automatically be asynchronous -->
</targets>
</nlog>
Remember to Flush is very important, when using asynchronous background writing. It ensures all logging is written before application exit.
Sometimes we require ALL targets to be wrapped in the same way, for example to add buffering and/or retrying. NLog provides <default-wrapper />
syntax for that. You simply put this element in the <targets />
section and all your targets will be automatically wrapped with the specified wrapper. Note that <default-wrapper />
applies to the single <targets />
section only and you can have multiple sections so you can define groups of targets that are wrapped in a similar manner.
<nlog>
<targets>
<default-wrapper xsi:type="BufferingWrapper" bufferSize="100"/>
<target name="f1" xsi:type="File" fileName="f1.txt"/>
<target name="f2" xsi:type="File" fileName="f2.txt"/>
</targets>
<targets>
<default-wrapper xsi:type="AsyncWrapper">
<wrapper-target xsi:type="RetryingWrapper"/>
</default-wrapper>
<target name="n1" xsi:type="Network" address="tcp://localhost:4001"/>
<target name="n2" xsi:type="Network" address="tcp://localhost:4002"/>
<target name="n3" xsi:type="Network" address="tcp://localhost:4003"/>
</targets>
</nlog>
In the above example we’ve defined two buffered File targets and three asynchronous and retrying Network targets.
Similar to default wrappers, NLog provides <default-target-parameters />
which enables you to specify default values of target parameters. For example, if you don’t want files to be kept open, you can either add keepFileOpen="false"
to each target, as in the following example:
<nlog>
<targets>
<target name="f1" xsi:type="File" fileName="f1.txt" keepFileOpen="false"/>
<target name="f2" xsi:type="File" fileName="f2.txt" keepFileOpen="false"/>
<target name="f3" xsi:type="File" fileName="f3.txt" keepFileOpen="false"/>
</targets>
</nlog>
Alternatively you can specify a single <default-target-parameters />
that applies to all targets in the <targets />
section. Default parameters are defined on a per-type basis and are applied BEFORE the actual attributes defined in the XML file:
<nlog>
<targets>
<default-target-parameters xsi:type="File" keepFileOpen="false"/>
<target name="f1" xsi:type="File" fileName="f1.txt"/>
<target name="f2" xsi:type="File" fileName="f2.txt"/>
<target name="f3" xsi:type="File" fileName="f3.txt"/>
</targets>
</nlog>
Extensions can be configured to include additional NLog packages or custom ones:
Just reference the DLL in the config in the <extensions />
as shown below.
The name should not include the .dll
Configuration file example:
<nlog>
<extensions>
<add assembly="MyAssembly"/>
</extensions>
<targets>
<target name="a1" type="MyTarget" host="localhost"/>
</targets>
<rules>
<logger name="*" minlevel="Info" appendTo="a1"/>
</rules>
</nlog>
With NLog 5.0 it is also possible to specify fully qualified type-name, instead of needing to update <extensions>
-section. This makes the snippets more isolated:
<nlog>
<targets>
<target name="a1" type="MyTarget, MyAssembly" host="localhost"/>
</targets>
<rules>
<logger name="*" minlevel="Info" appendTo="a1"/>
</rules>
</nlog>
NLog 5.0 no longer automatically scans and loads extensions from assemblies with NLog-prefix. Because it introduced overhead during startup, and failed to work with <packagereference>
. See also Register-your-custom-component
The configuration file is read automatically at program startup. In a long running process (such as a Windows service or an ASP.NET application) it’s sometimes desirable to temporarily increase the log level without stopping the application. NLog can monitor logging configuration files and re-read them each time they are modified. To enable this mechanism, you simply add autoReload="true"
parameter to the configuration file.
<nlog autoReload="true">
...
</nlog>
Note that automatic reconfiguration supports include files, so each time one of the included files is changed, the entire configuration gets reloaded.
Just to make it explicit, automatic reloading will NOT stop/recycle the IIS Application Pool.
NLog provides an include file feature so that configuration can be stored in multiple files.
<include file="nlog-common.config" />
Like most attributes in NLog config, the file attribute may reference variables. The following example includes a file named the same as the machine that nlog is running on.
<include file="${machinename}.config" ignoreErrors="true" />
Setting the attribute ignoreErrors
to true
prevents a startup failure if the include file cannot be loaded -- file not found, invalid XML, .... Use the Troubleshooting logging section to log errors. This attribute is optional and defaults to false
.
Since NLog 4.4.2, wildcards (*
) are allowed. E.g. <include file="nlog-*.config"/>
A larger example can be found here: XML config <include />
example
In the configuration file some characters needs to be escaped.
Because it XML file, the <
and >
brackets should be escaped with <
and >
. This also holds for the attribute values, like a condition.
Inside a layout we need to escape the }
bracket and the colon :
should be escaped because:
-
:
is the value separator. -
}
is the end of the layout
Nested layout renderers doesn't need escaping. Also the backslash doesn't need an escape.
Examples:
-
${appdomain:format={1\}{0\}}
(escape of}
) -
${rot13:inner=${scopenested:topFrames=3:separator=x}}
(no escaping needed) -
${when:when=1 == 1:Inner=Test\: Hello}
(escape of:
)
Sometimes our application doesn’t write anything to the log files, even though we have supposedly configured logging properly. There can be many reasons for logs not being written. The most common problems are permissions issues, usually in an ASP.NET process, where the aspnet_wp.exe
or w3wp.exe
process may not have write access to the directory where we want to store logs.
NLog is designed to swallow run-time exceptions that may result from logging. The following settings can change this behavior and/or redirect these messages.
-
<nlog throwExceptions="true" />
- adding thethrowExceptions
attribute in the config file causes NLog to stop masking exceptions and pass them to the calling application instead. This attribute is useful at deployment time to quickly locate any problems. It is critical that one configurethrowExceptions
to"false"
as soon as the application is properly configured to run, so accidental logging problems will not cause application to hang or crash. -
<nlog throwConfigExceptions="true" />
- Similar tothrowExceptions
but isolated to configuration exceptions only. UnlikethrowExceptions
then it is not dangerous to have enabled, and is recommended for production environments where it is critical that initial setup of logging configuration succeeds. Introduced in NLog 4.3. Defaultnull
(Means not configured and instead use value ofthrowExceptions
) -
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" />
– determines the internal log level. The higher the level, the less verbose the internal log output. The output is usually very helpful when needing to diagnose logging issues. See Internal-logging for options to setup output to File or Console.
See also Logging-troubleshooting
- Troubleshooting Guide - See available NLog Targets and Layouts: https://nlog-project.org/config
- Getting started
- How to use structured logging
- Troubleshooting
- FAQ
- Articles about NLog
-
All targets, layouts and layout renderers
Popular: - Using NLog with NLog.config
- Using NLog with appsettings.json