基于 Polly 的重试日志间歇性地未显示在 Windows Azure Function 的 App Insights 中

问题描述 投票:0回答:1

我们有一个 Windows Azure 函数,我们将 Polly 实现为 -

public async Task<T> ExecuteTaskWithRetryAsync<T>(int maxRetryAttempts, int delayBetweenFirstRetryInSeconds, string invocationIdentifier, Func<Task<T>> function)
{
    logger.LogInformation($"Executing {invocationIdentifier} with retries.");
    var retryPolicy = Policy
        .Handle<HttpRequestException>(ex => ex.StatusCode != HttpStatusCode.BadRequest && ex.StatusCode != HttpStatusCode.Unauthorized)
        .WaitAndRetryAsync(
        maxRetryAttempts,
        retryAttempt => TimeSpan.FromSeconds(delayBetweenFirstRetryInSeconds * Math.Pow(2, retryAttempt - 1)),
        (exception, timeSpan, retryCount, context) =>
        {
            logger.LogWarning("Execution of {identifier} failed. Waiting {sec} seconds before retry. Attempt  number {retryCount}. Exception - {exceptionMessage}", invocationIdentifier, timeSpan.Seconds, retryCount, exception.Message);
        });
    return await retryPolicy.ExecuteAsync<T>(async () =>
    {
        T result = await function();
        logger.LogInformation($"Successfully executed {invocationIdentifier}");
        return result;
    });

并被用作

var response = await retryService.ExecuteTaskWithRetryAsync(retryOptions.MaxRetryAttempts, retryOptions.DelayBetweenRetriesInSeconds, nameof(GetFromMetaRPAsync), async () =>
{
    return await httpClient.GetAsync(endpoint).ConfigureAwait(false);
});
if (!response.IsSuccessStatusCode)
{
    throw new HttpRequestException($"Failed to retrieve any results. Response with status code {response?.StatusCode} - {response?.ReasonPhrase}.");
}

但是在App Insights中,我们只能看到初始日志

“重试执行 {invocableIdentifier}”

然后抛出

HttpRequestException
,状态代码为 504 (GatewayTimeout)。

我可以看到一个开放问题,其中讨论了 Polly 重试未记录为单独的依赖项,但他们能够看到重试日志。我们甚至看不到

的重试日志

“重试前等待 {sec} 秒。”

当服务器出现问题时,例如BadGatewayGatewayTimeout

但是,我们能够间歇性地看到此日志行

“重试前等待 {sec} 秒...异常 - 发送请求时出错”。

在未捕获重试的情况下,我们将在大约 10 秒后收到调用的响应。 20秒。重试是否有可能在内部发生,但 App Insights 没有捕获?即使没有依赖项,是否仍应捕获重试日志? 我们如何验证重试是否确实发生?

我们已经在本地运行了代码,并且还进行了单元测试,在这两种情况下,我们都可以看到正在发生的重试。云上的行为会有所不同吗?

c# azure-functions azure-application-insights polly appinsights
1个回答
0
投票

仅当装饰的HttpClient

抛出
HttpRequestException
时,您的重试策略才会触发

.Handle<HttpRequestException>(...

这意味着如果您的

HttpClient
没有抛出 HRE 异常,但确实返回带有 504 状态代码的
HttpResponseMessage
那么您的重试逻辑将不会被触发。

可能会观察到网关超时的

HttpRequestException
,因为在策略执行后,您的代码会执行成功检查

if (!response.IsSuccessStatusCode)
{
    throw new HttpRequestException($"Failed to retrieve any results. Response with status code {response?.StatusCode} - {response?.ReasonPhrase}.");
}

选项#1

在策略执行中调用

EnsureSuccessStatusCode
方法。

var response = await retryService.ExecuteTaskWithRetryAsync(retryOptions.MaxRetryAttempts, retryOptions.DelayBetweenRetriesInSeconds, nameof(GetFromMetaRPAsync), async () =>
{
    var httpResponse = await httpClient.GetAsync(endpoint).ConfigureAwait(false);
    httpResponse.EnsureSuccessStatusCode();
    return httpResponse;
});

正如您在 dotnet 源代码中看到的那样,可能抛出的 HRE 包含状态代码以及原因短语。

选项#2

定义您的策略以触发

HttpResponseMessage

var retryPolicy = Policy
    .Handle<HttpRequestException>(ex => ex.StatusCode != HttpStatusCode.BadRequest && ex.StatusCode != HttpStatusCode.Unauthorized)
    .OrResult<HttpResponseMessage>(res => res.StatusCode != HttpStatusCode.BadRequest && res.StatusCode != HttpStatusCode.Unauthorized)
    .WaitAndRetryAsync(...

var nonRetryableStatusCodes = [ HttpStatusCode.BadRequest,  HttpStatusCode.Unauthorized];
...
var retryPolicy = Policy
    .Handle<HttpRequestException>(ex => nonRetryableStatusCodes.Contains(ex.StatusCode) is false)
    .OrResult<HttpResponseMessage>(res => nonRetryableStatusCodes.Contains(res.StatusCode) is false)
    .WaitAndRetryAsync(
© www.soinside.com 2019 - 2024. All rights reserved.