如何让 Serilog 使用来自 json 配置文件的自定义丰富器

Pau*_*lus 2 c# configuration serilog

我希望在我的 Serilog 输出中使用格式化的 UTC 时间戳。我编写了一个自定义丰富器,从 C# 代码调用时可以正常工作。

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();
Run Code Online (Sandbox Code Playgroud)

现在我希望在从我的自定义 json 配置文件配置记录器时使用 utcTimestamp 扩充器。

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

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(jsonLogconfiguration)
    .CreateLogger();
Run Code Online (Sandbox Code Playgroud)

我的 json 配置文件

{
  "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' "
        }
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

我在控制台上收到的消息:(我之前调用了 serilog selflog 来获取有关自身的 serilog 调试消息)

Serilog.Debugging.SelfLog.Enable(msg => Console.WriteLine(msg));
Run Code Online (Sandbox Code Playgroud)

Serilog 调试输出。

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)
Run Code Online (Sandbox Code Playgroud)

当我尝试使用时,我得到了类似的输出

    "Enrich": [ "FromLogContext" , "UtcTimestamp"], 
Run Code Online (Sandbox Code Playgroud)

Pet*_*ala 6

即使问题已经解决,我还是想分享我关于这个问题的 2 美分。

每当您创建自定义时,Enricher您有两种选择如何注册:

  • 要么通过代码
  • 或通过配置

通过代码

浓缩器

public class UtcTimestampEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
    {
      ...
    }
}
Run Code Online (Sandbox Code Playgroud)

登记

Log.Logger = new LoggerConfiguration()
    .Enrich.With<UtcTimestampEnricher>()
    .CreateLogger()
Run Code Online (Sandbox Code Playgroud)

通过配置

浓缩器

public class UtcTimestampEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory pf)
    {
      ...
    }
}
Run Code Online (Sandbox Code Playgroud)

注册助手

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

        return enrich.With<UtcTimestampEnricher>();
    }
}
Run Code Online (Sandbox Code Playgroud)

登记

{
  "Serilog": {
    ...,
    "Using": [ "Your.Assembly.Name" ],
    "Enrich": [ "FromLogContext", "WithUtcTimestamp" ]
  },
Run Code Online (Sandbox Code Playgroud)

因此,正如您所看到的,在基于配置的设置的情况下,您需要注册的是注册助手方法(而不是丰富器本身)。

  • 谢谢你,让它更清楚,我认为该领域的文档有点薄弱 (2认同)