将所有 ASP.NET 核心日志记录重定向到单个 NLog 记录器

Redirect all ASP.NET Core logging into a single NLog logger

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

但是在这个项目中,我有自己的 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 相关的东西都会转到 ASP 的名为 Microsoft 的 nlog 实例,而不管进程如何。

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

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

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

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

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

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

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

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

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

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

又是一个非常难看的解决方案,只应在无法弄清楚时使用,如何避免在所需 Nlog 目标的配置中使用记录器名称(例如,使用某些东西配置文件目标文件名否则)。

查看 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;
    }