Search code examples
c#asp.net-coreblazor-server-sideiloggeriloggerfactory

Trying to get appSettings.json settings in an ILogger provider


The ILogger provider I created runs fine. But I have two problems:

  1. The appSettings.json are not passed in to the provider constructor.
  2. The logging system ignores the appSettings.json set specifically for my provider.

appSettings.json:

"Logging": {
    "LogLevel": {
        "Default": "Warning",
        "LouisHowe": "Information",
        "ThirdPartyServices": "Information",
        "CommonUtilities": "Information",
        "Microsoft": "Warning"
    },

    "File": {
        "Path": "C:/temp/log-{yyyy-MM-dd}.txt",
        "Interval": "Day",
        "LogLevel": {
            "Default": "Information",
            "LouisHowe": "Trace",
            "Microsoft": "Warning"
        }
    },

The options classes:

public class FileLoggerOptions
{
    public string? Path { get; set; } = "";
    public string? Interval { get; set; } = "";
}

internal class FileLoggerOptionsSetup : ConfigureFromConfigurationOptions<FileLoggerOptions>
{
    public FileLoggerOptionsSetup(ILoggerProviderConfiguration<FileLoggerProvider> providerConfiguration)
        : base(providerConfiguration.Configuration)
    {
    }
}

The provider constructors:

public FileLoggerProvider(IOptionsMonitor<FileLoggerOptions> options)
    : this(options.CurrentValue)
{
    _settingsChangeToken = options.OnChange(opt => { _options = opt; });
}

public FileLoggerProvider(FileLoggerOptions options)
{
    options.Path = "C:/temp/log-{yyyy-MM-dd}.txt";
    _options = options;
}

And how it is added in Program.cs:

public static ILoggingBuilder AddFileLogger(this ILoggingBuilder builder)
{
    builder.AddConfiguration();

    builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, 
        FileLoggerProvider>());
    builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<FileLoggerOptions>, 
        FileLoggerOptionsSetup>());
    builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IOptionsChangeTokenSource<FileLoggerOptions>, 
        LoggerProviderOptionsChangeTokenSource<FileLoggerOptions, FileLoggerProvider>>());
    return builder;
}

I can do the following to get the configuration. But I want to understand why the above doesn't work. And the following does not get it to use the LogLevels set under File.

public FileLoggerProvider(IConfiguration config)
{
    _options = config.GetSection("Logging:File").Get<FileLoggerOptions>();
}

Solution

  • Found the solution. So simple, once you know what it is. Need the following attribute:

    [ProviderAlias("File")]
    public class FileLoggerProvider : ILoggerProvider, IAsyncDisposable
    

    And that makes sense. It needs to know what I named it in appSettings.json. With that added, it all works as expected.