.Net Core 3.1 将 Serilog 与 Microsoft.Extensions.Logger 结合使用

.Net Core 3.1 Using Serilog with Microsoft.Extensions.Logger

在这个应用程序中,我引入并设置了 Serilog,它适用于异常情况,我想将 Microsoft 的 Logger 与 Serilog 一起使用,但我似乎无法弄清楚如何在没有它的情况下将其 DI 到服务中dotnet build.

期间出错

我不确定让 ILogger 使用 Serilog 实例缺少什么?

dotnet build 错误:

[13:56:21 FTL] Host terminated unexpectedly
System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'App.Services.MyService'.) 

服务中的依赖注入:

using Microsoft.Extensions.Logging;

public class MyService : BaseService
{
    private readonly ILogger _logger;

    public MyService(
        ILogger logger)
        : base(context, httpContext)
    {
        _logger = logger;
    }
    
    // ... Removed for brevity
}

实施

public static int Main(string[] args)
{
    CreateLogger();

    try
    {
        Log.Information("Starting web host");
        CreateHostBuilder(args)
            .Build()
            .Run();
        return 0;
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "Host terminated unexpectedly");
        return 1;
    }
    finally
    {
        // Ensure buffered logs are written to their target sink
        Log.CloseAndFlush();
    }
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>())
        .UseSerilog();

private static void CreateLogger()
{
    string path = PrimeConstants.LOG_FILE_PATH;

    try
    {
        if (isDevelopment())
        {
            Directory.CreateDirectory(path);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Creating the logging directory failed: {0}", e.ToString());
    }

    var name = Assembly.GetExecutingAssembly().GetName();
    var outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}";

    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Information()
        .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
        .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
        .MinimumLevel.Override("System", LogEventLevel.Warning)
        .Enrich.FromLogContext()
        .Enrich.WithMachineName()
        .Enrich.WithProperty("Assembly", $"{name.Name}")
        .Enrich.WithProperty("Version", $"{name.Version}")
        .WriteTo.Console(
            outputTemplate: outputTemplate,
            theme: AnsiConsoleTheme.Code)
        .WriteTo.Async(a => a.File(
            $@"{path}/prime.log",
            outputTemplate: outputTemplate,
            rollingInterval: RollingInterval.Day,
            shared: true))
        .WriteTo.Async(a => a.File(
            new JsonFormatter(),
            $@"{path}/prime.json",
            rollingInterval: RollingInterval.Day))
        .CreateLogger();
}

ILogger 不可用于 DI。您可以使用以下方法之一:

  1. 注入ILogger<TCategoryName>:

     public class MyService : BaseService
     {
         private readonly ILogger _logger;
    
         public MyService(ILogger<MyService> logger)
             : base(context, httpContext)
         {
             _logger = logger;
         }
    
         // ...
     }
    
  2. 注入ILoggerFactory并使用它的CreateLogger方法:

     public class MyService : BaseService
     {
         private readonly ILogger _logger;
    
         public MyService(ILoggerFactory loggerFactory)
             : base(context, httpContext)
         {
             _logger = loggerFactory.CreateLogger("<YOUR_CATEGORY_NAME>");
         }
    
         // ...
     }
    

我推荐选项 #1,除非您想完全控制日志类别。请参阅 docs 以了解有关其含义的更多信息:

That category is included with each log message created by that instance of ILogger.