1+ using System ;
12using Polly . Hedging . Utils ;
3+ using Polly . Telemetry ;
24
35namespace Polly . Hedging . Controller ;
46
@@ -21,15 +23,21 @@ internal sealed class TaskExecution<T>
2123{
2224 private readonly ResilienceContext _cachedContext = ResilienceContext . Get ( ) ;
2325 private readonly CancellationTokenSourcePool _cancellationTokenSourcePool ;
26+ private readonly TimeProvider _timeProvider ;
27+ private readonly ResilienceStrategyTelemetry _telemetry ;
2428 private readonly HedgingHandler < T > _handler ;
2529 private CancellationTokenSource ? _cancellationSource ;
2630 private CancellationTokenRegistration ? _cancellationRegistration ;
2731 private ResilienceContext ? _activeContext ;
32+ private long _startExecutionTimestamp ;
33+ private long _stopExecutionTimestamp ;
2834
29- public TaskExecution ( HedgingHandler < T > handler , CancellationTokenSourcePool cancellationTokenSourcePool )
35+ public TaskExecution ( HedgingHandler < T > handler , CancellationTokenSourcePool cancellationTokenSourcePool , TimeProvider timeProvider , ResilienceStrategyTelemetry telemetry )
3036 {
3137 _handler = handler ;
3238 _cancellationTokenSourcePool = cancellationTokenSourcePool ;
39+ _timeProvider = timeProvider ;
40+ _telemetry = telemetry ;
3341 }
3442
3543 /// <summary>
@@ -56,6 +64,10 @@ public TaskExecution(HedgingHandler<T> handler, CancellationTokenSourcePool canc
5664
5765 public Action < TaskExecution < T > > ? OnReset { get ; set ; }
5866
67+ public TimeSpan ExecutionTime => _timeProvider . GetElapsedTime ( _startExecutionTimestamp , _stopExecutionTimestamp ) ;
68+
69+ public int Attempt { get ; private set ; }
70+
5971 public void AcceptOutcome ( )
6072 {
6173 if ( ExecutionTaskSafe ? . IsCompleted == true )
@@ -83,8 +95,10 @@ public async ValueTask<bool> InitializeAsync<TResult, TState>(
8395 TState state ,
8496 int attempt )
8597 {
98+ Attempt = attempt ;
8699 Type = type ;
87100 _cancellationSource = _cancellationTokenSourcePool . Get ( System . Threading . Timeout . InfiniteTimeSpan ) ;
101+ _startExecutionTimestamp = _timeProvider . GetTimestamp ( ) ;
88102 Properties . Replace ( snapshot . OriginalProperties ) ;
89103
90104 if ( snapshot . OriginalCancellationToken . CanBeCanceled )
@@ -109,6 +123,7 @@ public async ValueTask<bool> InitializeAsync<TResult, TState>(
109123 }
110124 catch ( Exception e )
111125 {
126+ _stopExecutionTimestamp = _timeProvider . GetTimestamp ( ) ;
112127 ExecutionTaskSafe = ExecuteCreateActionException < TResult > ( e ) ;
113128 return true ;
114129 }
@@ -164,9 +179,12 @@ public async ValueTask ResetAsync()
164179 IsHandled = false ;
165180 Properties . Clear ( ) ;
166181 OnReset = null ;
182+ Attempt = 0 ;
167183 _activeContext = null ;
168184 _cachedContext . Reset ( ) ;
169185 _cancellationSource = null ! ;
186+ _startExecutionTimestamp = 0 ;
187+ _stopExecutionTimestamp = 0 ;
170188 }
171189
172190 private async Task ExecuteSecondaryActionAsync < TResult > ( Func < ValueTask < Outcome < TResult > > > action )
@@ -182,6 +200,7 @@ private async Task ExecuteSecondaryActionAsync<TResult>(Func<ValueTask<Outcome<T
182200 outcome = new Outcome < TResult > ( e ) ;
183201 }
184202
203+ _stopExecutionTimestamp = _timeProvider . GetTimestamp ( ) ;
185204 await UpdateOutcomeAsync ( outcome ) . ConfigureAwait ( Context . ContinueOnCapturedContext ) ;
186205 }
187206
@@ -203,6 +222,7 @@ private async Task ExecutePrimaryActionAsync<TResult, TState>(Func<ResilienceCon
203222 outcome = new Outcome < TResult > ( e ) ;
204223 }
205224
225+ _stopExecutionTimestamp = _timeProvider . GetTimestamp ( ) ;
206226 await UpdateOutcomeAsync ( outcome ) . ConfigureAwait ( Context . ContinueOnCapturedContext ) ;
207227 }
208228
@@ -211,6 +231,7 @@ private async Task UpdateOutcomeAsync<TResult>(Outcome<TResult> outcome)
211231 var args = new OutcomeArguments < TResult , HedgingPredicateArguments > ( Context , outcome , new HedgingPredicateArguments ( ) ) ;
212232 Outcome = outcome . AsOutcome ( ) ;
213233 IsHandled = await _handler . ShouldHandle . HandleAsync ( args ) . ConfigureAwait ( Context . ContinueOnCapturedContext ) ;
234+ TelemetryUtil . ReportExecutionAttempt ( _telemetry , Context , outcome , Attempt , ExecutionTime , IsHandled ) ;
214235 }
215236
216237 private void PrepareContext ( ref ContextSnapshot snapshot )
0 commit comments