Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Serilog to use custom enricher from json config file

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"], 
like image 287
Paulus Avatar asked Dec 22 '22 17:12

Paulus


1 Answers

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:

  • Either via code
  • or via configuration

Via Code

Enricher

public class UtcTimestampEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
    {
      ...
    }
}

Registration

Log.Logger = new LoggerConfiguration()
    .Enrich.With<UtcTimestampEnricher>()
    .CreateLogger()

Via Configuration

Enricher

public class UtcTimestampEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
    {
      ...
    }
}

Registration helper

public static class LoggingExtensions
{
    public static LoggerConfiguration WithUtcTimestamp(
        this LoggerEnrichmentConfiguration enrich)
    {
        if (enrich == null)
            throw new ArgumentNullException(nameof(enrich));

        return enrich.With<UtcTimestampEnricher>();
    }
}

Registration

{
  "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.

like image 72
Peter Csala Avatar answered Apr 29 '23 14:04

Peter Csala