Как использовать Microsoft.Extensions.Logging в .NET Core 3.0 Worker Service - PullRequest
0 голосов
/ 30 октября 2019

Я запустил новый проект службы Windows и решил использовать шаблон .NET Core 3.0 Worker Service. Этот сервис никогда не будет использоваться в облачном / веб-проекте, но есть шанс, что в какой-то момент я захочу настроить его для работы в Linux.

Я хорошо знаком с использованием NLog для ведения журналов. Модель создания нового объекта статического регистратора в каждом классе очень интуитивно понятна. Я вижу, что Worker Service имеет встроенную инфраструктуру Microsoft.Extensions.Logging, так что работнику по умолчанию передается ILogger<Worker>. Это отлично подходит для "моей первой службы", но как насчет настоящей долго работающей службы смного классов, каждый из которых требует регистрации?

Все учебники, которые я найду для этого шаблона, касаются сервисов, которые выполняют всю работу и регистрируются в классе Worker. По историческим причинам в большинстве статей о ведении журнала рассматривается только ядро ​​ASP.NET, в котором DI является приоритетом. Я не нашел описания того, как создать приложение с деревом из нескольких долгоживущих классов, каждый из которых имеет свой собственный объект ILogger для записи.

Несмотря на то, что мне никогда не понадобится DI в этом проекте, кажется, что это может быть хорошим стандартом для использования в моей кодовой базе, первоначально подключив его к провайдеру NLog. Я мог бы взять IHostBuilder в моем Main, а затем добавить статическую функцию для создания логгеров из ILoggingBuilder аналогично NLog, но я не могу поверить, что это лучший способ.

Есть ли здесь признанная лучшая практика? Включает ли это удаление какой-то магии из шаблона Worker Service?

Ответы [ 2 ]

2 голосов
/ 30 октября 2019

NLog отлично работает в .Net Core без помощи внедрения зависимостей. Вы просто делаете, как всегда:

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

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

Но NLog также может интегрироваться с журналом расширений Microsoft (MEL) с помощью Microsoft Dependency Injection. Вам просто нужно зарегистрировать NLog LoggingProvider , и тогда вход MEL-ILogger будет перенаправлен на NLog.

В IHostBuilder.ConfigureLogging, тогда можно позвонить AddNLog() (Точно так же, как можно позвонить AddDebug() или AddConsole() для встроенных MEL-LoggingProviders)

Простой пример этого можно найти на вики-странице (также при необходимости имеется ссылка на ASP.NET Core):

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

Некоторым людям не нравится, что MEL-ILogger должен вводиться через конструктор классов даже для простых классов (слишком много беспорядка). Вместо этого они просто используют NLog.LogManager.GetCurrentClassLogger() напрямую.

0 голосов
/ 30 октября 2019

Может быть, стоит взглянуть на Serilog https://serilog.net/? Serilog очень гибок, и вы можете добавить различные варианты приемников, например: console, file ,asticsearch, seq, другие ... И вы неЯ должен DI повсюду.

Вот так я использую его для печати на консоль (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? Надеюсь, это поможет.

...