简体   繁体   English

以编程方式更改 log4net 日志记录级别

[英]Change log4net logging level programmatically

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.这与650694类似,但那里没有接受任何答案,我根本无法得到任何这些建议,而且我怀疑我的情况可能略有不同。

I'm calling log4net.Config.XmlConfigurator.Configure().我正在调用 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.但似乎都没有任何效果:我仍然在控制台上看到 DEBUG 和 INFO 日志记录语句。

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.我的预感是我正在添加一个新的 appender,它对 XML 配置中声明的 appender 没有影响(它告诉它打印 DEBUG 级别的消息),但我还没有任何证据证明这一点。

I've been digging through the log4net API for a while now, and I'm just not seeing it.我已经研究了 log4net API 一段时间了,但我只是没有看到它。 Is there something simple I'm missing?我错过了一些简单的东西吗?

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.您必须在更改其配置后调用 RaiseConfigurationChanged。

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需要从层次结构的 LevelMap 中获取 Level

Big thanks to Eddie for asking good pointed questions, which led me to google the right words.非常感谢 Eddie 提出了很好的尖锐问题,这让我在 google 上找到了正确的词。 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!) (旁白:Repository、Hierarchy、Logger、RootLogger、LevelMap——我什至不知道有可能让一个日志库变得如此复杂。它有大约 20 层间接层,我确信这使它足够灵活,可以处理任何事情,但是几乎不可能做一些简单的事情,比如“不要记录超过阈值 X 的任何消息”。啊!)

There's a simple way to do it:有一个简单的方法来做到这一点:

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

More information can be found here .可以在此处找到更多信息。

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.如果这对某人有用,以下是我在我的 Web 应用程序中实现通过 API 调用公开的切换级别端点的方法,因此我可以即时更改日志记录级别。

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;
}

JeanT's answer doesnt seem to work with the latest version of log4net. JeanT 的回答似乎不适用于最新版本的 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); }

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.然后我发现在配置文件中appender元素也指定了一个阈值。 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.因此,当我想在 appender 设置为警告的情况下将级别更改为 Debug 时,例如,该 appender 没有拾取其他消息,因为它们低于阈值。 So I removed the threshold from the appender configuration and just kept the level configuration.所以我从appender配置中删除了阈值,只保留了级别配置。

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

Then I ended up using Ken's solution to change the level at runtime.然后我最终使用 Ken 的解决方案在运行时更改级别。

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.我一直在寻找相同的方法,发现最新的 NLog 版本 3.2.0.0 提供了以下选项来更改运行时的日志记录级别。

 LogManager.GlobalThreshold = LogLevel.Debug;

I think another approach might be to use LogManager.Configuration to overwrite the config settings using variables.我认为另一种方法可能是使用LogManager.Configuration使用变量覆盖配置设置。

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.在我的情况下,我为不同的 appender 设置了不同的默认级别来设置配置,但是如果应用程序处于详细模式,我想覆盖它们。

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM