Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 11 additions & 20 deletions src/Polly.Core/Registry/RegistryPipelineComponentBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,20 @@ namespace Polly.Registry;
/// <summary>
/// Builds a <see cref="PipelineComponent"/> used by the registry.
/// </summary>
internal sealed class RegistryPipelineComponentBuilder<TBuilder, TKey>
internal sealed class RegistryPipelineComponentBuilder<TBuilder, TKey>(
Func<TBuilder> activator,
TKey key,
string builderName,
string? instanceName,
Action<TBuilder, ConfigureBuilderContext<TKey>> configure)
where TBuilder : ResiliencePipelineBuilderBase
where TKey : notnull
{
private readonly Func<TBuilder> _activator;
private readonly TKey _key;
private readonly string _builderName;
private readonly string? _instanceName;
private readonly Action<TBuilder, ConfigureBuilderContext<TKey>> _configure;

public RegistryPipelineComponentBuilder(
Func<TBuilder> activator,
TKey key,
string builderName,
string? instanceName,
Action<TBuilder, ConfigureBuilderContext<TKey>> configure)
{
_activator = activator;
_key = key;
_builderName = builderName;
_instanceName = instanceName;
_configure = configure;
}
private readonly Func<TBuilder> _activator = activator;
private readonly TKey _key = key;
private readonly string _builderName = builderName;
private readonly string? _instanceName = instanceName;
private readonly Action<TBuilder, ConfigureBuilderContext<TKey>> _configure = configure;

internal (ResilienceContextPool? ContextPool, PipelineComponent Component) CreateComponent()
{
Expand Down
6 changes: 4 additions & 2 deletions src/Polly.Core/ResiliencePipelineBuilderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,16 @@ internal PipelineComponent BuildPipelineComponent()
}

var source = new ResilienceTelemetrySource(Name, InstanceName, null);
var telemetry = new ResilienceStrategyTelemetry(source, TelemetryListener);

return PipelineComponentFactory.CreateComposite(components, new ResilienceStrategyTelemetry(source, TelemetryListener), TimeProviderInternal);
return PipelineComponentFactory.CreateComposite(components, telemetry, TimeProviderInternal);
}

