如何在.NET Core 3.0 Worker服务中使用Microsoft.Extensions.Logging

时间:2019-10-30 07:30:23

标签: logging .net-core nlog .net-core-3.0

我开始了一个新的Windows服务项目,并决定使用.NET Core 3.0 Worker Service模板。这项服务永远不会在云/ Web项目中使用,但是我可能有机会在某个时候使其适应Linux上的运行。

我对使用NLog进行日志记录非常熟悉。在每个类中创建新的静态记录器对象的模型非常直观。我看到Worker服务已加入Microsoft.Extensions.Logging框架,以至于默认的worker已直接传入了ILogger<Worker>。这对于“我的第一项服务”非常有用,但是真正的长期运行大量类的服务,每个类都需要记录?

我为该模板找到的所有教程都涉及服务,这些服务完成所有工作并登录Worker类。由于历史原因,大多数日志记录文章仅考虑以DI为优先的ASP.NET core。我还没有找到有关如何使用具有多个长期存在的类的树来构建应用程序的描述,每个类都有自己的ILogger对象要写入。

即使我在这个项目中永远不需要DI,但似乎在我的代码库中采用它可能是一个很好的标准,最初将其连接到NLog提供程序。我可以在IHostBuilder中抓取Main,然后添加一个静态函数以类似于NLog的方式从其ILoggingBuilder创建记录器,但是我不相信这是最好的方法

这里是否有既定的最佳实践?是否涉及从“工人服务”模板中挑选一些魔术?

2 个答案:

答案 0 :(得分:2)

NLog在.Net Core中可以正常工作,而无需依赖注入的任何帮助。您只是喜欢一如既往:

private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();

private static void Main()
{
    Logger.Info("Hello World");
}

但是NLog也可以使用Microsoft Dependency Injection与Microsoft Extension Logging(MEL)集成。您只需要注册NLog LoggingProvider,然后MEL-ILogger输入将转发到NLog。

IHostBuilder.ConfigureLogging中,您可以调用AddNLog()(就像可以为内置MEL-LoggingProviders调用AddDebug()AddConsole()一样)

您可以在Wiki页上找到一个简单的示例(如果需要,还可以链接到ASP.NET Core):

https://github.com/NLog/NLog/wiki/Getting-started-with-.NET-Core-2---Console-application

有些人不喜欢即使对于简单的类(过于混乱)也必须通过类构造器注入MEL-ILogger。相反,他们只是直接使用NLog.LogManager.GetCurrentClassLogger()

答案 1 :(得分:-1)

也许值得一看Serilog https://serilog.net/? Serilog非常灵活,您可以添加各种类型的接收器,例如:控制台,文件,elasticsearch,seq等。而且您不必到处乱写。

这就是我使用它打印到控制台(std :: out)的方式。

using System;
using System.IO;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Serilog;
namespace YourNamespace
{
public class Program
{
    private static readonly string _applicationName = System.Reflection.Assembly.GetEntryAssembly().GetName().Name;
    public static IConfiguration Configuration = new ConfigurationBuilder()
              .SetBasePath(Directory.GetCurrentDirectory())
              .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
              .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", reloadOnChange: true, optional: true)
              .AddEnvironmentVariables()
              .Build();

    public static int Main(string[] args)
    {
        // serilog
        Log.Logger = new LoggerConfiguration()
                        .ReadFrom.Configuration(Configuration)
                        .Enrich.FromLogContext()
                        .CreateLogger();

        try
        {
            if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")))
                throw new Exception("Hosting environment variable not set");

            Log.Information($"Bootstrapping application: {_applicationName}");
            CreateWebHostBuilder(args).Build().Run();
            Log.Information($"Gracefully closing application: {_applicationName}");
            return 0; // returning a zero, indicates a successful shutdown.
        }
        catch (Exception e)
        {
            Log.Information($"Host {_applicationName} - terminated unexpectedly.", e);
            return 1; // returning a none-zero, indicates failure.
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseConfiguration(Configuration)
            .UseSerilog(); // overrides default logger
}
}

现在您可以在程序中的任何位置使用它,例如控制器

try 
{
   Log.Information("Testing the logs..");
}
catch (Exception e)
{      
   Log.Error("{@e}", e); // stack trace or other objects where {@e} is the object template.
   return BadRequest($"Rule violation: {e.Message}");
}

以及相应的配置(仅写入控制台):

"Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": { // overrides default logger from MS
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },  
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {SourceContext}>{NewLine}{Exception}"
        }
      }
    ]
  }

还有小部件:

    <PackageReference Include="Serilog" Version="2.9.0" />
    <PackageReference Include="Serilog.AspNetCore" Version="3.1.0" />
    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />

如果您确实想使用DI记录器,也许您应该看看Autofac DI框架? 希望它会有所帮助。