Skip to content

Logging Rules FinalMinLevel

Rolf Kristensen edited this page Sep 22, 2023 · 17 revisions

finalMinLevel is an option for Logging Rules, that have been introduced with NLog ver 5.0. It is conceptually similar to the combination of the maxLevel and final option.

The main reason for the finalMinLevel option is to easily silence all noisy loggers from one subcomponent (like Microsoft.*), while overriding this behavior for a single logger of that subcomponent (like Microsoft.Hosting.Lifetime). This is similar to how the filtering works in Microsoft Extension Logging.

finalMinLevel is intended for configurations that have catch-all log-targets at the bottom of the logging rules.

Here's a small example to start with: if logs coming from Microsoft.* should only be logged if the log level is Warn or higher, and all other logs should be logged if the level is Info or higher, then the following configuration could be used:

<rules>
    <logger name="Microsoft.*" finalMinLevel="Warn" />
    <logger name="*" minLevel="Info" writeTo="console" />
</rules>

This can also be implemented using maxLevel and final in NLog v4:

<rules>
    <logger name="Microsoft.*" maxLevel="Info" final="true" />
    <logger name="*" minLevel="Info" writeTo="console" />
</rules>

In both examples, the first rule is a "black hole" that swallows the applicable logs. Also keep in mind that the order of the logger-rules are always very important.

The advantage of finalMinLevel is that it is easier to read, comprehend and reduces the configuration required, especially with more complex configurations. Additionally, it allows overriding previous finalMinLevel filters, such a pattern is not possible otherwise.

Levels

The following table describes which log levels are enabled depending on the finalMinLevel value:

FinalMinLevel Ordinal Enabled log levels
Trace 0 Trace, Debug, Info, Warn, Error and Fatal
Debug 1 Debug, Info, Warn, Error and Fatal
Info 2 Info, Warn, Error and Fatal
Warn 3 Warn, Error and Fatal
Error 4 Error and Fatal
Fatal 5 Fatal
Off 6

NLog includes LogLevel Off, that can be used to suppress all output from a noisy logger:

<rules>
    <logger name="NoisyLogger.*" finalMinLevel="Off" />
    <logger name="*" minLevel="Info" writeTo="console" />
</rules>

This can also be implemented using maxLevel and final in NLog v4:

<rules>
    <logger name="NoisyLogger.*" maxLevel="Off" final="true" />
    <logger name="*" minLevel="Info" writeTo="console" />
</rules>

Overrides

As mentioned before, finalMinLevel can override previous rules. For example, if we want Warn logs of higher from Microsoft.*, but Info logs or higher from Microsoft.Hosting.Lifetime, then this is a possible configuration:

<rules>
    <logger name="Microsoft.*" finalMinLevel="Warn" />
    <logger name="Microsoft.Hosting.Lifetime*" finalMinLevel="Info" />
    <logger name="*" minLevel="Info" writeTo="console" />
</rules>

Keep in mind that the order is still important. If the "Microsoft.* and Microsoft.Hosting.Lifetime* were reversed, then Microsoft.* would override Microsoft.Hosting.Lifetime* and both would be set to Warn.

Microsoft Extensions Logging Filters

The Microsoft Logging filters specified in appsettings.json are ignored by default when using NLog 5.0. This is to avoid that new users think NLog Logging Rules are not working, because Microsoft LoggerFactory filters are interfering.

The default logging logging configuration in appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

Can be configured through NLog.config like this:

<rules>
    <logger name="Microsoft.*" finalMinLevel="Warn" />
    <logger name="Microsoft.Hosting.Lifetime*" finalMinLevel="Info" />
    <logger name="*" minLevel="Info" writeTo="console" />
</rules>

Notice that the logger named Microsoft.Hosting.Lifetime* overrides the Microsoft.* logger.

See also ASP.NET Core with NLog Tutorial

Complete example

This example also filters logs from System.* and separates informative logs and error logs between the stdout and stderr output streams.

It is a good configuration for new ASP.NET projects.

<?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="stdout" xsi:type="Console" />
    <target name="stderr" xsi:type="Console" stdErr="true" />
  </targets>

  <rules>
    <logger name="System.*" finalMinLevel="Warn" />
    <logger name="Microsoft.*" finalMinLevel="Warn" />
    <logger name="Microsoft.Hosting.Lifetime*" finalMinLevel="Info" />
    <logger name="*" minLevel="Info" maxLevel="Warn" writeTo="stdout" />
    <logger name="*" minLevel="Error" writeTo="stderr" />
  </rules>
</nlog>

FinalMinLevel in combination with minLevel

It can be useful to combine finalMinLevel with MinLevel. Suppose there's a sub-module RequestLogger that should have its own dedicated log-target, but at the same time all Error or higher logs should flow to the catch-all log-target. This can be achieved through:

<logger name="RequestLogger" minLevel="Debug" writeTo="requestTarget" finalMinLevel="Error" />
<logger name="*" minLevel="Info" writeTo="catchAllTarget" />

It can also be configured like this if using NLog v4:

<logger name="RequestLogger" minLevel="Debug" writeTo="requestTarget" />
<logger name="RequestLogger" maxLevel="Warn" final="true" />
<logger name="*" minLevel="Info" writeTo="catchAllTarget" />

All logs coming from RequestLogger with a level between Debug and higher will be logged to requestTarget. All other logs with a level Info or higher will be logged to catchAllTarget, including Error and Fatal logs from RequestLogger.

Clone this wiki locally