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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With