private PipelineComponent CreateComponent(Entry entry)
{
var source = new ResilienceTelemetrySource(Name, InstanceName, entry.Options.Name);
var context = new StrategyBuilderContext(new ResilienceStrategyTelemetry(source, TelemetryListener), TimeProviderInternal);
var telemetry = new ResilienceStrategyTelemetry(source, TelemetryListener);
var context = new StrategyBuilderContext(telemetry, TimeProviderInternal);

var strategy = entry.Factory(context);
strategy.Options = entry.Options;
Expand Down
12 changes: 6 additions & 6 deletions src/Polly.Extensions/Telemetry/TelemetryListenerImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ namespace Polly.Telemetry;

internal sealed class TelemetryListenerImpl : TelemetryListener
{
internal static readonly Meter Meter = new(TelemetryUtil.PollyDiagnosticSource, "1.0");

private readonly ILogger _logger;
private readonly Func<ResilienceContext, object?, object?> _resultFormatter;
private readonly List<TelemetryListener> _listeners;
Expand All @@ -17,21 +15,23 @@ internal sealed class TelemetryListenerImpl : TelemetryListener
public TelemetryListenerImpl(TelemetryOptions options)
{
_enrichers = [.. options.MeteringEnrichers];
_logger = options.LoggerFactory.CreateLogger(TelemetryUtil.PollyDiagnosticSource);
_logger = options.LoggerFactory.CreateLogger(TelemetrySource.Name);
_resultFormatter = options.ResultFormatter;
_listeners = [.. options.TelemetryListeners];
_severityProvider = options.SeverityProvider;

Counter = Meter.CreateCounter<int>(
var meter = TelemetrySource.Instance.Meter;

Counter = meter.CreateCounter<int>(
"resilience.polly.strategy.events",
description: "Tracks the number of resilience events that occurred in resilience strategies.");

AttemptDuration = Meter.CreateHistogram<double>(
AttemptDuration = meter.CreateHistogram<double>(
"resilience.polly.strategy.attempt.duration",
unit: "ms",
description: "Tracks the duration of execution attempts.");

ExecutionDuration = Meter.CreateHistogram<double>(
ExecutionDuration = meter.CreateHistogram<double>(
"resilience.polly.pipeline.duration",
unit: "ms",
description: "The execution duration of resilience pipelines.");
Expand Down
50 changes: 50 additions & 0 deletions src/Polly.Extensions/Telemetry/TelemetrySource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Diagnostics.Metrics;

namespace Polly.Telemetry;

internal sealed class TelemetrySource
{
internal const string Name = "Polly";

public static readonly TelemetrySource Instance = new();

private TelemetrySource()
{
var version = GetVersion();
Meter = new(Name, version);
}

public Meter Meter { get; }

[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
private static string GetVersion()
{
var informationalVersion = typeof(TelemetrySource).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;

#if NET
var index = informationalVersion!.IndexOf('+', StringComparison.Ordinal);
#else
var index = informationalVersion!.IndexOf('+');
#endif
Comment thread
martincostello marked this conversation as resolved.

if (index > 0)
{
// Trim off any Git metadata
informationalVersion = informationalVersion.Substring(0, index);
}

#if NET
index = informationalVersion!.IndexOf('-', StringComparison.Ordinal);
#else
index = informationalVersion!.IndexOf('-');
#endif
Comment thread
martincostello marked this conversation as resolved.

if (index > 0)
{
// Trim off any prerelease version
informationalVersion = informationalVersion.Substring(0, index);
}

return informationalVersion;
}
}
5 changes: 5 additions & 0 deletions test/Polly.Core.Tests/ResiliencePipelineBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public void CopyCtor_Ok()
other.TelemetryListener.ShouldBeSameAs(builder.TelemetryListener);
}

[Fact]
public void CopyCtor_Reminder() =>
typeof(ResiliencePipelineBuilder).GetRuntimeProperties().Count()
.ShouldBe(7, "Make sure that when you increase this number, you also update the copy constructor to assign the new property.");

[Fact]
public void AddPipeline_Single_Ok()
{
Expand Down
16 changes: 8 additions & 8 deletions test/Polly.Core.Tests/StrategyBuilderContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@

namespace Polly.Core.Tests;

public class StrategyBuilderContextTests
public static class StrategyBuilderContextTests
{
[Fact]
public void Ctor_EnsureDefaults()
public static void Ctor_EnsureDefaults()
{
var timeProvider = new FakeTimeProvider();
var context = new StrategyBuilderContext(
new ResilienceStrategyTelemetry(new ResilienceTelemetrySource("builder-name", "instance", "strategy_name"),
Substitute.For<TelemetryListener>()), timeProvider);
new ResilienceStrategyTelemetry(
new ResilienceTelemetrySource("builder-name", "instance", "strategy_name"),
Substitute.For<TelemetryListener>()),
timeProvider);

context.Telemetry.TelemetrySource.PipelineName.ShouldBe("builder-name");
context.Telemetry.TelemetrySource.PipelineInstanceName.ShouldBe("instance");
context.Telemetry.TelemetrySource.StrategyName.ShouldBe("strategy_name");
context.TimeProvider.ShouldBe(timeProvider);
context.Telemetry.ShouldNotBeNull();

context.Telemetry.TelemetrySource.ShouldNotBeNull();
context.Telemetry.TelemetrySource.PipelineName.ShouldBe("builder-name");
context.Telemetry.TelemetrySource.PipelineInstanceName.ShouldBe("instance");
context.Telemetry.TelemetrySource.StrategyName.ShouldBe("strategy_name");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,21 @@ public ResilienceStrategyTelemetryTests()
"instance",
"strategy_name");

_sut = TestUtilities.CreateResilienceTelemetry(args => _args.Add(args));
_sut = TestUtilities.CreateResilienceTelemetry(_args.Add);
}

[Fact]
public void Ctor_Ok()
{
// Arrange
var listener = new FakeTelemetryListener((_) => { });

// Act
var sut = new ResilienceStrategyTelemetry(_source, listener);

// Assert
sut.Enabled.ShouldBeTrue();
sut.Listener.ShouldBe(listener);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.Net.Http;
using Microsoft.Extensions.Logging;
using Polly.Telemetry;
Expand All @@ -22,8 +21,6 @@ public class TelemetryListenerImplTests : IDisposable
[Fact]
public void Meter_Ok()
{
TelemetryListenerImpl.Meter.Name.ShouldBe("Polly");
TelemetryListenerImpl.Meter.Version.ShouldBe("1.0");
var source = new TelemetryListenerImpl(new TelemetryOptions());

source.Counter.Description.ShouldBe("Tracks the number of resilience events that occurred in resilience strategies.");
Expand Down
22 changes: 22 additions & 0 deletions test/Polly.Extensions.Tests/Telemetry/TelemetrySourceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Polly.Telemetry;

namespace Polly.Extensions.Tests.Telemetry;

public static class TelemetrySourceTests
{
[Fact]
public static void TelemetrySource_CreatesMeter()
{
var source = TelemetrySource.Instance;

source.ShouldNotBeNull();

source.Meter.ShouldNotBeNull();
source.Meter.Name.ShouldBe("Polly");
source.Meter.Version.ShouldNotBeNullOrEmpty();
source.Meter.Version.ShouldNotContain('-');
source.Meter.Version.ShouldNotContain('+');
Version.TryParse(source.Meter.Version, out var version).ShouldBeTrue();
version.ShouldBeGreaterThan(new(0, 0, 0));
}
}
Loading