如何正确地将 NLog 添加到 .NET 5 控制台应用程序?

How do I correctly add NLog to a .NET 5 Console App?

我正在尝试将 NLog 添加到 .NET 5 控制台应用程序。

我知道我不想对其中一些设置进行硬编码,并且 link 很快就会有一个应用程序设置文件,但我只想先记录所有内容,最低限度。

到目前为止我有:

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");

    var config = new LoggingConfiguration();

    var fileTarget = new FileTarget("fileTarget")
    {
        FileName = @"c:\AppLogs\TestApp\mylog-${shortdate}.log",
        Layout = "${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}"
    };

    if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
    {
        fileTarget = new FileTarget("fileTarget")
        {
            FileName = @"c:\AppLogs\TestApp_UAT\mylog-${shortdate}.log",
            Layout = "${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}"
        };
    }

    config.AddTarget(fileTarget);
    // rules
    config.AddRuleForOneLevel(NLog.LogLevel.Warn, fileTarget);
    config.AddRuleForOneLevel(NLog.LogLevel.Error, fileTarget);
    config.AddRuleForOneLevel(NLog.LogLevel.Fatal, fileTarget);
    LogManager.Configuration = config;

    var host = Host.CreateDefaultBuilder()
        .ConfigureServices((context, services) =>
        {
            services.AddTransient<TestService>();
        }).ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
            logging.AddNLog();
        }).Build();

    
    var svc = ActivatorUtilities.CreateInstance<TestService>(host.Services);
    svc.Run();
}

然后我尝试在 TestService 中记录一些东西:

public class TestService
    {
        public TestService(ILogger<TestService> logger)
        {
            Logger = logger;
        }

        public ILogger<TestService> Logger { get; }

        public void Run()
        {
            Console.WriteLine("my first log");
            Logger.LogInformation("my first log");
        }
    }

我没有收到任何错误,但也没有创建任何日志(文件或内容)。控制台输出,所以 TestServices 正确运行。

根据文档,我希望看到一个名为“BuildServiceProvider()”的方法链接在“ConfigureLogging()”之后,但我只有“Build()”。这与它有关吗,还是我错过了什么?

您正在执行 LogInformation,但您仅使用 AddRuleForOneLevel 启用了 Warn + Error + Fatal。也许用 AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, fileTarget) 代替?

您也可以尝试指定 RemoveLoggerFactoryFilter(以避免 Microsoft ILogger 过滤问题):

   .ConfigureLogging(logging =>
    {
        logging.ClearProviders();
        logging.AddNLog(new NLogProviderOptions { RemoveLoggerFactoryFilter = true );
    })

另请参阅:https://github.com/NLog/NLog.Extensions.Logging/blob/master/src/NLog.Extensions.Logging/Logging/NLogProviderOptions.cs

这是我完整封装的 NLog(针对 Console/CommandLine/DotNetCore)应用程序。

using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;

namespace Me.Configuration.DependencyInjection
{
    [ExcludeFromCodeCoverage]
    public static class NlogSharedConfiguration
    {
        public const string NlogPerEnvironmentNameTemplate = "nlog.{0}.config";
        public const string NlogDefaultFileName = "nlog.config";

        public static IServiceCollection ConfigureSharedNlog(
            this IServiceCollection services,
            IConfiguration configuration,
            IHostEnvironment hostEnvironmentProxy)
        {
            NLogProviderOptions nlpopts = new NLogProviderOptions
            {
                IgnoreEmptyEventId = true,
                CaptureMessageTemplates = true,
                CaptureMessageProperties = true,
                ParseMessageTemplates = true,
                IncludeScopes = true,
                ShutdownOnDispose = true
            };

            /* Note, appsettings.json (or appsettings.ENVIRONMENT.json) control what gets sent to NLog.  So the .json files must have the same (or more) detailed LogLevel set (compared to the Nlog setting) 
             * See  */
            services.AddLogging(
                builder =>
                {
                    builder.AddConsole().SetMinimumLevel(LogLevel.Trace);
                    builder.SetMinimumLevel(LogLevel.Trace);
                    builder.AddNLog(nlpopts);
                });

            string nlogPerEnvironmentName = string.Format(
                NlogPerEnvironmentNameTemplate,
                hostEnvironmentProxy.EnvironmentName);
            string nlogConfigName = File.Exists(nlogPerEnvironmentName) ? nlogPerEnvironmentName : NlogDefaultFileName;
            Console.WriteLine(string.Format("Nlog Configuration File. (FileName='{0}')", nlogConfigName));

            if (!File.Exists(nlogConfigName))
            {
                throw new ArgumentOutOfRangeException(
                    string.Format("Nlog Configuration File NOT FOUND. (FileName='{0}')", nlogConfigName));
            }

            LogManager.LoadConfiguration(nlogConfigName);

            NLogLoggerProvider nlogProv = new NLogLoggerProvider(nlpopts);
            ILoggerProvider castLoggerProvider = nlogProv as ILoggerProvider;

            services.AddSingleton<ILoggerProvider>(castLoggerProvider);
            return services;
        }
    }
}

我有(在我的 .exe 的根文件夹中)以下文件:

nlog.config
nlog.Development.config
NLog.xsd

nlog.Development.config 是可选的,但这就是我为本地开发人员设置的设置与其他设置略有不同的方式。 您可以在上面看到我的“如果文件存在”代码。

IHostEnvironment 来自这里:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-5.0#ihostenvironment