Reputation: 1279
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
Reputation: 1279
I found an acceptable answer and I'll post it here, in case someone needs it.
Steps are:
ILoggerProvider
and your ILogger
. The examples on Microsoft's page are a good guide.ILoggerProvider
implementation accept the needed settings on its constructor (via IOptions<T>
or simple parameters; I'm using an options object called MyCustomLoggerSettings
).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