简体   繁体   中英

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"], 

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.

I finally figured this out, and could get the custom enricher to work by specifying it in C# code

var jsonLogconfiguration = new ConfigurationBuilder()
    .AddJsonFile(logconfigFname)
    .Build();

Log.Logger = new LoggerConfiguration()
    .Enrich.With(new UtcTimestampEnricher()) // is necessary
    .ReadFrom.Configuration(jsonLogconfiguration)
    .CreateLogger()

and removing the enrich with from the config file

"Enrich": [ "FromLogContext" ],

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM