Custom logger configurations overwritten by last configuration entry.

huangapple go评论61阅读模式
英文:

Custom logger configurations overwritten by last configuration entry

问题

目前,我有两种类型的自定义日志记录器,它们都有自己的配置部分、ILoggerProvider 和 ILogger 实现。然而,似乎存在一个问题,即我的配置范围在将它们添加到我们的 ILoggingBuilder 时被读取为最后一个配置。

Appsetting 配置设置将被提取:

{    
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        },
        "Logger1": {
            "LogLevel": {
                "Default": "Information"
            },
            "BenchmarkConfig": {
                "Enable": true,
                "LogThreshold": {
                    "Critical": "00:00:15",
                    "Information": "00:00:00"
                }
            }
        },
        "Logger2": {
            "LogLevel": {
                "Default": "Critical"
            }
        }
    }
}

这是我在其中添加它们的 DI 层:

protected override void LoggingHook(IServiceCollection services, IConfiguration configuration)
{
    base.LoggingHook(services, configuration);

    _ = services.AddLogging(config => _ = config.AddLogger1(configuration));
    _ = services.AddLogging(config => _ = config.AddLogger2(configuration));
}

Logger1

public static class Logger1Extensions
{
    public static ILoggingBuilder AddLogger1(this ILoggingBuilder builder, IConfiguration configuration)
    {
        var configurationSection = configuration.GetSection(Logger1.Section);
        _ = builder.AddConfiguration(configurationSection);

        builder.Services.AddTransient<InitializedLogMessage>();
        builder.Services.AddSingleton<ILogger1Config>(configurationSection.Get<Logger1Config>());
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, Logger1Provider>());
        return builder;
    }
}

public interface ILogger1Config
{
    LogLevel LogLevel { get; set; }
    Logger1BenchmarkConfig BenchmarkConfig { get; set; }
}

public class Logger1 : ILogger
{
    private readonly ILambdaLogger _lambdaLogger;
    private readonly ILogger1Config _loggerConfig;

    public const string Section = "Logging:Logger1";
    public const string SectionLogLevel = Section + ":LogLevel";
    public const string SectionLogLevelDefault = SectionLogLevel + ":Default";

    public Logger1(ILambdaLogger logger, ILogger1Config loggerConfig, InitializedLogMessage logMessage)
    {
        _lambdaLogger = logger;
        _loggerConfig = loggerConfig;
        LogMessage = logMessage;
    }

    private InitializedLogMessage LogMessage { get; }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        if (IsEnabled(logLevel))
        {
            _lambdaLogger?.LogLine($"{GetScopePrefix()}[{logLevel}] {formatter(state, exception)}");
        }
    }

    public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;
}

Logger2

public static class Logger2Extensions
{
  public static ILoggingBuilder AddLogger2Generic<T>(this ILoggingBuilder builder,
    IConfiguration configuration) where T : class, ILoggerProvider
  {
    IConfigurationSection section = configuration.GetSection("Logging:Logger2");
    builder.AddConfiguration((IConfiguration) section);
    builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, T>());
    return builder;
  }

  public static ILoggingBuilder AddLogger2(this ILoggingBuilder builder,
    IConfiguration configuration)
  {
    return builder.AddLogger2Generic<Logger2Provider>(configuration);
  }
}

public class Logger2 : ILogger
{
    private _rest { get; set; }

    public Logger2(IRest rest)
    {
      _rest = rest
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        if (IsEnabled(logLevel))
        {
            _rest.log()
        }
    }

    public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None;
}

如果我注释掉 Logger2Extensions.AddLogger2Generic 中的配置添加部分,那么 Logger1 中的一切都正常工作。但一旦将 Logger2 添加进来,它不仅会覆盖 Logger1 的配置,还会错误地读取日志级别。因为我正在使用来自 Microsoft 的日志级别枚举,所以它导致了默认的跟踪级别,因为它选择要转换为枚举的内容是无效的。

英文:

Currently, I have two types of custom loggers that both have their own configuration section, ILoggerProvider, and Ilogger implementation. However, it seems there is an issue with how my configuration scope is being read as the last configuration to be added during DI to our ILoggingBuilder.

Appsetting configuration settings that will get pulled

{    
    &quot;Logging&quot;: {
        &quot;LogLevel&quot;: {
            &quot;Default&quot;: &quot;Warning&quot;
        },
        &quot;Logger1&quot;: {
            &quot;LogLevel&quot;: {
                &quot;Default&quot;: &quot;Information&quot;
            },
            &quot;BenchmarkConfig&quot;: {
                &quot;Enable&quot;: true,
                &quot;LogThreshold&quot;: {
                    &quot;Critical&quot;: &quot;00:00:15&quot;,
                    &quot;Information&quot;: &quot;00:00:00&quot;
                }
            }
        },
        &quot;Logger2&quot;: {
            &quot;LogLevel&quot;: {
                &quot;Default&quot;: &quot;Critical&quot;
            }
        }
    }
}

This is the DI layer that I add them in

protected override void LoggingHook(IServiceCollection services, IConfiguration configuration)
{
    base.LoggingHook(services, configuration);

    _ = services.AddLogging(config =&gt; _ = config.AddLogger1(configuration));
    _ = services.AddLogging(config =&gt; _ = config.AddLogger2(configuration));
}

Logger1

public static class Logger1Extensions
{
    public static ILoggingBuilder AddLogger1(this ILoggingBuilder builder, IConfiguration configuration)
    {
        var configurationSection = configuration.GetSection(Logger1.Section);
        _ = builder.AddConfiguration(configurationSection);

        builder.Services.AddTransient&lt;InitializedLogMessage&gt;();
        builder.Services.AddSingleton&lt;ILogger1Config&gt;(configurationSection.Get&lt;Logger1Config&gt;());
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton&lt;ILoggerProvider, Logger1Provider&gt;());
        return builder;
    }
}


public interface ILogger1Config
{
    LogLevel                LogLevel        { get; set; }
    Logger1BenchmarkConfig  BenchmarkConfig { get; set; }
}

public class Logger1 : ILogger
{
    private readonly ILambdaLogger  _lambdaLogger;
    private readonly ILogger1Config _loggerConfig;

    public const string Section                = &quot;Logging:Logger1&quot;;
    public const string SectionLogLevel        = Section + &quot;:LogLevel&quot;;
    public const string SectionLogLevelDefault = SectionLogLevel + &quot;:Default&quot;;

    public Logger1(ILambdaLogger logger, ILogger1Config loggerConfig, InitializedLogMessage logMessage)
    {
        _lambdaLogger = logger;
        _loggerConfig = loggerConfig;
        LogMessage    = logMessage;
    }

    private InitializedLogMessage LogMessage { get; }

    public void Log&lt;TState&gt;(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func&lt;TState, Exception, string&gt; formatter)
    {
        if (IsEnabled(logLevel))
        {
            _lambdaLogger?.LogLine($&quot;{GetScopePrefix()}[{logLevel}] {formatter(state, exception)}&quot;);
        }
    }

    public bool IsEnabled(LogLevel logLevel) =&gt; logLevel != LogLevel.None;
}

Logger2

public static class Logger2Extensions
{
  public static ILoggingBuilder AddLogger2Generic&lt;T&gt;(this ILoggingBuilder builder,
    IConfiguration configuration) where T : class, ILoggerProvider
  {
    IConfigurationSection section = configuration.GetSection(&quot;Logging:Logger2&quot;);
    builder.AddConfiguration((IConfiguration) section);
    builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton&lt;ILoggerProvider, T&gt;());
    return builder;
  }

  public static ILoggingBuilder AddLogger2(this ILoggingBuilder builder,
    IConfiguration configuration)
  {
    return builder.AddLogger2Generic&lt;Logger2Provider&gt;(configuration);
  }
}

public class Logger2 : ILogger
{
    private _rest { get; set; }

    public Logger2(IRest rest)
    {
      _rest = rest
    }

    public void Log&lt;TState&gt;(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func&lt;TState, Exception, string&gt; formatter)
    {
        if (IsEnabled(logLevel))
        {
            _rest.log()
        }
    }

    public bool IsEnabled(LogLevel logLevel) =&gt; logLevel != LogLevel.None;

}

If I comment out adding the configuration inside the Logger2Extesions.AddLogger2Generic then everything in Logger1 works fine. But once Logger2 is added into the mix it not only overwrites the configuration for Logger1 but it also reads the log level incorrectly. Since I am using the loglevel enum from microsoft it results in a defaulted loglevel of trace since what it picks up to cast to the enum is invalid.

答案1

得分: 1

在你的 AddLogger1AddLogger2/AddLogger2Generic 方法中,你调用了 AddConfiguration 并提供了特定日志记录器的部分。 相反,你应该只调用 AddConfiguration 一次,仅一次,并提供 &quot;Logging&quot; 部分。 你还可以考虑在此之前调用 ClearProviders

尝试在添加其他日志记录器之前添加以下内容(并记得从这些方法中移除 AddConfiguration 调用):

services.AddLogging(config =&gt;
{
    _ = config.ClearProviders();
    _ = config.AddConfiguration(configuration.GetSection(&quot;Logging&quot;));
});
英文:

In your AddLogger1 and AddLogger2/AddLogger2Generic methods, you are calling AddConfiguration and providing the section for that specific logger. Instead, you should call AddConfiguration once, and only once, and provide the &quot;Logging&quot; section. You may also want to call ClearProviders beforehand.

Try adding this before you add the other loggers (and remember to remove the AddConfiguration calls from those other methods):

services.AddLogging(config =&gt;
{
    _ = config.ClearProviders();
    _ = config.AddConfiguration(configuration.GetSection(&quot;Logging&quot;));
});

huangapple
  • 本文由 发表于 2023年2月24日 06:25:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75550945.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定