How can I get the current HttpContext in a SeriLog Sink?

I have been struggling trying to do the same and I finally found a proper solution.

Do not add the enricher when creating the Logger. You will have to add the enricher in the middleware where you can access the IServiceProvider. The key is that LogContext has a method, Push, that can add an enricher:

public async Task Invoke(HttpContext httpContext)
{
    IServiceProvider serviceProvider = httpContext.RequestServices;
    using (LogContext.Push(new LogEnricher(serviceProvider))) {
        await _next(httpContext);
    }
}

In the ConfigureServices, I add a services.AddScoped<HttpContextToLog>() call.

Then, I populate the HttpContextToLog object in several places, accessing it like this:

HttpContextToLog contextToLog = _serviceProvider.GetService<HttpContextToLog>();

in the Enrich method, in an IActionFilter, in an IPageFilter, etc.


UPDATE I think you may want to look at this article : http://mylifeforthecode.github.io/enriching-serilog-output-with-httpcontext-information-in-asp-net-core/

The idea is to register a custom middleware that will add all the contextual information to the current LogContext during the request.

For it to work you must configure your logger with

Log.Logger = new LoggerConfiguration()
      // snip ....MinimumLevel.Debug()
      .Enrich.FromLogContext()                
      // snip ...
.CreateLogger(); 

This article by Nicholas Blumhardt may also help : https://blog.getseq.net/smart-logging-middleware-for-asp-net-core/


WARNING - Solution below does not work in this case

The solution below cannot work if the logger is registered early (in Program.Main() )

First of all, if you want to add extra information attached to the logged event, I believe what you want is an Enricher.

You could then :

  • Register IHttpContextAccessor into your ServiceCollection (for instance, using AddHttpContextAccessor()) : services.AddHttpContextAccessor();
  • Create an implementation of ILogEventEnricher that accepts IHttpContextAccessor in its constructor
  • When configuring your logger, inject IHttpContextAccessor (by adding an argument of type IHttpContextAccessor to Startup.Configure()
  • Add this enricher to your logger

The enricher could look something like https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/ClaimValueEnricher.cs .

And you would configure your logger like this :

var logger = new LoggerConfiguration()
                .EnrichWith(new MyEnricher(contextAccessor))
                .WriteTo.Whatever()
                .CreateLogger();