如何在 Serilog Sink 中使用依赖注入?

How to use dependency injection in Serilog Sink?

我关注这篇文章。 Developing a sink

但是我需要注入IHttpClientFactory.

public class MySink : ILogEventSink
{
    //...

    public MySink(IFormatProvider formatProvider, IHttpClientFactory httpClientFactory)
    {
        //...
    }
}

public static class MySinkExtensions
{
    public static LoggerConfiguration MySink(
        this LoggerSinkConfiguration loggerConfiguration, 
        IHttpClientFactory httpClientFactory, 
        IFormatProvider formatProvider = null,
        LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose)
    {
        return loggerConfiguration.Sink(new MySink(formatProvider, httpClientFactory), restrictedToMinimumLevel);
    }
}

主程序:

class Program
{
    static async Task Main(string[] args)
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddHttpClient();

        var logger = new LoggerConfiguration()
            .ReadFrom.Configuration(configuration)
            .WriteTo.MySink(null) //<--How to get IHttpClientFactory?
            .CreateLogger();

        services.AddLogging(configure => configure.ClearProviders().AddSerilog(logger));

        var serviceProvider = services.BuildServiceProvider();
    }
}

应用程序设置:

{
"Serilog": {
    "Using": [ "Serilog.Sinks.Console", "MyTestProject" ],
    "WriteTo": [
        {
            "Name": "Console",
            "Args": {
                "restrictedToMinimumLevel": "Debug"
            }
        },
        {
            "Name": "MySink",
            "Args": {
                "restrictedToMinimumLevel": "Warning"
            }
        }
    ]
}

我可以使用 Args 注入 IHttpClientFactory 吗?

或者在 Main 方法中处理?

注意:我使用的是 net core 控制台应用程序。

更新: 根据

现在,主要程序是:

class Program
    {
        static async Task Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();
            serviceCollection.AddHttpClient();

            serviceCollection.AddSingleton<Serilog.ILogger>(sp =>
            {
                var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>();

                return new LoggerConfiguration()
                    .MinimumLevel.Debug()
                    .WriteTo.MySink(httpClientFactory)
                    .CreateLogger();
            });

            serviceCollection.AddLogging(configure => configure.ClearProviders().AddSerilog());

            var serviceProvider = serviceCollection.BuildServiceProvider();

            Log.Logger = serviceProvider.GetRequiredService<Serilog.ILogger>();
        }
    }

而且我可以在其他地方注入 ILogger class

class Test
{
    private readonly ILogger<Test> _logger;

    Test(ILogger<Test> logger)
    {
        _logger = logger;
    }
}

更新: (2020-07-01)

现在,在 asp 网络核心中,这个 package 提供依赖注入。

.UseSerilog((hostingContext, services, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext()
.WriteTo.SomeSink(services.GetRequiredService<ISomeDependency>()));

我试了一下,发现您可以在构建服务提供者后使用实现工厂来获取 IHttpClientFactory。您需要更改 service.AddLogging(...) 调用以使用此工厂实现:

static async Task Main(string[] args)
{
    var serviceCollection = new ServiceCollection();
    serviceCollection.AddHttpClient();

    serviceCollection.AddSingleton<Serilog.ILogger>(sp =>
    {
        var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>();

        return new LoggerConfiguration()
            .MinimumLevel.Debug()
            //.ReadFrom.Configuration(Configuration)
            .WriteTo.MySink(httpClientFactory)
            .CreateLogger();
    });

    serviceCollection.AddLogging(cfg =>
    {
        cfg.ClearProviders().AddSerilog();
    });


    var serviceProvider = serviceCollection.BuildServiceProvider();


    var logger = serviceProvider.GetService<Serilog.ILogger>();

    logger.Debug("Working");
}

在代码示例中,我们可以使用 AddSingleton 的工厂实现来仅在首次请求时创建记录器。这使我们能够从服务提供商那里提取任何已注册的服务并将它们注入我们的 class。在这种情况下,我们得到 IHttpClientFactory 并将其注入 MySink.

如果您在行 var logger = serviceProvider.GetService<Serilog.ILogger>() 上放置一个断点,当您进入该行时,它将调用 AddSingleton 中的 lambda 并为您创建记录器。