我的 .Net Core 应用程序中可以有两种不同类型的 ILogger 吗?

Posted

技术标签:

【中文标题】我的 .Net Core 应用程序中可以有两种不同类型的 ILogger 吗?【英文标题】:Can I have two different kinds of ILoggers in my .Net Core application? 【发布时间】:2021-09-06 15:51:11 【问题描述】:

我的应用程序有一部分只想登录到 EventLog。其余时间,我想登录到为我的ILoggers 设置的所有正常事件接收器。

我可以通过这样做在这些部分制作 ILogger:

var eventLogLoggerProvider = new Microsoft.Extensions.Logging.EventLog.EventLogLoggerProvider();
var eventLogger = eventLogLoggerProvider.CreateLogger("EventLogger");
eventLogger.LogWarning("We logged to the event log!");

但我觉得我应该通过依赖注入来做到这一点。但所有示例都只是显示为整个应用程序设置一次。

有没有办法将 ASP.Net Core 3.1 应用程序配置为具有两种不同类型的 ILogger?(并允许将其中一种注入到一个类中?)

【问题讨论】:

您的意思是像“将跟踪级别记录到控制台,将警告级别记录到 EventLog 并将错误级别记录到某些外部服务,这些服务会 ping 技术团队的手机”?可以使用为不同级别配置的一个记录器来完成.. 任何你可以用 new 做的事情,你可以用 DI 做,如果你可以教容器知道区别(比如有两个实现 ilogger 的类) - DI 不是魔法,它只是看着构造函数签名,然后“哦。这个构造函数想要一个 ConsoleLogger 而不是 ILogger,我已经注册了其中一个,给你”,在其他一些场景中发送一些其他注册的 impl;只需制作另一种类型的记录器并以 DI 可以判断使用哪个以及何时使用的方式注册它 在启动时检查环境并相应地注册不同的记录器会更简单吗? 【参考方案1】:

有多种选择供您选择。但是,它们都不会特别好。 .NET Extensions DI 有点简单,而您的方案似乎相当先进。

直接使用EventLog

如果您如此拘泥于在应用程序的特定位置使用 EventLog,那么直接使用它可能是有意义的,因为 ILogger 抽象基本上与您的要求相反。

有了ILogger 依赖,你说的是“给我一个记录器,不管它是什么,我不在乎”。但你确实在乎。那么为什么不直接使用EventLog呢?或者可能将其隐藏在接口和适配器后面以实现可测试性并将其注入。

日志配置

另外,如果您通过 appsettings.json 配置日志记录,则您会遇到更少的摩擦,以便 EventLog 具有默认的 LogLevel = None 和 LogLevel = Information 或任何您喜欢的事件记录程序集/命名空间。并且其余记录器对于事件记录区域具有 None LogLevel。例如:


  "Logging": 
    "LogLevel": 
      "Default": "Information",
      "My.EventLogged.Assembly": "None"
    ,
    "EventLog": 
        "Default": "None",
        "My.EventLogged.Assembly": "Information"
    
  

如果您将代码隔离到一个程序集或几个命名空间中,这会很好地工作,但很容易添加另一个您只需要事件日志的地方而忘记对其进行配置。

有关详细信息,请参阅 Logging in .NET Core and ASP.NET Core, Configuration section.

提供额外的上下文

如果您只需要事件日志记录的区域很容易分离,您可以提供一个具有单例生命周期的外观,它将创建一个单独的 IServiceCollection/IServicePrivoder,其中事件日志是该容器中唯一注册的 ILogger。

对事件记录代码的任何调用都应通过外观,该外观将使用内部 IServiceProvider 调用预期的实现。如果您需要从事件记录代码调用应用程序的其余部分,则需要执行相反的操作。

这并不简单,但即使 ASP.NET Core 本身也这样做(或至少这样做)是为了在服务初始化尚未完成时在启动期间提供日志记录。

但它肯定有令人惊讶的元素,并且可能会导致调试和诊断服务设置时有些头疼。设置中也会有重复。我确实认为这不是一个值得的方法。

使用不同的 IoC 容器

autofac 或 castle 等其他容器可能能够基于使用名称的实例标识来解析多个服务(在本例中为 ILogger)。参见例如AutoFac FAQ: How do I pick service implementation by context.

但是,我无法建议如何使用 ILogger 来执行此操作,因为日志记录注册相当复杂。

这些只是我能想到的一些方向。对于您的要求,我认为没有简单、规范的答案,您必须根据您的具体需求和情况进一步研究这些选项。

【讨论】:

在日志配置中可以指定一个过滤器,它只会在发送特定类别的消息时导致事件日志记录器记录。我认为这最接近预期结果

以上是关于我的 .Net Core 应用程序中可以有两种不同类型的 ILogger 吗?的主要内容,如果未能解决你的问题,请参考以下文章

启动时在 Linux 下运行 ASP.NET Core 应用程序

Asp.Net Core 入门—— ModelViewController

ASP.NET Core AWS Cognito JWT

在.Net Core中使用HttpClient添加证书

.Net Core in Docker

ASP.NET Core MVC 数据库重定向后不添加对象