【问题标题】:Injecting existing logger in the Hosted Service在托管服务中注入现有记录器
【发布时间】:2021-08-26 11:32:11
【问题描述】:

我的项目在 .net core 3.1 中。我已配置为使用 SeriLog 作为记录器。

MqttComunicationClient 服务之一正在将记录器注入到使用 serilog 配置的构造函数中。这里ILoggerMicrosoft.Extensions.Logging

public MqttCommunicationClient(
            IMqttCommunicationConfiguration mqttConfiguration,
            ILogger logger,
            )
        {
            this.mqttConfiguration = mqttConfiguration;
            this.logger = logger;            
        }

通过这个类的Init 方法,我正在初始化自定义编写的MQTT API。

public void Initialize()
        {
            var mqttClientId = $"{DefaultClientIdPattern}{Environment.MachineName}";

            serviceHost = Host.CreateDefaultBuilder()
                  .UseMQTTApi(opt =>
                  {                          
                      opt.UserName = "test";
                      opt.Password = "test";
                  })
                  .ConfigureServices(services =>
                  {
                      services.AddSingleton(logger);                           
                  })
                  .ConfigureHostConfiguration(c => { c.Build(); })
                  .Start();

            managedMqttClient = serviceHost.Services.GetRequiredService<IManagedMqttClient>();
        }

我的 MQTT Api 具有将在收到指定主题的消息时触发的处理程序。

其中一个处理程序具有以下构造函数。

public ConnectionStatusHandler(
         ILogger<ConnectionStatus> logger,
         IDeviceCommunications deviceCommunications)         
        {
            this.logger = logger;
            this.deviceCommunications = deviceCommunications;
        }

现在问题是当我调试我的MqttComunicationClient 时,记录器被配置为SeriLog。根据要求和配置,该类中使用的logger.LogInformation() 正在记录到日志文件中。

ConnectionStatusHandler 被调用时,logger 更改为Microsoft.Extensions.Logging.Logger Logger。

ConnectionStatusHandler 类中使用的记录器仅记录到控制台而不是文件中。

如何将相同的 serilog 配置 logger 对象从 MqttComunicationClient 传递到 ConnectionStatusHandler ? 我需要一些额外的设置吗?我是新手,因此感谢您的帮助。

修改serilog 配置为记录器的代码

public IServiceProvider CreateServiceProvider(string basePath)
  {
     var configuration = GetConfiguration(basePath);
     
     var logger = CreateLogger(configuration);
     var services = new ServiceCollection();
     services.AddSingleton(logger);
     return services.BuildServiceProvider();
  }

protected virtual ILogger CreateLogger(IConfiguration configuration)
  {
     return LogBuilder.CreateLogger(null, configuration);
  }
  
// Serilog configured here
public static ILogger CreateLogger(string categoryName, IConfiguration configuration, Action<string> selfLogAction = null)
  {
     var serilogLogger = new LoggerConfiguration()
                           .ReadFrom.Configuration(configuration)
                           .CreateLogger();

     using (var serilogLoggerProvider = new SerilogLoggerProvider(serilogLogger))
     {
        var logger = serilogLoggerProvider.CreateLogger(categoryName);

        if (selfLogAction != null)
        {
           Serilog.Debugging.SelfLog.Enable(selfLogAction);
        }

        return logger;
     }
  } 

// This method reads the configuration from the config json file.
protected virtual IConfiguration GetConfiguration(string basePath)
  {
     StringBuilder configLog = null;
     var mainConfiguration = new ConfigurationBuilder()
        .SetBasePath(basePath)
        .AddJsonFile("mytest.config.json")
        .Build();
     var builder = new ConfigurationBuilder();
     return BuildConfiguration(builder, mainConfiguration, basePath, configLog)
        .Build();
  }
  

【问题讨论】:

  • 能否分享一下依赖注入设置代码(通常在 Startup.cs 文件中)?
  • @MohsinMehmood 我已经在 Edits 下添加了代码。此代码位于名为“BaseServiceProvider”的单独公共项目中。我们将其用于服务的通用配置。谢谢。
  • 两个独立的服务集合,因此使用了提供者。
  • 您能否在更简单的应用程序中重新创建此场景,以便我们可以看到更多您的应用程序?我有一些关于可能是什么的线索,但是实际查看代码而不只是脱离上下文的 sn-ps 会更有帮助
  • @DominikSzymański 是的,它的行为对于其他应用程序也是相同的。它使用我在上面发布的相同代码,没有任何改变。你能提示你猜的问题是什么吗?谢谢

标签: c# dependency-injection asp.net-core-3.1 serilog ilogger


【解决方案1】:

看起来您的代码当前正在设置对 ILogger(未键入)的请求以解析为 Serilog,但 Host.CreateDefaultBuilder() 正在设置 ILogger&lt;T&gt; 以使用 Microsoft 的 Logger。

我建议使用Serilog.Extensions.Hosting 来处理您的 Serilog 注册,这样您只需将UseSerilog() 添加到您的主机构建器即可完成。

【讨论】:

  • 感谢您的回复,但是如何在 UseSerilog() 中添加退出的 serilog 配置的 ILogger 对象?我想要相同的日志记录配置。
  • 这个包包括 3 个带有各种参数的签名。其中之一确实允许您pass in an ILogger。其他允许您使用Action&lt;HostBuilderContext, LoggerConfiguration&gt; configureLoggerAction&lt;HostBuilderContext, IServiceProvider, LoggerConfiguration&gt; 构建配置。您可以将此类操作放在中心位置。
  • 无论如何,Serilog Hosting 包通过将 Microsoft ILoggerFactory 替换为来自 Serilog.Extensions.LoggingSerilogLoggerFactory 来处理 ILogger/ILogger&lt;T&gt; 部分。这两个包的来源至少相对较小,可能值得花时间阅读它们
  • @Tim,UseSerilog 默认不配置ILogger,只配置ILogger&lt;T&gt;。但这只是一件小事,否则你的答案正是解决方案,我正在考虑它,但无法得到那个确切的部分(因为 Serilog 需要配置多个东西)。在提供该解决方案方面做得很好:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-09
  • 1970-01-01
  • 2020-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多