From 5e917c902f0f02e60bdb690646e804f5b5e2980e Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:24:44 -0800 Subject: [PATCH] add metadata --- .../JsonWebTokenHandler.ValidateToken.cs | 1 + .../Configuration/ConfigurationManager.cs | 23 ++++++++++++++---- .../InternalAPI.Unshipped.txt | 16 ++++++------- .../Telemetry/ITelemetryInstrumentation.cs | 4 ++++ .../Telemetry/TelemetryInstrumentation.cs | 24 ++++++++++++------- .../JwtSecurityTokenHandler.cs | 1 + .../JsonWebTokenHandlerTelemetryTests.cs | 4 +++- .../ConfigurationManagerTelemetryTests.cs | 7 +++++- .../Telemetry/MockTelemetryInstrumentation.cs | 12 ++++++---- .../JwtSecurityTokenHandlerTelemetryTests.cs | 2 ++ 10 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs index b3c0844473..86028f361e 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs @@ -515,6 +515,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration) if (currentConfiguration != null) { _telemetryClient.IncrementConfigurationRefreshRequestCounter( + validationParameters.ConfigurationManager.MetadataAddress, TelemetryConstants.Protocols.LKG); validationParameters.ConfigurationManager.RequestRefresh(); diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index d099239d82..76743f0ef9 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -196,6 +196,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) result.ErrorMessage)); _telemetryClient.IncrementConfigurationRefreshRequestCounter( + MetadataAddress, TelemetryConstants.Protocols.FirstRefresh, ex); @@ -203,14 +204,17 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) } } - _telemetryClient.IncrementConfigurationRefreshRequestCounter(TelemetryConstants.Protocols.FirstRefresh); + _telemetryClient.IncrementConfigurationRefreshRequestCounter( + MetadataAddress, + TelemetryConstants.Protocols.FirstRefresh); + UpdateConfiguration(configuration); } catch (Exception ex) { - // counter for failure first time fetchMetadataFailure = ex; _telemetryClient.IncrementConfigurationRefreshRequestCounter( + MetadataAddress, TelemetryConstants.Protocols.FirstRefresh, ex); @@ -232,7 +236,10 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) { if (Interlocked.CompareExchange(ref _configurationRetrieverState, ConfigurationRetrieverRunning, ConfigurationRetrieverIdle) == ConfigurationRetrieverIdle) { - _telemetryClient.IncrementConfigurationRefreshRequestCounter(TelemetryConstants.Protocols.Automatic); + _telemetryClient.IncrementConfigurationRefreshRequestCounter( + MetadataAddress, + TelemetryConstants.Protocols.Automatic); + _ = Task.Run(UpdateCurrentConfiguration, CancellationToken.None); } } @@ -271,7 +278,9 @@ private void UpdateCurrentConfiguration() CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); var elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); - _telemetryClient.LogConfigurationRetrievalDuration(elapsedTime); + _telemetryClient.LogConfigurationRetrievalDuration( + MetadataAddress, + elapsedTime); if (_configValidator == null) { @@ -295,6 +304,7 @@ private void UpdateCurrentConfiguration() { var elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); _telemetryClient.LogConfigurationRetrievalDuration( + MetadataAddress, elapsedTime, ex); @@ -342,7 +352,10 @@ public override void RequestRefresh() { DateTimeOffset now = DateTimeOffset.UtcNow; - _telemetryClient.IncrementConfigurationRefreshRequestCounter(TelemetryConstants.Protocols.Direct); + _telemetryClient.IncrementConfigurationRefreshRequestCounter( + MetadataAddress, + TelemetryConstants.Protocols.Direct); + if (now >= DateTimeUtil.Add(_lastRequestRefresh.UtcDateTime, RefreshInterval) || _isFirstRefreshRequest) { _isFirstRefreshRequest = false; diff --git a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt index 5552393beb..2de44f1bbe 100644 --- a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt @@ -51,23 +51,23 @@ Microsoft.IdentityModel.Tokens.SecurityTokenInvalidOperationException.SecurityTo Microsoft.IdentityModel.Tokens.SignatureValidationError Microsoft.IdentityModel.Tokens.SignatureValidationError.InnerValidationError.get -> Microsoft.IdentityModel.Tokens.ValidationError Microsoft.IdentityModel.Tokens.SignatureValidationError.SignatureValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, Microsoft.IdentityModel.Tokens.ValidationError innerValidationError = null, System.Exception innerException = null) -> void +Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus) -> void +Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus, System.Exception exception) -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus) -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus, System.Exception exception) -> void Microsoft.IdentityModel.Tokens.TokenReplayValidationError Microsoft.IdentityModel.Tokens.TokenReplayValidationError.ExpirationTime.get -> System.DateTime? Microsoft.IdentityModel.Tokens.TokenReplayValidationError.TokenReplayValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, System.DateTime? expirationTime, System.Exception innerException = null) -> void Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.IdentityModelTelemetry() -> void Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation -Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus) -> void -Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus, System.Exception exception) -> void -Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration) -> void -Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration, System.Exception exception) -> void +Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration) -> void +Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration, System.Exception exception) -> void Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation -Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus) -> void -Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus, System.Exception exception) -> void -Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration) -> void -Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration, System.Exception exception) -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration) -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration, System.Exception exception) -> void Microsoft.IdentityModel.Tokens.Telemetry.TelemetryInstrumentation.TelemetryInstrumentation() -> void Microsoft.IdentityModel.Tokens.TokenTypeValidationError Microsoft.IdentityModel.Tokens.TokenTypeValidationError.InvalidTokenType.get -> string diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs index 1f7bdd06f5..5905e1c2ed 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs @@ -8,16 +8,20 @@ namespace Microsoft.IdentityModel.Tokens.Telemetry internal interface ITelemetryInstrumentation { internal void LogConfigurationRetrievalDuration( + string metadataAddress, TimeSpan operationDuration); internal void LogConfigurationRetrievalDuration( + string metadataAddress, TimeSpan operationDuration, Exception exception); internal void IncrementConfigurationRefreshRequestCounter( + string metadataAddress, string operationStatus); internal void IncrementConfigurationRefreshRequestCounter( + string metadataAddress, string operationStatus, Exception exception); } diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs index b1bdec373a..fb2e36f58b 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs @@ -9,27 +9,25 @@ namespace Microsoft.IdentityModel.Tokens.Telemetry { internal class TelemetryInstrumentation : ITelemetryInstrumentation { - static TagList ClientVerTagList = new() - { - { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer } - }; - public void IncrementConfigurationRefreshRequestCounter(string operationStatus) + public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus) { var tagList = new TagList() { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.MetadataAddressTag, metadataAddress }, { TelemetryConstants.OperationStatusTag, operationStatus } }; IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(tagList); } - public void IncrementConfigurationRefreshRequestCounter(string operationStatus, Exception exception) + public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus, Exception exception) { var tagList = new TagList() { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.MetadataAddressTag, metadataAddress }, { TelemetryConstants.OperationStatusTag, operationStatus }, { TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() } }; @@ -37,17 +35,25 @@ public void IncrementConfigurationRefreshRequestCounter(string operationStatus, IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(tagList); } - public void LogConfigurationRetrievalDuration(TimeSpan operationDuration) + public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan operationDuration) { + + var tagList = new TagList() + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.MetadataAddressTag, metadataAddress }, + }; + long durationInMilliseconds = (long)operationDuration.TotalMilliseconds; - IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(durationInMilliseconds, ClientVerTagList); + IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(durationInMilliseconds, tagList); } - public void LogConfigurationRetrievalDuration(TimeSpan operationDuration, Exception exception) + public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan operationDuration, Exception exception) { var tagList = new TagList() { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.MetadataAddressTag, metadataAddress }, { TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() } }; diff --git a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs index 86dc6cb1e8..9bf99b9241 100644 --- a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs +++ b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs @@ -891,6 +891,7 @@ private ClaimsPrincipal ValidateToken(string token, JwtSecurityToken outerToken, if (currentConfiguration != null) { _telemetryClient.IncrementConfigurationRefreshRequestCounter( + validationParameters.ConfigurationManager.MetadataAddress, TelemetryConstants.Protocols.LKG); validationParameters.ConfigurationManager.RequestRefresh(); diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs index fdea100b51..d884664434 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.IdentityModel.JsonWebTokens.Tests public class JsonWebTokenHandlerTelemetryTests { [Fact] - public async Task ValidateJWSWithConfigAsync() + public async Task ValidateJWSWithConfigAsync_ExpectedTagsExist() { var invalidIssuerConfig = new OpenIdConnectConfiguration() { @@ -57,7 +57,9 @@ public async Task ValidateJWSWithConfigAsync() var expectedCounterTagList = new Dictionary { + // metadata address is null because the configuration manager is made using an invalid config to trigger an exception { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.MetadataAddressTag, null }, { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.LKG } }; diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs index 11612bf6ce..e660600df6 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs @@ -22,7 +22,6 @@ public async Task RequestRefresh_ExpectedTagsExist() { // arrange var testTelemetryClient = new MockTelemetryInstrumentation(); - // mock up retirever to return something quickly var configurationManager = new ConfigurationManager( OpenIdConfigData.AccountsGoogle, new OpenIdConnectConfigurationRetriever(), @@ -43,12 +42,14 @@ public async Task RequestRefresh_ExpectedTagsExist() // assert var expectedCounterTagList = new Dictionary { + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.AccountsGoogle }, { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.Direct }, }; var expectedHistogramTagList = new Dictionary { + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.AccountsGoogle }, { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer } }; @@ -99,6 +100,7 @@ public static TheoryData { + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.AccountsGoogle }, { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.FirstRefresh }, } @@ -109,6 +111,7 @@ public static TheoryData { + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.HttpsBadUri }, { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.FirstRefresh }, { TelemetryConstants.ExceptionTypeTag, new IOException().GetType().ToString() }, @@ -122,6 +125,7 @@ public static TheoryData { + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.JsonFile }, { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.FirstRefresh }, { TelemetryConstants.ExceptionTypeTag, new InvalidConfigurationException().GetType().ToString() }, @@ -134,6 +138,7 @@ public static TheoryData { + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.AADCommonUrl }, { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.Automatic }, } diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs index 2d9222edf6..d56a5072c2 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs @@ -17,27 +17,31 @@ public void ClearExportedItems() ExportedItems.Clear(); } - public void IncrementConfigurationRefreshRequestCounter(string operationStatus) + public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus) { ExportedItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); + ExportedItems.Add(TelemetryConstants.MetadataAddressTag, metadataAddress); ExportedItems.Add(TelemetryConstants.OperationStatusTag, operationStatus); } - public void IncrementConfigurationRefreshRequestCounter(string operationStatus, Exception exception) + public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus, Exception exception) { ExportedItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); + ExportedItems.Add(TelemetryConstants.MetadataAddressTag, metadataAddress); ExportedItems.Add(TelemetryConstants.OperationStatusTag, operationStatus); ExportedItems.Add(TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString()); } - public void LogConfigurationRetrievalDuration(TimeSpan operationDuration) + public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan operationDuration) { ExportedHistogramItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); + ExportedHistogramItems.Add(TelemetryConstants.MetadataAddressTag, metadataAddress); } - public void LogConfigurationRetrievalDuration(TimeSpan operationDuration, Exception exception) + public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan operationDuration, Exception exception) { ExportedHistogramItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); + ExportedHistogramItems.Add(TelemetryConstants.MetadataAddressTag, metadataAddress); ExportedHistogramItems.Add(TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString()); } } diff --git a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs index 4652243d3d..c144d6a924 100644 --- a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs +++ b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs @@ -53,7 +53,9 @@ public void ValidateToken_ExpectedTagsExist() var expectedCounterTagList = new Dictionary { + // metadata address is null because the configuration manager is made using an invalid config to trigger an exception { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.MetadataAddressTag, null }, { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.LKG }, };