【问题标题】:Redirect all ASP.NET Core logging into a single NLog logger将所有 ASP.NET Core 日志记录重定向到单个 NLog 记录器
【发布时间】:2017-11-13 14:28:51
【问题描述】:

我有一个将其日志发送到 NLog 的 ASP.NET 项目。

但是在这个项目中,我有自己的 NLog 记录器,我想知道如何通过它路由所有日志。

我想我不应该将 NLog 添加为记录器,但我应该找到一种方法来注册每次 ASP 尝试记录任何内容时都会调用的方法。

如何做到这一点?


这是创建记录器的代码:

        // create the module name
        var ProcessName = Process.GetCurrentProcess().ProcessName;
        _ModuleName = ProcessName  + " (\"" + Oracle.GuessMyName() + "\")";

        // create the logger configuration
        var Configuration = new LoggingConfiguration();

        // create the file target
        var FileTarget = new FileTarget ("file")
        {
            FileName            = @"x:\Logs\${processname}.log",
            ArchiveFileName     = @"x:\Logs\${processname}.{#}.log",
            Layout              = @"${longdate}|${logger}|${level}|${message}${onexception:|Exception occurred:${exception:format=tostring}${newline}",
            ArchiveEvery        = FileArchivePeriod.Day,
            ArchiveNumbering    = ArchiveNumberingMode.Rolling,
            MaxArchiveFiles     = 7,
            ConcurrentWrites    = true
        };

        Configuration.AddTarget(FileTarget);


        // create the viewer target
        var ViewerTarget = new NLogViewerTarget ("viewer")
        {
            Layout              = @"${message}${onexception:${newline} --> Exception occurred\:${exception:format=tostring}",
            IncludeSourceInfo   = true,
            IncludeCallSite     = true,
            Address             = @"udp://127.0.0.1:9999"
        };

        Configuration.AddTarget(ViewerTarget);

        // set the rules
        Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, FileTarget));
        Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, ViewerTarget));

        // set the configuration
        LogManager.Configuration = Configuration;

        // create a new logger
        _Logger = LogManager.GetLogger(_ModuleName);

这也是 ASP.net 连接到 nlog 的方式:

        LoggerFactory.AddNLog();
        Application.AddNLogWeb();

现在两个进程的当前日志布局看起来像这样(每次重新启动进程时动物名称都会自动更改)

所以这两个进程:shinobi 和 mouserun 这里都有自己的日志输出,但是任何与 ASP 相关的内容都会转到名为 Microsoft 的 ASP 的 nlog 实例,而不管进程如何。

目标是让 shinobi 的 ASP 输出进入 shinobi 记录器,而 mouserun ASP 输出进入 mouserun 记录器。

【问题讨论】:

  • 不,我希望从 Shinobi 进程到 Microsoft 的任何东西都转到 Shinobi 记录器,从 Mouserun 到 Microsoft 的任何东西都转到 Mouserun 进程。我不希望 ASP 记录到 nlog,我希望 ASP 在它想要记录某些内容时给我一个回调,以便我可以写入进程的记录器
  • 添加所以它是包含一个记录器名称的 Log4J XML 输出,您以某种方式配置了所有内容。文件目标工作正常。
  • 是的,文件输出工作正常,但 UDP 不是
  • 没有办法改变逻辑以使用 NLogViewerTarget.Parameters 注入全局应用程序名称,然后在查看器中从 Log4J XML 中提取它吗?也许将其作为覆盖,因此如果全局应用程序参数元素存在则使用它,否则它会回退到记录器元素。
  • 没有实用的方法来做到这一点;最简单的可能是删除 ASP/Nlog 集成,然后为日志创建一个 ASP 中间件,该中间件将写入进程的记录器(至少从我在谷歌上看到的,这似乎是最直接的)

标签: asp.net nlog


【解决方案1】:

查看 NLog.Extensions.Logging 的代码,它在其中注入了自己的自定义日志提供程序。

您也可以这样做,只需包装您的全局记录器对象:

