如何在C#中将serilog记录器添加到GenericHost项目

M.H*_*adi 5 c# serilog .net-core

我在项目中使用通用宿主模式。我需要一个记录器来专门归档Serilog之类的滚动文件。如何将其添加到主机构建器的某些记录器配置中。

在通用主机中,我们可以添加日志配置,例如调试器和控制台。但是我想使用记录器来归档特定选项。我不知道该怎么做。

最佳做法是哪种?

Bri*_*ana 8

这是另一个例子,我希望这能为有需要的人提供一个完整的例子:

  • .NET 7 控制台应用程序
  • 带有顶级语句的 Microsoft Generic Host
  • 使用 Bootstrap Logger 捕获启动异常
  • 从 IConfiguration 加载记录器

程序.cs

using ConsoleUI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Core;
using Serilog.Events;

Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Override("Default", LogEventLevel.Debug)
            .Enrich.FromLogContext()
            .WriteTo.Console()
            .CreateBootstrapLogger();

try
{
    HostApplicationBuilder builder = Host.CreateApplicationBuilder();
    
    builder.Services.AddLogging(config =>
    {
        config.ClearProviders();

        Logger logger = new LoggerConfiguration()
            .ReadFrom.Configuration(builder.Configuration)
            .CreateLogger();

        config.AddSerilog(logger);
    });

    builder.Services.AddHostedService<App>();
    IHost app = builder.Build();
    app.Run();
}
catch (Exception ex)
{
    Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
    Log.CloseAndFlush();
}
Run Code Online (Sandbox Code Playgroud)

应用程序设置.json

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "System": "Information",
        "Microsoft": "Information",
        "Microsoft.AspNetCore": "Information",
        "Microsoft.EntityFrameworkCore": "Information",
        "Azure": "Information"
      }
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}|{Level:u3}|{SourceContext}|{Message:lj}{NewLine}{Exception}"
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/ConsoleUI-.log",
          "rollingInterval": "Day",
          "retainedFileCountLimit": 15,
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}|{Level:u3}|{SourceContext}|{Message:lj}{NewLine}{Exception}"
        }
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName" ],
    "Properties": {
      "Application": "ConsoleUI"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

应用程序.cs

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace ConsoleUI;

public class App : IHostedService
{
    private readonly IHostApplicationLifetime _hostApplicationLifetime;
    private readonly IConfiguration _config;
    private readonly ILogger<App> _logger;

    public App(IHostApplicationLifetime hostApplicationLifetime,
               IConfiguration configuration,
               ILogger<App> logger)
    {
        _hostApplicationLifetime = hostApplicationLifetime;
        _config = configuration;
        _logger = logger;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _hostApplicationLifetime.ApplicationStarted.Register(async () =>
        {
            try
            {
                await Task.Yield(); // https://github.com/dotnet/runtime/issues/36063
                await Task.Delay(1000); // Additional delay for Microsoft.Hosting.Lifetime messages
                await ExecuteAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Unhandled exception!");
            }
            finally
            {
                _hostApplicationLifetime.StopApplication();
            }
        });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    public async Task ExecuteAsync()
    {
        _logger.LogTrace("Hello, Trace!");
        _logger.LogDebug("Hello, Debug!");
        _logger.LogInformation("Hello, World!");
        _logger.LogWarning("Hello, Warning!");
        _logger.LogError("Hello, Error!");
        _logger.LogCritical("Hello, Critical!");

        await Task.Delay(1);
    }
}
Run Code Online (Sandbox Code Playgroud)

Nuget 包 在此输入图像描述

输出 在此输入图像描述


Nic*_*rdt 5

您需要Serilog.Extensions.Hosting

public static IHost BuildHost(string[] args) =>
    new HostBuilder()
        .UseSerilog() // <- Add this line
        .Build();
Run Code Online (Sandbox Code Playgroud)


M.H*_*adi 5

感谢这两个答案,我需要同时使用Serilog.Extensions.HostingSerilog.Sinks.RollingFile。然后它需要创建一个记录器对象,以便将其添加到主机构建器中,如下所示:

var logger = new LoggerConfiguration().WriteTo.RollingFile(
                outputTemplate: outputTemplate,
                restrictedToMinimumLevel: LogEventLevel.Information,
                pathFormat: Path.Combine(loggingDirectory, "systemlog-{Date}.text")
            .CreateLogger();
Run Code Online (Sandbox Code Playgroud)

请注意,pathFormat参数是有用且重要的。它由路径和格式组成,在Serilog.Sinks.RollingFile(文件名格式说明符)中进行了充分描述。这里我在路径后使用 {Date} 格式,这意味着:它每天创建一个文件。Filenames使用 yyyyMMdd 格式。

使用这样的配置创建记录器后,需要HostBuilder像这样添加它:

var host = new HostBuilder()
            .ConfigureLogging((context, builder) =>
            {
                builder.AddConsole();
                builder.AddSerilog(logger);
                //....<- some other option here
            })
            .Build();
Run Code Online (Sandbox Code Playgroud)