What does MinimumLevel and Override mean in appsettings.json logging context? - c#

I am looking at the appsettings.json from Serilog sample project, which has the following snippet:
"MinimumLevel": {
"Default": "Debug",
"Override": {
"System": "Information",
"Microsoft": "Information"
}
}
In this context, what is the purpose of Override? The System and Microsoft entries don't have a parent setting in the MinimumLevel node, so what is it overriding?
Unless I am completely misunderstanding the purpose of Override.

By default, you're saying any log entry that is severity "Debug" or higher should be sent to your sink(s) (console, file, etc).
This is similar behavior to Microsoft's document on logging:
For example, logging configuration is commonly provided by the Logging section of app settings files. The following example shows the contents of a typical appsettings.Development.json file:
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
},
"Console": {
"IncludeScopes": true
}
}
}
[...]
The LogLevel property under Logging specifies the minimum level to log for selected categories. In the example, System and Microsoft categories log at Information level, and all others log at Debug level.
The override section is for changing that minimum log level for types of a given namespace. In your example that means that a log from a System.* or Microsoft.* namespace must be Information or higher to be shown.
Normally you'd want to see Debug log entries for your code, but a higher level (like Information or Warning) for "not your code", like Microsoft and System.
Instead of putting this configuration in a configuation file you could also use code:
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog((ctx, cfg) =>
{
cfg.ReadFrom.Configuration(ctx.Configuration)
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information);
})
.Build();
Code from kimsereyblog.blogspot.com
Their explanation for the process is:
From the example we saw that we can configure a default minimum level of logging .MinimumLevel.Debug(). We can also override that default for certain namespaces, for example here we set the minimum level of logging for Microsoft namespace to Information. This will prevent ASP.NET Core to log all debug logs while keeping our own debug logs.
Another explanation, from nblumhardt.com:
The first argument of Override is a source context prefix, which is normally matched against the namespace-qualified type name of the class associated with the logger.
...
The effect of the configuration above, then, is to generate events only at or above the Warning level when the logger is owned by a type in a Microsoft.* namespace.

Related

Could someone help explain the priority of log level configuration of ASP.NET Core 6

I am now handling the logs in my ASP.NET Core project (based on .NET 6), and I need to reduce some logs from Microsoft.AspNetCore library.
I configured log setting in appsettings.json as below:
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.Hosting.Diagnostics": "Information", // Required
"Microsoft.AspNetCore": "Warning", // Avoid any logs from other classes under this namesapce
"Microsoft": "Information"
}
}
Could someone help me to check whether this setting can achieve my requirement?
Does the log level of Microsoft.AspNetCore will override the setting of Microsoft.AspNetCore.Hosting.Diagnostics?
Thank you.
Does the log level of Microsoft.AspNetCore will override the setting of Microsoft.AspNetCore.Hosting.Diagnostics?
No, as per docs the most specific category is applied.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
In the preceding JSON:
The "Default", "Microsoft", and "Microsoft.Hosting.Lifetime" log level categories are specified.
The "Default" value is applied to all categories that aren't otherwise specified, effectively making all default values for all categories "Information". You can override this behavior by specifying a value for a category.
The "Microsoft" category applies to all categories that start with "Microsoft".
The "Microsoft" category logs at a log level of Warning and higher.
The "Microsoft.Hosting.Lifetime" category is more specific than the "Microsoft" category, so the "Microsoft.Hosting.Lifetime" category logs at log level "Information" and higher.
A specific log provider is not specified, so LogLevel applies to all the enabled logging providers except for the Windows EventLog.

Logging to the Application Insights TRACE event type using ILogger in ASP.Net Core

