Search code examples
c#.netasp.net-core.net-corehttpcontext

How to set a value(correlationId) and make it accessible throughout a method execution (similar to accessing values from HttpContext) in .NET Core 6


I am trying to implement something similar to a correlationId, where all the methods have access to the header from HttpContext object and uses the correlationId for logging.

Except the code I am trying to execute is not triggered by a Http request. It resides in a background service and runs continuously for every 10 min. Below is an minimal example.

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        foreach(var item in items)
        {
            await _myService.PerformSomeOperations(item);
        }
        await Task.Delay(10 * 1000);   
    }
}
                

The PerformSomeOperations method internally might call multiple methods from many different classes. This will result in a lot of logs.

I want to be able to identify all the logs coming in from a certain PerformSomeOperations() call. And I want to do it without modifying all the method signatures to include a correlationId parameter and pass it along throughout the chain of calls.

Also, we might be performing the PerformSomeOperations() in parallel in the near future. Then the existing logs would mixup and we need something to identify all the logs coming under a single PerformSomeOperations() call.

Any help or leads with how to implement a viable solution is very much appreciated. Thanks.

Edit: Please note that I am using log4net for logging.


Solution

  • This is what ILogger.BeginScope is for. Its API is not very obvious; see this blog post for usage details.

    In summary, it looks like this:

    using (_logger.BeginScope(new Dictionary<string, object>() { ["CorrelationId"] = correlationId }))
    {
      // All log messages in here have a CorrelationId automatically applied.
    }