Polly v8.4.1中如何为ResiliencePipeline添加失败恢复日志?
Polly 8.4.1 为重试策略添加恢复日志记录的实现方案
问题描述
我在C#中使用Polly 8.4.1版本,通过ResiliencePipelineBuilder创建可复用的重试ResiliencePipeline,代码如下:
return new ResiliencePipelineBuilder() .AddRetry(new RetryStrategyOptions { MaxRetryAttempts = 5, DelayGenerator = { /* 自定义延迟逻辑 */ }, ShouldHandle = args => { /* 自定义异常/结果判定逻辑 */ } }).Build();我希望添加日志记录,追踪操作初始失败但后续成功的情况,例如输出:
{operations} recovered after 3 tries, in 22 seconds我了解旧版Polly可通过OnSuccess操作实现该需求,请问在v8.x版本中该如何操作?
解决方案
在Polly 8.x中,旧版的OnSuccess已被重构到重试策略的事件体系中,你需要通过RetryStrategyOptions.Events.OnRecovery事件实现需求——该事件会在重试后操作成功恢复时触发,完美匹配你要追踪的场景。结合ResilienceContext可以方便记录操作开始时间,进而计算总耗时。
完整代码示例
// 假设已通过依赖注入获取ILogger实例 private readonly ILogger _logger; public ResiliencePipeline CreateRetryPipeline() { return new ResiliencePipelineBuilder() .AddRetry(new RetryStrategyOptions { MaxRetryAttempts = 5, // 自定义延迟生成逻辑(示例为固定1秒延迟) DelayGenerator = args => ValueTask.FromResult(TimeSpan.FromSeconds(1)), // 自定义重试判定逻辑(示例为捕获HttpRequestException) ShouldHandle = args => ValueTask.FromResult(args.Outcome.Exception is HttpRequestException), Events = new RetryStrategyEvents { OnRecovery = args => { // 从上下文取出操作开始时间,计算总耗时 var startTime = args.Context.Properties.GetValue<DateTime>("OperationStartTime"); var elapsedSeconds = (DateTime.UtcNow - startTime).TotalSeconds; // AttemptNumber为从零开始的重试次数索引,总重试次数为AttemptNumber + 1 var totalRetries = args.AttemptNumber + 1; _logger.LogInformation("{Operation} recovered after {RetryCount} tries, in {Elapsed:F2} seconds", "业务操作名称", // 替换为实际操作标识 totalRetries, elapsedSeconds); return ValueTask.CompletedTask; } } }) .Build(); } // 使用重试管道时,传递操作开始时间到上下文 public async Task ExecuteBusinessOperationAsync() { var context = ResilienceContextPool.Shared.Get(); try { // 将操作开始时间存入上下文属性 context.Properties.Set("OperationStartTime", DateTime.UtcNow); await _retryPipeline.ExecuteAsync(async ctx => { // 此处替换为你的实际业务操作逻辑 await RiskyBusinessOperationAsync(); }, context); } finally { // 归还上下文到对象池,避免内存泄漏 ResilienceContextPool.Shared.Return(context); } }
关键说明
OnRecovery事件:仅在初始失败后通过重试成功恢复时触发,不会在首次调用成功时触发,完全符合你的日志追踪需求。AttemptNumber:从零开始计数的重试尝试索引,因此总重试次数需要加1(例如第一次重试成功时,AttemptNumber为0,总重试次数为1)。ResilienceContext:Polly提供的上下文传递容器,通过Properties存储自定义数据(如操作开始时间),配合对象池使用可避免频繁创建对象带来的性能损耗。
内容的提问来源于stack exchange,提问作者rediVider
相关产品推荐
相关产品推荐

