I am trying to use the EventId property in the output template for a console sink. When I add the event id using Serilog.Context.LogContext.PushProperty, it appears in the context as a Serilog.Events.ScalarValue. When I add the event id using the Microsoft.Extensions.Logging.ILogger.LogInformation overload that accepts an event id as the first parameter, it appears in the context as a Serilog.Events.StructureValue.
The following MRE produces the behavior:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Context;
internal class Program
{
private readonly Microsoft.Extensions.Logging.ILogger logger;
public Program(ILogger<Program> logger) => this.logger = logger;
static void Main()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.Enrich.FromLogContext()
.WriteTo.Console(
outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.ffff}] [{Level}] [{EventId}] {Message:l}{NewLine}{Exception}")
.WriteTo.EventLog(
nameof(SerilogRepro),
manageEventSource: true)
.CreateLogger();
var servicesProvider = new ServiceCollection()
.AddSingleton<Program>()
.AddLogging(logging => logging.AddSerilog())
.BuildServiceProvider();
var program = servicesProvider.GetRequiredService<Program>();
program.Run();
Log.CloseAndFlush();
}
public void Run()
{
using (LogContext.PushProperty("EventId", 42))
{
Log.Information("EventId added using Serilog.Context.LogContext.");
}
this.logger.LogInformation(52, "EventId added using Microsoft.Extensions.Logging.");
}
}
The resulting console output is as follows:
[2022-08-21 16:19:38.8027] [Information] [42] EventId added using Serilog.Context.LogContext.
[2022-08-21 16:19:38.9256] [Information] [{ Id: 52 }] EventId added using Microsoft.Extensions.Logging.
Since the EventId is a structure and not a scalar value when using Microsoft.Extensions.Logging, it is rendered incorrectly.
In my actual configuration, I use a custom event id provider with the event log sink that distinguishes the two types and applies the correct value. However, the console sink obviously does not facilitate this.
I need to be able to support calls to both libraries, what is the optimal approach for this case?