Home > Software design >  How to add a property to all log messages in ASP.NET Core
How to add a property to all log messages in ASP.NET Core

Time:04-01

I have an ASP.NET Core application that we are looking to enhance our logging on. Basically, we want to take the value from a request header and log it as a property on anything that is logged during that request. Here's an example:


public class ExampleController : Controller
{
    private readonly ILogger _logger;

    public ExampleController(ILogger<ExampleController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    [AllowAnonymous]
    public IActionResult TestLogging()
    {
        _logger.LogInformation("Insert Message Here");

        return Ok();
    }
}

So if we send this request GET /Example/TestLogging, we would like to see the aforementioned header attached to the "Insert Message Here" log message.

It seems like this should be possible either via middleware or filters or something, but I'm not really sure how to go about it. We're using Serilog as our log provider, but it'd be nice to do this generically with ILogger (presumably using BeginScope) to stay implementation unaware. I know we could write something like this in our method:

using (var scope = _logger.BeginScope(new Dictionary<string, object>() {{"HeaderName": "HeaderValue"}}))
{
    _logger.LogInformation("Insert Message Here");
}

but we'd like to do that generically for everything instead of on a per method basis.

CodePudding user response:

Create a simple middleware, that can extract from HttpContext the information you want for each request, using BeginScope as you said:

public class LoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public LoggingMiddleware(
        RequestDelegate next,
        ILogger<LoggingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        var state = new Dictionary<string, object>
        {
            ["headers:MY_HEADER"] = httpContext.Request.Headers["MY_HEADER"].ToString(),
        };

        using (_logger.BeginScope(state))
        {
            await _next(httpContext);
        }
    }
}

Add your middleware to the Dependency Injection:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseMiddleware<LoggingMiddleware>();
}
  • Related