Polly政策记录异常和重新抛出

时间:2017-03-22 12:46:52

标签: c# exception-handling polly

我考虑使用Polly来创建记录异常和重新抛出的策略。 我没有找到允许开箱即用的现有方法,但我看到的一些选项是

后备

// Specify a substitute value or func, calling an action (eg for logging) if the fallback is invoked.
Policy.Handle<Whatever>()  
 .Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) =>  
   {   _logger.Log(exception, context);
       throw exception;
  });

问题:可以从Fallback抛出异常吗?

超时

Policy.Timeout(1, T30meoutStrategy.Pessimistic, (context, timespan, task) =>  
   {        task.ContinueWith(t =>
 { // ContinueWith important!: the abandoned task may very well still be executing, when the caller times out on waiting for it!    
   if (t.IsFaulted      )           
  {             
       logger.Error(context,t.Exception);         
       throw exception;
  }   );    

重试

Policy.Handle<DivideByZeroException>().Retry(0, (exception, retryCount) =>   
  {                logger.Error(context,exception);         
throw exception;
  }   );  

问题:是否支持0次重试?

或者KISS并自己写点简单的try / catch

哪种方法更好? 你有什么建议?

2 个答案:

答案 0 :(得分:11)

如果你还没有混合使用Polly,那么尝试/ catch似乎最简单。

如果您已经混合使用Polly,FallbackPolicy可以按照您的建议安全地重新使用。 onFallback委托和后备操作或值are not governed by the .Handle<>() clauses of the Policy,因此您可以安全地从onFallback代理中重新抛出异常。

 Policy<UserAvatar>.Handle<Whatever>()  
 .Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) =>  
   {   _logger.Log(exception, context);
       throw exception;
  });

你的问题用TimeoutPolicy概述的方法只能捕获调用者之前由于超时而离开的代理抛出的异常,并且仅在TimeoutMode.Pessimistic中;并非所有例外情况。

您的问题概述.Retry(0, ...)的方法不起作用。如果未指定重试,则不会调用onRetry委托。

为了避免重新调整FallbackPolicy的不整洁,您还可以在Polly的结构中编写自己的LogThenRethrowPolicy代码。 This commit(添加了简单的NoOpPolicy)举例说明了添加新政策所需的最低要求。您可以添加类似于NoOpPolicy但只有try { } catch { /* log; rethrow */ }

的实现

编辑2019年1月:Polly.Contrib现在还包含Polly.Contrib.LoggingPolicy,可以为此提供帮助。

答案 1 :(得分:-1)

https://github.com/App-vNext/Polly-Samples/blob/master/PollyDemos/Async/AsyncDemo02_WaitAndRetryNTimes.cs显示您至少可以对WaitAndRetryAsync使用onRetry:选项。我还没有看其他人。

HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(3,
    retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))  // exponential back-off: 2, 4, 8 etc
                    + TimeSpan.FromMilliseconds(Jitterer.Next(0, 1000)), // plus some jitter: up to 1 second
    onRetry: (response, calculatedWaitDuration) =>
    {
        logger.LogError($"Failed attempt. Waited for {calculatedWaitDuration}. Retrying. {response.Exception.Message} - {response.Exception.StackTrace}");
    }
);