How can I suppress Execution Attempt log when using Polly V8 ResiliencePipelineBuilder?

176 Views Asked by At

In a .NET 8 project I'm using Serilog and Polly V8 and with ResiliencePipelineBuilder, and this log shows always, even if there is no retry:

Execution attempt. Source: 'screenshot-stream-with-retries/(null)/Retry', Operation Key: 'null', Result: 'System.IO.MemoryStream', Handled: 'false', Attempt: '0', Execution Time: '730.3186'

Here is my code:

public class ScreenshotStreamWithRetries
{
    private readonly ILogger<ScreenshotStreamWithRetries> _logger;

    public ScreenshotStreamWithRetries(ILogger<ScreenshotStreamWithRetries> logger)
    {
        _logger = logger;
    }

    public static string Name => "screenshot-stream-with-retries";

    public ResiliencePipelineBuilder<Stream> Configure(ResiliencePipelineBuilder<Stream> pipelineBuilder)
    {
        return pipelineBuilder.AddRetry(new RetryStrategyOptions<Stream>
        {
            MaxRetryAttempts = 3,
            Delay = TimeSpan.FromSeconds(2),
            BackoffType = DelayBackoffType.Exponential,
            ShouldHandle = new PredicateBuilder<Stream>()
                .Handle<Exception>(),
            OnRetry = retryArguments =>
            {               
                _logger.LogWarning($"Screenshot failed with exception {retryArguments.Outcome.Exception.Message}. " +
                             $"Waiting {retryArguments.Duration} before next retry. Retry attempt {retryArguments.AttemptNumber}");
                return ValueTask.CompletedTask;
            }
        });
    }
}

I found this in Polly V8 source code https://github.com/App-vNext/Polly/blob/main/src/Polly.Extensions/Telemetry/Log.cs

I'd like to suppress a log that's creating unnecessary clutter. Can it be done?

2

There are 2 best solutions below

3
Peter Csala On

TL;DR: No, you can't.


The Polly's telemetry can be enriched but not filtered.

What you see is that the initial attempt (Attempt: '0') is being performed. It is always emitted regardless the retry strategy is triggered or not.

The actual telemetry emission happens inside the RetryResilienceStrategy

TelemetryUtil.ReportExecutionAttempt(_telemetry, context, outcome, attempt, executionTime, handle);

That util class will only omit the telemetry if the entire telemetry is disabled

if (!telemetry.Enabled)
{
    return;
}

UPDATE #1

You might need to filter out these messages on the logger itself.
In case of nlog you can do something like this:

<rules>
    <logger ... >
          <filters>
            <when condition="contains('${message}',', Attempt: ''0'',')" action="Ignore" />
         </filters>
    </logger>
</rules>

For serilog something like this:

"Filter": [
    {
        "Name": "ByExcluding",
        "Args": {
            "expression": "Contains(@m, ', Attempt: ''0'',')"
        }
    }
]

Please bear in mind that ExecutionAttempt telemetry logs are emitted by the Retry and by the Hedging strategies.


UPDATE #2

Following your idea I changed Polly log level to Warning or above.

Please bear in mind that this solution is super fragile. Mainly because it relies on an implementation detail:

handled ? ResilienceEventSeverity.Warning : ResilienceEventSeverity.Information

This can be changed anytime without further notice!

0
Nicholas Blumhardt On

Using Serilog, you need some variation of:

// dotnet add package serilog.expressions

Log.Logger = new LoggerConfiguration()
    // Add this bit
    .Filter.ByExcluding("Attempt = 0")
    .CreateLogger();