9
9
using Microsoft . IdentityModel . Logging ;
10
10
using Microsoft . IdentityModel . Protocols . Configuration ;
11
11
using Microsoft . IdentityModel . Tokens ;
12
+ using Microsoft . IdentityModel . Telemetry ;
12
13
13
14
namespace Microsoft . IdentityModel . Protocols
14
15
{
@@ -45,6 +46,7 @@ public class ConfigurationManager<T> : BaseConfigurationManager, IConfigurationM
45
46
private int _configurationRetrieverState = ConfigurationRetrieverIdle ;
46
47
47
48
private readonly TimeProvider _timeProvider = TimeProvider . System ;
49
+ internal ITelemetryClient TelemetryClient = new TelemetryClient ( ) ;
48
50
49
51
// If a refresh is requested, then do the refresh as a blocking operation
50
52
// not on a background thread. RequestRefresh signals that the app is explicitly
@@ -53,6 +55,7 @@ public class ConfigurationManager<T> : BaseConfigurationManager, IConfigurationM
53
55
// refresh interval has passed.
54
56
bool _refreshRequested ;
55
57
58
+
56
59
/// <summary>
57
60
/// Instantiates a new <see cref="ConfigurationManager{T}"/> that manages automatic and controls refreshing on configuration data.
58
61
/// </summary>
@@ -190,7 +193,7 @@ public virtual async Task<T> GetConfigurationAsync(CancellationToken cancel)
190
193
try
191
194
{
192
195
// Don't use the individual CT here, this is a shared operation that shouldn't be affected by an individual's cancellation.
193
- // The transport should have it's own timeouts, etc.
196
+ // The transport should have its own timeouts, etc.
194
197
T configuration = await _configRetriever . GetConfigurationAsync (
195
198
MetadataAddress ,
196
199
_docRetriever ,
@@ -201,18 +204,29 @@ public virtual async Task<T> GetConfigurationAsync(CancellationToken cancel)
201
204
ConfigurationValidationResult result = _configValidator . Validate ( configuration ) ;
202
205
// in this case we have never had a valid configuration, so we will throw an exception if the validation fails
203
206
if ( ! result . Succeeded )
204
- throw LogHelper . LogExceptionMessage (
205
- new InvalidConfigurationException (
206
- LogHelper . FormatInvariant (
207
- LogMessages . IDX20810 ,
208
- result . ErrorMessage ) ) ) ;
207
+ {
208
+ var ex = new InvalidConfigurationException (
209
+ LogHelper . FormatInvariant (
210
+ LogMessages . IDX20810 ,
211
+ result . ErrorMessage ) ) ;
212
+
213
+ throw LogHelper . LogExceptionMessage ( ex ) ;
214
+ }
209
215
}
210
216
217
+ TelemetryClient . IncrementConfigurationRefreshRequestCounter (
218
+ MetadataAddress ,
219
+ TelemetryConstants . Protocols . FirstRefresh ) ;
220
+
211
221
UpdateConfiguration ( configuration ) ;
212
222
}
213
223
catch ( Exception ex )
214
224
{
215
225
fetchMetadataFailure = ex ;
226
+ TelemetryClient . IncrementConfigurationRefreshRequestCounter (
227
+ MetadataAddress ,
228
+ TelemetryConstants . Protocols . FirstRefresh ,
229
+ ex ) ;
216
230
217
231
LogHelper . LogExceptionMessage (
218
232
new InvalidOperationException (
@@ -234,11 +248,22 @@ public virtual async Task<T> GetConfigurationAsync(CancellationToken cancel)
234
248
{
235
249
if ( _refreshRequested )
236
250
{
251
+ // Log as manual because RequestRefresh was called
252
+ TelemetryClient . IncrementConfigurationRefreshRequestCounter (
253
+ MetadataAddress ,
254
+ TelemetryConstants . Protocols . Manual ) ;
255
+
237
256
UpdateCurrentConfiguration ( ) ;
238
257
_refreshRequested = false ;
239
258
}
240
259
else
260
+ {
261
+ TelemetryClient . IncrementConfigurationRefreshRequestCounter (
262
+ MetadataAddress ,
263
+ TelemetryConstants . Protocols . Automatic ) ;
264
+
241
265
_ = Task . Run ( UpdateCurrentConfiguration , CancellationToken . None ) ;
266
+ }
242
267
}
243
268
}
244
269
@@ -264,13 +289,20 @@ public virtual async Task<T> GetConfigurationAsync(CancellationToken cancel)
264
289
private void UpdateCurrentConfiguration ( )
265
290
{
266
291
#pragma warning disable CA1031 // Do not catch general exception types
292
+ long startTimestamp = _timeProvider . GetTimestamp ( ) ;
293
+
267
294
try
268
295
{
269
296
T configuration = _configRetriever . GetConfigurationAsync (
270
297
MetadataAddress ,
271
298
_docRetriever ,
272
299
CancellationToken . None ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
273
300
301
+ var elapsedTime = _timeProvider . GetElapsedTime ( startTimestamp ) ;
302
+ TelemetryClient . LogConfigurationRetrievalDuration (
303
+ MetadataAddress ,
304
+ elapsedTime ) ;
305
+
274
306
if ( _configValidator == null )
275
307
{
276
308
UpdateConfiguration ( configuration ) ;
@@ -291,6 +323,12 @@ private void UpdateCurrentConfiguration()
291
323
}
292
324
catch ( Exception ex )
293
325
{
326
+ var elapsedTime = _timeProvider . GetElapsedTime ( startTimestamp ) ;
327
+ TelemetryClient . LogConfigurationRetrievalDuration (
328
+ MetadataAddress ,
329
+ elapsedTime ,
330
+ ex ) ;
331
+
294
332
LogHelper . LogExceptionMessage (
295
333
new InvalidOperationException (
296
334
LogHelper . FormatInvariant (
@@ -336,7 +374,7 @@ ref Unsafe.As<DateTime, long>(ref _lastRequestRefresh),
336
374
/// Obtains an updated version of Configuration.
337
375
/// </summary>
338
376
/// <param name="cancel">CancellationToken</param>
339
- /// <returns>Configuration of type BaseConfiguration .</returns>
377
+ /// <returns>Configuration of type BaseConfiguration.</returns>
340
378
/// <remarks>If the time since the last call is less than <see cref="BaseConfigurationManager.AutomaticRefreshInterval"/> then <see cref="IConfigurationRetriever{T}.GetConfigurationAsync"/> is not called and the current Configuration is returned.</remarks>
341
379
public override async Task < BaseConfiguration > GetBaseConfigurationAsync ( CancellationToken cancel )
342
380
{
@@ -353,6 +391,7 @@ public override async Task<BaseConfiguration> GetBaseConfigurationAsync(Cancella
353
391
public override void RequestRefresh ( )
354
392
{
355
393
DateTime now = _timeProvider . GetUtcNow ( ) . UtcDateTime ;
394
+
356
395
if ( now >= DateTimeUtil . Add ( LastRequestRefresh , RefreshInterval ) || _isFirstRefreshRequest )
357
396
{
358
397
_isFirstRefreshRequest = false ;
0 commit comments