skip to Main Content

I have an app running in Azure and logging to a database. I’ve got the NLog settings coming from the appsettings.json file and everything seems to be working well. However, now I’d like to override the logging rules by adding an application setting to the app configuration in Azure and it’s failing.

This is the NLog entry in the app settings.json:

"NLog": {
    "autoReload": true,
    "throwConfigExceptions": true,
    //"internalLogLevel": "Info",
    //"internalLogFile": "x:/internal-nlog.txt",
    "extensions": [
      { "assembly": "NLog.Extensions.Logging" },
      { "assembly": "NLog.Web.AspNetCore" },
      { "assembly": "NLog.Database" }
    ],
    "targets": {
      "async": true,
      "database": {
        "type": "Database",
        "dbProvider": "System.Data.SqlClient",
        "connectionString": "<Connection String>",
        "keepConnection": "true",
        "commandText": "insert into LoggingMessages(Created, MessageType, Message, CallSite, ExceptionDetail) values(getutcdate(), @level, @message, @callsite, @exception);",
        "parameters": [
          {
            "name": "@level",
            "layout": "${level}"
          },
          {
            "name": "@message",
            "layout": "${message}"
          },
          {
            "name": "@logger",
            "layout": "${logger}"
          },
          {
            "name": "@callsite",
            "layout": "${callsite}"
          },
          {
            "name": "@exception",
            "layout": "${exception:tostring}"
          }
        ]
      },
      "logconsole": {
        "type": "Console"
      }
    },
    "rules": [
      {
        "logger": "microsoft.*",
        "maxLevel": "Debug",
        "final": true
      },
      {
        "logger": "*",
        "minLevel": "Trace",
        "writeTo": "database"
      }
    ]
  }

This line is in the Configuration method of my startup.cs:

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

And my CreateHostBuilder method in program.cs looks like this:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
           webBuilder.UseStartup<Startup>();
        })
        .UseNLog();

Within the App Configuration screen on the Azure Portal I’ve then created the following Application Setting entry:

Name Value
NLog:rules [{"logger": "microsoft.","maxLevel": "Debug","final": true},{"logger": "","minLevel": "Warning","writeTo": "database"}]

I’m thinking that either the call to LoadConfigurationFromAppSettings() either happens too early or it ignores the updated values, but of course, I could just be completely wrong in what I’m trying to do.

Any help would be great

4

Answers


  1. Chosen as BEST ANSWER

    So I couldn't get this to work the way I thought it should - just replacing the current rules - but I got it to work in the way that I need it. All I really wanted to do was change the minimum level for the database rule so that I could adjust this without having to update the code.

    What I ended up doing was adding an Application Setting in the Azure App Configuration: |Name|Value| |----|-----| |LoggingLevel|Debug|

    then adding some code similar to the following to the Configuration method of the startup.cs after the existing LogManager setup line.

    var loggingLevel = Configuration.GetValue<string>("LoggingLevel");
    var haveNewLoggingLevel = !string.IsNullOrWhiteSpace(loggingLevel);
    
    // only interested in the 'database' target
    var databaseTarget = LogManager.Configuration.FindTargetByName("database") as DatabaseTarget;
    
    if ((databaseTarget != null) && haveNewLoggingLevel)
    {
        var rules = LogManager.Configuration.LoggingRules;
        foreach (var rule in rules)
        {
            if (rule.Targets.Contains(databaseTarget))
            {
                rule.SetLoggingLevels(NLog.LogLevel.FromString(loggingLevel), NLog.LogLevel.Fatal);
            }
        }
    
        LogManager.ReconfigExistingLoggers();
    }
    

    With this I was able to achieve what I needed, butt I'm not sure it answers the question I originally asked. I also added similar code to update the connection string to the database from App Settings.


  2. The key-value ("NLog:rules") you created in Azure App Configuration is a JSON object. Make sure you set JSON content-type for it. Otherwise, it will be loaded as a string. For more information, see Use content type to store JSON key-values in App Configuration.

    I don’t see your code that loads data from Azure App Configuration.

    Login or Signup to reply.
  3. Maybe add an Application Setting to the Azure App Configuration:

    Name Value
    LoggingLevel Debug

    And use ${configsetting:LoggingLevel} in the NLog Logging Rule:

    "NLog": {
        "autoReload": true,
        "throwConfigExceptions": true,
        "extensions": [
          { "assembly": "NLog.Extensions.Logging" },
          { "assembly": "NLog.Web.AspNetCore" },
          { "assembly": "NLog.Database" }
        ],
        "targets": {
          "async": true,
          "database": {
            "type": "Database",
            "dbProvider": "System.Data.SqlClient",
            "connectionString": "<Connection String>",
            "keepConnection": "true",
            "commandText": "insert into LoggingMessages(Created, MessageType, Message, CallSite, ExceptionDetail) values(getutcdate(), @level, @message, @callsite, @exception);",
            "parameters": [
              {
                "name": "@level",
                "layout": "${level}"
              },
              {
                "name": "@message",
                "layout": "${message}"
              },
              {
                "name": "@logger",
                "layout": "${logger}"
              },
              {
                "name": "@callsite",
                "layout": "${callsite}"
              },
              {
                "name": "@exception",
                "layout": "${exception:tostring}"
              }
            ]
          },
          "logconsole": {
            "type": "Console"
          }
        },
        "rules": [
          {
            "logger": "microsoft.*",
            "maxLevel": "Debug",
            "final": true
          },
          {
            "logger": "*",
            "minLevel": "${configsetting:LoggingLevel:whenEmpty=Trace}",
            "writeTo": "database"
          }
        ]
      }
    

    See also: https://github.com/NLog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules

    See also: https://github.com/NLog/NLog/wiki/ConfigSetting-Layout-Renderer

    Login or Signup to reply.
  4. To override a nested value inside the appsettings.json using Azure App Configuration then one must use __.

    For example ApplicationInsights__InstrumentationKey will override this value in appsettings.json

    "ApplicationInsights": {
        "InstrumentationKey": "Will be overrridden"
    }
    

    See also: https://learn.microsoft.com/en-us/azure/app-service/configure-common?tabs=portal

    Notice to override nested value inside json-array requires extra magic (Ex. a specific NLog-Rule). You need to decorate with json-array-index-name. See also: https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-configuration-with-appsettings.json#logging-rule-override

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search