Search code examples
c#.netasp.net-coreloggingserilog

How to log HttpContext properties after request is complete


I have controller, background task and enricher to enrich some of HttpContext property (userAgent header for example). I'm using .net6, Serilog 3.1.1 and logging through the ILogger interface.

[HttpGet, Route("User/{id:int}")]
public async Task<IActionResult> GetUserById(int id)
{
    var user = await _repository.GetUser(id);

    SomeBackgroundTask(user);

    _logger.LogInformation("Something happened 1."); // There is UserAgent in log

    return Ok(user);
}

public async Task SomeBackgroundTask(User user)
{
    try
    {
        await Task.Delay(10000);
    }
    catch (Exception e)
    {
        _logger.LogError(e, "Something happened 2."); // There is not UserAgent in log
    }
}

So, when the request is complete, the enricher can't use _contextAccessor.HttpContext to get the necessary request headers.

Where and how I need to save the required properties, for logging them in the background task as well?


Solution

  • This is one of the many, many problems with fire-and-forget methods.

    The HttpContext is discarded when the request is complete, by design. Fire-and-forget runs code outside the request.

    The only real solution is to write your own. E.g., you should extract all necessary contextual information from the request and pass it explicitly into the fire-and-forget code. Then you can attach it to your log messages using logging scopes.

    Alternatively, move away from fire-and-forget towards a proper distributed architecture, which means a durable queue with a separate background processor. There's some work that's been done in OTEL to wire up automatic transfer from HttpContext (or other contextual data) to queue message metadata attributes, which are then extracted by the background processor and used as logging scopes. This is how the queue side of distributed tracing works.

    But if you're using fire-and-forget, you'll need to build that distributed tracing support yourself.