Léster
Léster

Reputation: 1279

How to inject settings from appsettings.json to an ILoggerProvider?

I'm implementing a custom ILogger<T> due to some special requirements, and one of those requirements is to have a section, inside the Logging section in the project's appsettings.json, with configuration values for that logger. Question is, what's the right way (or a good way) to inject those settings in the logger? I presume I should start by injecting those settings in the corresponding ILoggerProvider and have the provider instantiate a logger with those settings, but I'm stumped on how to properly inject those values in the provider.

So far I have this in Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureLogging((context, logging) =>
                {
                    logging.ClearProviders();
                    logging.AddConfiguration(context.Configuration.GetSection("Logging"));
                    logging.AddConsole();
                    logging.AddProvider(new CustomLoggerProvider());
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

, the relevant section in appsettings.json is:

"Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "CustomLogger": {
      "Level": "Error",
      "Url": "http://[URL]"
    }
  },

, and the provider implementation is as follows:

[ProviderAlias("CustomLogger")]
    public class CustomLoggerProvider : ILoggerProvider
    {
        private readonly Dictionary<string, CustomLogger> _loggers;
        private readonly LogLevel _level;
        
        private bool _already_disposed;

        public LogLevel Level
        {
            get => _level;
        }

        public CustomLoggerProvider()
        {
            //Here's where I don't know what should I do to inject the proper config values
            _level = LogLevel.Error;
        }

        public ILogger CreateLogger(string categoryName)
        {
            if (_loggers.ContainsKey(categoryName))
            {
                return _loggers[categoryName];
            }
            var l = new CustomLogger(this);
            _loggers.Add(categoryName, l);
            return l;
        }

        // Rest of implementation omitted for simplicity
    }

Upvotes: 0

Views: 864

Answers (1)

L&#233;ster
L&#233;ster

Reputation: 1279

I found an acceptable answer and I'll post it here, in case someone needs it.

Steps are:

  • Implement your ILoggerProvider and your ILogger. The examples on Microsoft's page are a good guide.
  • Have your ILoggerProvider implementation accept the needed settings on its constructor (via IOptions<T> or simple parameters; I'm using an options object called MyCustomLoggerSettings).
  • Register your ILoggerProvider in Startup.ConfigureServices() as a singleton, like this (let's say my implementation is called MyCustomLoggerProvider):
services.AddSingleton<ILoggerProvider>(p =>
{
    var options = p.GetService<IOptions<MyCustomLoggerSettings>>();
    return new MyCustomLoggerProvider(options);
});

Done.

As a bonus, in this way you can pass any other dependencies to this object (including objects registered on the service collection; the use of method overloads in services that accept an anonymous function give you the service collection as a parameter, and there you can use GetService<T> to resolve any dependencies.

Upvotes: 1

Related Questions