Reputation: 46322
In My .net core 6 console app I create a host builder
var builder = Host.CreateDefaultBuilder(args);
This gives me a HostBuilder instance with a logging factory set up for console, debug, event log, and event source providers, as well as configuration providers for user/system environment vars, appsettings.json, appsettings..json, etc.
I can inject ILogger or ILoggingFactory into my class and write to all the logging providers using the ILogger.Log function.
public class BusinessLogic
{
private IHostEnvironment _env;
private ILogger _logger;
public BusinessLogic(
IHostEnvironment env,
ILoggerFactory loggerFactor)
{
_env = env;
_logger = loggerFactor.CreateLogger<BusinessLogic>();
}
public void Run()
{
foreach (var level in Enum.GetValues<LogLevel>())
{
_logger.Log(level, $"Test logging at level {level}.");
}
Console.WriteLine("Hello, World! Press any key...");
Console.ReadLine();
}
}
Now I want to configure the event log application name and source name that the event log provider will write to. I'd rather not hard code this, so I was hoping to do this throught he appsettings.json file. I can't seem to get it to take affect. My appsettings.json file looks like this:
{
"Logging":
{
//Settings for the windows event log logging provider
"EventLog":
{
"LogName": "Application",
"SourceName": "MySource",
"LogLevel":
{
"Default": "Trace"
}
}
}
}
The above appsettings has no affect, so I thought I would try adding a new EventLog provider and pass it the configuration.
var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureAppConfiguration((context, builder) =>
{
var eventLogConfiguration = context.Configuration.GetSection("Logging:EventLog").Get<EventLogSettings>();
builder.AddEventLog(eventLogConfiguration);
});
That didn't work either, so I tried clearing the logging providers, in case adding duplicates was an issue.
var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureAppConfiguration((context, builder) =>
{
builder.ClearProviders();
var eventLogConfiguration = context.Configuration.GetSection("Logging:EventLog").Get<EventLogSettings>();
builder.AddEventLog(eventLogConfiguration);
});
That works, but what if I want all the other existing providers to be retained? Can I just replace one, or somehow apply the configuration to an existing provider, or is there some other/better way to do this?
Upvotes: 2
Views: 2480
Reputation: 155622
If you look at the source for CreateDefaultBuilder
it appears to already do all this:
// HostingHostBuilderExtensions.cs > AddDefaultServices
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
...
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
...
if (isWindows)
// Add the EventLogLoggerProvider on windows machines
logging.AddEventLog();
Given that AddConfiguration
call you shouldn't need GetSection("Logging:EventLog")
.
Given that AddEventLog
call you shouldn't need to call it again.
As it only works when you call ClearProviders()
first I think CreateDefaultBuilder
must be misconfiguring the event log somehow.
But, if that were the case GetSection("Logging:EventLog")
would fail or you'd see an error (as happens if you use AddEventLog
with an unrecognised source or log name).
I wonder if something in Logging
that isn't in Logging:EventLog
could be the problem?
I'm having a similar issue, but I don't have to call ClearProviders()
- adding AddEventLog
is enough for me, but that doesn't pick up anything from appsettings.json
unless I add it explicitly.
I think this might be a bug (or possibly LogName
and SourceName
just aren't supported from config). I have a workaround for now.
Basically, I manually set the config (like you), but with an OS check that code analysis understands and with the lambda that alters the config rather than applying it again.
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
public static void SetEventLogConfig(WebApplicationBuilder builder) {
string? eventLog = builder.Configuration["Logging:EventLog:SourceName"];
if(eventLog is not null)
builder.Logging.AddEventLog(c => c.SourceName = eventLog);
}
// then in program.cs
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
SetEventLogConfig(builder);
That works for my app, but I'm still not sure why you need to call ClearProviders
in your implementation.
Upvotes: 1