NLog / NLog.Extensions.Logging

NLog as Logging Provider for Microsoft Extension Logging
https://nlog-project.org
BSD 2-Clause "Simplified" License
392 stars 151 forks source link

NLog configuration isn't reload when appsetting.json is reloaded #592

Closed Irinniada closed 2 years ago

Irinniada commented 2 years ago

I'm trying to control LogLevel in log from appsetting.json. I've added my Nlog config here and custom field LogLevel. In rules I've added "${configsetting:item=LogLevel}" and it works. But I want to be able to change LogLevel when app is running. So I add autoReload to json and reloadOnChange = true to ConfigurationBuilder. But it's not working for NLog.

Some of appsetting.json:

  "LogLevel": "Info",
  "NLog": {
    "throwConfigExceptions": true,
    "autoReload": true,
    "internalLogToConsole": true,
    "extensions": [
      { "assembly": "SumoLogic.Logging.NLog" }
    ],
    "targets": {
      "async": true,
      "fileTarget": {
        "type": "File",
        "fileName": "${gdc:item=mainLogFileName}",
        "layout":"${longdate}|${level:uppercase=true}|${logger}|${message:exceptionSeparator=\r\n:withException=true}"
      },
      "errorFileTarget": {
        "type": "File",
        "fileName": "${gdc:item=errorLogFileName}",
        "layout":"${longdate}|${level:uppercase=true}|${logger}|${message:exceptionSeparator=\r\n:withException=true}"
      },
      "consoleTarget": {
        "type": "Console",
        "layout":"${message:exceptionSeparator=\r\n:withException=true}"
      }
    },
    "rules": [
      {
        "logger": "*",
        "minLevel": "${configsetting:item=LogLevel}",
        "writeTo": "consoleTarget"
      },
      {
        "logger": "*",
        "minLevel": "${configsetting:item=LogLevel}",
        "writeTo": "fileTarget"
      },
      {
        "logger": "*",
        "minLevel": "Error",
        "writeTo": "errorFileTarget"
      },   
    ]
  }

And my code is

var config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", false, true)
    .AddCommandLine(args)
    .AddEnvironmentVariables()
    .AddUserSecrets(Assembly.GetExecutingAssembly())
    .Build();

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

LogManager.ReconfigExistingLoggers();

The only way it works for me:

_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);

ConfigSettingLayoutRenderer.DefaultConfiguration = _config;

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

LogManager.ReconfigExistingLoggers();

but it means to write it under every log.

Is there any nice way to reload NLog with appsetting?

snakefoot commented 2 years ago

Used this example-application:

https://github.com/NLog/NLog.Extensions.Logging/tree/master/examples/NetCore2/ConsoleExampleJsonConfig

And updated with this appsettings.json

{
  "LogLevel": "Debug",
  "NLog": {
    "throwConfigExceptions": true,
    "autoReload": true,
    "internalLogToConsole": true,
    "internalLogLevel": "Debug",
    "targets": {
      "async": true,
      "fileTarget": {
        "type": "File",
        "fileName": "nlog-mainfile.txt",
        "layout": "${longdate}|${level:uppercase=true}|${logger}|${message:exceptionSeparator=\r\n:withException=true}"
      },
      "errorFileTarget": {
        "type": "File",
        "fileName": "nlog-errorfile.txt",
        "layout": "${longdate}|${level:uppercase=true}|${logger}|${message:exceptionSeparator=\r\n:withException=true}"
      },
      "consoleTarget": {
        "type": "Console",
        "layout": "${message:exceptionSeparator=\r\n:withException=true}"
      }
    },
    "rules": [
      {
        "logger": "*",
        "minLevel": "${configsetting:item=LogLevel}",
        "writeTo": "consoleTarget"
      },
      {
        "logger": "*",
        "minLevel": "${configsetting:item=LogLevel}",
        "writeTo": "fileTarget"
      },
      {
        "logger": "*",
        "minLevel": "Error",
        "writeTo": "errorFileTarget"
      }
    ]
  }
}

This produce the following NLog-config-ouput:

2022-05-19 08:02:35.7225 Debug logNamePattern: (:All) levels: [ Debug Info Warn Error Fatal ] writeTo: [ consoleTarget ]
2022-05-19 08:02:35.7225 Debug logNamePattern: (:All) levels: [ Debug Info Warn Error Fatal ] writeTo: [ fileTarget ]
2022-05-19 08:02:35.7225 Debug logNamePattern: (:All) levels: [ Error Fatal ] writeTo: [ errorFileTarget ]

Then changed "LogLevel": "Debug", to "LogLevel": "Info", and saved the appsettings.json file while the console-application was running:

2022-05-19 08:03:36.1285 Debug logNamePattern: (:All) levels: [ Info Warn Error Fatal ] writeTo: [ consoleTarget ]
2022-05-19 08:03:36.1285 Debug logNamePattern: (:All) levels: [ Info Warn Error Fatal ] writeTo: [ fileTarget ]
2022-05-19 08:03:36.1285 Debug logNamePattern: (:All) levels: [ Error Fatal ] writeTo: [ errorFileTarget ]

Please attach an example project that reproduces the issue with reload not working when updating appsettings.json-file.

Irinniada commented 2 years ago

Please attach an example project that reproduces the issue with reload not working when updating appsettings.json-file.

Here https://github.com/Irinniada/nlog_example.git

Irinniada commented 2 years ago

Ok, I analize project again and understood that I changed another .json 🤦 When I change config in Debug folder everything works. Sorry to bother you ^_^

snakefoot commented 2 years ago

Happy that you found the cause of the issue.

Btw. you don't have to perform an explict config-reload, unless you know the appsettings.json changed. So this:

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

Can just be this:

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

You can also remove the call LogManager.ReconfigExistingLoggers(); since it is only needed after having modified the LoggingRules of the existing configuration.