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

huangapple go评论76阅读模式
英文:

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

问题

我正在尝试实现类似于correlationId的东西,其中所有方法都可以访问HttpContext对象的标头,并使用correlationId进行日志记录。

但我正在尝试执行的代码未由Http请求触发。它驻留在后台服务中,每10分钟连续运行。

下面是一个最小示例。

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

PerformSomeOperations方法内部可能调用来自许多不同类的多个方法。这将导致大量日志。

我希望能够识别来自某个PerformSomeOperations()调用的所有日志。我想做到这一点,而不修改所有方法签名以包括correlationId参数并在整个调用链上传递它。

此外,我们可能会在不久的将来并行执行PerformSomeOperations()。然后现有的日志会混在一起,我们需要一些方法来识别所有属于单个PerformSomeOperations()调用的日志。

非常感谢任何有关如何实施可行解决方案的帮助或线索。谢谢。

编辑:
请注意,我在使用log4net进行日志记录。

英文:

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.

答案1

得分: 3

这是 ILogger.BeginScope 的用途。其 API 不太明显;请查看此博客文章以获取用法详细信息。

总结一下,它的使用如下:

using (_logger.BeginScope(new Dictionary<string, object>() { ["CorrelationId"] = correlationId }))
{
  // 此处的所有日志消息都会自动应用 CorrelationId。
}
英文:

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.
}

huangapple
  • 本文由 发表于 2023年5月20日 21:09:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76295391.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定