https://github.com/NLog/NLog.Extensions.Logging/blob/e48d6cc54d9abd70d976066265c7992117cbac5a/src/NLog.Extensions.Logging/NLogLoggerProvider.cs

https://github.com/NLog/NLog.Extensions.Logging/blob/1474ffe5b26d2ac95534ed01ef259133133bfb67/src/NLog.Extensions.Logging/NLogLoggerFactory.cs

https://github.com/NLog/NLog.Extensions.Logging/blob/2c05a4fbdda0fe026e60814d535e164e18786aef/src/NLog.Extensions.Logging/ConfigureExtensions.cs

    public static ILoggerFactory AddNLog(this ILoggerFactory factory, NLogProviderOptions options)
    {
        ConfigureHiddenAssemblies();

        using (var provider = new NLogLoggerProvider(options))
        {
            factory.AddProvider(provider);
        }
        return factory;
    }

【讨论】:

  • 正是我需要的!非常感谢您花时间研究这个问题!
  • 已创建 github.com/NLog/NLog/pull/2390,因此您可以直接在 NLogViewerTarget 上覆盖 LoggerName。
  • @Thomas NLog 4.5 RC 已发布,其中包含上述 PR,因此现在您无需实现自己的扩展逻辑来覆盖 NLogViewerTarget 中的 logger-name。只需使用 NLogViewerTarget.LoggerName
【解决方案2】:

您还可以创建自定义目标,并使用 NLog 规则将所有非全局记录器消息重定向到此目标:

https://github.com/nlog/NLog/wiki/Configuration-file#rules

然后自定义目标可以将日志事件转发到全局记录器:

https://github.com/NLog/NLog/wiki/How-to-write-a-custom-target

您应该小心循环日志记录。也许在自定义目标中有一个过滤器来忽略来自全局记录器的消息。

但我认为这是一个丑陋的解决方案,我无法理解只有一个记录器对象的限制。特别是当原因是因为它应该以应用程序命名时。为什么不使用名称的全局变量而不是滥用记录器名称?

【讨论】:

  • 原因是在同一个系统上有几个程序使用同一个lib,集中记录日志,同时运行;并且在每次新执行该程序时,我们都需要一个新的日志文件。因此,当应用程序启动时,它会生成一个名称(它是基本名称 + 随机部分),并且此特定实例的任何输出都必须通过以这种方式命名的记录器(我们需要 UDP + 文件输出)。
  • 该系统运行良好,但对于 ASP,因为 Nlog 集成创建了一个名为“Microsoft”的记录器实例,并且任何与 ASP 相关的内容都会通过它,合并 UDP 记录器中所有应用程序的 ASP 输出,因为数据按记录器名称排序
  • 所以,当前的解决方案有效,但我只需要 ASP 中的一个钩子,以便 I 可以记录它的日志输出,而不是 ASP 直接执行它。为此,我将删除 ASP/Nlog 集成,并且对于我收到的每条消息,我只需将其转发到应用实例的记录器
  • 还是不明白为什么NLog-logger-name是直接绑定UDP-target + file-target的。为什么不直接修复这些目标的 NLog-config,让它们不使用 Logger-name?
  • 名称定义如下:@"x:\Logs\${processname}.log";甚至没有 nlog 配置文件,它是设置记录器的代码,以便其输出与当前进程精确匹配;这是在为该进程生成记录器的全局实例时完成的;因为这在任何地方都使用,所以它不是可以改变的(无论如何使用系统的方式也没有意义)
【解决方案3】:

或者,您可以创建一个自定义目标包装器,将记录器固定在 LogEventInfo 上,因此当转发到包装目标(UDP-/文件目标)时,看起来它们都来自同一个记录器。

类似于这个人正在尝试做的事情:

https://github.com/NLog/NLog/issues/2352

又是一个非常丑陋的解决方案,只能在无法弄清楚如何避免在所需 Nlog-targets 的配置中使用 logger-name 时使用(例如,使用其他东西配置 file-target-filename) .

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 2019-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多