Skip to content

Commit

Permalink
Introduce TelemetryResilienceStrategyOptions.ResultFormatter (#1294)
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk authored Jun 14, 2023
1 parent 48a8530 commit 155a062
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/Polly.Extensions/Polly.Extensions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
<PackageReference Include="Microsoft.Extensions.Options" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" />
<Reference Include="System.Net.Http" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'"/>
</ItemGroup>
</Project>
12 changes: 8 additions & 4 deletions src/Polly.Extensions/Telemetry/TelemetryResilienceStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ internal sealed class TelemetryResilienceStrategy : ResilienceStrategy
private readonly string? _strategyKey;
private readonly List<Action<EnrichmentContext>> _enrichers;
private readonly ILogger _logger;
private readonly Func<ResilienceContext, object?, object?> _resultFormatter;

// Temporary only, until the TimeProvider is exposed
public TelemetryResilienceStrategy(
string builderName,
string? strategyKey,
ILoggerFactory loggerFactory,
Func<ResilienceContext, object?, object?> resultFormatter,
List<Action<EnrichmentContext>> enrichers)
: this(TimeProvider.System, builderName, strategyKey, loggerFactory, enrichers)
: this(TimeProvider.System, builderName, strategyKey, loggerFactory, resultFormatter, enrichers)
{
}

Expand All @@ -28,11 +30,13 @@ public TelemetryResilienceStrategy(
string? builderName,
string? strategyKey,
ILoggerFactory loggerFactory,
Func<ResilienceContext, object?, object?> resultFormatter,
List<Action<EnrichmentContext>> enrichers)
{
_timeProvider = timeProvider;
_builderName = builderName;
_strategyKey = strategyKey;
_resultFormatter = resultFormatter;
_enrichers = enrichers;
_logger = loggerFactory.CreateLogger(TelemetryUtil.PollyDiagnosticSource);
ExecutionDuration = ResilienceTelemetryDiagnosticSource.Meter.CreateHistogram<double>(
Expand All @@ -59,7 +63,7 @@ protected override async ValueTask<Outcome<TResult>> ExecuteCoreAsync<TResult, T
_builderName,
_strategyKey,
context.GetResultType(),
ExpandOutcome(outcome),
ExpandOutcome(context, outcome),
context.GetExecutionHealth(),
duration.TotalMilliseconds,
outcome.Exception);
Expand All @@ -85,9 +89,9 @@ private static Outcome<object> CreateOutcome<TResult>(Outcome<TResult> outcome)
new Outcome<object>(outcome.Result) :
new Outcome<object>(outcome.Exception!);

private static object? ExpandOutcome<TResult>(Outcome<TResult> outcome)
private object? ExpandOutcome<TResult>(ResilienceContext context, Outcome<TResult> outcome)
{
// stryker disable once all: no means to test this
return (object)outcome.Exception?.Message! ?? outcome.Result;
return (object)outcome.Exception?.Message! ?? _resultFormatter(context, outcome.Result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public static TBuilder EnableTelemetry<TBuilder>(this TBuilder builder, Telemetr
builder.BuilderName,
builder.Properties.GetValue(TelemetryUtil.StrategyKey, null!),
options.LoggerFactory,
options.ResultFormatter,
options.Enrichers.ToList());
strategies.Insert(0, telemetryStrategy);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Net.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

Expand All @@ -25,4 +27,20 @@ public class TelemetryResilienceStrategyOptions
/// Defaults to an empty collection.
/// </remarks>
public ICollection<Action<EnrichmentContext>> Enrichers { get; } = new List<Action<EnrichmentContext>>();

/// <summary>
/// Gets or sets the result formatter.
/// </summary>
/// <remarks>
/// Defaults to a formatter that returns a status code for HTTP based responses and the result as-is for all other result types.
/// <para>
/// This property is required.
/// </para>
/// </remarks>
[Required]
public Func<ResilienceContext, object?, object?> ResultFormatter { get; set; } = (_, result) => result switch
{
HttpResponseMessage response => (int)response.StatusCode,
_ => result,
};
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Net;
using System.Net.Http;
using Microsoft.Extensions.Logging.Abstractions;
using Polly.Extensions.Telemetry;

Expand All @@ -12,5 +14,11 @@ public void Ctor_EnsureDefaults()

options.Enrichers.Should().BeEmpty();
options.LoggerFactory.Should().Be(NullLoggerFactory.Instance);
var resilienceContext = ResilienceContext.Get();
options.ResultFormatter(resilienceContext, null).Should().BeNull();
options.ResultFormatter(resilienceContext, "dummy").Should().Be("dummy");

using var response = new HttpResponseMessage(HttpStatusCode.OK);
options.ResultFormatter(resilienceContext, response).Should().Be(200);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ public void Execute_WithResult_EnsureMetered(bool healthy)
}
}

private TelemetryResilienceStrategy CreateStrategy() => new("my-builder", "my-key", _loggerFactory, new List<Action<EnrichmentContext>> { c => _enricher?.Invoke(c) });
private TelemetryResilienceStrategy CreateStrategy() => new("my-builder", "my-key", _loggerFactory, (_, r) => r, new List<Action<EnrichmentContext>> { c => _enricher?.Invoke(c) });

public void Dispose()
{
_metering.Dispose();
Expand Down

0 comments on commit 155a062

Please sign in to comment.