如何在 ASP.NET Core MVC 的自定义记录器中正确实现 ILogger.IsEnabled()

How to properly implement ILogger.IsEnabled() in custom logger in ASP.NET Core MVC

我(作为新手)实现了我自己的自定义记录器,用于 ASP.NET 核心 MVC 应用程序。我让这个记录器在各个方面都正常工作。但到目前为止我作弊了一点,即我实现了 ILogger.IsEnabled 方法如下:

public bool IsEnabled(LogLevel logLevel)
{
    return true;
}

在功能上,这工作正常,因为框架确保 Log() 方法仅在日志级别等于或高于指定级别时才被调用。因此,正在记录正确的“事物”,而未按预期记录较低级别的“事物”。

但是,我也想在我的代码中支持以下情况,其中 _logger 被键入为 ILogger 并正确地注入到我的控制器中:

if (_logger.IsEnabled(LogLevel.Debug))
{
    _logger.LogDebug("This is an expensive message to generate: " +
        JsonConvert.SerializeObject(request));
}

为了使其有效,我的 IsEnabled() 方法应该能够知道用我的 LoggerProvider 创建的记录器实例的日志级别是什么,但我不知道如何直接获取该信息,或者如何将其正确传递到我正在使用的记录器的注入实例。

我能找到的复杂示例和教程似乎在每种情况下都是针对控制台应用程序类型而不是网络应用程序类型构建的,到目前为止,我一直未能成功地弄清楚如何通过模板化 Startup class 在 ASP.NET MVC 中。

什么是停止在我的自定义 IsEnabled() 方法中作弊的最简单和最有效的方法,以避免不必要的序列化(在我的示例中)如果注入的注册记录器 none实例正在处理 Debug 日志级别?或者您在 ASP.NET 核心设置中有最喜欢的示例或教程可以指给我看吗?

您可以查看内置记录器 source code 并了解它们是如何实现的。

简而言之,他们只检查 logLevel != LogLevel.None,但根据记录器逻辑,您可能还想检查一些其他配置。例如,DebugLogger 记录器还检查 Debugger.IsAttached 属性 和 EventLogLogger 检查 EventLogSettings.Filter(通过构造函数提供)。

更新

To make this effective, my IsEnabled() method should be able to know what the log level IS for the instance of the logger that was created with my LoggerProvider, but I don't know how to get that information directly, or how to pass it properly to the injected instance of the the logger I am working with.

您可以创建 ILoggerProvider 的实现,它又可以利用依赖注入来获得您想要的配置。如果你想使用选项模式来配置它,你必须按照以下行做一些事情:

public class MyLoggerProvider : ILoggerProvider
{
    private readonly IOptions<MyLoggerOptions> _options;

    public MyLoggerProvider(IOptions<MyLoggerOptions> options)
    {
        _options = options;
    }

    public ILogger CreateLogger(string name)
    {
        return new MyLogger(name, _options.Value);
    }
}

并可选择添加扩展方法以简化注册:

public static class MyLoggerExtensions
{
    public static ILoggingBuilder AddMyLogger(this ILoggingBuilder builder, Action<MyLoggerOptions> configure)
    {
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, MyLoggerProvider>());
        LoggerProviderOptions.RegisterProviderOptions<MyLoggerOptions, MyLoggerProvider>(builder.Services);
        builder.Services.Configure(configure);
    }
}