Reputation: 646
I have an extension method to configure my logger:
public static class Extensions
{
public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder) =>
webHostBuilder.UseSerilog((context, loggerConfiguration) =>
{
var logLevel = context.Configuration.GetValue<string>("Serilog:MinimumLevel");
if (!Enum.TryParse<LogEventLevel>(logLevel, true, out var level))
{
level = LogEventLevel.Information;
}
loggerConfiguration.Enrich
.FromLogContext()
.MinimumLevel.Is(level);
loggerConfiguration
.ReadFrom.Configuration(context.Configuration)
.WriteTo.Console(
theme: AnsiConsoleTheme.Code,
outputTemplate: "[{Timestamp:yy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}");
});
}
I add this line .ReadFrom.Configuration(context.Configuration)
and expect that all settings from appsettings.json will override current configuration. I mean if I specify in appsettings.json other outputTemplate then it will override the existing one.
"Serilog": {
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}"
}
}
]
}
but it doesn't work. Now the log messages are duplicated, one with formatting from code and another from config. How can I override the some settings from appsettings.json at runtime?
[03:59:09 INF] event processor service is starting.
[19-04-19 00:59:09 INF] event processor service is starting.
I have extension method that I use in services, but sometimes I need override some setting in appsettings.json (or env variables) how can I do that? because current solution didn't work and adds second logger
Upvotes: 3
Views: 4557
Reputation: 149
You basically have to check if the config already specifies a console logger. The field that stores the sinks is private. So you have to use something like that to react to the config. When you want to overwrite some properties on the logger you also need to use reflection to access those fields. The code below works for my simple test application.
public static class Extensions
{
public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder) =>
webHostBuilder.UseSerilog((context, loggerConfiguration) =>
{
var logLevel = context.Configuration.GetValue<string>("Serilog:MinimumLevel");
if (!Enum.TryParse<LogEventLevel>(logLevel, true, out var level))
{
level = LogEventLevel.Information;
}
loggerConfiguration.Enrich
.FromLogContext()
.MinimumLevel.Is(level);
loggerConfiguration
.ReadFrom.Configuration(context.Configuration);
// Get the field that holds the sinks.
var sinks = loggerConfiguration.GetType()
.GetField("_logEventSinks", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(loggerConfiguration) as List<ILogEventSink>;
// Get the sink type for reusage.
var sinkType = typeof(AnsiConsoleTheme).Assembly.GetType("Serilog.Sinks.SystemConsole.ConsoleSink");
// Find the first sink of the right type.
var sink = sinks?.FirstOrDefault(s => sinkType == s.GetType());
// Check if a sink was found.
if (sink == null)
{
// No sink found add a new one.
loggerConfiguration
.WriteTo.Console(
theme: AnsiConsoleTheme.Code,
outputTemplate:
"[{Timestamp:yy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}");
}
else
{
// Otherwise change the theme.
sinkType.GetField("_theme", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(sink, AnsiConsoleTheme.Code);
}
});
}
Upvotes: 3