如何在HTTP请求外(如后台任务)使用IDiagnosticContext?
在无HTTP上下文场景中使用Serilog的IDiagnosticContext收集日志属性
你猜的没错,AmbientDiagnosticContextCollector正是用来在非HTTP场景(比如后台任务)中实现IDiagnosticContext属性收集的核心类型。它通过维护一个 ambient 上下文范围,让你在范围内设置的属性可以被批量收集,最终附加到指定的日志条目里。
具体实现步骤
- 注入依赖:确保你的服务中注入了
AmbientDiagnosticContextCollector(Serilog.AspNetCore默认会将其注册到DI容器) - 创建上下文范围:用
Begin()方法开启一个属性收集范围,推荐用using块自动管理生命周期 - 设置属性:在范围内调用
Set()添加需要收集的属性 - 收集并附加属性:通过
TryComplete()获取收集到的属性字典,将其作为参数传递给日志方法
可运行代码示例
using System.Diagnostics; using Microsoft.Extensions.Logging; using Serilog.AspNetCore; public class MyBackgroundTask { private readonly AmbientDiagnosticContextCollector _diagnosticCollector; private readonly ILogger<MyBackgroundTask> _logger; public MyBackgroundTask(AmbientDiagnosticContextCollector diagnosticCollector, ILogger<MyBackgroundTask> logger) { _diagnosticCollector = diagnosticCollector; _logger = logger; } public async Task RunAsync(CancellationToken cancellationToken) { var stopwatch = Stopwatch.StartNew(); // 开启属性收集上下文范围 using var context = _diagnosticCollector.Begin(); // 批量设置需要附加到日志的属性 context.Set("foo", 1); context.Set("bar", 2); // 模拟后台业务逻辑 await Task.Delay(1500, cancellationToken); stopwatch.Stop(); var elapsedSeconds = stopwatch.Elapsed.TotalSeconds; // 完成上下文并获取收集到的属性 if (_diagnosticCollector.TryComplete(context, out var collectedProperties)) { // 将属性附加到目标日志条目 _logger.LogInformation("Completed in {Seconds}", elapsedSeconds, collectedProperties); } } }
关键说明
using块会自动处理上下文的清理,即使任务抛出异常也不会导致资源泄漏TryComplete方法会返回一个包含所有已设置属性的字典,将其作为日志的额外参数传递后,Serilog会自动将这些属性添加到日志条目中- 最终生成的日志条目会包含
Seconds、foo、bar三个属性,完全符合你的预期
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

