1
+ using System ;
1
2
using Polly . Hedging . Utils ;
3
+ using Polly . Telemetry ;
2
4
3
5
namespace Polly . Hedging . Controller ;
4
6
@@ -21,15 +23,21 @@ internal sealed class TaskExecution<T>
21
23
{
22
24
private readonly ResilienceContext _cachedContext = ResilienceContext . Get ( ) ;
23
25
private readonly CancellationTokenSourcePool _cancellationTokenSourcePool ;
26
+ private readonly TimeProvider _timeProvider ;
27
+ private readonly ResilienceStrategyTelemetry _telemetry ;
24
28
private readonly HedgingHandler < T > _handler ;
25
29
private CancellationTokenSource ? _cancellationSource ;
26
30
private CancellationTokenRegistration ? _cancellationRegistration ;
27
31
private ResilienceContext ? _activeContext ;
32
+ private long _startExecutionTimestamp ;
33
+ private long _stopExecutionTimestamp ;
28
34
29
- public TaskExecution ( HedgingHandler < T > handler , CancellationTokenSourcePool cancellationTokenSourcePool )
35
+ public TaskExecution ( HedgingHandler < T > handler , CancellationTokenSourcePool cancellationTokenSourcePool , TimeProvider timeProvider , ResilienceStrategyTelemetry telemetry )
30
36
{
31
37
_handler = handler ;
32
38
_cancellationTokenSourcePool = cancellationTokenSourcePool ;
39
+ _timeProvider = timeProvider ;
40
+ _telemetry = telemetry ;
33
41
}
34
42
35
43
/// <summary>
@@ -56,6 +64,10 @@ public TaskExecution(HedgingHandler<T> handler, CancellationTokenSourcePool canc
56
64
57
65
public Action < TaskExecution < T > > ? OnReset { get ; set ; }
58
66
67
+ public TimeSpan ExecutionTime => _timeProvider . GetElapsedTime ( _startExecutionTimestamp , _stopExecutionTimestamp ) ;
68
+
69
+ public int Attempt { get ; private set ; }
70
+
59
71
public void AcceptOutcome ( )
60
72
{
61
73
if ( ExecutionTaskSafe ? . IsCompleted == true )
@@ -83,8 +95,10 @@ public async ValueTask<bool> InitializeAsync<TResult, TState>(
83
95
TState state ,
84
96
int attempt )
85
97
{
98
+ Attempt = attempt ;
86
99
Type = type ;
87
100
_cancellationSource = _cancellationTokenSourcePool . Get ( System . Threading . Timeout . InfiniteTimeSpan ) ;
101
+ _startExecutionTimestamp = _timeProvider . GetTimestamp ( ) ;
88
102
Properties . Replace ( snapshot . OriginalProperties ) ;
89
103
90
104
if ( snapshot . OriginalCancellationToken . CanBeCanceled )
@@ -109,6 +123,7 @@ public async ValueTask<bool> InitializeAsync<TResult, TState>(
109
123
}
110
124
catch ( Exception e )
111
125
{
126
+ _stopExecutionTimestamp = _timeProvider . GetTimestamp ( ) ;
112
127
ExecutionTaskSafe = ExecuteCreateActionException < TResult > ( e ) ;
113
128
return true ;
114
129
}
@@ -164,9 +179,12 @@ public async ValueTask ResetAsync()
164
179
IsHandled = false ;
165
180
Properties . Clear ( ) ;
166
181
OnReset = null ;
182
+ Attempt = 0 ;
167
183
_activeContext = null ;
168
184
_cachedContext . Reset ( ) ;
169
185
_cancellationSource = null ! ;
186
+ _startExecutionTimestamp = 0 ;
187
+ _stopExecutionTimestamp = 0 ;
170
188
}
171
189
172
190
private async Task ExecuteSecondaryActionAsync < TResult > ( Func < ValueTask < Outcome < TResult > > > action )
@@ -182,6 +200,7 @@ private async Task ExecuteSecondaryActionAsync<TResult>(Func<ValueTask<Outcome<T
182
200
outcome = new Outcome < TResult > ( e ) ;
183
201
}
184
202
203
+ _stopExecutionTimestamp = _timeProvider . GetTimestamp ( ) ;
185
204
await UpdateOutcomeAsync ( outcome ) . ConfigureAwait ( Context . ContinueOnCapturedContext ) ;
186
205
}
187
206
@@ -203,6 +222,7 @@ private async Task ExecutePrimaryActionAsync<TResult, TState>(Func<ResilienceCon
203
222
outcome = new Outcome < TResult > ( e ) ;
204
223
}
205
224
225
+ _stopExecutionTimestamp = _timeProvider . GetTimestamp ( ) ;
206
226
await UpdateOutcomeAsync ( outcome ) . ConfigureAwait ( Context . ContinueOnCapturedContext ) ;
207
227
}
208
228
@@ -211,6 +231,7 @@ private async Task UpdateOutcomeAsync<TResult>(Outcome<TResult> outcome)
211
231
var args = new OutcomeArguments < TResult , HedgingPredicateArguments > ( Context , outcome , new HedgingPredicateArguments ( ) ) ;
212
232
Outcome = outcome . AsOutcome ( ) ;
213
233
IsHandled = await _handler . ShouldHandle . HandleAsync ( args ) . ConfigureAwait ( Context . ContinueOnCapturedContext ) ;
234
+ TelemetryUtil . ReportExecutionAttempt ( _telemetry , Context , outcome , Attempt , ExecutionTime , IsHandled ) ;
214
235
}
215
236
216
237
private void PrepareContext ( ref ContextSnapshot snapshot )
0 commit comments