Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serilog JSON config LoggingLevelSwitch access

Configuring Serilog using a JSON config, it is possible to configure log level switches as such:

"LevelSwitches": {
  "$appLogLevel": "Debug",
  "$netLogLevel": "Information",
  "$sysLogLevel": "Error"
},
"MinimumLevel": {
  "ControlledBy": "$appLogLevel",
  "Override": {
    "Microsoft": "$netLogLevel",
    "System": "$sysLogLevel"
  }
}

the purpose of the switches (when instantiated in code) is to be accessed at a later time in order to change the minimum log levels during run-time. However when configured via the JSON config, I can't find a way to access those switch instances. Does anyone know how to access them?

like image 461
Xorcist Avatar asked Jul 17 '18 20:07

Xorcist


1 Answers

My current project required highly configurable logging as well as the ability to adjust any of those configured log levels at runtime.

So I had actually already written a work-around (but in a more generalized way), by simply processing the "MinimalLevel" section of the config manually in my Program.cs, like this:

Requires a static dictionary for later reference:

public static Dictionary<String, LoggingLevelSwitch> LogLevel = null;

And a code block to bind the LoggingLevelSwitches:

//Configure logger (optional)
  if (appConfig.GetSection("Serilog").Exists()) {
  //Configure Serilog
    LoggerConfiguration logConfig = new LoggerConfiguration().ReadFrom.Configuration(appConfig);
  //If Serilog config parsed okay acquire LoggingLevelSwitches
    LogLevel = LoadLoggingLevelSwitches(appConfig);
  //Bind LoggingLevelSwitches        
    foreach (String name in LogLevel.Keys) {
      if (String.Equals(name, "Default", StringComparison.InvariantCultureIgnoreCase)) {
        logConfig.MinimumLevel.ControlledBy(LogLevel[name]);
      } else {
        logConfig.MinimumLevel.Override(name, LogLevel[name]);
      }
    }
  //Build logger from config
    Log.Logger = logConfig.CreateLogger();
  }

which utilizes a routine that instantiates all those switches (based on the config file):

public static Dictionary<String, LoggingLevelSwitch> LoadLoggingLevelSwitches(IConfiguration cfg) {
  Dictionary<String, LoggingLevelSwitch> levels = new Dictionary<String, LoggingLevelSwitch>(StringComparer.InvariantCultureIgnoreCase);
//Set default log level
  if (cfg.GetSection("Serilog:MinimumLevel:Default").Exists()) {
    levels.Add("Default", new LoggingLevelSwitch((LogEventLevel)Enum.Parse(typeof(LogEventLevel), cfg.GetValue<String>("Serilog:MinimumLevel:Default"))));
  }
//Set log level(s) overrides
  if (cfg.GetSection("Serilog:MinimumLevel:Override").Exists()) {
    foreach (IConfigurationSection levelOverride in cfg.GetSection("Serilog:MinimumLevel:Override").GetChildren()) {
      levels.Add(levelOverride.Key, new LoggingLevelSwitch((LogEventLevel)Enum.Parse(typeof(LogEventLevel), levelOverride.Value)));
    }
  }      
  return levels;
}

I have separate class that handles applying runtime logging level changes via these switches, but this was the easiest way to get anything and everything I needed, however...

after writing all that code and then finding out there was a way to just add the switches directly from the config with the"LevelSwitches" section, I realized I was probably doubling up on the work. Because obviously Serilog needs to be instantiating and binding it's own switches defined in the config... it just doesn't appear to give a nice and easy way to access them so I can use them later. Which is counter intuitive because the whole point of a LoggingLevelSwitch is to reference it later at runtime.

Seems if the switches are allowed to be created through the config, we should be given an easy way to access them. Perhaps I should add this as a feature request over on the Serilog GitHub.

like image 92
Xorcist Avatar answered Oct 11 '22 13:10

Xorcist