NLog - 在运行时设置日志记录器级别?

4

我正在使用最新的NLog v3.1,在运行时设置日志级别时有一个问题。我的NLog.config文件中只有一个目标(target)和一个记录器(logger)。记录器名称为"*",最小级别(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("一些文本")或Log.Error("一些错误")等方法。 我可以获取当前级别并将其显示给用户,但我希望用户能够更改日志记录级别为调试、信息、错误等,但我无法弄清如何在运行时设置配置文件中的minlevel而不必直接加载和修改配置XML。

4个回答

4

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 另请参阅:https://github.com/NLog/NLog/wiki/Environment-specific-NLog-Logging-Configuration

3
您可以通过访问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

谢谢Christiaan。这是改变日志级别的唯一方法吗?我只在我的配置文件中指定了minlevel,并希望简单地在Debug、Info和Error之间更改它。我不使用配置XML中的Levels标签(即Levels="Debug,Info,Error")。不确定使用这些是否有任何区别,但我想保留更高级别的日志记录(例如,如果启用Info,则仍会记录Error)。通过禁用级别的日志记录,我需要循环遍历级别并禁用低于用户选择的级别的级别。不确定如何处理。谢谢! - DataCrypt
禁用某个级别将导致仅禁用指定级别及其以下级别。因此,如果您禁用“info”,则不会记录级别:“trace”,“debug”和“info”,但仍会记录“warn”,“error”和“fatal”。 - Christiaan van Bergen
如果我只想在运行时更改特定记录器的最小级别,该怎么办? - pjdupreez
Chirstiaan,你确定禁用一个级别会禁用它下面的级别吗?由于可以为Debug和Error级别启用规则,但无法为Info级别启用规则,因此我认为禁用一个级别只适用于该级别。 - ROBERT RICHARDSON

2
C#
  using NLog;

  LogManager.GlobalThreshold = LogLevel.Debug;

我不确定在这种情况下这是否真的重要,因为这里没有太多的语法,但问题标记有 [tag:vb.net],所以提供一个 C# 的答案并不相关。话虽如此,我想基本概念在 VB.NET 中也应该适用。 - Jeremy Caney

0
您需要实现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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接