9

This is my default Serilog configuration

SeriLogLevelSwitch.MinimumLevel = LogEventLevel.Information;
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.ControlledBy(SeriLogLevelSwitch)
    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
    .Enrich.FromLogContext()
     ....

How can i change the loglevel to Debug for a specific namespace at runtime when the default is Information?

Marco
  • 337
  • 3
  • 10

2 Answers2

15

Each of your MinimumLevel.Override can have its own LoggingLevelSwitch, which allows you to control the log level for each particular override at run-time.

Create individual LoggingLevelSwitch for each override that you intend to modify whilst the app is running, and store these instances in a place that you can access from other parts of your application, which will allow you to change the MinimumLevel of these LoggingLevelSwitch(es).

e.g.

public class LoggingLevelSwitches
{
    // Logging level switch that will be used for the "Microsoft" namespace
    public static readonly LoggingLevelSwitch MicrosoftLevelSwitch
        = new LoggingLevelSwitch(LogEventLevel.Warning);

    // Logging level switch that will be used for the "Microsoft.Hosting.Lifetime" namespace
    public static readonly LoggingLevelSwitch MicrosoftHostingLifetimeLevelSwitch
        = new LoggingLevelSwitch(LogEventLevel.Information);
}

Configure your Serilog logging pipeline to use these LoggingLevelSwitch instances:

static void Main(string[] args)
{
    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Override("Microsoft", LoggingLevelSwitches.MicrosoftLevelSwitch)
        .MinimumLevel.Override("Microsoft.Hosting.Lifetime",
            LoggingLevelSwitches.MicrosoftHostingLifetimeLevelSwitch)
        .Enrich.FromLogContext()
        .CreateLogger();

    // ...
}

Then somewhere in your application, for example, in the code that handles your application configuration that can be changed at run-time, update the LoggingLevelSwitch instance(s) to the new LogEventLevel that you want:

public class AppSettings
{
    void ChangeLoggingEventLevel()
    {
        LoggingLevelSwitches.MicrosoftHostingLifetimeLevelSwitch
            .MinimumLevel = LogEventLevel.Error;

        LoggingLevelSwitches.MicrosoftHostingLifetimeLevelSwitch
            .MinimumLevel = LogEventLevel.Warning;

        // ...
    }
}

As you can see, the LogEventLevel is controlled by the LoggingLevelSwitch instances, so it's up to you to decide where in your application (and how) these instances will be modified, to affect the logging pipeline.

The example above I'm assuming you have a screen (or API) in your application that a user would be able to configure the logging levels.

If you don't have that, then another approach is to have a background thread that periodically checks a configuration file, an environment variable, or query a database, etc. to determine what these logging levels should be.

If you're using a .NET Core Host, you can use the Options pattern which can handle the refresh of the configuration for you, and allow you to execute code when the configuration changes (where you'd change the MinimumLevel of your LoggingLevelSwitch(es) you have.

C. Augusto Proiete
  • 24,684
  • 2
  • 63
  • 91
  • it appears the library doesn't really support what I want, but this answer comes closest to it. Thanks. – explunit May 30 '20 at 12:58
1

You can use an environment variable paired with another MinimumLevel.Override to change the loglevel to Debug for a specific namespace at runtime like so:

using System;

...

SeriLogLevelSwitch.MinimumLevel = LogEventLevel.Information;
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.ControlledBy(SeriLogLevelSwitch)
    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
    .MinimumLevel.Override(Environment.GetEnvironmentVariable("SPECIFIC_NAMESPACE"), LogEventLevel.Debug)
    .Enrich.FromLogContext()
     ....

Then, ensure the environment variable SPECIFIC_NAMESPACE is accessible by your application at runtime. Note that "namespace" is synonymous with "source context prefix"

Environment.GetEnvironmentVariable

richytong
  • 2,387
  • 1
  • 10
  • 21
  • This looks like a variation on the startup-time code. Are you sure it's really runtime? – explunit May 24 '20 at 12:15
  • Code that runs when an application starts (startup-time) is also part of runtime. The distinction of the times is only between run-time and compile-time. With the example from my answer, you can configure your logger dynamically when you run your application – richytong May 24 '20 at 17:10
  • I agree with @richytong and this was exactly what I've been looking for.+1 – gratinierer Nov 17 '20 at 12:48