Change log4net logging level programmatically

C#LoggingLog4net

C# Problem Overview


This is similar to 650694 but no answer was accepted there, I can't get any of those suggestions to work at all, and I suspect I may be in a slightly different situation.

I'm calling log4net.Config.XmlConfigurator.Configure(). But after that point in the program, I want to change the logging threshold to a value only known at runtime.

From the other question, I tried:

((log4net.Repository.Hierarchy.Logger)mylogger.Logger).Level = log4net.Core.Level.Error;

and:

var appender = new log4net.Appender.ColoredConsoleAppender();
appender.Layout = new log4net.Layout.PatternLayout(@"%date %-5level %message%newline");
appender.Threshold = log4net.Core.Level.Error;
appender.ActivateOptions();
log4net.Config.BasicConfigurator.Configure(appender);

but neither one seems to have any effect: I'm still seeing DEBUG and INFO logging statements on the console.

My hunch is that I'm adding a new appender, which has no effect on the appender declared in the XML config (which tells it to print DEBUG level messages), but I don't have any evidence for this yet.

I've been digging through the log4net API for a while now, and I'm just not seeing it. Is there something simple I'm missing?

C# Solutions


Solution 1 - C#

None of these solutions present here worked for me. It wasn't changing at runtime

Here is what worked for me:

((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root.Level = Level.Debug;
((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).RaiseConfigurationChanged(EventArgs.Empty);

You have to call RaiseConfigurationChanged after making changes to its config.

Solution 2 - C#

Finally found a working solution, here.

The big pieces were:

  • need to set the threshold on all loggers, including the "cannot be retrieved by name" root logger
  • need to get the Level from the Hierarchy's LevelMap

Big thanks to Eddie for asking good pointed questions, which led me to google the right words. I never would have figured this out alone.

(Aside: Repository, Hierarchy, Logger, RootLogger, LevelMap -- I had no idea it was even possible to make a logging library this complex. It's got about 20 layers of indirection, which I'm sure makes it flexible enough for anything, but makes it nearly impossible to do simple things like "don't log any messages above threshold X". Gah!)

Solution 3 - C#

There's a simple way to do it:

LogManager.GetRepository().Threshold = Level.Info;

More information can be found here.

Solution 4 - C#

If this works for someone, here is how I implemented in my web application a toggle level endpoint exposed via an API call, so I can change the logging level on the fly.

public HttpResponseMessage Post([FromBody] string logLevel)
{
    var newLevel = ToggleLogging(logLevel);

    // Create your own response here.
    return newLevel;
}

And the actual implementationt

private Level ToggleLogging(string logLevel)
{

    Level level = null;

    if (logLevel != null)
    {
        level = LogManager.GetRepository().LevelMap[logLevel];
    }

    
    if (level == null)
    {
        level = Level.Warn;
    }

    ILoggerRepository[] repositories = LogManager.GetAllRepositories();

    //Configure all loggers to be at the same level.
    foreach (ILoggerRepository repository in repositories)
    {
        repository.Threshold = level;
        Hierarchy hier = (Hierarchy)repository;
        ILogger[] loggers = hier.GetCurrentLoggers();
        foreach (ILogger logger in loggers)
        {
            ((Logger)logger).Level = level;
        }
    }

    //Configure the root logger.
    Hierarchy h = (Hierarchy)LogManager.GetRepository();
    Logger rootLogger = h.Root;
    rootLogger.Level = level;

    return level;
}

Solution 5 - C#

JeanT's answer doesnt seem to work with the latest version of log4net.

I adapted it to get it working, this changes to Debug level, but alter as required.

foreach(var r in LogManager.GetAllRepositories()) { ((log4net.Repository.Hierarchy.Hierarchy)r).Root.Level = Level.Debug; ((log4net.Repository.Hierarchy.Hierarchy)r).RaiseConfigurationChanged(EventArgs.Empty); }

Solution 6 - C#

Tried all these answers and none of them worked. In debugger I could see that all logger levels, root levels, thresholds were set as directed. Despite that, I did not see any log level change in the rolling file I was logging to.

Then I found that in the configuration file the appender element also specified a threshold value. So when I wanted to change the level to Debug while the appender was set to Warn, for example, that appender did not pick up additional messages as they were below the threshold. So I removed the threshold from the appender configuration and just kept the level configuration.

  <root>
    <level value="Warn" />
    <appender-ref ref="RollingFile" />
  </root>

Then I ended up using Ken's solution to change the level at runtime.

Solution 7 - C#

I was looking for the same approach and found that the latest NLog version 3.2.0.0 gives below option to change logging level on runtime.

 LogManager.GlobalThreshold = LogLevel.Debug;

I think another approach might be to use LogManager.Configuration to overwrite the config settings using variables.

Solution 8 - C#

In my case I had different default levels for different appenders set the config, but wanted to overide them if the application was in verbose mode.

I used the following:

var log4NetHierarchy = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
foreach (var appender in log4NetHierarchy.GetAppenders())
{
    if (appender is AppenderSkeleton appenderSkeleton)
    {
        appenderSkeleton.Threshold = Level.All;
    }
}
log4NetHierarchy.RaiseConfigurationChanged(EventArgs.Empty);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKenView Question on Stackoverflow
Solution 1 - C#JeanTView Answer on Stackoverflow
Solution 2 - C#KenView Answer on Stackoverflow
Solution 3 - C#AlexView Answer on Stackoverflow
Solution 4 - C#agarcianView Answer on Stackoverflow
Solution 5 - C#PSTView Answer on Stackoverflow
Solution 6 - C#Mark MeyerovichView Answer on Stackoverflow
Solution 7 - C#seUserView Answer on Stackoverflow
Solution 8 - C#Jonathan SayceView Answer on Stackoverflow