【问题标题】:How do I correctly add NLog to a .NET 5 Console App?如何正确地将 NLog 添加到 .NET 5 控制台应用程序?
【发布时间】:2021-09-09 14:56:28
【问题描述】:

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

我知道我不想对其中一些设置进行硬编码,并很快链接一个 appsettings 文件,但我只想让所有内容都先记录下来,而且最少。

到目前为止我有:

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运行正常。

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

【问题讨论】:

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

标签: c# nlog .net-5


【解决方案1】:

这是我完整且封装好的 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 https://stackoverflow.com/questions/47058036/nlog-not-logging-on-all-levels/47074246#47074246 */
            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

【讨论】:

  • 这看起来很棒,但我很笨!我已经添加了这个类,创建了带有基本目标和规则的 nlog.config,但什么也没有。我的意思是从 Main 调用这个类吗?对不起。
  • 是的,不是“内联”,而是调用扩展方法。服务。配置SharedNlog(); (服务在您的 startup.cs 或 program.cs 中)
  • 对不起,我很痛苦。从 Host.CreateDefaultBuilder().ConfigureServices 执行此操作,它正在请求 IHostEnvironement。我打算给它什么?
  • 抱歉,没有发现 .ConfigureServices() 的上下文是 HostBuilderContext,并且包含 HostEnvironment。您的解决方案效果很好。谢谢。
【解决方案2】:

您正在执行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

【讨论】:

  • 谢谢 Rolf,但这并没有什么不同。
  • 呃!谢谢,罗尔夫。这一直是我的问题!我现在走了一条不同的路线,但这同样有效!
猜你喜欢
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多