Search code examples
c#serilog

How to create a Serilog Sink Extension that will support configuration logic


I'm trying to wrap the configuration of the Serilog.Sinks.Elasticsearch sink so that my log configuration looks something like this.

    var logger = Log.Logger = new LoggerConfiguration()
          .ReadFrom.AppSettings()
          .Enrich.FromLogContext()
          .Enrich.WithMachineName()
          .Enrich.WithProcessId()
          .Enrich.WithThreadId()
          .WriteTo.ElasticsearchIfEnabled() // <--- Chained Sink
          .WriteTo.Async(
              a => a.File(
                  filePath,
                  outputTemplate: CanonicalTemplate,
                  retainedFileCountLimit: 31,
                  rollingInterval: RollingInterval.Day,
                  rollOnFileSizeLimit: true,
                  buffered: true,
                  flushToDiskInterval: TimeSpan.FromMilliseconds(500)))
        .CreateLogger();

My inspiration came from this answer, but I'm stuck with the internal condition logic, specifically if the the sink is disabled.

Here is what I have so far.

public static class MyConfigExtensions
{
    public static LoggerConfiguration ElasticsearchIfEnabled(this LoggerSinkConfiguration loggerSinkConfiguration)
    {
        var isElasticSinkEnabled = GetThisValue();

        if (isElasticSinkEnabled)
        {
            // Code necessary to configure sink....

            return loggerSinkConfiguration.Sink(new ElasticsearchSink(elasticSearchSinkOptions));
        }

        return loggerSinkConfiguration; // <-- what is passed here that will propagate the configuration?
    }
}

So my question is how to propagate the configuration when the internal sink is disabled, and I need to pass the original configuration on to the next sink in the chain?

There are a few properties of the configuration object, Logger, Sink, and Sink<> but I'm unsure of which to use, and more importantly, correctly.


Solution

  • This will work:

    return loggerSinkConfiguration.Sink(new LoggerConfiguration().CreateLogger());
    

    But, conditionally configuring the logger would, too:

    var configuration = new LoggerConfiguration()
          .ReadFrom.AppSettings()
          .Enrich.FromLogContext()
          .Enrich.WithMachineName()
          .Enrich.WithProcessId()
          .Enrich.WithThreadId();
    
    if (isElasticSinkEnabled)
        configuration.WriteTo.ElasticsearchIfEnabled();
    
    var logger = Log.Logger = configuration.WriteTo.Async(
              a => a.File(
                  filePath,
                  outputTemplate: CanonicalTemplate,
                  retainedFileCountLimit: 31,
                  rollingInterval: RollingInterval.Day,
                  rollOnFileSizeLimit: true,
                  buffered: true,
                  flushToDiskInterval: TimeSpan.FromMilliseconds(500)))
        .CreateLogger();