Skip to content

NLog configuration with appsettings.json

Rolf Kristensen edited this page Mar 14, 2024 · 41 revisions

NLog's configuration have always been highly configurable through XML. NLog also have the ability to load NLog-configuration from Microsoft Extension Configuration (Ex. appsettings.json).

Microsoft Extension Configuration can be initialized from many different sources (json, environment-variables, yaml, ex.), and then NLog can parse it configuration from Microsoft Extension ConfigurationSection. This requires one of these nuget-packages:

NLog.Extensions.Logging makes it possible to load NLog-configuration from appsettings.json with help from NLogLoggingConfiguration or LoadConfigurationFromSection.

NLog.Extensions.Logging also includes ${configsetting}, to lookup settings from appsettings.json. Also supported when loading NLog configuration from NLog.config-xml-file.

Loading from appsettings.json

Introduced with NLog.Extensions.Logging ver. 1.5.0

var config = new ConfigurationBuilder()
   .SetBasePath(System.IO.Directory.GetCurrentDirectory())
   .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
   .Build();

NLog.LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));

Fluent API added with NLog.Web.AspNetCore ver. 4.9.3

Supports appsettings.json override by loading environment specific settings based on ASPNETCORE_ENVIRONMENT:

var logger = LogManager.Setup()
                       .LoadConfigurationFromAppSettings()
                       .GetCurrentClassLogger();

Manual loading of appsettings.json with fluent API:

var config = new ConfigurationBuilder()
                .SetBasePath(basePath ?? Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{environment}.json", optional: true)
                .AddEnvironmentVariables().Build();
var logger = LogManager.Setup()
                       .LoadConfigurationFromSection(config)
                       .GetCurrentClassLogger();

Simple Json NLog Config Example

{
  "NLog": {
    "throwConfigExceptions": true,
    "targets": {
      "async": true,
      "logfile": {
        "type": "File",
        "fileName": "c:/temp/nlog-${shortdate}.log"
      },
      "logconsole": {
        "type": "ColoredConsole"
      }
    },
    "rules": [
      {
        "logger": "*",
        "minLevel": "Info",
        "writeTo": "logconsole"
      },
      {
        "logger": "*",
        "minLevel": "Debug",
        "writeTo": "logfile"
      }
    ]
  }
}

JSON Schema

JSON Schema is included in the official schema for appsettings.json files available at https://json.schemastore.org/appsettings.json.

Please note it has no auto-completion for the target properties

Extended Json NLog Config Example

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug"
    },
    "NLog": {
      "IncludeScopes": true,
      "RemoveLoggerFactoryFilter": true
    }
  },
  "NLog": {
    "autoReload": true,
    "throwConfigExceptions": true,
    "internalLogLevel": "Info",
    "internalLogFile": "${basedir}/internal-nlog.txt",
    "extensions": [
      { "assembly": "NLog.Extensions.Logging" },
      { "assembly": "NLog.Web.AspNetCore" },
      { "assembly": "NLog.Database" }
    ],
    "variables": {
      "var_logdir": "c:/temp"
    },
    "time": {
      "type": "AccurateUTC"
    },
    "default-wrapper": {
      "type": "AsyncWrapper",
      "overflowAction": "Block"
    },
    "targets": {
      "all-file": {
        "type": "File",
        "fileName": "${var_logdir}/nlog-all-${shortdate}.log",
        "layout": {
          "type": "JsonLayout",
          "Attributes": [
            {
              "name": "timestamp",
              "layout": "${date:format=o}"
            },
            {
              "name": "level",
              "layout": "${level}"
            },
            {
              "name": "logger",
              "layout": "${logger}"
            },
            {
              "name": "message",
              "layout": "${message:raw=true}"
            },
            {
              "name": "properties",
              "encode": false,
              "layout": {
                "type": "JsonLayout",
                "includeallproperties": "true"
              }
            }
          ]
        }
      },
      "own-console": {
        "type": "LimitingWrapper",
        "interval": "00:00:01",
        "messageLimit": 100,
        "target": {
          "type": "ColoredConsole",
          "layout": "${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}",
          "rowHighlightingRules": [
          {
            "condition": "level == LogLevel.Error",
            "foregroundColor": "Red"
          },
          {
            "condition": "level == LogLevel.Fatal",
            "foregroundColor": "Red",
            "backgroundColor": "White"
          }],
          "wordHighlightingRules": [
          {
            "regex": "on|off",
            "foregroundColor": "DarkGreen"
          },
          {
            "condition": "level == LogLevel.Debug",
            "text": "[TEST]",
            "foregroundColor": "Blue"
          }]
        }
      },
      "database": {
        "type": "Database",
        "dbProvider": "System.Data.SqlClient",
        "connectionString": "Data Source=database server;Initial Catalog=database;Trusted_Connection=False;User Id=AppUser;Password=AppUserPassword;",
        "keepConnection": "true",
        "commandText": "insert into dbo.log (Timestamp,Level,Message,Logger,Exception) values (@Timestamp, @Level, @Message, @Logger, @Exception);",
        "parameters": [
          {
            "name": "@Timestamp",
            "layout": "${date:format=o}",
            "dbType": "DbType.DateTime"
          },
          {
            "name": "@Level",
            "layout": "${level}"
          },
          {
            "name": "@Message",
            "layout": "${message}"
          },
          {
            "name": "@Logger",
            "layout": "${logger}"
          },
          {
            "name": "@Exception",
            "layout": "${exception:tostring}"
          }
        ]
      },
      "webFallback": {
        "type": "FallbackGroup",
        "returnToFirstOnSuccess": true,
        "targets": {
          "1stWeb": {
            "type": "WebService",
            "url": "http://localhost:1234/API/Post",
            "protocol": "JsonPost",
            "parameters": [
            {
              "name": "",
              "layout": {
                "type": "JsonLayout",
                "includeallproperties": "true"
              }
            }]
          },
          "2ndFile": {
            "type": "File",
            "fileName": "${basedir}/logs/webfallback-${shortdate}.log"
          }
        }
      }
    },
    "rules": [
      {
        "logger": "*",
        "minLevel": "Trace",
        "writeTo": "all-file"
      },
      {
        "logger": "Microsoft.*",
        "maxLevel": "Info",
        "final": true
      },
      {
        "logger": "*",
        "minLevel": "Debug",
        "writeTo": "own-console",
        "filterDefaultAction": "Log",
        "filters": {
          "whenRepeated": {
            "layout": "${message}",
            "action": "Ignore"
          }
        }
      },
      {
        "logger": "*",
        "minLevel": "Debug",
        "writeTo": "database"
      }
    ]
  }
}

