You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 09:58:22