【问题标题】:NLog - set the logger level in runtime?NLog - 在运行时设置记录器级别?
【发布时间】:2014-08-21 04:32:48
【问题描述】:

我正在使用最新的 NLog v3.1,并且对如何在运行时设置日志记录级别有疑问。我的 NLog.config 文件中只有一个目标和记录器。记录器名称 = "*" 和 minlevel = "Info"。我在模块中有以下代码来声明记录器以及函数 GetLoggingLevel,我可以传入记录器名称以检索它的级别。但是,如何设置日志记录级别?目前我必须打开 NLog.config XML 并修改 XML 中的 minlevel。由于我有 autoReload = "true",它会生效 - 但希望有一种方法可以使用 NLog 方法/属性来设置它。

Imports System.Xml
Imports NLog

Module modLogging

Private m_Log As Logger

Public ReadOnly Property Log As Logger
    Get
        If (m_Log Is Nothing) Then
            m_Log = LogManager.GetCurrentClassLogger
        End If
        Return m_Log
    End Get
End Property

Public Sub LogShutdown()
    LogManager.Shutdown()
End Sub

Public Function GetLoggingLevel(ByVal loggerName) As String
    Dim level As String = String.Empty

    If (LogManager.GetLogger(loggerName).IsInfoEnabled) Then
        level = "Info"
    ElseIf (LogManager.GetLogger(loggerName).IsErrorEnabled) Then
        level = "Error"
    ElseIf (LogManager.GetLogger(loggerName).IsDebugEnabled) Then
        level = "Debug"
    End If

    Return (level)
End Function

有了这个,我可以在我的项目中轻松调用 Log.Info("some text") 或 Log.Error("some error") 等。我可以获得当前级别并将其显示给用户,但我希望用户能够将日志记录级别更改为调试、信息、错误等,但我无法弄清楚如何在配置文件中设置 minlevel在运行时无需直接加载和修改配置 XML。任何帮助将不胜感激。

最诚挚的问候

【问题讨论】:

    标签: vb.net logging nlog


    【解决方案1】:

    您可以访问 LogManager.Configuration.LoggingRules 并启用或禁用特定级别的日志记录。例如,使用带有 NLog 配置的小项目:

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

    还有一个像

    这样的控制台应用程序
    Sub Main()
    
        Dim log As Logger = LogManager.GetCurrentClassLogger
    
        log.Debug("debug message")
        log.Info("info message")
    
        For Each rule As LoggingRule In LogManager.Configuration.LoggingRules
            rule.DisableLoggingForLevel(LogLevel.Debug)
        Next
    
        LogManager.ReconfigExistingLoggers()
    
        log.Debug("debug message") REM This line will not be logged
        log.Info("info message")
    
        Console.ReadLine()
    
    End Sub
    

    【讨论】:

    • 谢谢克里斯蒂安。这是更改日志记录级别的唯一方法吗?我只在我的配置文件中指定了 minlevel,并且想在 Debug、Info 和 Error 之间简单地更改它。我不在配置 XML 中使用 Levels 标记(即 Levels="Debug,Info,Error")。不确定使用这些是否有任何区别,但我想保留更高级别的日志记录(例如,如果启用了信息,错误仍然会记录)。通过禁用级别的日志记录,我需要遍历级别并禁用“低于”用户选择的级别。不知道该怎么做。谢谢!
    • 禁用某个级别将导致仅禁用该指定级别以及低于该级别的级别。因此,如果禁用“info”,则不会记录级别:“trace”、“debug”和“info”,但仍会记录“warn”、“error”和“fatal”。
    • 如果我只想在运行时更改特定记录器的最小级别怎么办?
    • Chirstiaan,你确定禁用一个级别会禁用它下面的级别吗?由于可以为 Debug 和 Error 级别启用规则,但不能为 Info 级别启用规则,我认为禁用某个级别仅适用于该级别。
    【解决方案2】:

    NLog 版本。 4.6.7 使您可以这样做:

    <nlog>
       <variable name="myLevel" value="Warn" />
        <rules>
          <logger minLevel="${var:myLevel}" />
        </rules>
    </nlog>
    

    然后你可以执行这段代码,它会动态更新日志规则:

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

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

    【讨论】:

      【解决方案3】:

      您需要实现ILoggerProvider 以返回您自己的自定义记录器。您创建的记录器可以实现ILogger。您将需要复制您的 nlog 配置文件并更改最小和最大级别以允许所有日志级别。这将在一个仅用于需要不同日志记录的特殊请求的类中被覆盖。

      VB:

      Public NotInheritable Class CustomLevelNLogProvider
          Inherits ILoggerProvider
      
          Private ReadOnly factory As NLog.LogFactory
      
          ' pass a separate nlog config path that has logging enabled all the way to trace level, you will override it down below in the LogWrapper class
          Public Sub New(ByVal customNlogConfigPath As String)
              factory = NLog.Web.NLogBuilder.ConfigureNLog(customNlogConfigPath)
          End Sub
      
          Public Function CreateLogger(ByVal categoryName As String) As ILogger
              Dim logger = factory.GetLogger(categoryName)
              Return New CustomLevelLogger(logger)
          End Function
      End Class
      
      Public NotInheritable Class CustomLevelLogger
          Inherits ILogger
      
          Private ReadOnly innerLogger As ILogger
          Private ReadOnly minLevel As LogLevel
          Private ReadOnly maxLevel As LogLevel
      
          Public Sub New(ByVal innerLogger As ILogger)
              Me.innerLogger = innerLogger
          End Sub
      
          ' call this method on each request that needs a temporary log level
          Public Sub SetLogLevels(ByVal minLevel As LogLevel, ByVal maxLevel As LogLevel)
              Me.minLevel = minLevel
              Me.maxLevel = maxLevel
          End Sub
      
          ' implement the ILogger interface, making sure to use minLevel and maxLevel properly, forward calls on to innerLogger if level matches
      }
      End Class
      

      C#:

      public sealed class CustomLevelNLogProvider : ILoggerProvider
      {
          private readonly NLog.LogFactory factory;
      
          // pass a separate nlog config path that has logging enabled all the way to trace level, you will override it down below in the LogWrapper class
          public CustomLevelNLogProvider(string customNlogConfigPath)
          {
              factory = NLog.Web.NLogBuilder.ConfigureNLog(customNlogConfigPath);
          }
      
          ' call this method on each request that needs a temporary log level
          public ILogger CreateLogger(string categoryName)
          {
              var logger = factory.GetLogger(categoryName);
              return new CustomLevelLogger(logger);
          }
      }
      
      public sealed class CustomLevelLogger : ILogger
      {
          private readonly ILogger innerLogger;
          private readonly LogLevel minLevel;
          private readonly LogLevel maxLevel;
      
          public CustomLevelLogger(ILogger innerLogger)
          {
              this.innerLogger = innerLogger;
          }
      
          // call this method on each request that needs a temporary log level
          public void SetLogLevels(LogLevel minLevel, LogLevel maxLevel)
          {
              this.minLevel = minLevel;
              this.maxLevel = maxLevel;
          }
      
          // implement the ILogger interface, making sure to use minLevel and maxLevel properly, forward calls on to innerLogger if level matches
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-14
        • 2016-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多