Environment specific configuration

ASP.NET Core uses the environment variable ASPNETCORE_ENVIRONMENT to configures app behavior based on the runtime environment. It also allows one to override appsettings for an environment:

  • appsettings.json - Default settings
  • appsettings.Production.json - Production specific settings.
  • appsettings.Development.json - Development specific settings.

This can also be used for the NLog-config, so one can have special NLog targets for a certain environment

It is also possible to adjust environment variables using launchsettings.json. Ex: "environmentVariables": { "NLOG_RULES_0_MINLEVEL": "Info" }

See also: Environment specific NLog Logging Configuration

Logging Rule Override

Example of how one can override logging-rule "1" and introduce an additional logging-rule "99":

appsettings.json

        "rules": {
            "0": {
                "logger": "Microsoft.*",
                "maxLevel": "Error",
                "final": true
            },
            "1": {
                "logger": "*",
                "minLevel": "Error",
                "writeTo": "errorFile,errorEmail"
            },
            "2": {
                "logger": "*",
                "minLevel": "Debug",
                "writeTo": "debugFile"
            }
        }

appsettings.development.json

        "rules": {
            "1": {
                "logger": "*",
                "minLevel": "Error",
                "writeTo": "errorFile"
            },
            "99": {
                "logger": "*",
                "minLevel": "Debug",
                "writeTo": "debugConsole"
            }
        }

Note one can also use more readable names instead of "0". Ex. call them "01_ErrorLog", "02_DebugFile". It is important to keep the numeric-prefix because the order of NLog Logging Rules are important (Ex. final-rules). For catch-all wildcard rules (Ex. logger: "*") then consider using a high value like "99_DebugConsole" to ensure it is sorted after more specific rules. Be aware that the readable name is case-sensitive when doing override.

Case Sensitivity Issues in override with NLog v4

NLog v5 has changed and is not case-sensitive when resolving config variables

While the ASP.NET Core configuration system is not case sensitive, you must be aware that in some cases NLog is case sensitive. For example, if you wanted to use an environment variable to override the var_logdir NLog variable in the configuration example above, you might be tempted to name the environment variable NLOG__VARIABLES__VAR_LOGDIR. This variable will result in an NLog configuration error, because NLog is looking for a variable named var_logdir. In order to work, your environment variable would need to be named NLOG__VARIABLES__var_logdir.

Dynamic override Logging Rules LogLevel

NLog 4.6.7 enables use of dynamic LogLevel values in the Logging Rules. So instead of overriding values in the invidual Logging Rules, then you can just override the LogLevel-values using ${configsetting}.

Alternative then one can also override the LogLevel when debugging the application locally:

#if DEBUG
        // First thing
        NLog.GlobalDiagnosticsContext.Set("DebugLogLevel", "Debug");
        NLog.LogManager.ReconfigureExistingLoggers();
#endif
      {
        "logger": "*",
        "minLevel": "${gdc:DebugLogLevel:whenEmpty=Info}",
        "writeTo": "file"
      }

See also: Dynamic Routing Rules