I wish to use formatted UTC timestamps in my Serilog output. I have written a custom enricher that works fine when called from C# code.
public class UtcTimestampEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
{
logEvent.AddPropertyIfAbsent(pf.CreateProperty("UtcTimestamp", logEvent.Timestamp.UtcDateTime));
}
}
....
var loggerConfig = new LoggerConfiguration().MinimumLevel.Debug()
.Enrich.FromLogContext()
.Enrich.With(new UtcTimestampEnricher())
.Filter
.ByIncludingOnly( expr) // need this .Filter to ensure that
// Serilog.Filters.Expressions.dll gets loaded, else filters in config file get ignored
.WriteTo.Console(
outputTemplate: "[{UtcTimestamp:HH:mm:ss.fff} {Level:u3} {Subsystem}] {Message:lj}{NewLine}{Exception}",
restrictedToMinimumLevel: LogEventLevel.Information);
Log.Logger = loggerConfig.CreateLogger();
Now I wish to use the utcTimestamp enricher while configuring the logger from my custom json config file.
var jsonLogconfiguration = new ConfigurationBuilder()
.AddJsonFile(logconfigFname)
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(jsonLogconfiguration)
.CreateLogger();
My json config file
{
"Serilog": {
"Using": [
"Serilog.Sinks.Console"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "{UtcTimestamp:yyyy,MM,dd,HH,mm,ss,fff },{Level:u3},{Subsystem},{Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext" , "UtcTimestampEnricher"],
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "Subsystem = 'Config' or Subsystem = 'Admin' "
}
}
]
}
}
The message I get on the console: ( I have previously called serilog selflog to get serilog debug messages about itself)
Serilog.Debugging.SelfLog.Enable(msg => Console.WriteLine(msg));
Serilog debug output.
2020-06-05T09:34:01.3898891Z Unable to find a method called UtcTimestampEnricher. Candidate methods are:
Serilog.LoggerConfiguration When(Serilog.Configuration.LoggerEnrichmentConfiguration, System.String, System.Action`1[Serilog.Configuration.LoggerEnrichmentConfiguration])
Serilog.LoggerConfiguration With(Serilog.Configuration.LoggerEnrichmentConfiguration, Serilog.Core.ILogEventEnricher)
Serilog.LoggerConfiguration FromLogContext(Serilog.Configuration.LoggerEnrichmentConfiguration)
I got similar output when I tried to use
"Enrich": [ "FromLogContext" , "UtcTimestamp"],
Even though the problem has been already solved I want to share my 2 cents regarding this problem.
Whenever you create a custom Enricher
you have two options how you can register that:
public class UtcTimestampEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
{
...
}
}
Log.Logger = new LoggerConfiguration()
.Enrich.With<UtcTimestampEnricher>()
.CreateLogger()
public class UtcTimestampEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
{
...
}
}
public static class LoggingExtensions
{
public static LoggerConfiguration WithUtcTimestamp(
this LoggerEnrichmentConfiguration enrich)
{
if (enrich == null)
throw new ArgumentNullException(nameof(enrich));
return enrich.With<UtcTimestampEnricher>();
}
}
{
"Serilog": {
...,
"Using": [ "Your.Assembly.Name" ],
"Enrich": [ "FromLogContext", "WithUtcTimestamp" ]
},
So, as you can see what you need to register is the registration helper method (not the enricher itself) in case of configuration based setup.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With