From ef63b0b204acbb54ed46218bd87665857578af94 Mon Sep 17 00:00:00 2001 From: peter-csala Date: Mon, 21 Oct 2024 17:08:49 +0200 Subject: [PATCH 1/6] Add TelemetrySource to ExecutionRejectedException --- .../Controller/CircuitStateController.cs | 13 ++-- src/Polly.Core/ExecutionRejectedException.cs | 8 +++ src/Polly.Core/PublicAPI.Unshipped.txt | 2 + .../Telemetry/ResilienceStrategyTelemetry.cs | 14 ++++ .../Timeout/TimeoutResilienceStrategy.cs | 1 + .../RateLimiterRejectedException.cs | 21 +++--- .../RateLimiterResilienceStrategy.cs | 6 +- .../RateLimiterRejectedExceptionTests.cs | 66 ++++++++++++++++--- 8 files changed, 104 insertions(+), 27 deletions(-) diff --git a/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs b/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs index 9076965334d..57d0afca782 100644 --- a/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs +++ b/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs @@ -95,7 +95,9 @@ public ValueTask IsolateCircuitAsync(ResilienceContext context) lock (_lock) { - SetLastHandledOutcome_NeedsLock(Outcome.FromException(new IsolatedCircuitException())); + var exception = new IsolatedCircuitException(); + _telemetry.UpdateTelemetrySource(exception); + SetLastHandledOutcome_NeedsLock(Outcome.FromException(exception)); OpenCircuitFor_NeedsLock(Outcome.FromResult(default), TimeSpan.MaxValue, manual: true, context, out task); _circuitState = CircuitState.Isolated; } @@ -123,7 +125,7 @@ public ValueTask CloseCircuitAsync(ResilienceContext context) { EnsureNotDisposed(); - Exception? exception = null; + BrokenCircuitException? exception = null; bool isHalfOpen = false; Task? task = null; @@ -157,6 +159,7 @@ public ValueTask CloseCircuitAsync(ResilienceContext context) if (exception is not null) { + _telemetry.UpdateTelemetrySource(exception); return Outcome.FromException(exception); } @@ -308,11 +311,13 @@ private void SetLastHandledOutcome_NeedsLock(Outcome outcome) private BrokenCircuitException CreateBrokenCircuitException() { TimeSpan retryAfter = _blockedUntil - _timeProvider.GetUtcNow(); - return _breakingException switch + BrokenCircuitException exception = _breakingException switch { - Exception exception => new BrokenCircuitException(BrokenCircuitException.DefaultMessage, retryAfter, exception), + Exception ex => new BrokenCircuitException(BrokenCircuitException.DefaultMessage, retryAfter, ex), _ => new BrokenCircuitException(BrokenCircuitException.DefaultMessage, retryAfter) }; + _telemetry.UpdateTelemetrySource(exception); + return exception; } private void OpenCircuit_NeedsLock(Outcome outcome, bool manual, ResilienceContext context, out Task? scheduledTask) diff --git a/src/Polly.Core/ExecutionRejectedException.cs b/src/Polly.Core/ExecutionRejectedException.cs index b5c8e4e0684..3718d30c457 100644 --- a/src/Polly.Core/ExecutionRejectedException.cs +++ b/src/Polly.Core/ExecutionRejectedException.cs @@ -2,6 +2,8 @@ using System.Runtime.Serialization; #endif +using Polly.Telemetry; + namespace Polly; /// @@ -49,4 +51,10 @@ protected ExecutionRejectedException(SerializationInfo info, StreamingContext co } #endif #pragma warning restore RS0016 // Add public types and members to the declared API + + /// + /// Gets the source of the strategy which has thrown the exception, if known. + /// + public virtual ResilienceTelemetrySource? TelemetrySource { get; internal set; } + } diff --git a/src/Polly.Core/PublicAPI.Unshipped.txt b/src/Polly.Core/PublicAPI.Unshipped.txt index f82785466ab..5101967e54e 100644 --- a/src/Polly.Core/PublicAPI.Unshipped.txt +++ b/src/Polly.Core/PublicAPI.Unshipped.txt @@ -3,3 +3,5 @@ Polly.CircuitBreaker.BrokenCircuitException.BrokenCircuitException(string! messa Polly.CircuitBreaker.BrokenCircuitException.BrokenCircuitException(string! message, System.TimeSpan retryAfter, System.Exception! inner) -> void Polly.CircuitBreaker.BrokenCircuitException.BrokenCircuitException(System.TimeSpan retryAfter) -> void Polly.CircuitBreaker.BrokenCircuitException.RetryAfter.get -> System.TimeSpan? +virtual Polly.ExecutionRejectedException.TelemetrySource.get -> Polly.Telemetry.ResilienceTelemetrySource? +Polly.Telemetry.ResilienceStrategyTelemetry.UpdateTelemetrySource(Polly.ExecutionRejectedException! exception) -> void diff --git a/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs b/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs index 966a74312df..1ec34820450 100644 --- a/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs +++ b/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs @@ -1,3 +1,5 @@ +using System.ComponentModel; + namespace Polly.Telemetry; /// @@ -21,6 +23,18 @@ internal ResilienceStrategyTelemetry(ResilienceTelemetrySource source, Telemetry internal ResilienceTelemetrySource TelemetrySource { get; } + /// + /// Updates the source of the telemetry on the provided exception. + /// + /// The to-be-updated exception. + [EditorBrowsable(EditorBrowsableState.Never)] + public void UpdateTelemetrySource(ExecutionRejectedException exception) + { + Guard.NotNull(exception); + + exception.TelemetrySource = TelemetrySource; + } + /// /// Reports an event that occurred in a resilience strategy. /// diff --git a/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs b/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs index 5b17fe2d720..e9e304b36b3 100644 --- a/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs +++ b/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs @@ -74,6 +74,7 @@ protected internal override async ValueTask> ExecuteCore(timeoutException.TrySetStackTrace()); } diff --git a/src/Polly.RateLimiting/RateLimiterRejectedException.cs b/src/Polly.RateLimiting/RateLimiterRejectedException.cs index a5fc88d5c0a..d9416332c26 100644 --- a/src/Polly.RateLimiting/RateLimiterRejectedException.cs +++ b/src/Polly.RateLimiting/RateLimiterRejectedException.cs @@ -44,7 +44,8 @@ public RateLimiterRejectedException(string message) /// The message that describes the error. /// The retry after value. public RateLimiterRejectedException(string message, TimeSpan retryAfter) - : base(message) => RetryAfter = retryAfter; + : base(message) + => RetryAfter = retryAfter; /// /// Initializes a new instance of the class. @@ -63,7 +64,8 @@ public RateLimiterRejectedException(string message, Exception inner) /// The retry after value. /// The inner exception. public RateLimiterRejectedException(string message, TimeSpan retryAfter, Exception inner) - : base(message, inner) => RetryAfter = retryAfter; + : base(message, inner) + => RetryAfter = retryAfter; /// /// Gets the amount of time to wait before retrying again. @@ -84,10 +86,10 @@ public RateLimiterRejectedException(string message, TimeSpan retryAfter, Excepti private RateLimiterRejectedException(SerializationInfo info, StreamingContext context) : base(info, context) { - var value = info.GetDouble("RetryAfter"); - if (value >= 0.0) + var retryAfter = info.GetDouble(nameof(RetryAfter)); + if (retryAfter >= 0.0) { - RetryAfter = TimeSpan.FromSeconds(value); + RetryAfter = TimeSpan.FromSeconds(retryAfter); } } @@ -96,14 +98,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont { Guard.NotNull(info); - if (RetryAfter.HasValue) - { - info.AddValue("RetryAfter", RetryAfter.Value.TotalSeconds); - } - else - { - info.AddValue("RetryAfter", -1.0); - } + info.AddValue(nameof(RetryAfter), RetryAfter.HasValue ? RetryAfter.Value.TotalSeconds : -1.0); base.GetObjectData(info, context); } diff --git a/src/Polly.RateLimiting/RateLimiterResilienceStrategy.cs b/src/Polly.RateLimiting/RateLimiterResilienceStrategy.cs index ec29f4c0ee1..861350558eb 100644 --- a/src/Polly.RateLimiting/RateLimiterResilienceStrategy.cs +++ b/src/Polly.RateLimiting/RateLimiterResilienceStrategy.cs @@ -65,7 +65,11 @@ protected override async ValueTask> ExecuteCore(exception.TrySetStackTrace()); } diff --git a/test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs b/test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs index b615e322bce..4239db541ca 100644 --- a/test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs +++ b/test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs @@ -4,19 +4,67 @@ namespace Polly.Core.Tests.Timeout; public class RateLimiterRejectedExceptionTests { + private readonly string _message = "dummy"; + private readonly TimeSpan _retryAfter = TimeSpan.FromSeconds(4); + [Fact] public void Ctor_Ok() { - var retryAfter = TimeSpan.FromSeconds(4); + var exception = new RateLimiterRejectedException(); + exception.InnerException.Should().BeNull(); + exception.Message.Should().Be("The operation could not be executed because it was rejected by the rate limiter."); + exception.RetryAfter.Should().BeNull(); + exception.TelemetrySource.Should().BeNull(); + } + + [Fact] + public void Ctor_RetryAfter_Ok() + { + var exception = new RateLimiterRejectedException(_retryAfter); + exception.InnerException.Should().BeNull(); + exception.Message.Should().Be($"The operation could not be executed because it was rejected by the rate limiter. It can be retried after '00:00:04'."); + exception.RetryAfter.Should().Be(_retryAfter); + exception.TelemetrySource.Should().BeNull(); + } + + [Fact] + public void Ctor_Message_Ok() + { + var exception = new RateLimiterRejectedException(_message); + exception.InnerException.Should().BeNull(); + exception.Message.Should().Be(_message); + exception.RetryAfter.Should().BeNull(); + exception.TelemetrySource.Should().BeNull(); + } + + [Fact] + public void Ctor_Message_RetryAfter_Ok() + { + var exception = new RateLimiterRejectedException(_message, _retryAfter); + exception.InnerException.Should().BeNull(); + exception.Message.Should().Be(_message); + exception.RetryAfter.Should().Be(_retryAfter); + exception.TelemetrySource.Should().BeNull(); + } + + [Fact] + public void Ctor_Message_InnerException_Ok() + { + var exception = new RateLimiterRejectedException(_message, new InvalidOperationException()); + exception.InnerException.Should().BeOfType(); + exception.Message.Should().Be(_message); + exception.RetryAfter.Should().BeNull(); + exception.TelemetrySource.Should().BeNull(); + } - new RateLimiterRejectedException().Message.Should().Be("The operation could not be executed because it was rejected by the rate limiter."); - new RateLimiterRejectedException().RetryAfter.Should().BeNull(); - new RateLimiterRejectedException("dummy").Message.Should().Be("dummy"); - new RateLimiterRejectedException("dummy", new InvalidOperationException()).Message.Should().Be("dummy"); - new RateLimiterRejectedException(retryAfter).RetryAfter.Should().Be(retryAfter); - new RateLimiterRejectedException(retryAfter).Message.Should().Be($"The operation could not be executed because it was rejected by the rate limiter. It can be retried after '{retryAfter}'."); - new RateLimiterRejectedException("dummy", retryAfter).RetryAfter.Should().Be(retryAfter); - new RateLimiterRejectedException("dummy", retryAfter, new InvalidOperationException()).RetryAfter.Should().Be(retryAfter); + [Fact] + public void Ctor_Message_RetryAfter_InnerException_Ok() + { + var exception = new RateLimiterRejectedException(_message, _retryAfter, new InvalidOperationException()); + exception.InnerException.Should().BeOfType(); + exception.Message.Should().Be(_message); + exception.RetryAfter.Should().Be(_retryAfter); + exception.TelemetrySource.Should().BeNull(); } #if !NETCOREAPP From 9a4b78d75f8179a894c669fa56b7b52147d4144d Mon Sep 17 00:00:00 2001 From: peter-csala Date: Tue, 22 Oct 2024 09:33:19 +0200 Subject: [PATCH 2/6] Add TelemetrySource to ExecutionRejectedException --- .../ResilienceStrategyTelemetryTests.cs | 23 +++++++++++++++++++ .../Timeout/TimeoutResilienceStrategyTests.cs | 21 +++++++++++++++++ .../RateLimiterResilienceStrategyTests.cs | 10 ++++---- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs b/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs index 90b58338be1..8bd787dc94b 100644 --- a/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs +++ b/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs @@ -1,4 +1,5 @@ using Polly.Telemetry; +using Polly.Timeout; namespace Polly.Core.Tests.Telemetry; @@ -94,4 +95,26 @@ public void Report_NoListener_ShouldNotThrow() .Should() .NotThrow(); } + + [Fact] + public void UpdateTelemetrySource_Ok() + { + var sut = new ResilienceStrategyTelemetry(_source, null); + var exception = new TimeoutRejectedException(); + + sut.UpdateTelemetrySource(exception); + + exception.TelemetrySource.Should().Be(_source); + } + + [Fact] + public void UpdateTelemetrySource_ShouldThrow() + { + ExecutionRejectedException? exception = null; + + _sut.Invoking(s => s.UpdateTelemetrySource(exception!)) + .Should() + .Throw() + .WithMessage("Value cannot be null. (Parameter 'exception')"); + } } diff --git a/test/Polly.Core.Tests/Timeout/TimeoutResilienceStrategyTests.cs b/test/Polly.Core.Tests/Timeout/TimeoutResilienceStrategyTests.cs index 1af944ab350..1d6c8e0a8ae 100644 --- a/test/Polly.Core.Tests/Timeout/TimeoutResilienceStrategyTests.cs +++ b/test/Polly.Core.Tests/Timeout/TimeoutResilienceStrategyTests.cs @@ -173,6 +173,27 @@ public async Task Execute_Timeout_EnsureStackTrace() } } + [Fact] + public async Task Execute_Timeout_EnsureTelemetrySource() + { + SetTimeout(TimeSpan.FromSeconds(2)); + var sut = CreateSut(); + + var outcome = await sut.ExecuteOutcomeAsync( + async (c, _) => + { + var delay = _timeProvider.Delay(TimeSpan.FromSeconds(4), c.CancellationToken); + _timeProvider.Advance(TimeSpan.FromSeconds(2)); + await delay; + + return Outcome.FromResult("dummy"); + }, + ResilienceContextPool.Shared.Get(), + "state"); + + outcome.Exception.Should().BeOfType().Subject.TelemetrySource.Should().NotBeNull(); + } + [Fact] public async Task Execute_Cancelled_EnsureNoTimeout() { diff --git a/test/Polly.RateLimiting.Tests/RateLimiterResilienceStrategyTests.cs b/test/Polly.RateLimiting.Tests/RateLimiterResilienceStrategyTests.cs index febb350bcf5..3032d3e3676 100644 --- a/test/Polly.RateLimiting.Tests/RateLimiterResilienceStrategyTests.cs +++ b/test/Polly.RateLimiting.Tests/RateLimiterResilienceStrategyTests.cs @@ -70,13 +70,13 @@ public async Task Execute_LeaseRejected(bool hasEvents, bool hasRetryAfter) var context = ResilienceContextPool.Shared.Get(cts.Token); var outcome = await strategy.ExecuteOutcomeAsync((_, _) => Outcome.FromResultAsValueTask("dummy"), context, "state"); - outcome.Exception + RateLimiterRejectedException exception = outcome.Exception .Should() - .BeOfType().Subject - .RetryAfter - .Should().Be((TimeSpan?)metadata); + .BeOfType().Subject; - outcome.Exception!.StackTrace.Should().Contain("Execute_LeaseRejected"); + exception.RetryAfter.Should().Be((TimeSpan?)metadata); + exception.StackTrace.Should().Contain("Execute_LeaseRejected"); + exception.TelemetrySource.Should().NotBeNull(); eventCalled.Should().Be(hasEvents); From c50e2c25291c0a927b8c780d80f0213b5dbd1cef Mon Sep 17 00:00:00 2001 From: peter-csala Date: Tue, 22 Oct 2024 10:18:01 +0200 Subject: [PATCH 3/6] Add TelemetrySource to ExecutionRejectedException --- .../Telemetry/ResilienceStrategyTelemetryTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs b/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs index 8bd787dc94b..8d73af5a07e 100644 --- a/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs +++ b/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs @@ -114,7 +114,6 @@ public void UpdateTelemetrySource_ShouldThrow() _sut.Invoking(s => s.UpdateTelemetrySource(exception!)) .Should() - .Throw() - .WithMessage("Value cannot be null. (Parameter 'exception')"); + .Throw(); } } From dff675ec0edd50ec1480108a7870df44b40b050d Mon Sep 17 00:00:00 2001 From: peter-csala Date: Tue, 22 Oct 2024 10:35:28 +0200 Subject: [PATCH 4/6] Add TelemetrySource to ExecutionRejectedException --- .../Controller/CircuitStateControllerTests.cs | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/test/Polly.Core.Tests/CircuitBreaker/Controller/CircuitStateControllerTests.cs b/test/Polly.Core.Tests/CircuitBreaker/Controller/CircuitStateControllerTests.cs index 7a623544629..091de464e3e 100644 --- a/test/Polly.Core.Tests/CircuitBreaker/Controller/CircuitStateControllerTests.cs +++ b/test/Polly.Core.Tests/CircuitBreaker/Controller/CircuitStateControllerTests.cs @@ -52,8 +52,9 @@ public async Task IsolateAsync_Ok() called.Should().BeTrue(); var outcome = await controller.OnActionPreExecuteAsync(ResilienceContextPool.Shared.Get()); - outcome.Value.Exception.Should().BeOfType() - .And.Subject.As().RetryAfter.Should().BeNull(); + var exception = outcome.Value.Exception.Should().BeOfType().Subject; + exception.RetryAfter.Should().BeNull(); + exception.TelemetrySource.Should().NotBeNull(); // now close it await controller.CloseCircuitAsync(ResilienceContextPool.Shared.Get()); @@ -119,8 +120,9 @@ public async Task OnActionPreExecute_CircuitOpenedByValue() using var controller = CreateController(); await OpenCircuit(controller, Outcome.FromResult(99)); - var error = (BrokenCircuitException)(await controller.OnActionPreExecuteAsync(ResilienceContextPool.Shared.Get())).Value.Exception!; - error.Should().BeOfType().And.Subject.As().RetryAfter.Should().NotBeNull(); + var exception = (BrokenCircuitException)(await controller.OnActionPreExecuteAsync(ResilienceContextPool.Shared.Get())).Value.Exception!; + exception.RetryAfter.Should().NotBeNull(); + exception.TelemetrySource.Should().NotBeNull(); GetBlockedTill(controller).Should().Be(_timeProvider.GetUtcNow() + _options.BreakDuration); } @@ -149,6 +151,7 @@ await OpenCircuit( stacks.Add(e.StackTrace!); e.Message.Should().Be("The circuit is now open and is not allowing calls."); e.RetryAfter.Should().NotBeNull(); + e.TelemetrySource.Should().NotBeNull(); if (innerException) { @@ -206,9 +209,10 @@ public async Task OnActionPreExecute_CircuitOpenedByException() using var controller = CreateController(); await OpenCircuit(controller, Outcome.FromException(new InvalidOperationException())); - var error = (BrokenCircuitException)(await controller.OnActionPreExecuteAsync(ResilienceContextPool.Shared.Get())).Value.Exception!; - error.InnerException.Should().BeOfType(); - error.RetryAfter.Should().NotBeNull(); + var exception = (BrokenCircuitException)(await controller.OnActionPreExecuteAsync(ResilienceContextPool.Shared.Get())).Value.Exception!; + exception.InnerException.Should().BeOfType(); + exception.RetryAfter.Should().NotBeNull(); + exception.TelemetrySource.Should().NotBeNull(); } [Fact] @@ -261,9 +265,11 @@ public async Task OnActionPreExecute_HalfOpen() // act await controller.OnActionPreExecuteAsync(ResilienceContextPool.Shared.Get()); var error = (await controller.OnActionPreExecuteAsync(ResilienceContextPool.Shared.Get())).Value.Exception; - error.Should().BeOfType().And.Subject.As().RetryAfter.Should().NotBeNull(); // assert + var exception = error.Should().BeOfType().Subject; + exception.RetryAfter.Should().NotBeNull(); + exception.TelemetrySource.Should().NotBeNull(); controller.CircuitState.Should().Be(CircuitState.HalfOpen); called.Should().BeTrue(); } @@ -465,7 +471,9 @@ public async Task OnActionFailureAsync_VoidResult_EnsureBreakingExceptionNotSet( // assert controller.LastException.Should().BeNull(); var outcome = await controller.OnActionPreExecuteAsync(ResilienceContextPool.Shared.Get()); - outcome.Value.Exception.Should().BeOfType().And.Subject.As().RetryAfter.Should().NotBeNull(); + var exception = outcome.Value.Exception.Should().BeOfType().Subject; + exception.RetryAfter.Should().NotBeNull(); + exception.TelemetrySource.Should().NotBeNull(); } [Fact] @@ -501,8 +509,9 @@ public async Task Flow_Closed_HalfOpen_Open_HalfOpen_Closed() TimeSpan advanceTimeRejected = TimeSpan.FromMilliseconds(1); AdvanceTime(advanceTimeRejected); var outcome = await controller.OnActionPreExecuteAsync(ResilienceContextPool.Shared.Get()); - outcome.Value.Exception.Should().BeOfType() - .And.Subject.As().RetryAfter.Should().Be(_options.BreakDuration - advanceTimeRejected); + var exception = outcome.Value.Exception.Should().BeOfType().Subject; + exception.RetryAfter.Should().Be(_options.BreakDuration - advanceTimeRejected); + exception.TelemetrySource.Should().NotBeNull(); // wait and try, transition to half open AdvanceTime(_options.BreakDuration + _options.BreakDuration); From 4565335a4cc7bf6d28a0da034a5cf06a26a1f6c8 Mon Sep 17 00:00:00 2001 From: peter-csala Date: Wed, 23 Oct 2024 14:11:21 +0200 Subject: [PATCH 5/6] Add TelemetrySource to ExecutionRejectedException --- .../CircuitBreaker/Controller/CircuitStateController.cs | 8 ++++---- src/Polly.Core/ExecutionRejectedException.cs | 1 - src/Polly.Core/PublicAPI.Unshipped.txt | 2 +- src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs | 4 ++-- src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs | 2 +- src/Polly.RateLimiting/RateLimiterResilienceStrategy.cs | 6 +++--- .../Telemetry/ResilienceStrategyTelemetryTests.cs | 8 ++++---- 7 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs b/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs index 57d0afca782..53b4a3c04ed 100644 --- a/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs +++ b/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs @@ -96,7 +96,7 @@ public ValueTask IsolateCircuitAsync(ResilienceContext context) lock (_lock) { var exception = new IsolatedCircuitException(); - _telemetry.UpdateTelemetrySource(exception); + _telemetry.SetTelemetrySource(exception); SetLastHandledOutcome_NeedsLock(Outcome.FromException(exception)); OpenCircuitFor_NeedsLock(Outcome.FromResult(default), TimeSpan.MaxValue, manual: true, context, out task); _circuitState = CircuitState.Isolated; @@ -159,7 +159,7 @@ public ValueTask CloseCircuitAsync(ResilienceContext context) if (exception is not null) { - _telemetry.UpdateTelemetrySource(exception); + _telemetry.SetTelemetrySource(exception); return Outcome.FromException(exception); } @@ -311,12 +311,12 @@ private void SetLastHandledOutcome_NeedsLock(Outcome outcome) private BrokenCircuitException CreateBrokenCircuitException() { TimeSpan retryAfter = _blockedUntil - _timeProvider.GetUtcNow(); - BrokenCircuitException exception = _breakingException switch + var exception = _breakingException switch { Exception ex => new BrokenCircuitException(BrokenCircuitException.DefaultMessage, retryAfter, ex), _ => new BrokenCircuitException(BrokenCircuitException.DefaultMessage, retryAfter) }; - _telemetry.UpdateTelemetrySource(exception); + _telemetry.SetTelemetrySource(exception); return exception; } diff --git a/src/Polly.Core/ExecutionRejectedException.cs b/src/Polly.Core/ExecutionRejectedException.cs index 3718d30c457..bffece9058e 100644 --- a/src/Polly.Core/ExecutionRejectedException.cs +++ b/src/Polly.Core/ExecutionRejectedException.cs @@ -56,5 +56,4 @@ protected ExecutionRejectedException(SerializationInfo info, StreamingContext co /// Gets the source of the strategy which has thrown the exception, if known. /// public virtual ResilienceTelemetrySource? TelemetrySource { get; internal set; } - } diff --git a/src/Polly.Core/PublicAPI.Unshipped.txt b/src/Polly.Core/PublicAPI.Unshipped.txt index 5101967e54e..df1ac3ec332 100644 --- a/src/Polly.Core/PublicAPI.Unshipped.txt +++ b/src/Polly.Core/PublicAPI.Unshipped.txt @@ -4,4 +4,4 @@ Polly.CircuitBreaker.BrokenCircuitException.BrokenCircuitException(string! messa Polly.CircuitBreaker.BrokenCircuitException.BrokenCircuitException(System.TimeSpan retryAfter) -> void Polly.CircuitBreaker.BrokenCircuitException.RetryAfter.get -> System.TimeSpan? virtual Polly.ExecutionRejectedException.TelemetrySource.get -> Polly.Telemetry.ResilienceTelemetrySource? -Polly.Telemetry.ResilienceStrategyTelemetry.UpdateTelemetrySource(Polly.ExecutionRejectedException! exception) -> void +Polly.Telemetry.ResilienceStrategyTelemetry.SetTelemetrySource(Polly.ExecutionRejectedException! exception) -> void diff --git a/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs b/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs index 1ec34820450..55381aa003e 100644 --- a/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs +++ b/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs @@ -24,11 +24,11 @@ internal ResilienceStrategyTelemetry(ResilienceTelemetrySource source, Telemetry internal ResilienceTelemetrySource TelemetrySource { get; } /// - /// Updates the source of the telemetry on the provided exception. + /// Sets the source of the telemetry on the provided exception. /// /// The to-be-updated exception. [EditorBrowsable(EditorBrowsableState.Never)] - public void UpdateTelemetrySource(ExecutionRejectedException exception) + public void SetTelemetrySource(ExecutionRejectedException exception) { Guard.NotNull(exception); diff --git a/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs b/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs index e9e304b36b3..98f570c87fb 100644 --- a/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs +++ b/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs @@ -74,7 +74,7 @@ protected internal override async ValueTask> ExecuteCore(timeoutException.TrySetStackTrace()); } diff --git a/src/Polly.RateLimiting/RateLimiterResilienceStrategy.cs b/src/Polly.RateLimiting/RateLimiterResilienceStrategy.cs index 861350558eb..f7431e571f6 100644 --- a/src/Polly.RateLimiting/RateLimiterResilienceStrategy.cs +++ b/src/Polly.RateLimiting/RateLimiterResilienceStrategy.cs @@ -65,11 +65,11 @@ protected override async ValueTask> ExecuteCore(exception.TrySetStackTrace()); } diff --git a/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs b/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs index 8d73af5a07e..743271b6c07 100644 --- a/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs +++ b/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs @@ -97,22 +97,22 @@ public void Report_NoListener_ShouldNotThrow() } [Fact] - public void UpdateTelemetrySource_Ok() + public void SetTelemetrySource_Ok() { var sut = new ResilienceStrategyTelemetry(_source, null); var exception = new TimeoutRejectedException(); - sut.UpdateTelemetrySource(exception); + sut.SetTelemetrySource(exception); exception.TelemetrySource.Should().Be(_source); } [Fact] - public void UpdateTelemetrySource_ShouldThrow() + public void SetTelemetrySource_ShouldThrow() { ExecutionRejectedException? exception = null; - _sut.Invoking(s => s.UpdateTelemetrySource(exception!)) + _sut.Invoking(s => s.SetTelemetrySource(exception!)) .Should() .Throw(); } From 167592c8e4c84bd3f4946c4f627fec152d0f1c5e Mon Sep 17 00:00:00 2001 From: peter-csala <57183693+peter-csala@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:20:22 +0200 Subject: [PATCH 6/6] Update src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs Co-authored-by: Martin Costello --- src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs b/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs index 55381aa003e..e793202e7ad 100644 --- a/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs +++ b/src/Polly.Core/Telemetry/ResilienceStrategyTelemetry.cs @@ -26,7 +26,7 @@ internal ResilienceStrategyTelemetry(ResilienceTelemetrySource source, Telemetry /// /// Sets the source of the telemetry on the provided exception. /// - /// The to-be-updated exception. + /// The to-be-set exception. [EditorBrowsable(EditorBrowsableState.Never)] public void SetTelemetrySource(ExecutionRejectedException exception) {