【问题标题】:Reconfigure NLog LoggingConfiguration filters programmatically以编程方式重新配置 NLog LoggingConfiguration 过滤器
【发布时间】:2012-05-05 08:44:29
【问题描述】:

这是我第一次使用 NLog 包进行日志记录,但到目前为止它非常好用。

在我的场景中,我需要以编程方式初始化我的 NLog LoggingConfiguration 设置,而不是通过更典型的配置文件场景。我已经对此进行了测试,并且默认情况下它都按照我想要的方式工作。但是我将如何在运行时以编程方式修改我的设置?

这里最常见的情况可能是应用程序的日志记录级别默认设置为 ERROR,但在特定模块中出现了一个错误,我想将日志记录级别切换为更详细以跟踪错误。

我想编写一个小的 Web 界面,以便在运行时轻松调整这些设置,但我想确保我采取了正确的方法。

【问题讨论】:

  • 请记住,将最低级别更改为Trace 可以仅使用 XML 配置完成,而无需重新启动应用程序。

标签: .net logging nlog


【解决方案1】:

我知道我迟到了一年,但我遇到了类似的情况,我需要为用户提供对记录器的动态控制。幸运的是,使用 nlog 相对容易。在这里,我只是对已创建的 Logger 启用 Trace 级别的日志记录,但显然您可以做任何您想做的事情,包括添加新的 Targets/Rules 或完全将 LoggerConfiguration 替换为您以编程方式生成的。

基本 ColoredConsole nlog.config:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <targets>
    <target xsi:type="ColoredConsole" name="c"
            layout="${longdate} ${uppercase:${level}} ${message}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Error" writeTo="c" />
  </rules>
</nlog>

简单的控制台应用程序:

public class Program 
{
  //Initialize default Logger from config file
  private static readonly Logger m_log = LogManager.GetCurrentClassLogger();

  public static Logger Log 
  {
      get { return m_log; }
  }

  public static void Main(string[] args) 
  {
    Log.Trace("You won't see me because config is at LogLevel.Error");
    EnabledTraceForAllRules();
    Log.Trace("You will see me now though!");

    //Pause console window
    Console.WriteLine("Press any key to continue...");
    Console.ReadKey(true);

    /* Prints:
    2013-05-07 16:04:22.7050 TRACE You will see me now though!
    Press any key to continue...
    */
  }

  public static void EnabledTraceForAllRules() 
  {
    foreach(var rule in LogManager.Configuration.LoggingRules)
    {
      rule.EnableLoggingForLevel(LogLevel.Trace);
    }

    //Call to update existing Loggers created with GetLogger() or 
    //GetCurrentClassLogger()
    LogManager.ReconfigExistingLoggers();
  }
}

如果您需要从进程外部更改日志记录配置并且必须以编程方式完成,我建议您使用 WCF。您可以从您的应用程序或网站公开一个小型 WCF 服务,该服务提供重新配置 nlog 的方法。

【讨论】:

  • 我建议使用 websocket 服务,它比 Wcf 更容易使用。
  • LogManager.ReconfigExistingLoggers(); 是这里的关键。没有这个,您将无法添加日志记录目标/规则
【解决方案2】:

