Skip to content

Allow an array-style config format for Serilog:MinimumLevel:Override #214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jez9999 opened this issue Mar 29, 2020 · 6 comments
Closed

Comments

@jez9999
Copy link

jez9999 commented Mar 29, 2020

Starting afresh because the other issue was closed.

At the moment, the way you specify Serilog's minimum level overrides in configuration is in the following format:

"MinimumLevel": {
	"Default": "Information",
	"Override": {
		"Microsoft.AspNetCore.Mvc.Infrastructure": "Debug",
		"Microsoft": "Warning",
		"Microsoft.Hosting.Lifetime": "Information",
		"Microsoft.AspNetCore.Authentication": "Verbose",
	}
}

The source context (or 'namespace') is specified in the setting name, rather than a value. The trouble with this is that not all configuration providers lend themselves to having long, complex configuration key names. For example, I've tried to configure the equivalent to this on an Azure web app (using the double-underscore namespace separator as a replacement for the colon), and the best I could get to was:

"Serilog:MinimumLevel:Override:Microsoft_AspNetCore_Mvc_Infras": "Debug"

On my local machine, which is using appsettings.json, this is how it (correctly) looks:

"Serilog:MinimumLevel:Override:Microsoft.AspNetCore.Mvc.Infrastructure": "Debug"

The dots have been replaced with underscores, and more importantly there is a very restrictive length limit on config key names from these environment variables. So I think the solution is not to try and put complex/long information like a namespace in the key name, but as a key value. Thus, I propose that Serilog support the following syntax for minimum level overrides:

"MinimumLevel": {
	"Default": "Information",
	"Override": [
		{
			"SourceContext": "Microsoft.AspNetCore.Mvc.Infrastructure",
			"Level": "Debug"
		},
		{
			"SourceContext": "Microsoft",
			"Level": "Warning"
		},
		{
			"SourceContext": "Microsoft.Hosting.Lifetime",
			"Level": "Information"
		},
		{
			"SourceContext": "Microsoft.AspNetCore.Authentication",
			"Level": "Verbose"
		}
	]
}

When Override is an array, it takes a set of objects with SourceContext/Level that specify the override level for the given source context. This results in the following kind of config structure, which works even with config providers that have restrictive key names:

"Serilog:MinimumLevel:Override:0:SourceContext": "Microsoft.AspNetCore.Mvc.Infrastructure"
"Serilog:MinimumLevel:Override:0:Level": "Debug"
@skomis-mm
Copy link
Contributor

skomis-mm commented Mar 29, 2020

@jez9999

So where did you hit "61 characters limit" on key names? Can you make a repro steps? Or is having "dots" in namespace name is the only reason for a new syntax?

@jez9999
Copy link
Author

jez9999 commented Mar 29, 2020

Looks like it's actually 64 characters. To repro:

  1. Create an Azure web app capable of outputting its key names and settings.
  2. Create setting with key name x234567890x234567890x234567890x234567890x234567890x234567890x234567890xxxxx
  3. Run web app
  4. See that the app gets the setting with key name x234567890x234567890x234567890x234567890x234567890x234567890x234

@sungam3r
Copy link
Contributor

Fixed by #212

@skomis-mm
Copy link
Contributor

Thanks. So it is Linux Web App running-in-container limitation. Need think about it. Here the link for a reference:
https://techcommunity.microsoft.com/t5/azure-app-service/things-you-should-know-web-apps-and-linux/ba-p/392472#EnvLimit

@skomis-mm
Copy link
Contributor

Currently, if App Setting names are longer than 64 characters, only the first 64 characters of the environment variable will be imported into the container.

The key word Currently. It is a matter of time when this limitation will be cleared. So some workarounds should be enough. Take this one-liner:

public static class Extensions
{
    public static LoggerConfiguration ApplyCustomOverrides(this LoggerConfiguration cfg, IConfigurationSection section)
        => section.GetChildren().Aggregate(cfg, (c, s) => c.MinimumLevel.Override(s.GetValue<string>("SourceContext"), s.GetValue<LogEventLevel>("Level")));
}

Config:

"MinimumLevel": {
	"Default": "Information",
	"OverrideList": [
		{
			"SourceContext": "Microsoft.AspNetCore.Mvc.Infrastructure",
			"Level": "Debug"
		},
		{
			"SourceContext": "Microsoft",
			"Level": "Warning"
		},
		{
			"SourceContext": "Microsoft.Hosting.Lifetime",
			"Level": "Information"
		},
		{
			"SourceContext": "Microsoft.AspNetCore.Authentication",
			"Level": "Verbose"
		}
	]
}

Usage:

var logger = new LoggerConfiguration()
    .ApplyCustomOverrides(configuration.GetSection("Serilog:MinimumLevel:OverrideList"))
    .ReadFrom.Configuration(configuration)
    .CreateLogger();

@jez9999
Copy link
Author

jez9999 commented Mar 29, 2020

How do you know it's a matter of time?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants