Creating custom serilog enrichers
14 Aug 2018If like me you think Serilog is pretty fantastic then you might have wanted to extend your implementation with custom enrichers.
Below are a couple templates you can use to dynamically enrich your logs with whatever properties you need.
In my example I’m enriching my logs with the property ReleaseNumber
given the environment variable RELEASE_NUMBER
.
1. Create the log event enricher
This is the real meat when it comes to creating a custom Serilog enricher. The two important aspects are setting a constant PropertyName
value
and providing a means to resolve the value of that property.
public class ReleaseNumberEnricher : ILogEventEnricher
{
LogEventProperty _cachedProperty;
public const string PropertyName = "ReleaseNumber";
/// <summary>
/// Enrich the log event.
/// </summary>
/// <param name="logEvent">The log event to enrich.</param>
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
logEvent.AddPropertyIfAbsent(GetLogEventProperty(propertyFactory));
}
private LogEventProperty GetLogEventProperty(ILogEventPropertyFactory propertyFactory)
{
// Don't care about thread-safety, in the worst case the field gets overwritten and one property will be GCed
if (_cachedProperty == null)
_cachedProperty = CreateProperty(propertyFactory);
return _cachedProperty;
}
// Qualify as uncommon-path
[MethodImpl(MethodImplOptions.NoInlining)]
private static LogEventProperty CreateProperty(ILogEventPropertyFactory propertyFactory)
{
var value = Environment.GetEnvironmentVariable("RELEASE_NUMBER") ?? "local";
return propertyFactory.CreateProperty(PropertyName, value);
}
}
2. Provide a means to add your enricher to your logger configuration
public static class LoggingExtensions
{
public static LoggerConfiguration WithReleaseNumber(
this LoggerEnrichmentConfiguration enrich)
{
if (enrich == null)
throw new ArgumentNullException(nameof(enrich));
return enrich.With<ReleaseNumberEnricher>();
}
}
3 Time to use your enricher!
There’s two ways we can go about using a custom enricher. First is probably the simplest and most commonly adopted way.
Builder style
Along with any other setup, here we can add our own enricher to the configuration builder.
var logger = new LoggerConfiguration()
.Enrich.WithReleaseNumber()
.CreateLogger();
Configuration style
The alternative way is to import your enricher using an appsettings.json
file using the Serilog.Settings.Configuration
package.
This package will scan all assemblies listed in the Using
property (as well as any assemblies belonging to the Serilog
namespace)
for methods extending the LoggerEnrichmentConfiguration
object.
If your enricher isn’t being applied then double check the Using
property
matches the dll
where your extension method resides.
{
"Serilog": {
"MinimumLevel": {
"Default": "Debug"
},
"WriteTo": [
{
"Name": "Console"
}
],
"Using": [ "Example.Assembly.Name" ],
"Enrich": [ "FromLogContext", "WithReleaseNumber" ]
}
}
Done!
How painless was that?
— Dan