【问题标题】:How to use dependency injection in Serilog Sink?如何在 Serilog Sink 中使用依赖注入?
【发布时间】:2022-02-24 18:49:57
【问题描述】:

我关注这篇文章。 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 控制台应用程序。

更新:根据asnwer

现在,主程序是:

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 Test
{
    private readonly ILogger<Test> _logger;

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

更新:(2020-07-01)

现在,在 asp net core 中,这个 package 提供依赖注入。

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

【问题讨论】:

  • 为什么需要注入IHttpClientFactory?对于接收器,您只需传递配置选项,例如一个 URL 等,因为接收器会知道它需要创建什么,即一个 HttpClient,才能运行。如果您查看Elastic Search Sink 的代码,您可以看到它们传递了 URI,但接收器会自行创建客户端 - ElasticLowLevelClient
  • 在这种情况下,您可以在接收器中使用new HttpClientFactory() 并调用它来创建您的客户端吗?
  • 我不能新建 HttpClientFactory。 IHttpClientFactory由DefaultHttpClientFactory(DefaultHttpClientFactory)实现,是一个内部类。

标签: c# .net-core serilog


【解决方案1】:

我玩了一会儿,发现您可以在构建服务提供者后使用实现工厂来获取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 的工厂实现,仅在首次请求时创建记录器。这允许我们从服务提供者那里提取任何注册的服务并将它们注入到我们的类中。在这种情况下,我们获取IHttpClientFactory 并将其注入MySink

如果您在进入时将断点放在var logger = serviceProvider.GetService&lt;Serilog.ILogger&gt;() 行上,它将调用AddSingleton 中的lambda 并为您创建记录器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多