动态设置每个 Logger 实例的 Nlog 日志级别 ASP.Net Core 2.x

目标:动态选择我想要详细记录的 HTTP 请求(不同的日志级别)。


概述:我有一个 ASP.Net core 2.1 Web 服务器正在运行,并且一旦投入生产,如果我需要调试问题,我希望能够更改日志级别。我找到了如何全局更改日志级别;但是,更改日志级别是持久的......也就是每次调用我的控制器后都不会重置。


    [HttpGet]

    public async Task<IEnumerable<string>> Get()

    {

        this.Logger.LogTrace("This should NOT get logged");

        SetMinLogLevel(LogLevel.Trace);

        this.Logger.LogTrace("This should be logged");


        return new string[] { "value1", "value2" };

    }


   public static void SetMinLogLevel(LogLevel NewLogLevel)

    {

        foreach (var rule in LogManager.Configuration.LoggingRules)

        {

            rule.EnableLoggingForLevel(NewLogLevel);

        }


        //Call to update existing Loggers created with GetLogger() or 

        //GetCurrentClassLogger()

        LogManager.ReconfigExistingLoggers();

    }

我希望请求者能够在他们的 HTTP 请求(标头或 cookie)中设置一个标志,以便为每个请求启用更详细的日志记录级别。这样我就不会用来自请求者的详细日志淹没我的日志。


问题:如何动态设置每个记录器实例的日志级别?(我相信这是正确的措辞)


我目前正在使用 NLog 包 4.5。


拉丁的传说
浏览 558回答 3
3回答

跃然一笑

NLog 4.6.7 允许您在日志记录规则过滤器中使用布局minLevel/maxLevel您可以使用默认日志级别的 NLog-Config-Variable,然后在您的 Web 应用程序上创建一个隐藏方法来修改 NLog-Config-Variable 并调用ReconfigExistingLoggers().然后设置一个计时器,在 30 秒后将该 NLog-Config-Variable 恢复为其原始值。并且还调用了ReconfigExistingLoggers()。另见:https&nbsp;:&nbsp;//github.com/NLog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules

30秒到达战场

与其尝试自定义 NLog 日志记录级别(这会影响整个过程),我认为您应该寻求一种解决方案来修改日志语句本身的日志级别。要完成这项工作,您需要具备以下条件:一种机制,用于识别您想要调试日志记录的请求记录器的包装器,以便您可以动态覆盖日志级别第一个要求很简单 - 设置 cookie 或自定义 HTTP 标头,并检查两者是否存在。您需要将此检查的结果提供给您的 LogWrapper 实例,以便它知道什么时候应该做一些特殊的事情。LogWrapper 必须针对每个请求进行实例化,以便实例不会跨请求共享。最简单的方法是在控制器的构造函数中按需创建它(但你也可以将它连接到 DI 容器以进行自动注入)。这看起来像这样:public class HomeController : Controller{&nbsp; &nbsp; private readonly LogWrapper _logger;&nbsp; &nbsp; public HomeController(ILogger<HomeController> logger)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var isDebugRequest = ...;&nbsp; &nbsp; &nbsp; &nbsp; _logger = new LogWrapper<HomeController>(logger, isDebugRequest);&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; ...}此处解释了为 NLog 创建日志包装器的基础知识,但您似乎已经在使用为 Microsoft.Extensions.Logging 创建的包装器,因此您需要改为包装该接口:public class LogWrapper<T> : Microsoft.Extensions.Logging.ILogger{&nbsp; &nbsp; private readonly ILogger<T> _logger;&nbsp; &nbsp; private readonly bool _debug;&nbsp; &nbsp; public LogWrapper(ILogger<T> logger, bool isDebug)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _logger = logger;&nbsp; &nbsp; &nbsp; &nbsp; _debug = isDebug;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; public void Log<TState>(LogLevel logLevel,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EventId eventId,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TState state,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Exception exception,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Func<TState, Exception, string> formatter)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (_debug)&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // override log level here&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _logger.Log(LogLevel.Warning, eventId, state, exception, formatter);&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _logger.Log(logLevel, eventId, state, exception, formatter);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // ILogger has two other methods you'll need to implement}&nbsp; &nbsp;&nbsp;这种方法的缺点是日志语句没有其原始日志级别,这对您的用例可能重要也可能不重要。

POPMUISE

也许您可以使用 session-cookie 来控制是否启用调试模式:<targets>&nbsp; &nbsp; <target type="file" name="logfile" filename="applog.txt" /></targets><rules>&nbsp; &nbsp; <logger name="*" minlevel="Off" writeTo="logfile" ruleName="debugCookieRule">&nbsp; &nbsp; &nbsp; <filters defaultAction="Log">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<when condition="'${aspnet-session:EnableDebugMode}' == ''" action="Ignore" />&nbsp; &nbsp; &nbsp; </filters>&nbsp; &nbsp; </logger></rules>然后像这样激活会话cookie:public void SetMinLogLevel(LogLevel NewLogLevel){&nbsp; &nbsp; var cookieRule = LogManager.Configuration.FindRuleByName("debugCookieRule");&nbsp; &nbsp; if (cookieRule != null)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; cookieRule.MinLevel = NewLogLevel;&nbsp; &nbsp; &nbsp; &nbsp; // Schedule disabling of logging-rule again in 60 secs.&nbsp; &nbsp; &nbsp; &nbsp; Task.Run(async () => { await Task.Delay(60000).ConfigureAwait(false); cookieRule.MinLevel = LogLevel.Off; LogManager.ReconfigExistingLoggers(); });&nbsp; &nbsp; &nbsp; &nbsp; // Activate EnableDebugMode for this session&nbsp; &nbsp; &nbsp; &nbsp; HttpContext.Session.SetString("EnableDebugMode", "Doctor has arrived");&nbsp; &nbsp; }&nbsp; &nbsp; LogManager.ReconfigExistingLoggers();&nbsp; // Refresh loggers}如果${aspnet-session}不需要session-cookies ,那么 NLog.Web.AspNetCore 有其他选项来提取 HttpContext-details。另见:https : //nlog-project.org/config/?tab=layout-renderers&search=package : nlog.web.aspnetcore
打开App,查看更多内容
随时随地看视频慕课网APP