我在 NLog 文档 (https://github.com/NLog/NLog/wiki/Configure-from-code) 中找到了“配置 API”,可能会对您有所帮助。也请查看 NLog 程序集中的 NLog.Config 命名空间。

另见:https://github.com/NLog/NLog/wiki/Reinitialize-NLog-configuration

【讨论】:

    【解决方案3】:

    我看到答案一次启用一个级别,但是如果您想反映 NLog.config 文件的行为,其中设置单个级别也会启用所有较高优先级(并禁用较低优先级),您需要启用使用SetLoggingLevels 的一系列级别,如下所示:

    NLog.config:

      <rules>
        <logger name="*" minlevel="Trace" writeTo="your-target-name" />
      </rules>
    

    代码:

    public static void SetLogLevel(LogLevel newLogLevel)
    {
        foreach (var rule in LogManager.Configuration.LoggingRules)
        {
            foreach (var target in rule.Targets)
            {
                if (target.Name == "your-target-name")
                {
                    rule.SetLoggingLevels(newLogLevel, LogLevel.Fatal);
                }
    
            }
        }
    
        LogManager.ReconfigExistingLoggers();
    }
    

    来自 NLog 文档:

    public void SetLoggingLevels(LogLevel minLevel, LogLevel maxLevel);
    

    启用记录(包括)minLevelmaxLevel。所有其他级别都将被禁用。

    【讨论】:

    • NLog 4.6.7 允许您在日志规则中使用 NLog 布局逻辑:stackoverflow.com/a/59535855/193178
    • 记得在更新完所有 LoggingRules 后调用LogManager.ReconfigExistingLoggers();。否则更改只会对新创建的 Logger 对象生效。
    • @RolfKristensen 谢谢,忘记复制了。现已修复。
    【解决方案4】:

    NLog 4.6.7 引入了在 LoggingRules 中使用布局逻辑的能力。因此,您可以拥有一个 NLog.config,其中包含可在运行时轻松调整的日志记录规则:

    <nlog>
       <variable name='myLevel' value='Warn'/>
        <rules>
          <logger minLevel='${var:myLevel}' writeTo="your-target-name" />
        </rules>
    </nlog>
    

    然后可以在运行时更新myLevel

    LogManager.Configuration.Variables["myLevel"] = "Debug";
    LogManager.ReconfigExistingLoggers();
    

    另请参阅:https://github.com/NLog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules

    【讨论】:

      【解决方案5】:

      NLog 教程页面here 上给出了一个程序化的初始设置示例,我已将其包含在下面。 (有一个更广泛的版本here。)

      public static void Startup()
      {
          var config = new NLog.Config.LoggingConfiguration();
      
          // Targets where to log to: File and Console
          var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "file.txt" };
          var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
      
          // Rules for mapping loggers to targets            
          config.AddRule(LogLevel.Info, LogLevel.Fatal, logconsole);
          config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
      
          // Apply config           
          NLog.LogManager.Configuration = config;
          LogManager.ReconfigExistingLoggers();
      }
      

      然后,更改日志级别,其中logconsole 是您要更改的目标:

      public static void SetConsoleLogLevel(LogLevel level)
      {
          foreach (var rule in LogManager.Configuration.LoggingRules)
          {
              foreach (var ruleTarget in rule.Targets)
              {
                  if (ruleTarget != logconsole) continue;
      
                  DisableLoggingForLevels(rule, LogLevel.Trace, level);
                  rule.EnableLoggingForLevels(level, LogLevel.Fatal);
                  LogManager.GetCurrentClassLogger().Log(level, "Changed logger level to {0}", level);
              }
          }
      
          LogManager.ReconfigExistingLoggers();
      }
      

      其中DisableLoggingForLevels 是一个私有方法,与NLog.Config.LoggingRule.EnableLoggingForLevels 完全相同,只是它禁用了:

      private static void DisableLoggingForLevels(LoggingRule rule, LogLevel minLevel, LogLevel maxLevel)
      {
          for (var ordinal = minLevel.Ordinal; ordinal <= maxLevel.Ordinal; ++ordinal)
              rule.DisableLoggingForLevel(LogLevel.FromOrdinal(ordinal));
      }
      

      【讨论】:

        【解决方案6】:
        using NLog;
        
        private void SetLogLevel(LogLevel level)
        {
          LogManager.GlobalThreshold = level;
        }
        

        【讨论】:

          【解决方案7】:

          大多数 NLog 示例都使用某种 NLog 配置文件,但我希望有一个完全可重新配置的编程解决方案,如果你用纯代码来做 - 它可能看起来像这样:

              var conf = new NLog.Config.LoggingConfiguration();
              var consoletarget = new ColoredConsoleTarget() { Layout = "${message}" };
          
              conf.AddTarget("console", consoletarget);
              //conf.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Debug, consoletarget));
              //conf.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Info, consoletarget));
              conf.AddRuleForAllLevels(consoletarget);
          
              NLog.LogManager.Configuration = conf;
          
              var log = NLog.LogManager.GetLogger("hello");
          
              log.Trace("trace");
              log.Debug("debug");
              log.Info("info");
              log.Warn("warn");
              log.Error("error");
              log.Fatal("fatal");
          
          

          我留下了一些代码注释,以防万一您想重新配置将向最终用户显示的日志级别。 (默认全部显示)

          【讨论】:

            猜你喜欢
            • 2016-12-14
            • 1970-01-01
            • 2018-01-23
            • 1970-01-01
            • 1970-01-01
            • 2014-03-21
            • 1970-01-01
            • 2012-03-15
            相关资源
            最近更新 更多