ASP.NET Core, targeting net7.0
I am using the .NET Core ILogger machinery to log messages to Application Insights.
I want to display application debug information, (I need to debug an app deployed to Azure). But I can't convince Application Insights NOT to filter out my logged debug messages.
EDIT:
It seems to me that I am trying to get Application Insights to do something it's not designed to do - that is, consistently display ALL of a particular type of message. Is there a better way to log debug message in an app deployed to Azure?
END-OF-EDIT
I use what I think is the standard setup and usage pattern:
In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry();
In my application code:
private readonly ILogger<MyCode> _logger;
/// <summary> DI constructor. </summary>
public MyCode(ILogger<MyApp.MyCode> logger)
{
_logger = logger;
}
// <summary> My method </summary>
public void MyMethod()
{
_logger.LogDebug("My message");
}
In appsetings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"MyApp": "Trace"
}
}
}
I do see my log output in the debug window, so I know it's making its way through the ILogger machinery, presumably to all of the listeners. I assume the adaptive sampling scheme is filtering out my messages.
EDIT:
I've verified that calling _logger.LogWarning results in a "TRACE" message in ApplicationInsights. But I don't want to use Warning error level for debugging because there is no easy way to turn off the debug logging (e.g., in appsettings.json). I would need to modify the source code to remove the warning-level log messages.
You could:
Change "LogLevel": { "Default": "Information", to "Trace"; or
Set ApplicationInsights -> LogLevel -> Default (see below); or
Change the log level in the code: builder.AddFilter<ApplicationInsightsLoggerProvider>("", LogLevel.Trace);; or
Log these "really important" messages as Information or even Warning - the problem with changing App Insight's log levels is that unless you get it right you'll get A LOT of other Debug+Trace messages not from your code. Don't worry about the word Warning - it's just a level.
Create filter rules in configuration with appsettings.json from
says:
ApplicationInsightsLoggerProvider is aliased as "ApplicationInsights". The following section of appsettings.json overrides the default LogLevel.Warning log level of Application Insights to log categories that start with "Microsoft" at level LogLevel.Error and higher.
{
"Logging": {
"LogLevel": {
"Default": "Warning"
},
"ApplicationInsights": {
"LogLevel": {
"Microsoft": "Error"
}
}
}
}

Trouble getting Serilog to read appsettings.json settings

I have the following code in my console application.
// Build configuration
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(ApplicationInfo.DataPath)
.AddJsonFile("appsettings.json", false, false)
.Build();
// Configure Serilog
string logFormat = "[{Timestamp:yyyy-MM-dd hh:mm:ss tt}][{Level:u3}] {Message:lj}{NewLine}{Exception}";
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.WriteTo.Console(LogEventLevel.Verbose, logFormat)
.WriteTo.File(ApplicationInfo.GetDataFileName("log"), LogEventLevel.Verbose, logFormat)
.CreateLogger();
AppHost = Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureServices((context, services) =>
{
services.AddDbContext<TTApplicationDbContext>(options =>
{
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
});
services.Configure<EmailSettings>(configuration.GetSection("EmailSettings"));
services.Configure<SftpSettings>(configuration.GetSection("FtpSettings"));
})
.Build();
This seems to be working. However, when I add the following section to my appsettings.json file, I do not get any of the verbose logging from within the framework. All I get is the logging that I specifically log in my application.
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"System": "Information"
}
}
}
As best I can tell, Serilog is ignoring these settings. How can I change that?
Update:
If I change the Default value to Debug in appsettings.json, that does in fact control whether or not my own calls to LogDebug() show up. But I don't understand why none of Microsoft's logging shows up. Wouldn't Microsoft's code use whatever logger is configured?
While configuring a DotNet Core App, I had the same problem. I found that if I added the Nuget Package serilog-extensions-hosting, it will also start outputting the framework messages to the logs.
https://github.com/serilog/serilog-extensions-hosting
I hope this helps

Serilog ignoring LogLevel from Microsoft.Extension.Logging

I am using NET5 ASP.NET MVC application. Application is using Serilog.AspNetCore 3.4.0 for logging
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Error"
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.Console"],
"WriteTo": [
{
"Name": "Console"
}
]
}
}
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
})
.UseSerilog((hostingContext, logging) =>
{
logging.ReadFrom.Configuration(hostingContext.Configuration);
});
});
I have also tried
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(hostingContext.Configuration)
.CreateLogger();
logging.AddSerilog();
});
});
Issue
My expectation is no Information log will be shown in Console since default LogLevel is Error.
However, that is not working. In console I see every request is getting logged including Information
Throughout my application I am using Microsoft.Extensions.Logging.ILogger<MyClassName> to log information. All those statements are actually logging Info even if the LogLevel is Error.
Looks like Serilog ignoring LogLevel from Microsoft.Extensions.Logging.
Note that, I can set serilog's restrictedToMinimumLevel property to Error and that stops logging information. However I think serilog should obey the LogLevel from Microsoft.Extension.Logging
Use MinimumLevel property:
"Logging": {
"MinimumLevel": {
"Default": "Error"
}
}
Also it supports overrides for categories:
"Logging": {
"MinimumLevel": {
"Default": "Error",
"Override": {
"System": "Information",
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.EntityFrameworkCore": "Debug"
}
}
}
If you check the project's Github page it advises to actually remove the standard "Logging" section in appsettings.json :-(
I think this is bad since it actually breaks the compatibility with Microsoft.Extensions.Logging framework (you can't anymore change the actual log provider (Log4Net, NLog, Serilog) without changing the appsettings.json).
If you use Serilog.Extensions.Logging and AddSerilog() on ILoggingBuilder, you'll get what you're expecting.
However, IHostBuilder.UseSerilog() (provided by Serilog.Extensions.Hosting, via Serilog.AspNetCore) is almost always a better choice, hence that's what all the Serilog docs show.
Although it seems more "integrated" to use the default configuration section this way, what you're getting behind the scenes is actually two different logging frameworks running at the same time, e.g. in the AddSerilog() case (or in the default NLog configuration):
ILogger<T> -->
MEL (routing, configuration, levels, filters) -->
Serilog (routing, configuration, levels, filters)
Logging is supposed to be very predictable/reliable and lightweight. Having two logging frameworks running at the same time erodes this and creates problems where the levels and filters specified for one framework don't match the other. (E.g. Debug and trace logs not printed when using Nlog and ILoggerFactory in .NetCore console app).
In the UseSerilog() case, (and when NLog's ReplaceLoggerFactory option is specified - mentioned in a comment on the SO thread above), you get:
ILogger<T> -->
Serilog (routing, configuration, levels, filters)
You give up support for the default "Logging" configuration section, but in exchange, you get rid of a whole logging framework at runtime, and all of your Serilog (or NLog) configuration just works, with the Microsoft.Extensions.Logging ILogger<T> available to your application code and the framework.

How to limit logging per component?

In my .NET Core app, I define a logger factory with Serilog and then pass it to various components in the system.
When I set my logging level to Debug, some components (Memcached client, for instance) completely and utterly overwhelm the logs due to how much they log.
Is there a way to specify that I want Debug for all, except certain ones? I see that there is an Override entry, but I am not clear as to how to specify a specific component.
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Information"
}
}
}

Categories