Search code examples
c#configuration.net-5serilogserilog-sinks-file

Serilog: restrictedToMinimumLevel using LevelSwitches


I am using Serilog in a .Net 5 application, and I am configuring it loading the configuration from appsettings.{env}.json.

In this file I want to specify a different minimum logging level for each sink, and I would like to control it with a LevelSwitch so that I don't need to restart my application only for changing this. To achieve this, I know that restrictedToMinimumLevel can be specified for each sink, but I cannot find an example where it is controlled by a switch. It seems it can only be a string with the logging level, since when I tried to bind it to a switch I got this exception:

System.InvalidOperationException: 'Cannot create instance of type 'Serilog.Events.LogEventLevel' because it is missing a public parameterless constructor.'

Am I missing something? How can I set the minimum logging level for each sink to be easily changed at runtime without restarting my application?

These are my settings:

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "LevelSwitches": {
      "$baseSwitch": "Verbose",
      "$consoleSwitch": "Warning"
    },
    "MinimumLevel": {
      "ControlledBy": "$baseSwitch"
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          //"restrictedToMinimumLevel": "Warning",   ---> this works
          //"restrictedToMinimumLevel": {            ---> this is what I need, but doesn't work
          //  "ControlledBy": "$consoleSwitch"
          //},
          "outputTemplate": "{Timestamp} [{Level:u3}] [{LogSource}]: {Message} {Properties}{NewLine}{Exception}"
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "Logs/log.txt"
        }
      }
    ],
    "Enrich": [
      "FromLogContext"
    ]
  }
}

I am open also to other solutions. Thank you.


Solution

  • The name of the level switch reference should not have the $ prefix. The $ prefix is only for referencing the level switch declared

    {
        "Serilog": {
            "LevelSwitches": { "consoleSwitch": "Verbose" }, <<<< No $ prefix
            "WriteTo": [
                {
                    "Name": "Console",
                    "Args": {
                        "levelSwitch": "$consoleSwitch" <<<<<< $ prefix
                    }
                }
            ]
        }
    }
    

    Also, the name of the argument for the level switch has to match what's declared in the extension method for the sink. In the case of the Console sink, it's called levelSwitch.