From c5e5d9103546a6a3481578c12078c7984dc58ea6 Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:49:35 -0800 Subject: [PATCH 01/15] Add request count and duration telemetry --- build/dependencies.props | 1 + .../IdentityModelTelemetry.cs | 49 ++++++++++++++++ .../IdentityModelTelemetryUtil.cs | 57 +++++++++++++++++++ .../InternalAPI.Unshipped.txt | 29 ++++++++++ .../InternalsVisibleTo.cs | 1 + .../Microsoft.IdentityModel.Logging.csproj | 4 ++ .../WatchUtility.cs | 15 +++++ .../Configuration/ConfigurationManager.cs | 33 ++++++++++- .../InternalAPI.Unshipped.txt | 1 + 9 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs create mode 100644 src/Microsoft.IdentityModel.Logging/WatchUtility.cs diff --git a/build/dependencies.props b/build/dependencies.props index 3acadea8e2..9b004bf3db 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -8,6 +8,7 @@ 1.0.0 2.0.3 13.0.3 + 7.0.2 4.5.5 4.5.0 8.0.5 diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs new file mode 100644 index 0000000000..3018d4a0a0 --- /dev/null +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics; +using System.Diagnostics.Metrics; + +namespace Microsoft.IdentityModel.Logging +{ + internal class IdentityModelTelemetry + { + /// + /// Meter name for MicrosoftIdentityModel. + /// + public const string MeterName = "MicrosoftIdentityModel_Meter"; + public const string ServiceName = "MicrosoftIdentityModel"; + + /// + /// The meter responsible for creating instruments. + /// + public static readonly Meter WilsonMeter = new(MeterName, "1.0.0"); + + internal const string TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS"; + + /// + /// Counter to capture requests to configuration manager. + /// + internal const string WilsonConfigurationManagerCounterName = "WilsonConfigurationManagerCounter"; + internal const string WilsonConfigurationManagerCounterDescription = "Counter capturing configuration manager operations."; + internal static readonly Counter ConfigurationManagerCounter = WilsonMeter.CreateCounter(WilsonConfigurationManagerCounterName, description: WilsonConfigurationManagerCounterDescription); + + /// + /// Histogram to capture total duration of configuration manager operations in milliseconds. + /// + internal static readonly Histogram TotalDurationHistogram = WilsonMeter.CreateHistogram( + TotalDurationHistogramName, + unit: "ms", + description: "Performance of getting configuration calls total latency"); + + internal static void RecordTotalDurationHistogram(long requestDurationInMs, in TagList tagList) + { + TotalDurationHistogram.Record(requestDurationInMs, tagList); + } + + internal static void IncrementConfigurationManagerCounter(in TagList tagList) + { + ConfigurationManagerCounter.Add(1, tagList); + } + } +} diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs index 74a8a0e7ac..004673f641 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs @@ -6,6 +6,7 @@ using System.Collections.Concurrent; using System.Reflection; using System.Net.Http; +using System.Diagnostics; namespace Microsoft.IdentityModel.Logging { @@ -23,6 +24,27 @@ public static class IdentityModelTelemetryUtil [versionTelemetry] = ClientVer }; + // Static attribute tags + internal const string WilsonVersionTag = "WilsonVersion"; + internal const string MetadataAddressTag = "MetadataAddress"; + internal const string RefreshReasonTag = "RefreshReason"; + internal const string OperationStatusTag = "OperationStatus"; + internal const string ExceptionTypeTag = "ExceptionType"; + + // Validation result values + internal const string Success = "Success"; + internal const string Failure = "Failure"; + + // Configuration manager refresh reasons + internal const string Requested = "Requested"; + internal const string Scheduled = "Scheduled"; + internal const string LKG = "LastKnownGood"; + + // Configuration manager exception types + internal const string ConfigurationInvalid = "ConfigurationInvalid"; + internal const string ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed"; + + /// /// Get the string that represents the client SKU. /// @@ -135,5 +157,40 @@ internal static bool UpdateDefaultTelemetryData(string key, string value) telemetryData[key] = value; return true; } + + internal static void IncrementConfigurationManagerCounter( + string metadataAddress, + string refreshReason, + string operationStatus, + string exceptionType) + { + var tagList = new TagList() + { + { WilsonVersionTag, ClientVer }, + { MetadataAddressTag, metadataAddress }, + { RefreshReasonTag, refreshReason}, + { OperationStatusTag, operationStatus }, + { ExceptionTypeTag, exceptionType } + }; + } + + internal static void RecordTotalDuration( + long durationInMs, + string metadataAddress, + string refreshReason, + string operationStatus, + string exceptionType) + { + var tagList = new TagList() + { + { WilsonVersionTag, ClientVer }, + { MetadataAddressTag, metadataAddress }, + { RefreshReasonTag, refreshReason}, + { OperationStatusTag, operationStatus }, + { ExceptionTypeTag, exceptionType } + }; + + IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMs, tagList); + } } } diff --git a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt index e69de29bb2..1779c80952 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt @@ -0,0 +1,29 @@ +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.MeterName = "MicrosoftIdentityModel_Meter" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ServiceName = "MicrosoftIdentityModel" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.WilsonConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.WilsonConfigurationManagerCounterName = "WilsonConfigurationManagerCounter" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ConfigurationInvalid = "ConfigurationInvalid" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ExceptionTypeTag = "ExceptionType" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Failure = "Failure" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.LKG = "LastKnownGood" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.MetadataAddressTag = "MetadataAddress" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.OperationStatusTag = "OperationStatus" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RefreshReasonTag = "RefreshReason" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Requested = "Requested" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Scheduled = "Scheduled" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Success = "Success" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.WilsonVersionTag = "WilsonVersion" -> string +Microsoft.IdentityModel.Logging.IdentityModelTelemetry +Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelTelemetry() -> void +Microsoft.IdentityModel.Logging.WatchUtility +Microsoft.IdentityModel.Logging.WatchUtility.WatchUtility() -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementConfigurationManagerCounter(in System.Diagnostics.TagList tagList) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordTotalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter(string metadataAddress, string refreshReason, string operationStatus, string exceptionType) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RecordTotalDuration(long durationInMs, string metadataAddress, string refreshReason, string operationStatus, string exceptionType) -> void +static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter +static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram +static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.WilsonMeter -> System.Diagnostics.Metrics.Meter +static readonly Microsoft.IdentityModel.Logging.WatchUtility.Watch -> System.Diagnostics.Stopwatch diff --git a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs index fc43ff8880..daf0ee8d56 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs +++ b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs @@ -6,3 +6,4 @@ [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/Microsoft.IdentityModel.Logging/Microsoft.IdentityModel.Logging.csproj b/src/Microsoft.IdentityModel.Logging/Microsoft.IdentityModel.Logging.csproj index e6a1110b05..4b9733a6f5 100644 --- a/src/Microsoft.IdentityModel.Logging/Microsoft.IdentityModel.Logging.csproj +++ b/src/Microsoft.IdentityModel.Logging/Microsoft.IdentityModel.Logging.csproj @@ -32,6 +32,10 @@ + + + + diff --git a/src/Microsoft.IdentityModel.Logging/WatchUtility.cs b/src/Microsoft.IdentityModel.Logging/WatchUtility.cs new file mode 100644 index 0000000000..1bf9c92842 --- /dev/null +++ b/src/Microsoft.IdentityModel.Logging/WatchUtility.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics; + +namespace Microsoft.IdentityModel.Logging +{ + /// + /// A utility class to measure time. + /// + internal class WatchUtility + { + internal static readonly Stopwatch Watch = Stopwatch.StartNew(); + } +} diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index cd06188f0f..0d1dc72677 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -147,8 +147,14 @@ public async Task GetConfigurationAsync() /// If the time since the last call is less than then is not called and the current Configuration is returned. public virtual async Task GetConfigurationAsync(CancellationToken cancel) { + var methodStartTicks = WatchUtility.Watch.Elapsed.Ticks; + if (_currentConfiguration != null && _syncAfter > DateTimeOffset.UtcNow) + { + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.LKG, IdentityModelTelemetryUtil.Success, string.Empty); return _currentConfiguration; + } Exception fetchMetadataFailure = null; @@ -164,6 +170,8 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) await _configurationNullLock.WaitAsync(cancel).ConfigureAwait(false); if (_currentConfiguration != null) { + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.LKG, IdentityModelTelemetryUtil.Success, string.Empty); _configurationNullLock.Release(); return _currentConfiguration; } @@ -183,11 +191,15 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) ConfigurationValidationResult result = _configValidator.Validate(configuration); // in this case we have never had a valid configuration, so we will throw an exception if the validation fails if (!result.Succeeded) + { + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.Requested, IdentityModelTelemetryUtil.Failure, IdentityModelTelemetryUtil.ConfigurationInvalid); throw LogHelper.LogExceptionMessage( new InvalidConfigurationException( LogHelper.FormatInvariant( LogMessages.IDX20810, result.ErrorMessage))); + } } UpdateConfiguration(configuration); @@ -220,8 +232,14 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) // If metadata exists return it. if (_currentConfiguration != null) + { + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.Requested, IdentityModelTelemetryUtil.Success, string.Empty); return _currentConfiguration; + } + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.Requested, IdentityModelTelemetryUtil.Failure, IdentityModelTelemetryUtil.ConfigurationRetrievalFailed); throw LogHelper.LogExceptionMessage( new InvalidOperationException( LogHelper.FormatInvariant( @@ -293,7 +311,7 @@ private void UpdateConfiguration(T configuration) /// Obtains an updated version of Configuration. /// /// CancellationToken - /// Configuration of type BaseConfiguration . + /// Configuration of type BaseConfiguration. /// If the time since the last call is less than then is not called and the current Configuration is returned. public override async Task GetBaseConfigurationAsync(CancellationToken cancel) { @@ -322,6 +340,19 @@ public override void RequestRefresh() } } + internal void TrackGetConfiguration(long methodStartTicks, string refreshReason, string operationStatus, string exceptionType) + { + IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter( + MetadataAddress, refreshReason, operationStatus, exceptionType); + + IdentityModelTelemetryUtil.RecordTotalDuration( + (WatchUtility.Watch.Elapsed.Ticks - methodStartTicks) / TimeSpan.TicksPerMillisecond, + MetadataAddress, + refreshReason, + operationStatus, + exceptionType); + } + /// /// 12 hours is the default time interval that afterwards, will obtain new configuration. /// diff --git a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt index e69de29bb2..1b49692536 100644 --- a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt @@ -0,0 +1 @@ +Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackGetConfiguration(long methodStartTicks, string refreshReason, string operationStatus, string exceptionType) -> void \ No newline at end of file From c8bdbdf481b3e682ec5702a319fc95630b8b71ed Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:49:35 -0800 Subject: [PATCH 02/15] Add request count and duration telemetry --- build/dependencies.props | 1 + build/dependenciesTest.props | 1 + .../IdentityModelTelemetry.cs | 49 +++++ .../IdentityModelTelemetryUtil.cs | 59 +++++ .../InternalAPI.Unshipped.txt | 29 +++ .../InternalsVisibleTo.cs | 1 + .../Microsoft.IdentityModel.Logging.csproj | 4 + .../WatchUtility.cs | 15 ++ .../Configuration/ConfigurationManager.cs | 33 ++- .../InternalAPI.Unshipped.txt | 1 + .../ConfigurationManagerTelemetryTests.cs | 201 ++++++++++++++++++ ...Model.Protocols.OpenIdConnect.Tests.csproj | 2 + 12 files changed, 395 insertions(+), 1 deletion(-) create mode 100644 src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs create mode 100644 src/Microsoft.IdentityModel.Logging/WatchUtility.cs create mode 100644 test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs diff --git a/build/dependencies.props b/build/dependencies.props index 3acadea8e2..9b004bf3db 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -8,6 +8,7 @@ 1.0.0 2.0.3 13.0.3 + 7.0.2 4.5.5 4.5.0 8.0.5 diff --git a/build/dependenciesTest.props b/build/dependenciesTest.props index 65daedcf38..834da0378c 100644 --- a/build/dependenciesTest.props +++ b/build/dependenciesTest.props @@ -7,6 +7,7 @@ 17.11.1 2.0.3 13.0.3 + 1.10.0 4.3.4 4.3.0 8.0.5 diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs new file mode 100644 index 0000000000..3018d4a0a0 --- /dev/null +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics; +using System.Diagnostics.Metrics; + +namespace Microsoft.IdentityModel.Logging +{ + internal class IdentityModelTelemetry + { + /// + /// Meter name for MicrosoftIdentityModel. + /// + public const string MeterName = "MicrosoftIdentityModel_Meter"; + public const string ServiceName = "MicrosoftIdentityModel"; + + /// + /// The meter responsible for creating instruments. + /// + public static readonly Meter WilsonMeter = new(MeterName, "1.0.0"); + + internal const string TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS"; + + /// + /// Counter to capture requests to configuration manager. + /// + internal const string WilsonConfigurationManagerCounterName = "WilsonConfigurationManagerCounter"; + internal const string WilsonConfigurationManagerCounterDescription = "Counter capturing configuration manager operations."; + internal static readonly Counter ConfigurationManagerCounter = WilsonMeter.CreateCounter(WilsonConfigurationManagerCounterName, description: WilsonConfigurationManagerCounterDescription); + + /// + /// Histogram to capture total duration of configuration manager operations in milliseconds. + /// + internal static readonly Histogram TotalDurationHistogram = WilsonMeter.CreateHistogram( + TotalDurationHistogramName, + unit: "ms", + description: "Performance of getting configuration calls total latency"); + + internal static void RecordTotalDurationHistogram(long requestDurationInMs, in TagList tagList) + { + TotalDurationHistogram.Record(requestDurationInMs, tagList); + } + + internal static void IncrementConfigurationManagerCounter(in TagList tagList) + { + ConfigurationManagerCounter.Add(1, tagList); + } + } +} diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs index 74a8a0e7ac..a3636ec359 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs @@ -6,6 +6,7 @@ using System.Collections.Concurrent; using System.Reflection; using System.Net.Http; +using System.Diagnostics; namespace Microsoft.IdentityModel.Logging { @@ -23,6 +24,27 @@ public static class IdentityModelTelemetryUtil [versionTelemetry] = ClientVer }; + // Static attribute tags + internal const string WilsonVersionTag = "WilsonVersion"; + internal const string MetadataAddressTag = "MetadataAddress"; + internal const string RefreshReasonTag = "RefreshReason"; + internal const string OperationStatusTag = "OperationStatus"; + internal const string ExceptionTypeTag = "ExceptionType"; + + // Validation result values + internal const string Success = "Success"; + internal const string Failure = "Failure"; + + // Configuration manager refresh reasons + internal const string Requested = "Requested"; + internal const string Scheduled = "Scheduled"; + internal const string LKG = "LastKnownGood"; + + // Configuration manager exception types + internal const string ConfigurationInvalid = "ConfigurationInvalid"; + internal const string ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed"; + + /// /// Get the string that represents the client SKU. /// @@ -135,5 +157,42 @@ internal static bool UpdateDefaultTelemetryData(string key, string value) telemetryData[key] = value; return true; } + + internal static void IncrementConfigurationManagerCounter( + string metadataAddress, + string refreshReason, + string operationStatus, + string exceptionType) + { + var tagList = new TagList() + { + { WilsonVersionTag, ClientVer }, + { MetadataAddressTag, metadataAddress }, + { RefreshReasonTag, refreshReason}, + { OperationStatusTag, operationStatus }, + { ExceptionTypeTag, exceptionType } + }; + + IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); + } + + internal static void RecordTotalDuration( + long durationInMs, + string metadataAddress, + string refreshReason, + string operationStatus, + string exceptionType) + { + var tagList = new TagList() + { + { WilsonVersionTag, ClientVer }, + { MetadataAddressTag, metadataAddress }, + { RefreshReasonTag, refreshReason}, + { OperationStatusTag, operationStatus }, + { ExceptionTypeTag, exceptionType } + }; + + IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMs, tagList); + } } } diff --git a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt index e69de29bb2..1779c80952 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt @@ -0,0 +1,29 @@ +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.MeterName = "MicrosoftIdentityModel_Meter" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ServiceName = "MicrosoftIdentityModel" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.WilsonConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.WilsonConfigurationManagerCounterName = "WilsonConfigurationManagerCounter" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ConfigurationInvalid = "ConfigurationInvalid" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ExceptionTypeTag = "ExceptionType" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Failure = "Failure" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.LKG = "LastKnownGood" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.MetadataAddressTag = "MetadataAddress" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.OperationStatusTag = "OperationStatus" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RefreshReasonTag = "RefreshReason" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Requested = "Requested" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Scheduled = "Scheduled" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Success = "Success" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.WilsonVersionTag = "WilsonVersion" -> string +Microsoft.IdentityModel.Logging.IdentityModelTelemetry +Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelTelemetry() -> void +Microsoft.IdentityModel.Logging.WatchUtility +Microsoft.IdentityModel.Logging.WatchUtility.WatchUtility() -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementConfigurationManagerCounter(in System.Diagnostics.TagList tagList) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordTotalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter(string metadataAddress, string refreshReason, string operationStatus, string exceptionType) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RecordTotalDuration(long durationInMs, string metadataAddress, string refreshReason, string operationStatus, string exceptionType) -> void +static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter +static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram +static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.WilsonMeter -> System.Diagnostics.Metrics.Meter +static readonly Microsoft.IdentityModel.Logging.WatchUtility.Watch -> System.Diagnostics.Stopwatch diff --git a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs index fc43ff8880..daf0ee8d56 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs +++ b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs @@ -6,3 +6,4 @@ [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/Microsoft.IdentityModel.Logging/Microsoft.IdentityModel.Logging.csproj b/src/Microsoft.IdentityModel.Logging/Microsoft.IdentityModel.Logging.csproj index e6a1110b05..4b9733a6f5 100644 --- a/src/Microsoft.IdentityModel.Logging/Microsoft.IdentityModel.Logging.csproj +++ b/src/Microsoft.IdentityModel.Logging/Microsoft.IdentityModel.Logging.csproj @@ -32,6 +32,10 @@ + + + + diff --git a/src/Microsoft.IdentityModel.Logging/WatchUtility.cs b/src/Microsoft.IdentityModel.Logging/WatchUtility.cs new file mode 100644 index 0000000000..1bf9c92842 --- /dev/null +++ b/src/Microsoft.IdentityModel.Logging/WatchUtility.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics; + +namespace Microsoft.IdentityModel.Logging +{ + /// + /// A utility class to measure time. + /// + internal class WatchUtility + { + internal static readonly Stopwatch Watch = Stopwatch.StartNew(); + } +} diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index cd06188f0f..0d1dc72677 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -147,8 +147,14 @@ public async Task GetConfigurationAsync() /// If the time since the last call is less than then is not called and the current Configuration is returned. public virtual async Task GetConfigurationAsync(CancellationToken cancel) { + var methodStartTicks = WatchUtility.Watch.Elapsed.Ticks; + if (_currentConfiguration != null && _syncAfter > DateTimeOffset.UtcNow) + { + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.LKG, IdentityModelTelemetryUtil.Success, string.Empty); return _currentConfiguration; + } Exception fetchMetadataFailure = null; @@ -164,6 +170,8 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) await _configurationNullLock.WaitAsync(cancel).ConfigureAwait(false); if (_currentConfiguration != null) { + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.LKG, IdentityModelTelemetryUtil.Success, string.Empty); _configurationNullLock.Release(); return _currentConfiguration; } @@ -183,11 +191,15 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) ConfigurationValidationResult result = _configValidator.Validate(configuration); // in this case we have never had a valid configuration, so we will throw an exception if the validation fails if (!result.Succeeded) + { + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.Requested, IdentityModelTelemetryUtil.Failure, IdentityModelTelemetryUtil.ConfigurationInvalid); throw LogHelper.LogExceptionMessage( new InvalidConfigurationException( LogHelper.FormatInvariant( LogMessages.IDX20810, result.ErrorMessage))); + } } UpdateConfiguration(configuration); @@ -220,8 +232,14 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) // If metadata exists return it. if (_currentConfiguration != null) + { + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.Requested, IdentityModelTelemetryUtil.Success, string.Empty); return _currentConfiguration; + } + TrackGetConfiguration( + methodStartTicks, IdentityModelTelemetryUtil.Requested, IdentityModelTelemetryUtil.Failure, IdentityModelTelemetryUtil.ConfigurationRetrievalFailed); throw LogHelper.LogExceptionMessage( new InvalidOperationException( LogHelper.FormatInvariant( @@ -293,7 +311,7 @@ private void UpdateConfiguration(T configuration) /// Obtains an updated version of Configuration. /// /// CancellationToken - /// Configuration of type BaseConfiguration . + /// Configuration of type BaseConfiguration. /// If the time since the last call is less than then is not called and the current Configuration is returned. public override async Task GetBaseConfigurationAsync(CancellationToken cancel) { @@ -322,6 +340,19 @@ public override void RequestRefresh() } } + internal void TrackGetConfiguration(long methodStartTicks, string refreshReason, string operationStatus, string exceptionType) + { + IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter( + MetadataAddress, refreshReason, operationStatus, exceptionType); + + IdentityModelTelemetryUtil.RecordTotalDuration( + (WatchUtility.Watch.Elapsed.Ticks - methodStartTicks) / TimeSpan.TicksPerMillisecond, + MetadataAddress, + refreshReason, + operationStatus, + exceptionType); + } + /// /// 12 hours is the default time interval that afterwards, will obtain new configuration. /// diff --git a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt index e69de29bb2..1b49692536 100644 --- a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt @@ -0,0 +1 @@ +Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackGetConfiguration(long methodStartTicks, string refreshReason, string operationStatus, string exceptionType) -> void \ No newline at end of file diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs new file mode 100644 index 0000000000..d7b8a3e1f3 --- /dev/null +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +//using System; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Protocols.OpenIdConnect.Configuration; +using Microsoft.IdentityModel.TestUtils; +using OpenTelemetry; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using Xunit; + +namespace Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests +{ + public class ConfigurationManagerTelemetryTests + { + readonly List ExportedItems; + readonly MeterProvider MeterProvider; + + public ConfigurationManagerTelemetryTests() + { + ExportedItems = new List(); + + MeterProvider = Sdk.CreateMeterProviderBuilder() + .SetResourceBuilder(ResourceBuilder.CreateDefault()) + .AddMeter(IdentityModelTelemetry.MeterName) + .AddInMemoryExporter(ExportedItems, (options) => + { + options.PeriodicExportingMetricReaderOptions = new PeriodicExportingMetricReaderOptions + { + ExportIntervalMilliseconds = 10, + }; + }) + .Build(); + } + + [Theory, MemberData(nameof(GetConfiguration_ExpectedTagList_TheoryData), DisableDiscoveryEnumeration = true)] + public async Task GetConfigurationAsync_ExpectedTagList(ConfigurationManagerTelemetryTheoryData theoryData) + { + var configurationManager = new ConfigurationManager( + theoryData.MetadataAddress, + new OpenIdConnectConfigurationRetriever(), + theoryData.DocumentRetriever, + theoryData.ConfigurationValidator); + try + { + + await configurationManager.GetConfigurationAsync(); + + if (theoryData.SecondRequest) + { + await configurationManager.GetConfigurationAsync(); + } + } + catch (Exception) + { + // Ignore exceptions + } + MeterProvider.ForceFlush(); + MeterProvider.Shutdown(); + MeterProvider.Dispose(); + + VerifyConfigurationManagerCounter(ExportedItems, theoryData.ExpectedTagList); + VerifyHistogramReporting(ExportedItems, theoryData.ExpectedTagList); + } + + public static TheoryData> GetConfiguration_ExpectedTagList_TheoryData() + { + return new TheoryData> + { + new ConfigurationManagerTelemetryTheoryData("Success-retrieve from endpoint") + { + MetadataAddress = OpenIdConfigData.AccountsGoogle, + DocumentRetriever = new HttpDocumentRetriever(), + ConfigurationValidator = new OpenIdConnectConfigurationValidator(), + ExpectedTagList = new Dictionary + { + { IdentityModelTelemetryUtil.MetadataAddressTag, OpenIdConfigData.AccountsGoogle }, + { IdentityModelTelemetryUtil.RefreshReasonTag, IdentityModelTelemetryUtil.Requested }, + { IdentityModelTelemetryUtil.OperationStatusTag, IdentityModelTelemetryUtil.Success }, + { IdentityModelTelemetryUtil.ExceptionTypeTag, string.Empty } + } + }, + new ConfigurationManagerTelemetryTheoryData("Success-retrieve from cache") + { + MetadataAddress = OpenIdConfigData.AADCommonUrl, + DocumentRetriever = new HttpDocumentRetriever(), + ConfigurationValidator = new OpenIdConnectConfigurationValidator(), + SecondRequest = true, + ExpectedTagList = new Dictionary + { + { IdentityModelTelemetryUtil.MetadataAddressTag, OpenIdConfigData.AADCommonUrl }, + { IdentityModelTelemetryUtil.RefreshReasonTag, IdentityModelTelemetryUtil.LKG }, + { IdentityModelTelemetryUtil.OperationStatusTag, IdentityModelTelemetryUtil.Success }, + { IdentityModelTelemetryUtil.ExceptionTypeTag, string.Empty } + } + }, + new ConfigurationManagerTelemetryTheoryData("Failure-invalid metadata address") + { + MetadataAddress = OpenIdConfigData.HttpsBadUri, + DocumentRetriever = new HttpDocumentRetriever(), + ConfigurationValidator = new OpenIdConnectConfigurationValidator(), + ExpectedTagList = new Dictionary + { + { IdentityModelTelemetryUtil.MetadataAddressTag, OpenIdConfigData.HttpsBadUri }, + { IdentityModelTelemetryUtil.RefreshReasonTag, IdentityModelTelemetryUtil.Requested }, + { IdentityModelTelemetryUtil.OperationStatusTag, IdentityModelTelemetryUtil.Failure }, + { IdentityModelTelemetryUtil.ExceptionTypeTag, IdentityModelTelemetryUtil.ConfigurationRetrievalFailed } + } + }, + new ConfigurationManagerTelemetryTheoryData("Failure-invalid config") + { + MetadataAddress = OpenIdConfigData.JsonFile, + DocumentRetriever = new FileDocumentRetriever(), + // The config being loaded has two keys; require three to force invalidity + ConfigurationValidator = new OpenIdConnectConfigurationValidator() { MinimumNumberOfKeys = 3 }, + ExpectedTagList = new Dictionary + { + { IdentityModelTelemetryUtil.MetadataAddressTag, OpenIdConfigData.JsonFile }, + { IdentityModelTelemetryUtil.RefreshReasonTag, IdentityModelTelemetryUtil.Requested }, + { IdentityModelTelemetryUtil.OperationStatusTag, IdentityModelTelemetryUtil.Failure }, + { IdentityModelTelemetryUtil.ExceptionTypeTag, IdentityModelTelemetryUtil.ConfigurationInvalid } + } + }, + }; + } + + private void VerifyConfigurationManagerCounter(List exportedMetrics, Dictionary expectedTagList) + { + var expectedTagsFound = false; + foreach (Metric metric in exportedMetrics) + { + if (!metric.Name.Equals(IdentityModelTelemetry.WilsonConfigurationManagerCounterName)) + continue; + + foreach (MetricPoint metricPoint in metric.GetMetricPoints()) + { + if (MatchTagValues(metricPoint, expectedTagList)) + expectedTagsFound = true; + } + } + Assert.True(expectedTagsFound); + } + + private void VerifyHistogramReporting(List exportedMetrics, Dictionary expectedTagList) + { + var histogramMetricFound = false; + foreach (Metric metric in exportedMetrics) + { + if (!metric.Name.Equals(IdentityModelTelemetry.TotalDurationHistogramName)) + continue; + + Assert.Equal(MetricType.Histogram, metric.MetricType); + foreach (var metricPoint in metric.GetMetricPoints()) + { + if (MatchTagValues(metricPoint, expectedTagList)) + histogramMetricFound = true; + } + } + Assert.True(histogramMetricFound); + } + + private bool MatchTagValues(MetricPoint metricPoint, Dictionary expectedTagList) + { + foreach (var expectedTag in expectedTagList.Keys) + { + Dictionary tags = []; + foreach (var tag in metricPoint.Tags) + { + tags[tag.Key] = tag.Value?.ToString() ?? "null"; + } + + if (!tags.ContainsKey(expectedTag)) + return false; + + if (tags[expectedTag] != expectedTagList[expectedTag]) + return false; + } + + return true; + } + } + + public class ConfigurationManagerTelemetryTheoryData : TheoryDataBase where T : class + { + public ConfigurationManagerTelemetryTheoryData(string testId) : base(testId) { } + + public string MetadataAddress { get; set; } + + public IDocumentRetriever DocumentRetriever { get; set; } + + public IConfigurationValidator ConfigurationValidator { get; set; } + + public bool SecondRequest { get; set; } = false; + + public Dictionary ExpectedTagList { get; set; } + } +} diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests.csproj b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests.csproj index 1cbfb9eed3..2b34740058 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests.csproj +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests.csproj @@ -25,6 +25,8 @@ + + From 49790e373e7cef4e93e4183ed570c078ad7613ee Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:31:40 -0800 Subject: [PATCH 03/15] small fix --- .../IdentityModelTelemetryUtil.cs | 2 ++ .../ConfigurationManagerTelemetryTests.cs | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs index 004673f641..a3636ec359 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs @@ -172,6 +172,8 @@ internal static void IncrementConfigurationManagerCounter( { OperationStatusTag, operationStatus }, { ExceptionTypeTag, exceptionType } }; + + IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); } internal static void RecordTotalDuration( diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs index d7b8a3e1f3..446a59ee1a 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs @@ -47,7 +47,6 @@ public async Task GetConfigurationAsync_ExpectedTagList(ConfigurationManagerTele theoryData.ConfigurationValidator); try { - await configurationManager.GetConfigurationAsync(); if (theoryData.SecondRequest) From 09c3b49e24dfa29b5fd2f249921e3644fd8587e2 Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Wed, 4 Dec 2024 11:09:13 -0800 Subject: [PATCH 04/15] Feedback, remodel timing and counters --- build/dependencies.props | 2 +- build/dependenciesTest.props | 2 +- .../IdentityModelTelemetry.cs | 10 +-- .../IdentityModelTelemetryUtil.cs | 60 +++++++++------- .../InternalAPI.Unshipped.txt | 22 +++--- .../WatchUtility.cs | 15 ---- .../Configuration/ConfigurationManager.cs | 71 ++++++++++++------- .../InternalAPI.Unshipped.txt | 6 +- .../ConfigurationManagerTelemetryTests.cs | 4 +- 9 files changed, 105 insertions(+), 87 deletions(-) delete mode 100644 src/Microsoft.IdentityModel.Logging/WatchUtility.cs diff --git a/build/dependencies.props b/build/dependencies.props index 9b004bf3db..472d04ac96 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -8,7 +8,7 @@ 1.0.0 2.0.3 13.0.3 - 7.0.2 + 9.0.0 4.5.5 4.5.0 8.0.5 diff --git a/build/dependenciesTest.props b/build/dependenciesTest.props index 834da0378c..4e5f755ef4 100644 --- a/build/dependenciesTest.props +++ b/build/dependenciesTest.props @@ -7,7 +7,7 @@ 17.11.1 2.0.3 13.0.3 - 1.10.0 + 1.6.0 4.3.4 4.3.0 8.0.5 diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs index 3018d4a0a0..3731aef604 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs @@ -17,21 +17,21 @@ internal class IdentityModelTelemetry /// /// The meter responsible for creating instruments. /// - public static readonly Meter WilsonMeter = new(MeterName, "1.0.0"); + public static readonly Meter IdentityModelMeter = new(MeterName, "1.0.0"); internal const string TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS"; /// /// Counter to capture requests to configuration manager. /// - internal const string WilsonConfigurationManagerCounterName = "WilsonConfigurationManagerCounter"; - internal const string WilsonConfigurationManagerCounterDescription = "Counter capturing configuration manager operations."; - internal static readonly Counter ConfigurationManagerCounter = WilsonMeter.CreateCounter(WilsonConfigurationManagerCounterName, description: WilsonConfigurationManagerCounterDescription); + internal const string IdentityModelConfigurationManagerCounterName = "WilsonConfigurationManagerCounter"; + internal const string IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations."; + internal static readonly Counter ConfigurationManagerCounter = IdentityModelMeter.CreateCounter(IdentityModelConfigurationManagerCounterName, description: IdentityModelConfigurationManagerCounterDescription); /// /// Histogram to capture total duration of configuration manager operations in milliseconds. /// - internal static readonly Histogram TotalDurationHistogram = WilsonMeter.CreateHistogram( + internal static readonly Histogram TotalDurationHistogram = IdentityModelMeter.CreateHistogram( TotalDurationHistogramName, unit: "ms", description: "Performance of getting configuration calls total latency"); diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs index a3636ec359..1fbdaca4c6 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using System.Collections.Concurrent; +using System.Diagnostics; using System.Reflection; using System.Net.Http; -using System.Diagnostics; namespace Microsoft.IdentityModel.Logging { @@ -25,19 +25,15 @@ public static class IdentityModelTelemetryUtil }; // Static attribute tags - internal const string WilsonVersionTag = "WilsonVersion"; + internal const string IdentityModelVersionTag = "IdentityModelVersion"; internal const string MetadataAddressTag = "MetadataAddress"; - internal const string RefreshReasonTag = "RefreshReason"; internal const string OperationStatusTag = "OperationStatus"; internal const string ExceptionTypeTag = "ExceptionType"; - // Validation result values - internal const string Success = "Success"; - internal const string Failure = "Failure"; - - // Configuration manager refresh reasons - internal const string Requested = "Requested"; - internal const string Scheduled = "Scheduled"; + // Configuration manager refresh statuses + internal const string Automatic = "Automatic"; + internal const string Direct = "Direct"; + internal const string FirstRefresh = "FirstRefresh"; internal const string LKG = "LastKnownGood"; // Configuration manager exception types @@ -159,40 +155,50 @@ internal static bool UpdateDefaultTelemetryData(string key, string value) } internal static void IncrementConfigurationManagerCounter( - string metadataAddress, - string refreshReason, - string operationStatus, - string exceptionType) + string operationStatus) { var tagList = new TagList() { - { WilsonVersionTag, ClientVer }, - { MetadataAddressTag, metadataAddress }, - { RefreshReasonTag, refreshReason}, - { OperationStatusTag, operationStatus }, - { ExceptionTypeTag, exceptionType } + { IdentityModelVersionTag, ClientVer }, + { OperationStatusTag, operationStatus } }; IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); } - internal static void RecordTotalDuration( - long durationInMs, - string metadataAddress, - string refreshReason, + internal static void IncrementConfigurationManagerCounter( string operationStatus, string exceptionType) { var tagList = new TagList() { - { WilsonVersionTag, ClientVer }, - { MetadataAddressTag, metadataAddress }, - { RefreshReasonTag, refreshReason}, + { IdentityModelVersionTag, ClientVer }, { OperationStatusTag, operationStatus }, { ExceptionTypeTag, exceptionType } }; - IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMs, tagList); + IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); + } + + internal static void RecordTotalDuration(long totalMilliseconds) + { + var tagList = new TagList() + { + { IdentityModelVersionTag, ClientVer } + }; + + IdentityModelTelemetry.RecordTotalDurationHistogram(totalMilliseconds, tagList); + } + + internal static void RecordTotalDuration(long totalMilliseconds, string exception) + { + var tagList = new TagList() + { + { IdentityModelVersionTag, ClientVer }, + { ExceptionTypeTag, exception } + }; + + IdentityModelTelemetry.RecordTotalDurationHistogram(totalMilliseconds, tagList); } } } diff --git a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt index 1779c80952..8c08edd566 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt @@ -1,29 +1,29 @@ +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName = "WilsonConfigurationManagerCounter" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.MeterName = "MicrosoftIdentityModel_Meter" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ServiceName = "MicrosoftIdentityModel" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.WilsonConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.WilsonConfigurationManagerCounterName = "WilsonConfigurationManagerCounter" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Automatic = "Automatic" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ConfigurationInvalid = "ConfigurationInvalid" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Direct = "Direct" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ExceptionTypeTag = "ExceptionType" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Failure = "Failure" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.FirstRefresh = "FirstRefresh" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IdentityModelVersionTag = "IdentityModelVersion" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.LKG = "LastKnownGood" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.MetadataAddressTag = "MetadataAddress" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.OperationStatusTag = "OperationStatus" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RefreshReasonTag = "RefreshReason" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Requested = "Requested" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Scheduled = "Scheduled" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Success = "Success" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.WilsonVersionTag = "WilsonVersion" -> string Microsoft.IdentityModel.Logging.IdentityModelTelemetry Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelTelemetry() -> void Microsoft.IdentityModel.Logging.WatchUtility Microsoft.IdentityModel.Logging.WatchUtility.WatchUtility() -> void static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementConfigurationManagerCounter(in System.Diagnostics.TagList tagList) -> void static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordTotalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter(string metadataAddress, string refreshReason, string operationStatus, string exceptionType) -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RecordTotalDuration(long durationInMs, string metadataAddress, string refreshReason, string operationStatus, string exceptionType) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter(string operationStatus) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter(string operationStatus, string exceptionType) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RecordTotalDuration(long totalMilliseconds) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RecordTotalDuration(long totalMilliseconds, string exception) -> void static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter +static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelMeter -> System.Diagnostics.Metrics.Meter static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram -static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.WilsonMeter -> System.Diagnostics.Metrics.Meter static readonly Microsoft.IdentityModel.Logging.WatchUtility.Watch -> System.Diagnostics.Stopwatch diff --git a/src/Microsoft.IdentityModel.Logging/WatchUtility.cs b/src/Microsoft.IdentityModel.Logging/WatchUtility.cs deleted file mode 100644 index 1bf9c92842..0000000000 --- a/src/Microsoft.IdentityModel.Logging/WatchUtility.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Diagnostics; - -namespace Microsoft.IdentityModel.Logging -{ - /// - /// A utility class to measure time. - /// - internal class WatchUtility - { - internal static readonly Stopwatch Watch = Stopwatch.StartNew(); - } -} diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index 0d1dc72677..669cc139ad 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -35,6 +35,8 @@ public class ConfigurationManager : BaseConfigurationManager, IConfigurationM private const int ConfigurationRetrieverRunning = 1; private int _configurationRetrieverState = ConfigurationRetrieverIdle; + internal TimeProvider _timeProvider = TimeProvider.System; + /// /// Instantiates a new that manages automatic and controls refreshing on configuration data. /// @@ -147,12 +149,8 @@ public async Task GetConfigurationAsync() /// If the time since the last call is less than then is not called and the current Configuration is returned. public virtual async Task GetConfigurationAsync(CancellationToken cancel) { - var methodStartTicks = WatchUtility.Watch.Elapsed.Ticks; - if (_currentConfiguration != null && _syncAfter > DateTimeOffset.UtcNow) { - TrackGetConfiguration( - methodStartTicks, IdentityModelTelemetryUtil.LKG, IdentityModelTelemetryUtil.Success, string.Empty); return _currentConfiguration; } @@ -170,8 +168,6 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) await _configurationNullLock.WaitAsync(cancel).ConfigureAwait(false); if (_currentConfiguration != null) { - TrackGetConfiguration( - methodStartTicks, IdentityModelTelemetryUtil.LKG, IdentityModelTelemetryUtil.Success, string.Empty); _configurationNullLock.Release(); return _currentConfiguration; } @@ -180,7 +176,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) try { // Don't use the individual CT here, this is a shared operation that shouldn't be affected by an individual's cancellation. - // The transport should have it's own timeouts, etc. + // The transport should have its own timeouts, etc. T configuration = await _configRetriever.GetConfigurationAsync( MetadataAddress, _docRetriever, @@ -192,21 +188,29 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) // in this case we have never had a valid configuration, so we will throw an exception if the validation fails if (!result.Succeeded) { - TrackGetConfiguration( - methodStartTicks, IdentityModelTelemetryUtil.Requested, IdentityModelTelemetryUtil.Failure, IdentityModelTelemetryUtil.ConfigurationInvalid); - throw LogHelper.LogExceptionMessage( - new InvalidConfigurationException( - LogHelper.FormatInvariant( - LogMessages.IDX20810, - result.ErrorMessage))); + var ex = new InvalidConfigurationException( + LogHelper.FormatInvariant( + LogMessages.IDX20810, + result.ErrorMessage)); + + TrackRequestRefresh( + IdentityModelTelemetryUtil.FirstRefresh, + ex.GetType().ToString()); + + throw LogHelper.LogExceptionMessage(ex); } } + TrackRequestRefresh(IdentityModelTelemetryUtil.FirstRefresh); UpdateConfiguration(configuration); } catch (Exception ex) { + // counter for failure first time fetchMetadataFailure = ex; + TrackRequestRefresh( + IdentityModelTelemetryUtil.FirstRefresh, + ex.GetType().ToString()); LogHelper.LogExceptionMessage( new InvalidOperationException( @@ -233,13 +237,9 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) // If metadata exists return it. if (_currentConfiguration != null) { - TrackGetConfiguration( - methodStartTicks, IdentityModelTelemetryUtil.Requested, IdentityModelTelemetryUtil.Success, string.Empty); return _currentConfiguration; } - TrackGetConfiguration( - methodStartTicks, IdentityModelTelemetryUtil.Requested, IdentityModelTelemetryUtil.Failure, IdentityModelTelemetryUtil.ConfigurationRetrievalFailed); throw LogHelper.LogExceptionMessage( new InvalidOperationException( LogHelper.FormatInvariant( @@ -258,6 +258,8 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) private void UpdateCurrentConfiguration() { #pragma warning disable CA1031 // Do not catch general exception types + long startTimestamp = _timeProvider.GetTimestamp(); + try { T configuration = _configRetriever.GetConfigurationAsync( @@ -265,6 +267,9 @@ private void UpdateCurrentConfiguration() _docRetriever, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); + TimeSpan elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); + TrackRetrievalDuration(elapsedTime); + if (_configValidator == null) { UpdateConfiguration(configuration); @@ -285,6 +290,9 @@ private void UpdateCurrentConfiguration() } catch (Exception ex) { + TimeSpan elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); + TrackRetrievalDuration(elapsedTime, ex.GetType().ToString()); + LogHelper.LogExceptionMessage( new InvalidOperationException( LogHelper.FormatInvariant( @@ -329,6 +337,8 @@ public override void RequestRefresh() { DateTimeOffset now = DateTimeOffset.UtcNow; + // direct refresh request + TrackRequestRefresh(IdentityModelTelemetryUtil.Direct); if (now >= DateTimeUtil.Add(_lastRequestRefresh.UtcDateTime, RefreshInterval) || _isFirstRefreshRequest) { _isFirstRefreshRequest = false; @@ -340,15 +350,28 @@ public override void RequestRefresh() } } - internal void TrackGetConfiguration(long methodStartTicks, string refreshReason, string operationStatus, string exceptionType) + internal static void TrackRetrievalDuration(TimeSpan duration) { - IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter( - MetadataAddress, refreshReason, operationStatus, exceptionType); + IdentityModelTelemetryUtil.RecordTotalDuration( + (long)duration.TotalMilliseconds); + } + internal static void TrackRetrievalDuration(TimeSpan duration, string exception) + { IdentityModelTelemetryUtil.RecordTotalDuration( - (WatchUtility.Watch.Elapsed.Ticks - methodStartTicks) / TimeSpan.TicksPerMillisecond, - MetadataAddress, - refreshReason, + (long)duration.TotalMilliseconds, + exception); + } + + internal static void TrackRequestRefresh(string operationStatus) + { + IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter( + operationStatus); + } + + internal static void TrackRequestRefresh(string operationStatus, string exceptionType) + { + IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter( operationStatus, exceptionType); } diff --git a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt index 1b49692536..2a92335ac9 100644 --- a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt @@ -1 +1,5 @@ -Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackGetConfiguration(long methodStartTicks, string refreshReason, string operationStatus, string exceptionType) -> void \ No newline at end of file +Microsoft.IdentityModel.Protocols.ConfigurationManager._timeProvider -> System.TimeProvider +static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRequestRefresh(string operationStatus) -> void +static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRequestRefresh(string operationStatus, string exceptionType) -> void +static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRetrievalDuration(System.TimeSpan duration) -> void +static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRetrievalDuration(System.TimeSpan duration, string exception) -> void \ No newline at end of file diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs index 446a59ee1a..431b011096 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -//using System; using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -45,6 +44,7 @@ public async Task GetConfigurationAsync_ExpectedTagList(ConfigurationManagerTele new OpenIdConnectConfigurationRetriever(), theoryData.DocumentRetriever, theoryData.ConfigurationValidator); + try { await configurationManager.GetConfigurationAsync(); @@ -132,7 +132,7 @@ private void VerifyConfigurationManagerCounter(List exportedMetrics, Dic var expectedTagsFound = false; foreach (Metric metric in exportedMetrics) { - if (!metric.Name.Equals(IdentityModelTelemetry.WilsonConfigurationManagerCounterName)) + if (!metric.Name.Equals(IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName)) continue; foreach (MetricPoint metricPoint in metric.GetMetricPoints()) From 57c1a90516f96e3c1de3da1a28d46dd6418190ad Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:08:49 -0800 Subject: [PATCH 05/15] Use interface for logging, move constants to class --- .../JsonWebTokenHandler.ValidateToken.cs | 6 + ...gurationManagerTelemetryInstrumentation.cs | 54 +++++++++ .../ITelemetryInstrumentation.cs | 26 +++++ .../IdentityModelTelemetry.cs | 2 +- .../IdentityModelTelemetryUtil.cs | 110 ++++++++---------- .../InternalAPI.Unshipped.txt | 27 ++++- .../InternalsVisibleTo.cs | 2 + .../TelemetryConstants.cs | 24 ++++ .../Configuration/ConfigurationManager.cs | 23 ++-- .../InternalAPI.Unshipped.txt | 3 +- .../JwtSecurityTokenHandler.cs | 5 + .../ConfigurationManagerTelemetryTests.cs | 24 ++-- 12 files changed, 211 insertions(+), 95 deletions(-) create mode 100644 src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs create mode 100644 src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs create mode 100644 src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs index 918788932f..4892508aef 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs @@ -17,6 +17,8 @@ namespace Microsoft.IdentityModel.JsonWebTokens /// This partial class contains methods and logic related to the validation of tokens. public partial class JsonWebTokenHandler : TokenHandler { + private readonly ConfigurationManagerTelemetryInstrumentation _telemetryClient = new(); + /// /// Returns a value that indicates if this handler can validate a . /// @@ -511,6 +513,10 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration) // where a new valid configuration was somehow published during validation time. if (currentConfiguration != null) { + _telemetryClient.IncrementOperationCounter( + IdentityModelTelemetryUtil.ClientVer, + TelemetryConstants.LKG); + validationParameters.ConfigurationManager.RequestRefresh(); validationParameters.RefreshBeforeValidation = true; var lastConfig = currentConfiguration; diff --git a/src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs new file mode 100644 index 0000000000..37966c5601 --- /dev/null +++ b/src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics; + +namespace Microsoft.IdentityModel.Logging +{ + internal class ConfigurationManagerTelemetryInstrumentation : ITelemetryInstrumentation + { + public void IncrementOperationCounter(string clientVer, string operationStatus) + { + var tagList = new TagList() + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.OperationStatusTag, operationStatus } + }; + + IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); + } + + public void IncrementOperationCounter(string clientVer, string operationStatus, string exceptionType) + { + var tagList = new TagList() + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.OperationStatusTag, operationStatus }, + { TelemetryConstants.ExceptionTypeTag, exceptionType } + }; + + IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); + } + + public void LogOperationDuration(string clientVer, long durationInMilliseconds) + { + var tagList = new TagList() + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer } + }; + + IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMilliseconds, tagList); + } + + public void LogOperationDuration(string clientVer, long durationInMilliseconds, string exceptionType) + { + var tagList = new TagList() + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.ExceptionTypeTag, exceptionType } + }; + + IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMilliseconds, tagList); + } + } +} diff --git a/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs new file mode 100644 index 0000000000..0aa7e4d406 --- /dev/null +++ b/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.IdentityModel.Logging +{ + internal interface ITelemetryInstrumentation + { + internal void LogOperationDuration( + string clientVer, + long durationInMilliseconds); + + internal void LogOperationDuration( + string clientVer, + long durationInMilliseconds, + string exceptionType); + + internal void IncrementOperationCounter( + string clientVer, + string operationStatus); + + internal void IncrementOperationCounter( + string clientVer, + string operationStatus, + string exceptionType); + } +} diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs index 3731aef604..596b57e113 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs @@ -24,7 +24,7 @@ internal class IdentityModelTelemetry /// /// Counter to capture requests to configuration manager. /// - internal const string IdentityModelConfigurationManagerCounterName = "WilsonConfigurationManagerCounter"; + internal const string IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManagerCounter"; internal const string IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations."; internal static readonly Counter ConfigurationManagerCounter = IdentityModelMeter.CreateCounter(IdentityModelConfigurationManagerCounterName, description: IdentityModelConfigurationManagerCounterDescription); diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs index 1fbdaca4c6..f1b1786d60 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Collections.Concurrent; -using System.Diagnostics; using System.Reflection; using System.Net.Http; @@ -24,23 +23,6 @@ public static class IdentityModelTelemetryUtil [versionTelemetry] = ClientVer }; - // Static attribute tags - internal const string IdentityModelVersionTag = "IdentityModelVersion"; - internal const string MetadataAddressTag = "MetadataAddress"; - internal const string OperationStatusTag = "OperationStatus"; - internal const string ExceptionTypeTag = "ExceptionType"; - - // Configuration manager refresh statuses - internal const string Automatic = "Automatic"; - internal const string Direct = "Direct"; - internal const string FirstRefresh = "FirstRefresh"; - internal const string LKG = "LastKnownGood"; - - // Configuration manager exception types - internal const string ConfigurationInvalid = "ConfigurationInvalid"; - internal const string ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed"; - - /// /// Get the string that represents the client SKU. /// @@ -154,51 +136,51 @@ internal static bool UpdateDefaultTelemetryData(string key, string value) return true; } - internal static void IncrementConfigurationManagerCounter( - string operationStatus) - { - var tagList = new TagList() - { - { IdentityModelVersionTag, ClientVer }, - { OperationStatusTag, operationStatus } - }; - - IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); - } - - internal static void IncrementConfigurationManagerCounter( - string operationStatus, - string exceptionType) - { - var tagList = new TagList() - { - { IdentityModelVersionTag, ClientVer }, - { OperationStatusTag, operationStatus }, - { ExceptionTypeTag, exceptionType } - }; - - IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); - } - - internal static void RecordTotalDuration(long totalMilliseconds) - { - var tagList = new TagList() - { - { IdentityModelVersionTag, ClientVer } - }; - - IdentityModelTelemetry.RecordTotalDurationHistogram(totalMilliseconds, tagList); - } - - internal static void RecordTotalDuration(long totalMilliseconds, string exception) - { - var tagList = new TagList() - { - { IdentityModelVersionTag, ClientVer }, - { ExceptionTypeTag, exception } - }; - - IdentityModelTelemetry.RecordTotalDurationHistogram(totalMilliseconds, tagList); - } + //internal static void IncrementConfigurationManagerCounter( + // string operationStatus) + //{ + // var tagList = new TagList() + // { + // { TelemetryConstants.IdentityModelVersionTag, ClientVer }, + // { TelemetryConstants.OperationStatusTag, operationStatus } + // }; + + // IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); + //} + + //internal static void IncrementConfigurationManagerCounter( + // string operationStatus, + // string exceptionType) + //{ + // var tagList = new TagList() + // { + // { TelemetryConstants.IdentityModelVersionTag, ClientVer }, + // { TelemetryConstants.OperationStatusTag, operationStatus }, + // { TelemetryConstants.ExceptionTypeTag, exceptionType } + // }; + + // IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); + //} + + //internal static void RecordTotalDuration(long totalMilliseconds) + //{ + // var tagList = new TagList() + // { + // { TelemetryConstants.IdentityModelVersionTag, ClientVer } + // }; + + // IdentityModelTelemetry.RecordTotalDurationHistogram(totalMilliseconds, tagList); + //} + + //internal static void RecordTotalDuration(long totalMilliseconds, string exception) + //{ + // var tagList = new TagList() + // { + // { TelemetryConstants.IdentityModelVersionTag, ClientVer }, + // { TelemetryConstants.ExceptionTypeTag, exception } + // }; + + // IdentityModelTelemetry.RecordTotalDurationHistogram(totalMilliseconds, tagList); + //} } } diff --git a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt index 8c08edd566..b5458893b1 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt @@ -1,5 +1,5 @@ const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName = "WilsonConfigurationManagerCounter" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManagerCounter" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.MeterName = "MicrosoftIdentityModel_Meter" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ServiceName = "MicrosoftIdentityModel" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string @@ -13,10 +13,30 @@ const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IdentityModelVe const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.LKG = "LastKnownGood" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.MetadataAddressTag = "MetadataAddress" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.OperationStatusTag = "OperationStatus" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Automatic = "Automatic" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationInvalid = "ConfigurationInvalid" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Direct = "Direct" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.FirstRefresh = "FirstRefresh" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.LKG = "LastKnownGood" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.ConfigurationManagerTelemetryInstrumentation() -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string clientVer, string operationStatus) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string clientVer, string operationStatus, string exceptionType) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(string clientVer, long durationInMilliseconds) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(string clientVer, long durationInMilliseconds, string exceptionType) -> void Microsoft.IdentityModel.Logging.IdentityModelTelemetry Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelTelemetry() -> void -Microsoft.IdentityModel.Logging.WatchUtility -Microsoft.IdentityModel.Logging.WatchUtility.WatchUtility() -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string clientVer, string operationStatus) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string clientVer, string operationStatus, string exceptionType) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(string clientVer, long durationInMilliseconds) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(string clientVer, long durationInMilliseconds, string exceptionType) -> void +Microsoft.IdentityModel.Logging.TelemetryConstants static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementConfigurationManagerCounter(in System.Diagnostics.TagList tagList) -> void static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordTotalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter(string operationStatus) -> void @@ -26,4 +46,3 @@ static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RecordTotalDur static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelMeter -> System.Diagnostics.Metrics.Meter static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram -static readonly Microsoft.IdentityModel.Logging.WatchUtility.Watch -> System.Diagnostics.Stopwatch diff --git a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs index daf0ee8d56..7a4ee016c2 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs +++ b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.JsonWebTokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.IdentityModel.Tokens.Jwt, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs b/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs new file mode 100644 index 0000000000..95652e657f --- /dev/null +++ b/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.IdentityModel.Logging +{ + internal static class TelemetryConstants + { + // Static attribute tags + public const string IdentityModelVersionTag = "IdentityModelVersion"; + public const string MetadataAddressTag = "MetadataAddress"; + public const string OperationStatusTag = "OperationStatus"; + public const string ExceptionTypeTag = "ExceptionType"; + + // Configuration manager refresh statuses + public const string Automatic = "Automatic"; + public const string Direct = "Direct"; + public const string FirstRefresh = "FirstRefresh"; + public const string LKG = "LastKnownGood"; + + // Configuration manager exception types + public const string ConfigurationInvalid = "ConfigurationInvalid"; + public const string ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed"; + } +} diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index 669cc139ad..2735836925 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -36,6 +36,7 @@ public class ConfigurationManager : BaseConfigurationManager, IConfigurationM private int _configurationRetrieverState = ConfigurationRetrieverIdle; internal TimeProvider _timeProvider = TimeProvider.System; + internal static readonly ConfigurationManagerTelemetryInstrumentation _telemetryClient = new(); /// /// Instantiates a new that manages automatic and controls refreshing on configuration data. @@ -194,14 +195,14 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) result.ErrorMessage)); TrackRequestRefresh( - IdentityModelTelemetryUtil.FirstRefresh, + TelemetryConstants.FirstRefresh, ex.GetType().ToString()); throw LogHelper.LogExceptionMessage(ex); } } - TrackRequestRefresh(IdentityModelTelemetryUtil.FirstRefresh); + TrackRequestRefresh(TelemetryConstants.FirstRefresh); UpdateConfiguration(configuration); } catch (Exception ex) @@ -209,7 +210,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) // counter for failure first time fetchMetadataFailure = ex; TrackRequestRefresh( - IdentityModelTelemetryUtil.FirstRefresh, + TelemetryConstants.FirstRefresh, ex.GetType().ToString()); LogHelper.LogExceptionMessage( @@ -230,6 +231,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) { if (Interlocked.CompareExchange(ref _configurationRetrieverState, ConfigurationRetrieverRunning, ConfigurationRetrieverIdle) == ConfigurationRetrieverIdle) { + TrackRequestRefresh(TelemetryConstants.Automatic); _ = Task.Run(UpdateCurrentConfiguration, CancellationToken.None); } } @@ -337,8 +339,7 @@ public override void RequestRefresh() { DateTimeOffset now = DateTimeOffset.UtcNow; - // direct refresh request - TrackRequestRefresh(IdentityModelTelemetryUtil.Direct); + TrackRequestRefresh(TelemetryConstants.Direct); if (now >= DateTimeUtil.Add(_lastRequestRefresh.UtcDateTime, RefreshInterval) || _isFirstRefreshRequest) { _isFirstRefreshRequest = false; @@ -352,26 +353,30 @@ public override void RequestRefresh() internal static void TrackRetrievalDuration(TimeSpan duration) { - IdentityModelTelemetryUtil.RecordTotalDuration( + _telemetryClient.LogOperationDuration( + IdentityModelTelemetryUtil.ClientVer, (long)duration.TotalMilliseconds); } internal static void TrackRetrievalDuration(TimeSpan duration, string exception) { - IdentityModelTelemetryUtil.RecordTotalDuration( + _telemetryClient.LogOperationDuration( + IdentityModelTelemetryUtil.ClientVer, (long)duration.TotalMilliseconds, exception); } internal static void TrackRequestRefresh(string operationStatus) { - IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter( + _telemetryClient.IncrementOperationCounter( + IdentityModelTelemetryUtil.ClientVer, operationStatus); } internal static void TrackRequestRefresh(string operationStatus, string exceptionType) { - IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter( + _telemetryClient.IncrementOperationCounter( + IdentityModelTelemetryUtil.ClientVer, operationStatus, exceptionType); } diff --git a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt index 2a92335ac9..71c62ec568 100644 --- a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt @@ -2,4 +2,5 @@ Microsoft.IdentityModel.Protocols.ConfigurationManager._timeProvider -> Syste static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRequestRefresh(string operationStatus) -> void static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRequestRefresh(string operationStatus, string exceptionType) -> void static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRetrievalDuration(System.TimeSpan duration) -> void -static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRetrievalDuration(System.TimeSpan duration, string exception) -> void \ No newline at end of file +static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRetrievalDuration(System.TimeSpan duration, string exception) -> void +static readonly Microsoft.IdentityModel.Protocols.ConfigurationManager._telemetryClient -> Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation \ No newline at end of file diff --git a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs index e9c10ef213..3b00d1716a 100644 --- a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs +++ b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs @@ -35,6 +35,7 @@ public class JwtSecurityTokenHandler : SecurityTokenHandler private Dictionary _outboundAlgorithmMap; private static string _shortClaimType = _namespace + "/ShortTypeName"; private bool _mapInboundClaims = DefaultMapInboundClaims; + private readonly ConfigurationManagerTelemetryInstrumentation _telemetryClient = new(); /// /// Default claim type mapping for inbound claims. @@ -887,6 +888,10 @@ private ClaimsPrincipal ValidateToken(string token, JwtSecurityToken outerToken, // where a new valid configuration was somehow published during validation time. if (currentConfiguration != null) { + _telemetryClient.IncrementOperationCounter( + IdentityModelTelemetryUtil.ClientVer, + TelemetryConstants.LKG); + validationParameters.ConfigurationManager.RequestRefresh(); validationParameters.RefreshBeforeValidation = true; var lastConfig = currentConfiguration; diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs index 431b011096..3aa11293ba 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs @@ -77,10 +77,8 @@ public static TheoryData { - { IdentityModelTelemetryUtil.MetadataAddressTag, OpenIdConfigData.AccountsGoogle }, - { IdentityModelTelemetryUtil.RefreshReasonTag, IdentityModelTelemetryUtil.Requested }, - { IdentityModelTelemetryUtil.OperationStatusTag, IdentityModelTelemetryUtil.Success }, - { IdentityModelTelemetryUtil.ExceptionTypeTag, string.Empty } + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.AccountsGoogle }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Automatic }, } }, new ConfigurationManagerTelemetryTheoryData("Success-retrieve from cache") @@ -91,10 +89,8 @@ public static TheoryData { - { IdentityModelTelemetryUtil.MetadataAddressTag, OpenIdConfigData.AADCommonUrl }, - { IdentityModelTelemetryUtil.RefreshReasonTag, IdentityModelTelemetryUtil.LKG }, - { IdentityModelTelemetryUtil.OperationStatusTag, IdentityModelTelemetryUtil.Success }, - { IdentityModelTelemetryUtil.ExceptionTypeTag, string.Empty } + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.AADCommonUrl }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Direct }, } }, new ConfigurationManagerTelemetryTheoryData("Failure-invalid metadata address") @@ -104,10 +100,8 @@ public static TheoryData { - { IdentityModelTelemetryUtil.MetadataAddressTag, OpenIdConfigData.HttpsBadUri }, - { IdentityModelTelemetryUtil.RefreshReasonTag, IdentityModelTelemetryUtil.Requested }, - { IdentityModelTelemetryUtil.OperationStatusTag, IdentityModelTelemetryUtil.Failure }, - { IdentityModelTelemetryUtil.ExceptionTypeTag, IdentityModelTelemetryUtil.ConfigurationRetrievalFailed } + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.HttpsBadUri }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.FirstRefresh }, } }, new ConfigurationManagerTelemetryTheoryData("Failure-invalid config") @@ -118,10 +112,8 @@ public static TheoryData { - { IdentityModelTelemetryUtil.MetadataAddressTag, OpenIdConfigData.JsonFile }, - { IdentityModelTelemetryUtil.RefreshReasonTag, IdentityModelTelemetryUtil.Requested }, - { IdentityModelTelemetryUtil.OperationStatusTag, IdentityModelTelemetryUtil.Failure }, - { IdentityModelTelemetryUtil.ExceptionTypeTag, IdentityModelTelemetryUtil.ConfigurationInvalid } + { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.JsonFile }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.LKG }, } }, }; From 3262cffc68e37905121cb1d6084200cc4c4f9333 Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Thu, 5 Dec 2024 17:16:51 -0800 Subject: [PATCH 06/15] some interface changes, rework tests --- .../InternalAPI.Unshipped.txt | 1 + .../JsonWebTokenHandler.ValidateToken.cs | 3 +- ...gurationManagerTelemetryInstrumentation.cs | 8 +- .../ITelemetryInstrumentation.cs | 4 - .../IdentityModelTelemetry.cs | 2 +- .../IdentityModelTelemetryUtil.cs | 47 ------ .../InternalAPI.Unshipped.txt | 28 +-- .../InternalsVisibleTo.cs | 2 + .../TelemetryConstants.cs | 12 +- .../Configuration/ConfigurationManager.cs | 52 ++---- .../InternalAPI.Unshipped.txt | 25 ++- .../InternalsVisibleTo.cs | 4 + .../InternalAPI.Unshipped.txt | 3 +- .../JwtSecurityTokenHandler.cs | 4 +- .../JsonWebTokenHandlerTelemetryTests.cs | 66 ++++++++ ...crosoft.IdentityModel.Logging.Tests.csproj | 2 + .../MockTelemetryInstrumentation.cs | 42 +++++ .../ConfigurationManagerTelemetryTests.cs | 159 ++++++++---------- ...Model.Protocols.OpenIdConnect.Tests.csproj | 7 +- .../JwtSecurityTokenHandlerTelemetryTests.cs | 62 +++++++ ...stem.IdentityModel.Tokens.Jwt.Tests.csproj | 2 + 21 files changed, 319 insertions(+), 216 deletions(-) create mode 100644 src/Microsoft.IdentityModel.Protocols/InternalsVisibleTo.cs create mode 100644 test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs create mode 100644 test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs create mode 100644 test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt index cb23d777b2..c4e9578c3a 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt @@ -1,3 +1,4 @@ +Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler._telemetryClient -> Microsoft.IdentityModel.Logging.ITelemetryInstrumentation static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(string payload, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, string compressionAlgorithm, System.Collections.Generic.IDictionary additionalHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs index 4892508aef..83ef331f28 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs @@ -17,7 +17,7 @@ namespace Microsoft.IdentityModel.JsonWebTokens /// This partial class contains methods and logic related to the validation of tokens. public partial class JsonWebTokenHandler : TokenHandler { - private readonly ConfigurationManagerTelemetryInstrumentation _telemetryClient = new(); + internal ITelemetryInstrumentation _telemetryClient = new ConfigurationManagerTelemetryInstrumentation(); /// /// Returns a value that indicates if this handler can validate a . @@ -514,7 +514,6 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration) if (currentConfiguration != null) { _telemetryClient.IncrementOperationCounter( - IdentityModelTelemetryUtil.ClientVer, TelemetryConstants.LKG); validationParameters.ConfigurationManager.RequestRefresh(); diff --git a/src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs index 37966c5601..71bf648271 100644 --- a/src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs @@ -7,7 +7,7 @@ namespace Microsoft.IdentityModel.Logging { internal class ConfigurationManagerTelemetryInstrumentation : ITelemetryInstrumentation { - public void IncrementOperationCounter(string clientVer, string operationStatus) + public void IncrementOperationCounter(string operationStatus) { var tagList = new TagList() { @@ -18,7 +18,7 @@ public void IncrementOperationCounter(string clientVer, string operationStatus) IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); } - public void IncrementOperationCounter(string clientVer, string operationStatus, string exceptionType) + public void IncrementOperationCounter(string operationStatus, string exceptionType) { var tagList = new TagList() { @@ -30,7 +30,7 @@ public void IncrementOperationCounter(string clientVer, string operationStatus, IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); } - public void LogOperationDuration(string clientVer, long durationInMilliseconds) + public void LogOperationDuration(long durationInMilliseconds) { var tagList = new TagList() { @@ -40,7 +40,7 @@ public void LogOperationDuration(string clientVer, long durationInMilliseconds) IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMilliseconds, tagList); } - public void LogOperationDuration(string clientVer, long durationInMilliseconds, string exceptionType) + public void LogOperationDuration(long durationInMilliseconds, string exceptionType) { var tagList = new TagList() { diff --git a/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs index 0aa7e4d406..65ed7adf3c 100644 --- a/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs @@ -6,20 +6,16 @@ namespace Microsoft.IdentityModel.Logging internal interface ITelemetryInstrumentation { internal void LogOperationDuration( - string clientVer, long durationInMilliseconds); internal void LogOperationDuration( - string clientVer, long durationInMilliseconds, string exceptionType); internal void IncrementOperationCounter( - string clientVer, string operationStatus); internal void IncrementOperationCounter( - string clientVer, string operationStatus, string exceptionType); } diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs index 596b57e113..f90f70c459 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs @@ -34,7 +34,7 @@ internal class IdentityModelTelemetry internal static readonly Histogram TotalDurationHistogram = IdentityModelMeter.CreateHistogram( TotalDurationHistogramName, unit: "ms", - description: "Performance of getting configuration calls total latency"); + description: "Configuration retrieval latency during configuration manager operations."); internal static void RecordTotalDurationHistogram(long requestDurationInMs, in TagList tagList) { diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs index f1b1786d60..74a8a0e7ac 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetryUtil.cs @@ -135,52 +135,5 @@ internal static bool UpdateDefaultTelemetryData(string key, string value) telemetryData[key] = value; return true; } - - //internal static void IncrementConfigurationManagerCounter( - // string operationStatus) - //{ - // var tagList = new TagList() - // { - // { TelemetryConstants.IdentityModelVersionTag, ClientVer }, - // { TelemetryConstants.OperationStatusTag, operationStatus } - // }; - - // IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); - //} - - //internal static void IncrementConfigurationManagerCounter( - // string operationStatus, - // string exceptionType) - //{ - // var tagList = new TagList() - // { - // { TelemetryConstants.IdentityModelVersionTag, ClientVer }, - // { TelemetryConstants.OperationStatusTag, operationStatus }, - // { TelemetryConstants.ExceptionTypeTag, exceptionType } - // }; - - // IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); - //} - - //internal static void RecordTotalDuration(long totalMilliseconds) - //{ - // var tagList = new TagList() - // { - // { TelemetryConstants.IdentityModelVersionTag, ClientVer } - // }; - - // IdentityModelTelemetry.RecordTotalDurationHistogram(totalMilliseconds, tagList); - //} - - //internal static void RecordTotalDuration(long totalMilliseconds, string exception) - //{ - // var tagList = new TagList() - // { - // { TelemetryConstants.IdentityModelVersionTag, ClientVer }, - // { TelemetryConstants.ExceptionTypeTag, exception } - // }; - - // IdentityModelTelemetry.RecordTotalDurationHistogram(totalMilliseconds, tagList); - //} } } diff --git a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt index b5458893b1..49bf064785 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt @@ -13,29 +13,29 @@ const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IdentityModelVe const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.LKG = "LastKnownGood" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.MetadataAddressTag = "MetadataAddress" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.OperationStatusTag = "OperationStatus" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Automatic = "Automatic" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationInvalid = "ConfigurationInvalid" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Direct = "Direct" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Automatic = "Microsoft.IdentityModel.Protocols.Automatic" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationInvalid = "Microsoft.IdentityModel.Protocols.ConfigurationInvalid" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationRetrievalFailed = "Microsoft.IdentityModel.Protocols.ConfigurationRetrievalFailed" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Direct = "Microsoft.IdentityModel.Protocols.Direct" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.FirstRefresh = "FirstRefresh" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.FirstRefresh = "Microsoft.IdentityModel.Protocols.FirstRefresh" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.LKG = "LastKnownGood" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.LKG = "Microsoft.IdentityModel.Protocols.LastKnownGood" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.ConfigurationManagerTelemetryInstrumentation() -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string clientVer, string operationStatus) -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string clientVer, string operationStatus, string exceptionType) -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(string clientVer, long durationInMilliseconds) -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(string clientVer, long durationInMilliseconds, string exceptionType) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string operationStatus, string exceptionType) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds, string exceptionType) -> void Microsoft.IdentityModel.Logging.IdentityModelTelemetry Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelTelemetry() -> void Microsoft.IdentityModel.Logging.ITelemetryInstrumentation -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string clientVer, string operationStatus) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string clientVer, string operationStatus, string exceptionType) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(string clientVer, long durationInMilliseconds) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(string clientVer, long durationInMilliseconds, string exceptionType) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string operationStatus, string exceptionType) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds, string exceptionType) -> void Microsoft.IdentityModel.Logging.TelemetryConstants static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementConfigurationManagerCounter(in System.Diagnostics.TagList tagList) -> void static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordTotalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void diff --git a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs index 7a4ee016c2..44b121b658 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs +++ b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.JsonWebTokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.JsonWebTokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] @@ -9,3 +10,4 @@ [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.IdentityModel.Tokens.Jwt, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.IdentityModel.Tokens.Jwt.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs b/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs index 95652e657f..9dec03e165 100644 --- a/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs +++ b/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs @@ -12,13 +12,13 @@ internal static class TelemetryConstants public const string ExceptionTypeTag = "ExceptionType"; // Configuration manager refresh statuses - public const string Automatic = "Automatic"; - public const string Direct = "Direct"; - public const string FirstRefresh = "FirstRefresh"; - public const string LKG = "LastKnownGood"; + public const string Automatic = "Microsoft.IdentityModel.Protocols.Automatic"; + public const string Direct = "Microsoft.IdentityModel.Protocols.Direct"; + public const string FirstRefresh = "Microsoft.IdentityModel.Protocols.FirstRefresh"; + public const string LKG = "Microsoft.IdentityModel.Protocols.LastKnownGood"; // Configuration manager exception types - public const string ConfigurationInvalid = "ConfigurationInvalid"; - public const string ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed"; + public const string ConfigurationInvalid = "Microsoft.IdentityModel.Protocols.ConfigurationInvalid"; + public const string ConfigurationRetrievalFailed = "Microsoft.IdentityModel.Protocols.ConfigurationRetrievalFailed"; } } diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index 2735836925..4a74bab705 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -36,7 +36,7 @@ public class ConfigurationManager : BaseConfigurationManager, IConfigurationM private int _configurationRetrieverState = ConfigurationRetrieverIdle; internal TimeProvider _timeProvider = TimeProvider.System; - internal static readonly ConfigurationManagerTelemetryInstrumentation _telemetryClient = new(); + internal ITelemetryInstrumentation _telemetryClient = new ConfigurationManagerTelemetryInstrumentation(); /// /// Instantiates a new that manages automatic and controls refreshing on configuration data. @@ -194,7 +194,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) LogMessages.IDX20810, result.ErrorMessage)); - TrackRequestRefresh( + _telemetryClient.IncrementOperationCounter( TelemetryConstants.FirstRefresh, ex.GetType().ToString()); @@ -202,14 +202,14 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) } } - TrackRequestRefresh(TelemetryConstants.FirstRefresh); + _telemetryClient.IncrementOperationCounter(TelemetryConstants.FirstRefresh); UpdateConfiguration(configuration); } catch (Exception ex) { // counter for failure first time fetchMetadataFailure = ex; - TrackRequestRefresh( + _telemetryClient.IncrementOperationCounter( TelemetryConstants.FirstRefresh, ex.GetType().ToString()); @@ -231,7 +231,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) { if (Interlocked.CompareExchange(ref _configurationRetrieverState, ConfigurationRetrieverRunning, ConfigurationRetrieverIdle) == ConfigurationRetrieverIdle) { - TrackRequestRefresh(TelemetryConstants.Automatic); + _telemetryClient.IncrementOperationCounter(TelemetryConstants.Automatic); _ = Task.Run(UpdateCurrentConfiguration, CancellationToken.None); } } @@ -269,8 +269,8 @@ private void UpdateCurrentConfiguration() _docRetriever, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); - TimeSpan elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); - TrackRetrievalDuration(elapsedTime); + long elapsedTime = (long)_timeProvider.GetElapsedTime(startTimestamp).TotalMilliseconds; + _telemetryClient.LogOperationDuration(elapsedTime); if (_configValidator == null) { @@ -292,8 +292,10 @@ private void UpdateCurrentConfiguration() } catch (Exception ex) { - TimeSpan elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); - TrackRetrievalDuration(elapsedTime, ex.GetType().ToString()); + long elapsedTime = (long)_timeProvider.GetElapsedTime(startTimestamp).TotalMilliseconds; + _telemetryClient.LogOperationDuration( + elapsedTime, + ex.GetType().ToString()); LogHelper.LogExceptionMessage( new InvalidOperationException( @@ -339,7 +341,7 @@ public override void RequestRefresh() { DateTimeOffset now = DateTimeOffset.UtcNow; - TrackRequestRefresh(TelemetryConstants.Direct); + _telemetryClient.IncrementOperationCounter(TelemetryConstants.Direct); if (now >= DateTimeUtil.Add(_lastRequestRefresh.UtcDateTime, RefreshInterval) || _isFirstRefreshRequest) { _isFirstRefreshRequest = false; @@ -351,36 +353,6 @@ public override void RequestRefresh() } } - internal static void TrackRetrievalDuration(TimeSpan duration) - { - _telemetryClient.LogOperationDuration( - IdentityModelTelemetryUtil.ClientVer, - (long)duration.TotalMilliseconds); - } - - internal static void TrackRetrievalDuration(TimeSpan duration, string exception) - { - _telemetryClient.LogOperationDuration( - IdentityModelTelemetryUtil.ClientVer, - (long)duration.TotalMilliseconds, - exception); - } - - internal static void TrackRequestRefresh(string operationStatus) - { - _telemetryClient.IncrementOperationCounter( - IdentityModelTelemetryUtil.ClientVer, - operationStatus); - } - - internal static void TrackRequestRefresh(string operationStatus, string exceptionType) - { - _telemetryClient.IncrementOperationCounter( - IdentityModelTelemetryUtil.ClientVer, - operationStatus, - exceptionType); - } - /// /// 12 hours is the default time interval that afterwards, will obtain new configuration. /// diff --git a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt index 71c62ec568..1c6e0b4fbd 100644 --- a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt @@ -1,6 +1,19 @@ -Microsoft.IdentityModel.Protocols.ConfigurationManager._timeProvider -> System.TimeProvider -static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRequestRefresh(string operationStatus) -> void -static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRequestRefresh(string operationStatus, string exceptionType) -> void -static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRetrievalDuration(System.TimeSpan duration) -> void -static Microsoft.IdentityModel.Protocols.ConfigurationManager.TrackRetrievalDuration(System.TimeSpan duration, string exception) -> void -static readonly Microsoft.IdentityModel.Protocols.ConfigurationManager._telemetryClient -> Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation \ No newline at end of file +const Microsoft.IdentityModel.Logging.TelemetryConstants.Automatic = "Microsoft.IdentityModel.Protocols.Automatic" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationInvalid = "Microsoft.IdentityModel.Protocols.ConfigurationInvalid" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationRetrievalFailed = "Microsoft.IdentityModel.Protocols.ConfigurationRetrievalFailed" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Direct = "Microsoft.IdentityModel.Protocols.Direct" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.FirstRefresh = "Microsoft.IdentityModel.Protocols.FirstRefresh" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.LKG = "Microsoft.IdentityModel.Protocols.LastKnownGood" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.ConfigurationManagerTelemetryInstrumentation() -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string operationStatus, string exceptionType) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds) -> void +Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds, string exceptionType) -> void +Microsoft.IdentityModel.Logging.TelemetryConstants +Microsoft.IdentityModel.Protocols.ConfigurationManager._telemetryClient -> Microsoft.IdentityModel.Logging.ITelemetryInstrumentation +Microsoft.IdentityModel.Protocols.ConfigurationManager._timeProvider -> System.TimeProvider \ No newline at end of file diff --git a/src/Microsoft.IdentityModel.Protocols/InternalsVisibleTo.cs b/src/Microsoft.IdentityModel.Protocols/InternalsVisibleTo.cs new file mode 100644 index 0000000000..5e00856ea6 --- /dev/null +++ b/src/Microsoft.IdentityModel.Protocols/InternalsVisibleTo.cs @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt b/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt index 47d5d10352..3b31c9fa88 100644 --- a/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt +++ b/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt @@ -1,2 +1,3 @@ System.IdentityModel.Tokens.Jwt.JwtHeader.JwtHeader(Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, System.Collections.Generic.IDictionary outboundAlgorithmMap, string tokenType, System.Collections.Generic.IDictionary additionalHeaderClaims, bool includeKeyIdInHeader) -> void -System.IdentityModel.Tokens.Jwt.JwtHeader.JwtHeader(Microsoft.IdentityModel.Tokens.SigningCredentials signingCredentials, System.Collections.Generic.IDictionary outboundAlgorithmMap, string tokenType, System.Collections.Generic.IDictionary additionalInnerHeaderClaims, bool includeKeyIdInHeader) -> void \ No newline at end of file +System.IdentityModel.Tokens.Jwt.JwtHeader.JwtHeader(Microsoft.IdentityModel.Tokens.SigningCredentials signingCredentials, System.Collections.Generic.IDictionary outboundAlgorithmMap, string tokenType, System.Collections.Generic.IDictionary additionalInnerHeaderClaims, bool includeKeyIdInHeader) -> void +System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler._telemetryClient -> Microsoft.IdentityModel.Logging.ITelemetryInstrumentation \ No newline at end of file diff --git a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs index 3b00d1716a..61766f3975 100644 --- a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs +++ b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs @@ -35,7 +35,8 @@ public class JwtSecurityTokenHandler : SecurityTokenHandler private Dictionary _outboundAlgorithmMap; private static string _shortClaimType = _namespace + "/ShortTypeName"; private bool _mapInboundClaims = DefaultMapInboundClaims; - private readonly ConfigurationManagerTelemetryInstrumentation _telemetryClient = new(); + + internal ITelemetryInstrumentation _telemetryClient = new ConfigurationManagerTelemetryInstrumentation(); /// /// Default claim type mapping for inbound claims. @@ -889,7 +890,6 @@ private ClaimsPrincipal ValidateToken(string token, JwtSecurityToken outerToken, if (currentConfiguration != null) { _telemetryClient.IncrementOperationCounter( - IdentityModelTelemetryUtil.ClientVer, TelemetryConstants.LKG); validationParameters.ConfigurationManager.RequestRefresh(); diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs new file mode 100644 index 0000000000..875c6f01ec --- /dev/null +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Logging.Tests; +using Microsoft.IdentityModel.Protocols; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Microsoft.IdentityModel.TestUtils; +using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Validators; +using Xunit; + +namespace Microsoft.IdentityModel.JsonWebTokens.Tests +{ + public class JsonWebTokenHandlerTelemetryTests + { + [Fact] + public async Task ValidateJWSWithConfigAsync() + { + var invalidIssuerConfig = new OpenIdConnectConfiguration() + { + TokenEndpoint = Default.Issuer + "oauth/token", + Issuer = Default.Issuer + "2" + }; + invalidIssuerConfig.SigningKeys.Add(KeyingMaterial.DefaultX509Key_2048); + + var validationParameters = new TokenValidationParameters + { + ConfigurationManager = new StaticConfigurationManager(invalidIssuerConfig), + ValidateIssuerSigningKey = true, + RequireSignedTokens = true, + ValidateIssuer = true, + ValidateAudience = false, + ValidateLifetime = false + }; + + var testTelemetryClient = new MockTelemetryInstrumentation(); + try + { + var handler = new JsonWebTokenHandler() + { + _telemetryClient = testTelemetryClient + }; + var jwt = handler.ReadJsonWebToken(Default.AsymmetricJws); + AadIssuerValidator.GetAadIssuerValidator(Default.AadV1Authority).ConfigurationManagerV1 = validationParameters.ConfigurationManager; + var validationResult = await handler.ValidateTokenAsync(jwt, validationParameters); + var rawTokenValidationResult = await handler.ValidateTokenAsync(Default.AsymmetricJws, validationParameters); + } + catch (Exception) + { + // ignore exceptions + } + + var expectedCounterTagList = new Dictionary + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.LKG } + }; + + Assert.Equal(expectedCounterTagList, testTelemetryClient.ExportedItems); + } + } +} diff --git a/test/Microsoft.IdentityModel.Logging.Tests/Microsoft.IdentityModel.Logging.Tests.csproj b/test/Microsoft.IdentityModel.Logging.Tests/Microsoft.IdentityModel.Logging.Tests.csproj index 0d29cd28cd..6ed8578f22 100644 --- a/test/Microsoft.IdentityModel.Logging.Tests/Microsoft.IdentityModel.Logging.Tests.csproj +++ b/test/Microsoft.IdentityModel.Logging.Tests/Microsoft.IdentityModel.Logging.Tests.csproj @@ -23,6 +23,8 @@ + + diff --git a/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs b/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs new file mode 100644 index 0000000000..71b37b5a37 --- /dev/null +++ b/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; + +namespace Microsoft.IdentityModel.Logging.Tests +{ + public class MockTelemetryInstrumentation : ITelemetryInstrumentation + { + public Dictionary ExportedItems = new Dictionary(); + public Dictionary ExportedHistogramItems = new Dictionary(); + + public void ClearExportedItems() + { + ExportedItems.Clear(); + } + + public void IncrementOperationCounter(string operationStatus) + { + ExportedItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); + ExportedItems.Add(TelemetryConstants.OperationStatusTag, operationStatus); + } + + public void IncrementOperationCounter(string operationStatus, string exceptionType) + { + ExportedItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); + ExportedItems.Add(TelemetryConstants.OperationStatusTag, operationStatus); + ExportedItems.Add(TelemetryConstants.ExceptionTypeTag, exceptionType); + } + + public void LogOperationDuration(long durationInMilliseconds) + { + ExportedHistogramItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); + } + + public void LogOperationDuration(long durationInMilliseconds, string exceptionType) + { + ExportedHistogramItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); + ExportedHistogramItems.Add(TelemetryConstants.ExceptionTypeTag, exceptionType); + } + } +} diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs index 3aa11293ba..290c069b50 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs @@ -3,8 +3,11 @@ using System; using System.Collections.Generic; +using System.IO; using System.Threading.Tasks; using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Logging.Tests; +using Microsoft.IdentityModel.Protocols.Configuration; using Microsoft.IdentityModel.Protocols.OpenIdConnect.Configuration; using Microsoft.IdentityModel.TestUtils; using OpenTelemetry; @@ -36,34 +39,76 @@ public ConfigurationManagerTelemetryTests() .Build(); } + [Fact] + 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(), + new HttpDocumentRetriever(), + new OpenIdConnectConfigurationValidator()) + { + _telemetryClient = testTelemetryClient + }; + + // act + configurationManager.RequestRefresh(); + //// Wait for UpdateCurrentConfiguration to complete + while (TestUtilities.GetField(configurationManager, "_currentConfiguration") == null) + { + await Task.Delay(100); + } + + // assert + var expectedCounterTagList = new Dictionary + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Direct }, + }; + + var expectedHistogramTagList = new Dictionary + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer } + }; + + Assert.Equal(expectedCounterTagList, testTelemetryClient.ExportedItems); + Assert.Equal(expectedHistogramTagList, testTelemetryClient.ExportedHistogramItems); + } + [Theory, MemberData(nameof(GetConfiguration_ExpectedTagList_TheoryData), DisableDiscoveryEnumeration = true)] - public async Task GetConfigurationAsync_ExpectedTagList(ConfigurationManagerTelemetryTheoryData theoryData) + public async Task GetConfigurationAsync_ExpectedTagsExist(ConfigurationManagerTelemetryTheoryData theoryData) { + var testTelemetryClient = new MockTelemetryInstrumentation(); + var configurationManager = new ConfigurationManager( theoryData.MetadataAddress, new OpenIdConnectConfigurationRetriever(), theoryData.DocumentRetriever, - theoryData.ConfigurationValidator); + theoryData.ConfigurationValidator) + { + _telemetryClient = testTelemetryClient + }; try { await configurationManager.GetConfigurationAsync(); - - if (theoryData.SecondRequest) + if (theoryData.SyncAfter != null) { + testTelemetryClient.ClearExportedItems(); + TestUtilities.SetField(configurationManager, "_syncAfter", theoryData.SyncAfter); await configurationManager.GetConfigurationAsync(); } + } catch (Exception) { // Ignore exceptions } - MeterProvider.ForceFlush(); - MeterProvider.Shutdown(); - MeterProvider.Dispose(); - VerifyConfigurationManagerCounter(ExportedItems, theoryData.ExpectedTagList); - VerifyHistogramReporting(ExportedItems, theoryData.ExpectedTagList); + Assert.Equal(theoryData.ExpectedTagList, testTelemetryClient.ExportedItems); } public static TheoryData> GetConfiguration_ExpectedTagList_TheoryData() @@ -73,35 +118,22 @@ public static TheoryData("Success-retrieve from endpoint") { MetadataAddress = OpenIdConfigData.AccountsGoogle, - DocumentRetriever = new HttpDocumentRetriever(), - ConfigurationValidator = new OpenIdConnectConfigurationValidator(), - ExpectedTagList = new Dictionary - { - { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.AccountsGoogle }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.Automatic }, - } - }, - new ConfigurationManagerTelemetryTheoryData("Success-retrieve from cache") - { - MetadataAddress = OpenIdConfigData.AADCommonUrl, - DocumentRetriever = new HttpDocumentRetriever(), ConfigurationValidator = new OpenIdConnectConfigurationValidator(), - SecondRequest = true, ExpectedTagList = new Dictionary { - { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.AADCommonUrl }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.Direct }, + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.FirstRefresh }, } }, new ConfigurationManagerTelemetryTheoryData("Failure-invalid metadata address") { MetadataAddress = OpenIdConfigData.HttpsBadUri, - DocumentRetriever = new HttpDocumentRetriever(), ConfigurationValidator = new OpenIdConnectConfigurationValidator(), ExpectedTagList = new Dictionary { - { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.HttpsBadUri }, + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, { TelemetryConstants.OperationStatusTag, TelemetryConstants.FirstRefresh }, + { TelemetryConstants.ExceptionTypeTag, new IOException().GetType().ToString() }, } }, new ConfigurationManagerTelemetryTheoryData("Failure-invalid config") @@ -112,66 +144,23 @@ public static TheoryData { - { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.JsonFile }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.LKG }, + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.FirstRefresh }, + { TelemetryConstants.ExceptionTypeTag, new InvalidConfigurationException().GetType().ToString() }, } }, - }; - } - - private void VerifyConfigurationManagerCounter(List exportedMetrics, Dictionary expectedTagList) - { - var expectedTagsFound = false; - foreach (Metric metric in exportedMetrics) - { - if (!metric.Name.Equals(IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName)) - continue; - - foreach (MetricPoint metricPoint in metric.GetMetricPoints()) + new ConfigurationManagerTelemetryTheoryData("Success-refresh") { - if (MatchTagValues(metricPoint, expectedTagList)) - expectedTagsFound = true; - } - } - Assert.True(expectedTagsFound); - } - - private void VerifyHistogramReporting(List exportedMetrics, Dictionary expectedTagList) - { - var histogramMetricFound = false; - foreach (Metric metric in exportedMetrics) - { - if (!metric.Name.Equals(IdentityModelTelemetry.TotalDurationHistogramName)) - continue; - - Assert.Equal(MetricType.Histogram, metric.MetricType); - foreach (var metricPoint in metric.GetMetricPoints()) - { - if (MatchTagValues(metricPoint, expectedTagList)) - histogramMetricFound = true; - } - } - Assert.True(histogramMetricFound); - } - - private bool MatchTagValues(MetricPoint metricPoint, Dictionary expectedTagList) - { - foreach (var expectedTag in expectedTagList.Keys) - { - Dictionary tags = []; - foreach (var tag in metricPoint.Tags) - { - tags[tag.Key] = tag.Value?.ToString() ?? "null"; - } - - if (!tags.ContainsKey(expectedTag)) - return false; - - if (tags[expectedTag] != expectedTagList[expectedTag]) - return false; - } - - return true; + MetadataAddress = OpenIdConfigData.AADCommonUrl, + ConfigurationValidator = new OpenIdConnectConfigurationValidator(), + SyncAfter = DateTime.UtcNow - TimeSpan.FromDays(2), + ExpectedTagList = new Dictionary + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Automatic }, + } + }, + }; } } @@ -181,11 +170,11 @@ public ConfigurationManagerTelemetryTheoryData(string testId) : base(testId) { } public string MetadataAddress { get; set; } - public IDocumentRetriever DocumentRetriever { get; set; } + public IDocumentRetriever DocumentRetriever { get; set; } = new HttpDocumentRetriever(); public IConfigurationValidator ConfigurationValidator { get; set; } - public bool SecondRequest { get; set; } = false; + public DateTimeOffset? SyncAfter { get; set; } = null; public Dictionary ExpectedTagList { get; set; } } diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests.csproj b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests.csproj index 2b34740058..c7913cbd45 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests.csproj +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests.csproj @@ -19,16 +19,15 @@ + - - - - + + diff --git a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs new file mode 100644 index 0000000000..49ee5544a4 --- /dev/null +++ b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using Microsoft.IdentityModel.Logging; +using Microsoft.IdentityModel.Logging.Tests; +using Microsoft.IdentityModel.Protocols; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Microsoft.IdentityModel.TestUtils; +using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Validators; +using Xunit; + +namespace System.IdentityModel.Tokens.Jwt.Tests +{ + public class JwtSecurityTokenHandlerTelemetryTests + { + [Fact] + public void ValidateToken_ExpectedTagsExist() + { + var invalidIssuerConfig = new OpenIdConnectConfiguration() + { + TokenEndpoint = Default.Issuer + "oauth/token", + Issuer = Default.Issuer + "2" + }; + invalidIssuerConfig.SigningKeys.Add(KeyingMaterial.DefaultX509Key_2048); + + var validationParameters = new TokenValidationParameters + { + ConfigurationManager = new StaticConfigurationManager(invalidIssuerConfig), + ValidateIssuerSigningKey = true, + RequireSignedTokens = true, + ValidateIssuer = true, + ValidateAudience = false, + ValidateLifetime = false + }; + + var testTelemetryClient = new MockTelemetryInstrumentation(); + try + { + AadIssuerValidator.GetAadIssuerValidator(Default.AadV1Authority).ConfigurationManagerV1 = validationParameters.ConfigurationManager; + var handler = new JwtSecurityTokenHandler() + { + _telemetryClient = testTelemetryClient + }; + handler.ValidateToken(Default.AsymmetricJws, validationParameters, out _); + } + catch (Exception) + { + // ignore exceptions + } + + var expectedCounterTagList = new Dictionary + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.LKG }, + }; + + Assert.Equal(expectedCounterTagList, testTelemetryClient.ExportedItems); + } + } +} diff --git a/test/System.IdentityModel.Tokens.Jwt.Tests/System.IdentityModel.Tokens.Jwt.Tests.csproj b/test/System.IdentityModel.Tokens.Jwt.Tests/System.IdentityModel.Tokens.Jwt.Tests.csproj index e68913b3b0..55c2caee3c 100644 --- a/test/System.IdentityModel.Tokens.Jwt.Tests/System.IdentityModel.Tokens.Jwt.Tests.csproj +++ b/test/System.IdentityModel.Tokens.Jwt.Tests/System.IdentityModel.Tokens.Jwt.Tests.csproj @@ -13,8 +13,10 @@ + + From 4a36bdd8e49fab889b5248eebee1ed1ca3e60e2c Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Thu, 5 Dec 2024 18:50:27 -0800 Subject: [PATCH 07/15] fix naming --- .../JsonWebTokenHandler.ValidateToken.cs | 2 +- .../IdentityModelTelemetry.cs | 2 +- .../InternalAPI.Unshipped.txt | 28 +++++-------------- ...ntation.cs => TelemetryInstrumentation.cs} | 6 ++-- .../Configuration/ConfigurationManager.cs | 2 +- .../InternalAPI.Unshipped.txt | 19 +------------ .../JwtSecurityTokenHandler.cs | 2 +- 7 files changed, 15 insertions(+), 46 deletions(-) rename src/Microsoft.IdentityModel.Logging/{ConfigurationManagerTelemetryInstrumentation.cs => TelemetryInstrumentation.cs} (87%) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs index 83ef331f28..0f1009324a 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs @@ -17,7 +17,7 @@ namespace Microsoft.IdentityModel.JsonWebTokens /// This partial class contains methods and logic related to the validation of tokens. public partial class JsonWebTokenHandler : TokenHandler { - internal ITelemetryInstrumentation _telemetryClient = new ConfigurationManagerTelemetryInstrumentation(); + internal ITelemetryInstrumentation _telemetryClient = new TelemetryInstrumentation(); /// /// Returns a value that indicates if this handler can validate a . diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs index f90f70c459..7db8dcffc6 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs @@ -41,7 +41,7 @@ internal static void RecordTotalDurationHistogram(long requestDurationInMs, in T TotalDurationHistogram.Record(requestDurationInMs, tagList); } - internal static void IncrementConfigurationManagerCounter(in TagList tagList) + internal static void IncrementOperationCounter(in TagList tagList) { ConfigurationManagerCounter.Add(1, tagList); } diff --git a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt index 49bf064785..7cfb4654be 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt @@ -3,16 +3,6 @@ const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfig const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.MeterName = "MicrosoftIdentityModel_Meter" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ServiceName = "MicrosoftIdentityModel" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Automatic = "Automatic" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ConfigurationInvalid = "ConfigurationInvalid" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.Direct = "Direct" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.ExceptionTypeTag = "ExceptionType" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.FirstRefresh = "FirstRefresh" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IdentityModelVersionTag = "IdentityModelVersion" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.LKG = "LastKnownGood" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.MetadataAddressTag = "MetadataAddress" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.OperationStatusTag = "OperationStatus" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.Automatic = "Microsoft.IdentityModel.Protocols.Automatic" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationInvalid = "Microsoft.IdentityModel.Protocols.ConfigurationInvalid" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationRetrievalFailed = "Microsoft.IdentityModel.Protocols.ConfigurationRetrievalFailed" -> string @@ -23,12 +13,6 @@ const Microsoft.IdentityModel.Logging.TelemetryConstants.IdentityModelVersionTag const Microsoft.IdentityModel.Logging.TelemetryConstants.LKG = "Microsoft.IdentityModel.Protocols.LastKnownGood" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.ConfigurationManagerTelemetryInstrumentation() -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string operationStatus, string exceptionType) -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds) -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds, string exceptionType) -> void Microsoft.IdentityModel.Logging.IdentityModelTelemetry Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelTelemetry() -> void Microsoft.IdentityModel.Logging.ITelemetryInstrumentation @@ -37,12 +21,14 @@ Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCoun Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds) -> void Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds, string exceptionType) -> void Microsoft.IdentityModel.Logging.TelemetryConstants -static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementConfigurationManagerCounter(in System.Diagnostics.TagList tagList) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus, string exceptionType) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds, string exceptionType) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.TelemetryInstrumentation() -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementOperationCounter(in System.Diagnostics.TagList tagList) -> void static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordTotalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter(string operationStatus) -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.IncrementConfigurationManagerCounter(string operationStatus, string exceptionType) -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RecordTotalDuration(long totalMilliseconds) -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetryUtil.RecordTotalDuration(long totalMilliseconds, string exception) -> void static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelMeter -> System.Diagnostics.Metrics.Meter static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram diff --git a/src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs similarity index 87% rename from src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs rename to src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs index 71bf648271..1031c29695 100644 --- a/src/Microsoft.IdentityModel.Logging/ConfigurationManagerTelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs @@ -5,7 +5,7 @@ namespace Microsoft.IdentityModel.Logging { - internal class ConfigurationManagerTelemetryInstrumentation : ITelemetryInstrumentation + internal class TelemetryInstrumentation : ITelemetryInstrumentation { public void IncrementOperationCounter(string operationStatus) { @@ -15,7 +15,7 @@ public void IncrementOperationCounter(string operationStatus) { TelemetryConstants.OperationStatusTag, operationStatus } }; - IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); + IdentityModelTelemetry.IncrementOperationCounter(tagList); } public void IncrementOperationCounter(string operationStatus, string exceptionType) @@ -27,7 +27,7 @@ public void IncrementOperationCounter(string operationStatus, string exceptionTy { TelemetryConstants.ExceptionTypeTag, exceptionType } }; - IdentityModelTelemetry.IncrementConfigurationManagerCounter(tagList); + IdentityModelTelemetry.IncrementOperationCounter(tagList); } public void LogOperationDuration(long durationInMilliseconds) diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index 4a74bab705..35b8c099dc 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -36,7 +36,7 @@ public class ConfigurationManager : BaseConfigurationManager, IConfigurationM private int _configurationRetrieverState = ConfigurationRetrieverIdle; internal TimeProvider _timeProvider = TimeProvider.System; - internal ITelemetryInstrumentation _telemetryClient = new ConfigurationManagerTelemetryInstrumentation(); + internal ITelemetryInstrumentation _telemetryClient = new TelemetryInstrumentation(); /// /// Instantiates a new that manages automatic and controls refreshing on configuration data. diff --git a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt index 1c6e0b4fbd..85148fd8b1 100644 --- a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt @@ -1,19 +1,2 @@ -const Microsoft.IdentityModel.Logging.TelemetryConstants.Automatic = "Microsoft.IdentityModel.Protocols.Automatic" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationInvalid = "Microsoft.IdentityModel.Protocols.ConfigurationInvalid" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationRetrievalFailed = "Microsoft.IdentityModel.Protocols.ConfigurationRetrievalFailed" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Direct = "Microsoft.IdentityModel.Protocols.Direct" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.FirstRefresh = "Microsoft.IdentityModel.Protocols.FirstRefresh" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.LKG = "Microsoft.IdentityModel.Protocols.LastKnownGood" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.ConfigurationManagerTelemetryInstrumentation() -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.IncrementOperationCounter(string operationStatus, string exceptionType) -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds) -> void -Microsoft.IdentityModel.Logging.ConfigurationManagerTelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds, string exceptionType) -> void -Microsoft.IdentityModel.Logging.TelemetryConstants Microsoft.IdentityModel.Protocols.ConfigurationManager._telemetryClient -> Microsoft.IdentityModel.Logging.ITelemetryInstrumentation -Microsoft.IdentityModel.Protocols.ConfigurationManager._timeProvider -> System.TimeProvider \ No newline at end of file +Microsoft.IdentityModel.Protocols.ConfigurationManager._timeProvider -> System.TimeProvider diff --git a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs index 61766f3975..ffb835a57f 100644 --- a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs +++ b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs @@ -36,7 +36,7 @@ public class JwtSecurityTokenHandler : SecurityTokenHandler private static string _shortClaimType = _namespace + "/ShortTypeName"; private bool _mapInboundClaims = DefaultMapInboundClaims; - internal ITelemetryInstrumentation _telemetryClient = new ConfigurationManagerTelemetryInstrumentation(); + internal ITelemetryInstrumentation _telemetryClient = new TelemetryInstrumentation(); /// /// Default claim type mapping for inbound claims. From 7a1847a0f5b653be125658057765df2ffc2540f8 Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Mon, 9 Dec 2024 09:16:23 -0800 Subject: [PATCH 08/15] address interface feedback --- build/dependencies.props | 2 +- .../ITelemetryInstrumentation.cs | 10 +++++--- .../InternalAPI.Unshipped.txt | 12 ++++----- .../TelemetryInstrumentation.cs | 25 +++++++++++-------- .../Configuration/ConfigurationManager.cs | 10 ++++---- .../MockTelemetryInstrumentation.cs | 11 ++++---- 6 files changed, 38 insertions(+), 32 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 472d04ac96..850005c2c8 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -8,7 +8,7 @@ 1.0.0 2.0.3 13.0.3 - 9.0.0 + 8.0.1 4.5.5 4.5.0 8.0.5 diff --git a/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs index 65ed7adf3c..a017d66fdd 100644 --- a/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs @@ -1,22 +1,24 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; + namespace Microsoft.IdentityModel.Logging { internal interface ITelemetryInstrumentation { internal void LogOperationDuration( - long durationInMilliseconds); + TimeSpan operationDuration); internal void LogOperationDuration( - long durationInMilliseconds, - string exceptionType); + TimeSpan operationDuration, + Exception exception); internal void IncrementOperationCounter( string operationStatus); internal void IncrementOperationCounter( string operationStatus, - string exceptionType); + Exception exception); } } diff --git a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt index 7cfb4654be..d602246e89 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt @@ -17,15 +17,15 @@ Microsoft.IdentityModel.Logging.IdentityModelTelemetry Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelTelemetry() -> void Microsoft.IdentityModel.Logging.ITelemetryInstrumentation Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string operationStatus, string exceptionType) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds, string exceptionType) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string operationStatus, System.Exception exception) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration, System.Exception exception) -> void Microsoft.IdentityModel.Logging.TelemetryConstants Microsoft.IdentityModel.Logging.TelemetryInstrumentation Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus, string exceptionType) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(long durationInMilliseconds, string exceptionType) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus, System.Exception exception) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration, System.Exception exception) -> void Microsoft.IdentityModel.Logging.TelemetryInstrumentation.TelemetryInstrumentation() -> void static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementOperationCounter(in System.Diagnostics.TagList tagList) -> void static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordTotalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void diff --git a/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs index 1031c29695..96d6f27d2c 100644 --- a/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs @@ -1,12 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using System.Diagnostics; namespace Microsoft.IdentityModel.Logging { internal class TelemetryInstrumentation : ITelemetryInstrumentation { + static TagList ClientVerTagList = new TagList() + { + { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer } + }; + public void IncrementOperationCounter(string operationStatus) { var tagList = new TagList() @@ -18,36 +24,33 @@ public void IncrementOperationCounter(string operationStatus) IdentityModelTelemetry.IncrementOperationCounter(tagList); } - public void IncrementOperationCounter(string operationStatus, string exceptionType) + public void IncrementOperationCounter(string operationStatus, Exception exception) { var tagList = new TagList() { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, { TelemetryConstants.OperationStatusTag, operationStatus }, - { TelemetryConstants.ExceptionTypeTag, exceptionType } + { TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() } }; IdentityModelTelemetry.IncrementOperationCounter(tagList); } - public void LogOperationDuration(long durationInMilliseconds) + public void LogOperationDuration(TimeSpan operationDuration) { - var tagList = new TagList() - { - { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer } - }; - - IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMilliseconds, tagList); + long durationInMilliseconds = (long)operationDuration.TotalMilliseconds; + IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMilliseconds, ClientVerTagList); } - public void LogOperationDuration(long durationInMilliseconds, string exceptionType) + public void LogOperationDuration(TimeSpan operationDuration, Exception exception) { var tagList = new TagList() { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, - { TelemetryConstants.ExceptionTypeTag, exceptionType } + { TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() } }; + long durationInMilliseconds = (long)operationDuration.TotalMilliseconds; IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMilliseconds, tagList); } } diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index 35b8c099dc..3bde6c65a4 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -196,7 +196,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) _telemetryClient.IncrementOperationCounter( TelemetryConstants.FirstRefresh, - ex.GetType().ToString()); + ex); throw LogHelper.LogExceptionMessage(ex); } @@ -211,7 +211,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) fetchMetadataFailure = ex; _telemetryClient.IncrementOperationCounter( TelemetryConstants.FirstRefresh, - ex.GetType().ToString()); + ex); LogHelper.LogExceptionMessage( new InvalidOperationException( @@ -269,7 +269,7 @@ private void UpdateCurrentConfiguration() _docRetriever, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); - long elapsedTime = (long)_timeProvider.GetElapsedTime(startTimestamp).TotalMilliseconds; + var elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); _telemetryClient.LogOperationDuration(elapsedTime); if (_configValidator == null) @@ -292,10 +292,10 @@ private void UpdateCurrentConfiguration() } catch (Exception ex) { - long elapsedTime = (long)_timeProvider.GetElapsedTime(startTimestamp).TotalMilliseconds; + var elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); _telemetryClient.LogOperationDuration( elapsedTime, - ex.GetType().ToString()); + ex); LogHelper.LogExceptionMessage( new InvalidOperationException( diff --git a/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs b/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs index 71b37b5a37..860bed8408 100644 --- a/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs +++ b/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using System.Collections.Generic; namespace Microsoft.IdentityModel.Logging.Tests @@ -21,22 +22,22 @@ public void IncrementOperationCounter(string operationStatus) ExportedItems.Add(TelemetryConstants.OperationStatusTag, operationStatus); } - public void IncrementOperationCounter(string operationStatus, string exceptionType) + public void IncrementOperationCounter(string operationStatus, Exception exception) { ExportedItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); ExportedItems.Add(TelemetryConstants.OperationStatusTag, operationStatus); - ExportedItems.Add(TelemetryConstants.ExceptionTypeTag, exceptionType); + ExportedItems.Add(TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString()); } - public void LogOperationDuration(long durationInMilliseconds) + public void LogOperationDuration(TimeSpan operationDuration) { ExportedHistogramItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); } - public void LogOperationDuration(long durationInMilliseconds, string exceptionType) + public void LogOperationDuration(TimeSpan operationDuration, Exception exception) { ExportedHistogramItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); - ExportedHistogramItems.Add(TelemetryConstants.ExceptionTypeTag, exceptionType); + ExportedHistogramItems.Add(TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString()); } } } From 44b97faa84851cc4f82a3324f0d34e8f662af315 Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Tue, 10 Dec 2024 10:22:09 -0800 Subject: [PATCH 09/15] Interface and namespace changes --- .../InternalAPI.Unshipped.txt | 18 ++++++++++ .../JsonWebTokenHandler.ValidateToken.cs | 4 +-- .../ITelemetryInstrumentation.cs | 8 ++--- .../IdentityModelTelemetry.cs | 10 +++--- .../InternalAPI.Unshipped.txt | 35 ++++++++++--------- .../TelemetryConstants.cs | 19 +++++----- .../TelemetryInstrumentation.cs | 18 +++++----- .../Configuration/ConfigurationManager.cs | 18 +++++----- .../JwtSecurityTokenHandler.cs | 4 +-- .../JsonWebTokenHandlerTelemetryTests.cs | 2 +- .../MockTelemetryInstrumentation.cs | 8 ++--- .../ConfigurationManagerTelemetryTests.cs | 33 +++-------------- .../JwtSecurityTokenHandlerTelemetryTests.cs | 2 +- 13 files changed, 89 insertions(+), 90 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt index c4e9578c3a..b66932282a 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt @@ -1,4 +1,22 @@ +const Microsoft.IdentityModel.Logging.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.Automatic = "Microsoft.IdentityModel.Protocols.Automatic" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.ConfigurationInvalid = "Microsoft.IdentityModel.Protocols.ConfigurationInvalid" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.ConfigurationRetrievalFailed = "Microsoft.IdentityModel.Protocols.ConfigurationRetrievalFailed" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.Direct = "Microsoft.IdentityModel.Protocols.Direct" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.FirstRefresh = "Microsoft.IdentityModel.Protocols.FirstRefresh" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.LKG = "Microsoft.IdentityModel.Protocols.LastKnownGood" -> string Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler._telemetryClient -> Microsoft.IdentityModel.Logging.ITelemetryInstrumentation +Microsoft.IdentityModel.Logging.TelemetryConstants +Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols +Microsoft.IdentityModel.Logging.TelemetryInstrumentation +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus, System.Exception exception) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration, System.Exception exception) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.TelemetryInstrumentation() -> void static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(string payload, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, string compressionAlgorithm, System.Collections.Generic.IDictionary additionalHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs index 0f1009324a..5b42a94c75 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs @@ -513,8 +513,8 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration) // where a new valid configuration was somehow published during validation time. if (currentConfiguration != null) { - _telemetryClient.IncrementOperationCounter( - TelemetryConstants.LKG); + _telemetryClient.IncrementConfigurationRefreshRequestCounter( + TelemetryConstants.Protocols.LKG); validationParameters.ConfigurationManager.RequestRefresh(); validationParameters.RefreshBeforeValidation = true; diff --git a/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs index a017d66fdd..f6b0a84ab4 100644 --- a/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs @@ -7,17 +7,17 @@ namespace Microsoft.IdentityModel.Logging { internal interface ITelemetryInstrumentation { - internal void LogOperationDuration( + internal void LogConfigurationRetrievalDuration( TimeSpan operationDuration); - internal void LogOperationDuration( + internal void LogConfigurationRetrievalDuration( TimeSpan operationDuration, Exception exception); - internal void IncrementOperationCounter( + internal void IncrementConfigurationRefreshRequestCounter( string operationStatus); - internal void IncrementOperationCounter( + internal void IncrementConfigurationRefreshRequestCounter( string operationStatus, Exception exception); } diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs index 7db8dcffc6..f1f56e7632 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs +++ b/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs @@ -22,26 +22,26 @@ internal class IdentityModelTelemetry internal const string TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS"; /// - /// Counter to capture requests to configuration manager. + /// Counter to capture configuration refresh requests to ConfigurationManager. /// - internal const string IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManagerCounter"; + internal const string IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManager"; internal const string IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations."; internal static readonly Counter ConfigurationManagerCounter = IdentityModelMeter.CreateCounter(IdentityModelConfigurationManagerCounterName, description: IdentityModelConfigurationManagerCounterDescription); /// - /// Histogram to capture total duration of configuration manager operations in milliseconds. + /// Histogram to capture total duration of configuration retrieval by ConfigurationManager in milliseconds. /// internal static readonly Histogram TotalDurationHistogram = IdentityModelMeter.CreateHistogram( TotalDurationHistogramName, unit: "ms", description: "Configuration retrieval latency during configuration manager operations."); - internal static void RecordTotalDurationHistogram(long requestDurationInMs, in TagList tagList) + internal static void RecordConfigurationRetrievalDurationHistogram(long requestDurationInMs, in TagList tagList) { TotalDurationHistogram.Record(requestDurationInMs, tagList); } - internal static void IncrementOperationCounter(in TagList tagList) + internal static void IncrementConfigurationRefreshRequestCounter(in TagList tagList) { ConfigurationManagerCounter.Add(1, tagList); } diff --git a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt index d602246e89..31feabb55e 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt @@ -1,34 +1,35 @@ const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManagerCounter" -> string +const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManager" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.MeterName = "MicrosoftIdentityModel_Meter" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ServiceName = "MicrosoftIdentityModel" -> string const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Automatic = "Microsoft.IdentityModel.Protocols.Automatic" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationInvalid = "Microsoft.IdentityModel.Protocols.ConfigurationInvalid" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.ConfigurationRetrievalFailed = "Microsoft.IdentityModel.Protocols.ConfigurationRetrievalFailed" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Direct = "Microsoft.IdentityModel.Protocols.Direct" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.FirstRefresh = "Microsoft.IdentityModel.Protocols.FirstRefresh" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.LKG = "Microsoft.IdentityModel.Protocols.LastKnownGood" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string const Microsoft.IdentityModel.Logging.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.Automatic = "Automatic" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.ConfigurationInvalid = "ConfigurationInvalid" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.Direct = "Direct" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.FirstRefresh = "FirstRefresh" -> string +const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.LKG = "LastKnownGood" -> string Microsoft.IdentityModel.Logging.IdentityModelTelemetry Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelTelemetry() -> void Microsoft.IdentityModel.Logging.ITelemetryInstrumentation -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementOperationCounter(string operationStatus, System.Exception exception) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration, System.Exception exception) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus, System.Exception exception) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration) -> void +Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration, System.Exception exception) -> void Microsoft.IdentityModel.Logging.TelemetryConstants +Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols Microsoft.IdentityModel.Logging.TelemetryInstrumentation -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus, System.Exception exception) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration, System.Exception exception) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus, System.Exception exception) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration) -> void +Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration, System.Exception exception) -> void Microsoft.IdentityModel.Logging.TelemetryInstrumentation.TelemetryInstrumentation() -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementOperationCounter(in System.Diagnostics.TagList tagList) -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordTotalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(in System.Diagnostics.TagList tagList) -> void +static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelMeter -> System.Diagnostics.Metrics.Meter static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram diff --git a/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs b/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs index 9dec03e165..11a4b4e95f 100644 --- a/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs +++ b/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs @@ -11,14 +11,17 @@ internal static class TelemetryConstants public const string OperationStatusTag = "OperationStatus"; public const string ExceptionTypeTag = "ExceptionType"; - // Configuration manager refresh statuses - public const string Automatic = "Microsoft.IdentityModel.Protocols.Automatic"; - public const string Direct = "Microsoft.IdentityModel.Protocols.Direct"; - public const string FirstRefresh = "Microsoft.IdentityModel.Protocols.FirstRefresh"; - public const string LKG = "Microsoft.IdentityModel.Protocols.LastKnownGood"; + public static class Protocols + { + // Configuration manager refresh statuses + public const string Automatic = "Automatic"; + public const string Direct = "Direct"; + public const string FirstRefresh = "FirstRefresh"; + public const string LKG = "LastKnownGood"; - // Configuration manager exception types - public const string ConfigurationInvalid = "Microsoft.IdentityModel.Protocols.ConfigurationInvalid"; - public const string ConfigurationRetrievalFailed = "Microsoft.IdentityModel.Protocols.ConfigurationRetrievalFailed"; + // Configuration manager exception types + public const string ConfigurationInvalid = "ConfigurationInvalid"; + public const string ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed"; + } } } diff --git a/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs index 96d6f27d2c..b39c3e422b 100644 --- a/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs @@ -8,12 +8,12 @@ namespace Microsoft.IdentityModel.Logging { internal class TelemetryInstrumentation : ITelemetryInstrumentation { - static TagList ClientVerTagList = new TagList() + static TagList ClientVerTagList = new() { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer } }; - public void IncrementOperationCounter(string operationStatus) + public void IncrementConfigurationRefreshRequestCounter(string operationStatus) { var tagList = new TagList() { @@ -21,10 +21,10 @@ public void IncrementOperationCounter(string operationStatus) { TelemetryConstants.OperationStatusTag, operationStatus } }; - IdentityModelTelemetry.IncrementOperationCounter(tagList); + IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(tagList); } - public void IncrementOperationCounter(string operationStatus, Exception exception) + public void IncrementConfigurationRefreshRequestCounter(string operationStatus, Exception exception) { var tagList = new TagList() { @@ -33,16 +33,16 @@ public void IncrementOperationCounter(string operationStatus, Exception exceptio { TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() } }; - IdentityModelTelemetry.IncrementOperationCounter(tagList); + IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(tagList); } - public void LogOperationDuration(TimeSpan operationDuration) + public void LogConfigurationRetrievalDuration(TimeSpan operationDuration) { long durationInMilliseconds = (long)operationDuration.TotalMilliseconds; - IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMilliseconds, ClientVerTagList); + IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(durationInMilliseconds, ClientVerTagList); } - public void LogOperationDuration(TimeSpan operationDuration, Exception exception) + public void LogConfigurationRetrievalDuration(TimeSpan operationDuration, Exception exception) { var tagList = new TagList() { @@ -51,7 +51,7 @@ public void LogOperationDuration(TimeSpan operationDuration, Exception exception }; long durationInMilliseconds = (long)operationDuration.TotalMilliseconds; - IdentityModelTelemetry.RecordTotalDurationHistogram(durationInMilliseconds, tagList); + IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(durationInMilliseconds, tagList); } } } diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index 3bde6c65a4..6b1454c5e8 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -194,23 +194,23 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) LogMessages.IDX20810, result.ErrorMessage)); - _telemetryClient.IncrementOperationCounter( - TelemetryConstants.FirstRefresh, + _telemetryClient.IncrementConfigurationRefreshRequestCounter( + TelemetryConstants.Protocols.FirstRefresh, ex); throw LogHelper.LogExceptionMessage(ex); } } - _telemetryClient.IncrementOperationCounter(TelemetryConstants.FirstRefresh); + _telemetryClient.IncrementConfigurationRefreshRequestCounter(TelemetryConstants.Protocols.FirstRefresh); UpdateConfiguration(configuration); } catch (Exception ex) { // counter for failure first time fetchMetadataFailure = ex; - _telemetryClient.IncrementOperationCounter( - TelemetryConstants.FirstRefresh, + _telemetryClient.IncrementConfigurationRefreshRequestCounter( + TelemetryConstants.Protocols.FirstRefresh, ex); LogHelper.LogExceptionMessage( @@ -231,7 +231,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) { if (Interlocked.CompareExchange(ref _configurationRetrieverState, ConfigurationRetrieverRunning, ConfigurationRetrieverIdle) == ConfigurationRetrieverIdle) { - _telemetryClient.IncrementOperationCounter(TelemetryConstants.Automatic); + _telemetryClient.IncrementConfigurationRefreshRequestCounter(TelemetryConstants.Protocols.Automatic); _ = Task.Run(UpdateCurrentConfiguration, CancellationToken.None); } } @@ -270,7 +270,7 @@ private void UpdateCurrentConfiguration() CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); var elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); - _telemetryClient.LogOperationDuration(elapsedTime); + _telemetryClient.LogConfigurationRetrievalDuration(elapsedTime); if (_configValidator == null) { @@ -293,7 +293,7 @@ private void UpdateCurrentConfiguration() catch (Exception ex) { var elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); - _telemetryClient.LogOperationDuration( + _telemetryClient.LogConfigurationRetrievalDuration( elapsedTime, ex); @@ -341,7 +341,7 @@ public override void RequestRefresh() { DateTimeOffset now = DateTimeOffset.UtcNow; - _telemetryClient.IncrementOperationCounter(TelemetryConstants.Direct); + _telemetryClient.IncrementConfigurationRefreshRequestCounter(TelemetryConstants.Protocols.Direct); if (now >= DateTimeUtil.Add(_lastRequestRefresh.UtcDateTime, RefreshInterval) || _isFirstRefreshRequest) { _isFirstRefreshRequest = false; diff --git a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs index ffb835a57f..0340322d4b 100644 --- a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs +++ b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs @@ -889,8 +889,8 @@ private ClaimsPrincipal ValidateToken(string token, JwtSecurityToken outerToken, // where a new valid configuration was somehow published during validation time. if (currentConfiguration != null) { - _telemetryClient.IncrementOperationCounter( - TelemetryConstants.LKG); + _telemetryClient.IncrementConfigurationRefreshRequestCounter( + TelemetryConstants.Protocols.LKG); validationParameters.ConfigurationManager.RequestRefresh(); validationParameters.RefreshBeforeValidation = true; diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs index 875c6f01ec..481a3640f1 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs @@ -57,7 +57,7 @@ public async Task ValidateJWSWithConfigAsync() var expectedCounterTagList = new Dictionary { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.LKG } + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.LKG } }; Assert.Equal(expectedCounterTagList, testTelemetryClient.ExportedItems); diff --git a/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs b/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs index 860bed8408..4e8462e4b0 100644 --- a/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs +++ b/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs @@ -16,25 +16,25 @@ public void ClearExportedItems() ExportedItems.Clear(); } - public void IncrementOperationCounter(string operationStatus) + public void IncrementConfigurationRefreshRequestCounter(string operationStatus) { ExportedItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); ExportedItems.Add(TelemetryConstants.OperationStatusTag, operationStatus); } - public void IncrementOperationCounter(string operationStatus, Exception exception) + public void IncrementConfigurationRefreshRequestCounter(string operationStatus, Exception exception) { ExportedItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); ExportedItems.Add(TelemetryConstants.OperationStatusTag, operationStatus); ExportedItems.Add(TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString()); } - public void LogOperationDuration(TimeSpan operationDuration) + public void LogConfigurationRetrievalDuration(TimeSpan operationDuration) { ExportedHistogramItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); } - public void LogOperationDuration(TimeSpan operationDuration, Exception exception) + public void LogConfigurationRetrievalDuration(TimeSpan operationDuration, Exception exception) { ExportedHistogramItems.Add(TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer); ExportedHistogramItems.Add(TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString()); diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs index 290c069b50..f7aed91136 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs @@ -10,35 +10,12 @@ using Microsoft.IdentityModel.Protocols.Configuration; using Microsoft.IdentityModel.Protocols.OpenIdConnect.Configuration; using Microsoft.IdentityModel.TestUtils; -using OpenTelemetry; -using OpenTelemetry.Metrics; -using OpenTelemetry.Resources; using Xunit; namespace Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests { public class ConfigurationManagerTelemetryTests { - readonly List ExportedItems; - readonly MeterProvider MeterProvider; - - public ConfigurationManagerTelemetryTests() - { - ExportedItems = new List(); - - MeterProvider = Sdk.CreateMeterProviderBuilder() - .SetResourceBuilder(ResourceBuilder.CreateDefault()) - .AddMeter(IdentityModelTelemetry.MeterName) - .AddInMemoryExporter(ExportedItems, (options) => - { - options.PeriodicExportingMetricReaderOptions = new PeriodicExportingMetricReaderOptions - { - ExportIntervalMilliseconds = 10, - }; - }) - .Build(); - } - [Fact] public async Task RequestRefresh_ExpectedTagsExist() { @@ -66,7 +43,7 @@ public async Task RequestRefresh_ExpectedTagsExist() var expectedCounterTagList = new Dictionary { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.Direct }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.Direct }, }; var expectedHistogramTagList = new Dictionary @@ -122,7 +99,7 @@ public static TheoryData { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.FirstRefresh }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.FirstRefresh }, } }, new ConfigurationManagerTelemetryTheoryData("Failure-invalid metadata address") @@ -132,7 +109,7 @@ public static TheoryData { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.FirstRefresh }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.FirstRefresh }, { TelemetryConstants.ExceptionTypeTag, new IOException().GetType().ToString() }, } }, @@ -145,7 +122,7 @@ public static TheoryData { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.FirstRefresh }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.FirstRefresh }, { TelemetryConstants.ExceptionTypeTag, new InvalidConfigurationException().GetType().ToString() }, } }, @@ -157,7 +134,7 @@ public static TheoryData { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.Automatic }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.Automatic }, } }, }; diff --git a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs index 49ee5544a4..5665c17f11 100644 --- a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs +++ b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs @@ -53,7 +53,7 @@ public void ValidateToken_ExpectedTagsExist() var expectedCounterTagList = new Dictionary { { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.LKG }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.LKG }, }; Assert.Equal(expectedCounterTagList, testTelemetryClient.ExportedItems); From 7b3d16dcd1b9e1e4b9cc4aed451f6d7bff0978ec Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Tue, 10 Dec 2024 15:32:49 -0800 Subject: [PATCH 10/15] avoid friend assemblies --- .../InternalAPI.Unshipped.txt | 20 +---------- .../JsonWebTokenHandler.ValidateToken.cs | 1 + .../InternalAPI.Unshipped.txt | 35 ------------------- .../InternalsVisibleTo.cs | 5 --- .../Configuration/ConfigurationManager.cs | 1 + .../InternalAPI.Unshipped.txt | 2 +- .../InternalAPI.Unshipped.txt | 35 +++++++++++++++++++ .../Telemetry}/ITelemetryInstrumentation.cs | 2 +- .../Telemetry}/IdentityModelTelemetry.cs | 2 +- .../Telemetry}/TelemetryConstants.cs | 2 +- .../Telemetry}/TelemetryInstrumentation.cs | 3 +- .../InternalAPI.Unshipped.txt | 2 +- .../JwtSecurityTokenHandler.cs | 1 + .../JsonWebTokenHandlerTelemetryTests.cs | 3 +- .../ConfigurationManagerTelemetryTests.cs | 3 +- .../MockTelemetryInstrumentation.cs | 3 +- .../JwtSecurityTokenHandlerTelemetryTests.cs | 3 +- 17 files changed, 54 insertions(+), 69 deletions(-) rename src/{Microsoft.IdentityModel.Logging => Microsoft.IdentityModel.Tokens/Telemetry}/ITelemetryInstrumentation.cs (92%) rename src/{Microsoft.IdentityModel.Logging => Microsoft.IdentityModel.Tokens/Telemetry}/IdentityModelTelemetry.cs (97%) rename src/{Microsoft.IdentityModel.Logging => Microsoft.IdentityModel.Tokens/Telemetry}/TelemetryConstants.cs (95%) rename src/{Microsoft.IdentityModel.Logging => Microsoft.IdentityModel.Tokens/Telemetry}/TelemetryInstrumentation.cs (96%) rename test/{Microsoft.IdentityModel.Logging.Tests => Microsoft.IdentityModel.Tokens.Tests/Telemetry}/MockTelemetryInstrumentation.cs (95%) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt index b66932282a..02f2a0a845 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt @@ -1,22 +1,4 @@ -const Microsoft.IdentityModel.Logging.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.Automatic = "Microsoft.IdentityModel.Protocols.Automatic" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.ConfigurationInvalid = "Microsoft.IdentityModel.Protocols.ConfigurationInvalid" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.ConfigurationRetrievalFailed = "Microsoft.IdentityModel.Protocols.ConfigurationRetrievalFailed" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.Direct = "Microsoft.IdentityModel.Protocols.Direct" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.FirstRefresh = "Microsoft.IdentityModel.Protocols.FirstRefresh" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.LKG = "Microsoft.IdentityModel.Protocols.LastKnownGood" -> string -Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler._telemetryClient -> Microsoft.IdentityModel.Logging.ITelemetryInstrumentation -Microsoft.IdentityModel.Logging.TelemetryConstants -Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols -Microsoft.IdentityModel.Logging.TelemetryInstrumentation -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementOperationCounter(string operationStatus, System.Exception exception) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogOperationDuration(System.TimeSpan operationDuration, System.Exception exception) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.TelemetryInstrumentation() -> void +Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler._telemetryClient -> Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(string payload, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, string compressionAlgorithm, System.Collections.Generic.IDictionary additionalHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs index 5b42a94c75..b3c0844473 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs @@ -10,6 +10,7 @@ using Microsoft.IdentityModel.Abstractions; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Tokens.Telemetry; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; namespace Microsoft.IdentityModel.JsonWebTokens diff --git a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt index 31feabb55e..e69de29bb2 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Logging/InternalAPI.Unshipped.txt @@ -1,35 +0,0 @@ -const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManager" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.MeterName = "MicrosoftIdentityModel_Meter" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ServiceName = "MicrosoftIdentityModel" -> string -const Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.Automatic = "Automatic" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.ConfigurationInvalid = "ConfigurationInvalid" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.Direct = "Direct" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.FirstRefresh = "FirstRefresh" -> string -const Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols.LKG = "LastKnownGood" -> string -Microsoft.IdentityModel.Logging.IdentityModelTelemetry -Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelTelemetry() -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus, System.Exception exception) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration) -> void -Microsoft.IdentityModel.Logging.ITelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration, System.Exception exception) -> void -Microsoft.IdentityModel.Logging.TelemetryConstants -Microsoft.IdentityModel.Logging.TelemetryConstants.Protocols -Microsoft.IdentityModel.Logging.TelemetryInstrumentation -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.IncrementConfigurationRefreshRequestCounter(string operationStatus, System.Exception exception) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.LogConfigurationRetrievalDuration(System.TimeSpan operationDuration, System.Exception exception) -> void -Microsoft.IdentityModel.Logging.TelemetryInstrumentation.TelemetryInstrumentation() -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(in System.Diagnostics.TagList tagList) -> void -static Microsoft.IdentityModel.Logging.IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void -static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter -static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.IdentityModelMeter -> System.Diagnostics.Metrics.Meter -static readonly Microsoft.IdentityModel.Logging.IdentityModelTelemetry.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram diff --git a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs index 44b121b658..fc43ff8880 100644 --- a/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs +++ b/src/Microsoft.IdentityModel.Logging/InternalsVisibleTo.cs @@ -1,13 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.JsonWebTokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.JsonWebTokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.IdentityModel.Tokens.Jwt, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.IdentityModel.Tokens.Jwt.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index 6b1454c5e8..9a7c5cfc35 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -8,6 +8,7 @@ using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Protocols.Configuration; using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Tokens.Telemetry; namespace Microsoft.IdentityModel.Protocols { diff --git a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt index 85148fd8b1..1c3509c864 100644 --- a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt @@ -1,2 +1,2 @@ -Microsoft.IdentityModel.Protocols.ConfigurationManager._telemetryClient -> Microsoft.IdentityModel.Logging.ITelemetryInstrumentation +Microsoft.IdentityModel.Protocols.ConfigurationManager._telemetryClient -> Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation Microsoft.IdentityModel.Protocols.ConfigurationManager._timeProvider -> System.TimeProvider diff --git a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt index 23c18b30a7..50e2ca6243 100644 --- a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt @@ -3,6 +3,21 @@ const Microsoft.IdentityModel.Tokens.LogMessages.IDX10268 = "IDX10268: Unable to const Microsoft.IdentityModel.Tokens.LogMessages.IDX10269 = "IDX10269: IssuerValidationDelegate threw an exception, see inner exception." -> string const Microsoft.IdentityModel.Tokens.LogMessages.IDX10271 = "IDX10271: LifetimeValidationDelegate threw an exception, see inner exception." -> string const Microsoft.IdentityModel.Tokens.LogMessages.IDX10275 = "IDX10275: TokenTypeValidationDelegate threw an exception, see inner exception." -> string +const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string +const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManager" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.MeterName = "MicrosoftIdentityModel_Meter" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.ServiceName = "MicrosoftIdentityModel" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.OperationStatusTag = "OperationStatus" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.Automatic = "Automatic" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.ConfigurationInvalid = "ConfigurationInvalid" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.Direct = "Direct" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.FirstRefresh = "FirstRefresh" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.LKG = "LastKnownGood" -> string Microsoft.IdentityModel.Tokens.AlgorithmValidationError Microsoft.IdentityModel.Tokens.AlgorithmValidationError.AlgorithmValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidAlgorithm, System.Exception innerException = null) -> void Microsoft.IdentityModel.Tokens.AlgorithmValidationError.InvalidAlgorithm.get -> string @@ -23,6 +38,21 @@ Microsoft.IdentityModel.Tokens.IssuerValidationSource.IssuerMatchedValidationPar Microsoft.IdentityModel.Tokens.LifetimeValidationError.Expires.get -> System.DateTime? Microsoft.IdentityModel.Tokens.LifetimeValidationError.LifetimeValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, System.DateTime? notBefore, System.DateTime? expires, System.Exception innerException = null) -> void Microsoft.IdentityModel.Tokens.LifetimeValidationError.NotBefore.get -> System.DateTime? +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.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.TelemetryInstrumentation() -> void Microsoft.IdentityModel.Tokens.TokenTypeValidationError Microsoft.IdentityModel.Tokens.TokenTypeValidationError.TokenTypeValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidTokenType, System.Exception innerException = null) -> void Microsoft.IdentityModel.Tokens.TokenTypeValidationError._invalidTokenType -> string @@ -40,8 +70,13 @@ override Microsoft.IdentityModel.Tokens.AlgorithmValidationError.GetException() override Microsoft.IdentityModel.Tokens.IssuerSigningKeyValidationError.GetException() -> System.Exception override Microsoft.IdentityModel.Tokens.TokenTypeValidationError.GetException() -> System.Exception static Microsoft.IdentityModel.Tokens.IssuerSigningKeyValidationError.NullParameter(string parameterName, System.Diagnostics.StackFrame stackFrame) -> Microsoft.IdentityModel.Tokens.IssuerSigningKeyValidationError +static Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(in System.Diagnostics.TagList tagList) -> void +static Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void static Microsoft.IdentityModel.Tokens.Utility.SerializeAsSingleCommaDelimitedString(System.Collections.Generic.IList strings) -> string static Microsoft.IdentityModel.Tokens.ValidationError.GetCurrentStackFrame(string filePath = "", int lineNumber = 0, int skipFrames = 1) -> System.Diagnostics.StackFrame +static readonly Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter +static readonly Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.IdentityModelMeter -> System.Diagnostics.Metrics.Meter +static readonly Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.IssuerValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.LifetimeValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.NoTokenAudiencesProvided -> Microsoft.IdentityModel.Tokens.ValidationFailureType diff --git a/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs similarity index 92% rename from src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs rename to src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs index f6b0a84ab4..1f7bdd06f5 100644 --- a/src/Microsoft.IdentityModel.Logging/ITelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.IdentityModel.Logging +namespace Microsoft.IdentityModel.Tokens.Telemetry { internal interface ITelemetryInstrumentation { diff --git a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs similarity index 97% rename from src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs rename to src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs index f1f56e7632..a281810b36 100644 --- a/src/Microsoft.IdentityModel.Logging/IdentityModelTelemetry.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs @@ -4,7 +4,7 @@ using System.Diagnostics; using System.Diagnostics.Metrics; -namespace Microsoft.IdentityModel.Logging +namespace Microsoft.IdentityModel.Tokens.Telemetry { internal class IdentityModelTelemetry { diff --git a/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs similarity index 95% rename from src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs rename to src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs index 11a4b4e95f..780c3c4401 100644 --- a/src/Microsoft.IdentityModel.Logging/TelemetryConstants.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -namespace Microsoft.IdentityModel.Logging +namespace Microsoft.IdentityModel.Tokens.Telemetry { internal static class TelemetryConstants { diff --git a/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs similarity index 96% rename from src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs rename to src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs index b39c3e422b..b1bdec373a 100644 --- a/src/Microsoft.IdentityModel.Logging/TelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs @@ -3,8 +3,9 @@ using System; using System.Diagnostics; +using Microsoft.IdentityModel.Logging; -namespace Microsoft.IdentityModel.Logging +namespace Microsoft.IdentityModel.Tokens.Telemetry { internal class TelemetryInstrumentation : ITelemetryInstrumentation { diff --git a/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt b/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt index 3b31c9fa88..64592dad8f 100644 --- a/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt +++ b/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt @@ -1,3 +1,3 @@ System.IdentityModel.Tokens.Jwt.JwtHeader.JwtHeader(Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, System.Collections.Generic.IDictionary outboundAlgorithmMap, string tokenType, System.Collections.Generic.IDictionary additionalHeaderClaims, bool includeKeyIdInHeader) -> void System.IdentityModel.Tokens.Jwt.JwtHeader.JwtHeader(Microsoft.IdentityModel.Tokens.SigningCredentials signingCredentials, System.Collections.Generic.IDictionary outboundAlgorithmMap, string tokenType, System.Collections.Generic.IDictionary additionalInnerHeaderClaims, bool includeKeyIdInHeader) -> void -System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler._telemetryClient -> Microsoft.IdentityModel.Logging.ITelemetryInstrumentation \ No newline at end of file +System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler._telemetryClient -> Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation \ No newline at end of file diff --git a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs index 0340322d4b..86dc6cb1e8 100644 --- a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs +++ b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs @@ -15,6 +15,7 @@ using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Tokens.Telemetry; using TokenLogMessages = Microsoft.IdentityModel.Tokens.LogMessages; namespace System.IdentityModel.Tokens.Jwt diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs index 481a3640f1..fdea100b51 100644 --- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs @@ -5,11 +5,12 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.IdentityModel.Logging; -using Microsoft.IdentityModel.Logging.Tests; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Tokens.Telemetry; +using Microsoft.IdentityModel.Tokens.Telemetry.Tests; using Microsoft.IdentityModel.Validators; using Xunit; diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs index f7aed91136..11612bf6ce 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs @@ -6,10 +6,11 @@ using System.IO; using System.Threading.Tasks; using Microsoft.IdentityModel.Logging; -using Microsoft.IdentityModel.Logging.Tests; using Microsoft.IdentityModel.Protocols.Configuration; using Microsoft.IdentityModel.Protocols.OpenIdConnect.Configuration; using Microsoft.IdentityModel.TestUtils; +using Microsoft.IdentityModel.Tokens.Telemetry; +using Microsoft.IdentityModel.Tokens.Telemetry.Tests; using Xunit; namespace Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests diff --git a/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs similarity index 95% rename from test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs rename to test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs index 4e8462e4b0..2d9222edf6 100644 --- a/test/Microsoft.IdentityModel.Logging.Tests/MockTelemetryInstrumentation.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs @@ -3,8 +3,9 @@ using System; using System.Collections.Generic; +using Microsoft.IdentityModel.Logging; -namespace Microsoft.IdentityModel.Logging.Tests +namespace Microsoft.IdentityModel.Tokens.Telemetry.Tests { public class MockTelemetryInstrumentation : ITelemetryInstrumentation { diff --git a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs index 5665c17f11..4652243d3d 100644 --- a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs +++ b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs @@ -3,11 +3,12 @@ using System.Collections.Generic; using Microsoft.IdentityModel.Logging; -using Microsoft.IdentityModel.Logging.Tests; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.TestUtils; using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.Tokens.Telemetry; +using Microsoft.IdentityModel.Tokens.Telemetry.Tests; using Microsoft.IdentityModel.Validators; using Xunit; 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 11/15] 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 }, }; From 4011af9965c9080d79882a9a31e9fdc130881f0c Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Fri, 13 Dec 2024 19:53:09 -0800 Subject: [PATCH 12/15] doc comments for tags --- .../Telemetry/TelemetryConstants.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs index 780c3c4401..72ea0e91d0 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs @@ -6,21 +6,61 @@ namespace Microsoft.IdentityModel.Tokens.Telemetry internal static class TelemetryConstants { // Static attribute tags + + /// + /// Telemetry tag indicating the version of the IdentityModel library. + /// public const string IdentityModelVersionTag = "IdentityModelVersion"; + + /// + /// Telemetry tag indicating the endpoint from which a configuration is retrieved. + /// public const string MetadataAddressTag = "MetadataAddress"; + + /// + /// Telemetry tag describing the operation being performed. + /// public const string OperationStatusTag = "OperationStatus"; + + /// + /// Telemetry tag indicating the type of exception that occurred. + /// public const string ExceptionTypeTag = "ExceptionType"; public static class Protocols { // Configuration manager refresh statuses + + /// + /// Telemetry tag indicating configuration retrieval after the refresh interval has expired. + /// public const string Automatic = "Automatic"; + + /// + /// Telemetry tag indicating configuration retrieval per a call to RequestRefresh. + /// public const string Direct = "Direct"; + + /// + /// Telemetry tag indicating configuration retrieval when there is no previously cached configuration. + /// public const string FirstRefresh = "FirstRefresh"; + + /// + /// Telemetry tag indicating configuration retrieval when the last known good configuration is needed. + /// public const string LKG = "LastKnownGood"; // Configuration manager exception types + + /// + /// Telemetry tag indicating that configuration could not be sucessfully validated after retrieval. + /// public const string ConfigurationInvalid = "ConfigurationInvalid"; + + /// + /// Telemetry tag indicating that configuration could not be retrieved successfully. + /// public const string ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed"; } } From f71d13a89f7f4322ec54c44a66f2703a30347cb6 Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:45:44 -0700 Subject: [PATCH 13/15] PR feedback --- build/dependencies.props | 2 +- .../InternalAPI.Unshipped.txt | 2 +- .../JsonWebTokenHandler.ValidateToken.cs | 4 +-- .../Configuration/ConfigurationManager.cs | 33 +++++++------------ .../InternalAPI.Unshipped.txt | 4 +-- .../InternalAPI.Unshipped.txt | 27 +++++++-------- ...Instrumentation.cs => ITelemetryClient.cs} | 2 +- .../Telemetry/IdentityModelTelemetry.cs | 6 ++-- ...yInstrumentation.cs => TelemetryClient.cs} | 11 ++++--- .../Telemetry/TelemetryConstants.cs | 4 +-- .../InternalAPI.Unshipped.txt | 2 +- .../JwtSecurityTokenHandler.cs | 6 ++-- .../JsonWebTokenHandlerTelemetryTests.cs | 6 ++-- .../ConfigurationManagerTelemetryTests.cs | 10 +++--- ...trumentation.cs => MockTelemetryClient.cs} | 2 +- .../JwtSecurityTokenHandlerTelemetryTests.cs | 6 ++-- 16 files changed, 60 insertions(+), 67 deletions(-) rename src/Microsoft.IdentityModel.Tokens/Telemetry/{ITelemetryInstrumentation.cs => ITelemetryClient.cs} (94%) rename src/Microsoft.IdentityModel.Tokens/Telemetry/{TelemetryInstrumentation.cs => TelemetryClient.cs} (82%) rename test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/{MockTelemetryInstrumentation.cs => MockTelemetryClient.cs} (96%) diff --git a/build/dependencies.props b/build/dependencies.props index d6afffb2c6..fe2fbf086a 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -8,7 +8,7 @@ 1.0.0 2.0.3 13.0.3 - 8.0.1 + 6.0.2 4.5.5 4.5.0 8.0.5 diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt index 02f2a0a845..2cfd5e0431 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt @@ -1,4 +1,4 @@ -Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler._telemetryClient -> Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation +Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler._telemetryClient -> Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryClient static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(string payload, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, string compressionAlgorithm, System.Collections.Generic.IDictionary additionalHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs index 86028f361e..c37fb5d876 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs @@ -18,7 +18,7 @@ namespace Microsoft.IdentityModel.JsonWebTokens /// This partial class contains methods and logic related to the validation of tokens. public partial class JsonWebTokenHandler : TokenHandler { - internal ITelemetryInstrumentation _telemetryClient = new TelemetryInstrumentation(); + internal Tokens.Telemetry.ITelemetryClient _telemetryClient = new TelemetryClient(); /// /// Returns a value that indicates if this handler can validate a . @@ -516,7 +516,7 @@ await ValidateJWEAsync(jsonWebToken, validationParameters, currentConfiguration) { _telemetryClient.IncrementConfigurationRefreshRequestCounter( validationParameters.ConfigurationManager.MetadataAddress, - TelemetryConstants.Protocols.LKG); + TelemetryConstants.Protocols.Lkg); validationParameters.ConfigurationManager.RequestRefresh(); validationParameters.RefreshBeforeValidation = true; diff --git a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs index 76743f0ef9..1e5455861d 100644 --- a/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs +++ b/src/Microsoft.IdentityModel.Protocols/Configuration/ConfigurationManager.cs @@ -36,8 +36,8 @@ public class ConfigurationManager : BaseConfigurationManager, IConfigurationM private const int ConfigurationRetrieverRunning = 1; private int _configurationRetrieverState = ConfigurationRetrieverIdle; - internal TimeProvider _timeProvider = TimeProvider.System; - internal ITelemetryInstrumentation _telemetryClient = new TelemetryInstrumentation(); + internal TimeProvider TimeProvider = TimeProvider.System; + internal ITelemetryClient TelemetryClient = new TelemetryClient(); /// /// Instantiates a new that manages automatic and controls refreshing on configuration data. @@ -152,9 +152,7 @@ public async Task GetConfigurationAsync() public virtual async Task GetConfigurationAsync(CancellationToken cancel) { if (_currentConfiguration != null && _syncAfter > DateTimeOffset.UtcNow) - { return _currentConfiguration; - } Exception fetchMetadataFailure = null; @@ -195,16 +193,11 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) LogMessages.IDX20810, result.ErrorMessage)); - _telemetryClient.IncrementConfigurationRefreshRequestCounter( - MetadataAddress, - TelemetryConstants.Protocols.FirstRefresh, - ex); - throw LogHelper.LogExceptionMessage(ex); } } - _telemetryClient.IncrementConfigurationRefreshRequestCounter( + TelemetryClient.IncrementConfigurationRefreshRequestCounter( MetadataAddress, TelemetryConstants.Protocols.FirstRefresh); @@ -213,7 +206,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) catch (Exception ex) { fetchMetadataFailure = ex; - _telemetryClient.IncrementConfigurationRefreshRequestCounter( + TelemetryClient.IncrementConfigurationRefreshRequestCounter( MetadataAddress, TelemetryConstants.Protocols.FirstRefresh, ex); @@ -236,7 +229,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) { if (Interlocked.CompareExchange(ref _configurationRetrieverState, ConfigurationRetrieverRunning, ConfigurationRetrieverIdle) == ConfigurationRetrieverIdle) { - _telemetryClient.IncrementConfigurationRefreshRequestCounter( + TelemetryClient.IncrementConfigurationRefreshRequestCounter( MetadataAddress, TelemetryConstants.Protocols.Automatic); @@ -246,9 +239,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) // If metadata exists return it. if (_currentConfiguration != null) - { return _currentConfiguration; - } throw LogHelper.LogExceptionMessage( new InvalidOperationException( @@ -268,7 +259,7 @@ public virtual async Task GetConfigurationAsync(CancellationToken cancel) private void UpdateCurrentConfiguration() { #pragma warning disable CA1031 // Do not catch general exception types - long startTimestamp = _timeProvider.GetTimestamp(); + long startTimestamp = TimeProvider.GetTimestamp(); try { @@ -277,8 +268,8 @@ private void UpdateCurrentConfiguration() _docRetriever, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); - var elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); - _telemetryClient.LogConfigurationRetrievalDuration( + var elapsedTime = TimeProvider.GetElapsedTime(startTimestamp); + TelemetryClient.LogConfigurationRetrievalDuration( MetadataAddress, elapsedTime); @@ -302,8 +293,8 @@ private void UpdateCurrentConfiguration() } catch (Exception ex) { - var elapsedTime = _timeProvider.GetElapsedTime(startTimestamp); - _telemetryClient.LogConfigurationRetrievalDuration( + var elapsedTime = TimeProvider.GetElapsedTime(startTimestamp); + TelemetryClient.LogConfigurationRetrievalDuration( MetadataAddress, elapsedTime, ex); @@ -352,9 +343,9 @@ public override void RequestRefresh() { DateTimeOffset now = DateTimeOffset.UtcNow; - _telemetryClient.IncrementConfigurationRefreshRequestCounter( + TelemetryClient.IncrementConfigurationRefreshRequestCounter( MetadataAddress, - TelemetryConstants.Protocols.Direct); + TelemetryConstants.Protocols.Manual); if (now >= DateTimeUtil.Add(_lastRequestRefresh.UtcDateTime, RefreshInterval) || _isFirstRefreshRequest) { diff --git a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt index 1c3509c864..5d0bb6b3c4 100644 --- a/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Protocols/InternalAPI.Unshipped.txt @@ -1,2 +1,2 @@ -Microsoft.IdentityModel.Protocols.ConfigurationManager._telemetryClient -> Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation -Microsoft.IdentityModel.Protocols.ConfigurationManager._timeProvider -> System.TimeProvider +Microsoft.IdentityModel.Protocols.ConfigurationManager.TelemetryClient -> Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryClient +Microsoft.IdentityModel.Protocols.ConfigurationManager.TimeProvider -> System.TimeProvider diff --git a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt index 21bfa0d625..c478a749f9 100644 --- a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt @@ -20,10 +20,10 @@ const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.OperationStatu const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.Automatic = "Automatic" -> string const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.ConfigurationInvalid = "ConfigurationInvalid" -> string const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.ConfigurationRetrievalFailed = "ConfigurationRetrievalFailed" -> string -const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.Direct = "Direct" -> string const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.FirstRefresh = "FirstRefresh" -> string -const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.LKG = "LastKnownGood" -> string const Microsoft.IdentityModel.Tokens.LogMessages.IDX10277 = "IDX10277: RequireAudience property on ValidationParameters is set to false. Exiting without validating the audience." -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.Lkg = "LastKnownGood" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.Manual = "Manual" -> string Microsoft.IdentityModel.Tokens.AlgorithmValidationError Microsoft.IdentityModel.Tokens.AlgorithmValidationError.AlgorithmValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidAlgorithm, System.Exception innerException = null) -> void Microsoft.IdentityModel.Tokens.AlgorithmValidationError.InvalidAlgorithm.get -> string @@ -52,24 +52,25 @@ 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.Telemetry.ITelemetryClient +Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryClient.IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus) -> void +Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryClient.IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus, System.Exception exception) -> void +Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryClient.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration) -> void +Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryClient.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration, System.Exception exception) -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.ClientVer -> string +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus) -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus, System.Exception exception) -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration) -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration, System.Exception exception) -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.TelemetryClient() -> 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.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.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 Microsoft.IdentityModel.Tokens.TokenTypeValidationError.TokenTypeValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidTokenType, System.Exception innerException = null) -> void diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryClient.cs similarity index 94% rename from src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs rename to src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryClient.cs index 5905e1c2ed..350a0076ae 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/ITelemetryClient.cs @@ -5,7 +5,7 @@ namespace Microsoft.IdentityModel.Tokens.Telemetry { - internal interface ITelemetryInstrumentation + internal interface ITelemetryClient { internal void LogConfigurationRetrievalDuration( string metadataAddress, diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs index a281810b36..94af3b2a1f 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs @@ -11,13 +11,13 @@ internal class IdentityModelTelemetry /// /// Meter name for MicrosoftIdentityModel. /// - public const string MeterName = "MicrosoftIdentityModel_Meter"; - public const string ServiceName = "MicrosoftIdentityModel"; + private const string MeterName = "MicrosoftIdentityModel_Meter"; + //public const string ServiceName = "MicrosoftIdentityModel"; /// /// The meter responsible for creating instruments. /// - public static readonly Meter IdentityModelMeter = new(MeterName, "1.0.0"); + private static readonly Meter IdentityModelMeter = new(MeterName, "1.0.0"); internal const string TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS"; diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs similarity index 82% rename from src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs rename to src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs index fb2e36f58b..3839c56b89 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryInstrumentation.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs @@ -7,14 +7,15 @@ namespace Microsoft.IdentityModel.Tokens.Telemetry { - internal class TelemetryInstrumentation : ITelemetryInstrumentation + internal class TelemetryClient : ITelemetryClient { + public string ClientVer = IdentityModelTelemetryUtil.ClientVer; public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus) { var tagList = new TagList() { - { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.IdentityModelVersionTag, ClientVer }, { TelemetryConstants.MetadataAddressTag, metadataAddress }, { TelemetryConstants.OperationStatusTag, operationStatus } }; @@ -26,7 +27,7 @@ public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, { var tagList = new TagList() { - { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.IdentityModelVersionTag, ClientVer }, { TelemetryConstants.MetadataAddressTag, metadataAddress }, { TelemetryConstants.OperationStatusTag, operationStatus }, { TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() } @@ -40,7 +41,7 @@ public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan o var tagList = new TagList() { - { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.IdentityModelVersionTag, ClientVer }, { TelemetryConstants.MetadataAddressTag, metadataAddress }, }; @@ -52,7 +53,7 @@ public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan o { var tagList = new TagList() { - { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, + { TelemetryConstants.IdentityModelVersionTag, ClientVer }, { TelemetryConstants.MetadataAddressTag, metadataAddress }, { TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() } }; diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs index 72ea0e91d0..2e49b8774e 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryConstants.cs @@ -39,7 +39,7 @@ public static class Protocols /// /// Telemetry tag indicating configuration retrieval per a call to RequestRefresh. /// - public const string Direct = "Direct"; + public const string Manual = "Manual"; /// /// Telemetry tag indicating configuration retrieval when there is no previously cached configuration. @@ -49,7 +49,7 @@ public static class Protocols /// /// Telemetry tag indicating configuration retrieval when the last known good configuration is needed. /// - public const string LKG = "LastKnownGood"; + public const string Lkg = "LastKnownGood"; // Configuration manager exception types diff --git a/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt b/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt index 64592dad8f..bfbb59b541 100644 --- a/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt +++ b/src/System.IdentityModel.Tokens.Jwt/InternalAPI.Unshipped.txt @@ -1,3 +1,3 @@ System.IdentityModel.Tokens.Jwt.JwtHeader.JwtHeader(Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, System.Collections.Generic.IDictionary outboundAlgorithmMap, string tokenType, System.Collections.Generic.IDictionary additionalHeaderClaims, bool includeKeyIdInHeader) -> void System.IdentityModel.Tokens.Jwt.JwtHeader.JwtHeader(Microsoft.IdentityModel.Tokens.SigningCredentials signingCredentials, System.Collections.Generic.IDictionary outboundAlgorithmMap, string tokenType, System.Collections.Generic.IDictionary additionalInnerHeaderClaims, bool includeKeyIdInHeader) -> void -System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler._telemetryClient -> Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryInstrumentation \ No newline at end of file +System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.TelemetryClient -> Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryClient diff --git a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs index 9bf99b9241..3dc8c80767 100644 --- a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs +++ b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs @@ -37,7 +37,7 @@ public class JwtSecurityTokenHandler : SecurityTokenHandler private static string _shortClaimType = _namespace + "/ShortTypeName"; private bool _mapInboundClaims = DefaultMapInboundClaims; - internal ITelemetryInstrumentation _telemetryClient = new TelemetryInstrumentation(); + internal Microsoft.IdentityModel.Tokens.Telemetry.ITelemetryClient TelemetryClient = new TelemetryClient(); /// /// Default claim type mapping for inbound claims. @@ -890,9 +890,9 @@ private ClaimsPrincipal ValidateToken(string token, JwtSecurityToken outerToken, // where a new valid configuration was somehow published during validation time. if (currentConfiguration != null) { - _telemetryClient.IncrementConfigurationRefreshRequestCounter( + TelemetryClient.IncrementConfigurationRefreshRequestCounter( validationParameters.ConfigurationManager.MetadataAddress, - TelemetryConstants.Protocols.LKG); + TelemetryConstants.Protocols.Lkg); validationParameters.ConfigurationManager.RequestRefresh(); validationParameters.RefreshBeforeValidation = true; diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTelemetryTests.cs index d884664434..556e182a41 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_ExpectedTagsExist() + public async Task ValidateJwsWithConfigAsync_ExpectedTagsExist() { var invalidIssuerConfig = new OpenIdConnectConfiguration() { @@ -38,7 +38,7 @@ public async Task ValidateJWSWithConfigAsync_ExpectedTagsExist() ValidateLifetime = false }; - var testTelemetryClient = new MockTelemetryInstrumentation(); + var testTelemetryClient = new MockTelemetryClient(); try { var handler = new JsonWebTokenHandler() @@ -60,7 +60,7 @@ public async Task ValidateJWSWithConfigAsync_ExpectedTagsExist() // 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 } + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.Lkg } }; Assert.Equal(expectedCounterTagList, testTelemetryClient.ExportedItems); diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs index e660600df6..6d61e16b19 100644 --- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs +++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/ConfigurationManagerTelemetryTests.cs @@ -21,14 +21,14 @@ public class ConfigurationManagerTelemetryTests public async Task RequestRefresh_ExpectedTagsExist() { // arrange - var testTelemetryClient = new MockTelemetryInstrumentation(); + var testTelemetryClient = new MockTelemetryClient(); var configurationManager = new ConfigurationManager( OpenIdConfigData.AccountsGoogle, new OpenIdConnectConfigurationRetriever(), new HttpDocumentRetriever(), new OpenIdConnectConfigurationValidator()) { - _telemetryClient = testTelemetryClient + TelemetryClient = testTelemetryClient }; // act @@ -44,7 +44,7 @@ public async Task RequestRefresh_ExpectedTagsExist() { { TelemetryConstants.MetadataAddressTag, OpenIdConfigData.AccountsGoogle }, { TelemetryConstants.IdentityModelVersionTag, IdentityModelTelemetryUtil.ClientVer }, - { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.Direct }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.Manual }, }; var expectedHistogramTagList = new Dictionary @@ -60,7 +60,7 @@ public async Task RequestRefresh_ExpectedTagsExist() [Theory, MemberData(nameof(GetConfiguration_ExpectedTagList_TheoryData), DisableDiscoveryEnumeration = true)] public async Task GetConfigurationAsync_ExpectedTagsExist(ConfigurationManagerTelemetryTheoryData theoryData) { - var testTelemetryClient = new MockTelemetryInstrumentation(); + var testTelemetryClient = new MockTelemetryClient(); var configurationManager = new ConfigurationManager( theoryData.MetadataAddress, @@ -68,7 +68,7 @@ public async Task GetConfigurationAsync_ExpectedTagsExist(ConfigurationManagerTe theoryData.DocumentRetriever, theoryData.ConfigurationValidator) { - _telemetryClient = testTelemetryClient + TelemetryClient = testTelemetryClient }; try diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryClient.cs similarity index 96% rename from test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs rename to test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryClient.cs index d56a5072c2..c7cd1b71fc 100644 --- a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryInstrumentation.cs +++ b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/MockTelemetryClient.cs @@ -7,7 +7,7 @@ namespace Microsoft.IdentityModel.Tokens.Telemetry.Tests { - public class MockTelemetryInstrumentation : ITelemetryInstrumentation + public class MockTelemetryClient : ITelemetryClient { public Dictionary ExportedItems = new Dictionary(); public Dictionary ExportedHistogramItems = new Dictionary(); diff --git a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs index c144d6a924..f181c00961 100644 --- a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs +++ b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTelemetryTests.cs @@ -36,13 +36,13 @@ public void ValidateToken_ExpectedTagsExist() ValidateLifetime = false }; - var testTelemetryClient = new MockTelemetryInstrumentation(); + var testTelemetryClient = new MockTelemetryClient(); try { AadIssuerValidator.GetAadIssuerValidator(Default.AadV1Authority).ConfigurationManagerV1 = validationParameters.ConfigurationManager; var handler = new JwtSecurityTokenHandler() { - _telemetryClient = testTelemetryClient + TelemetryClient = testTelemetryClient }; handler.ValidateToken(Default.AsymmetricJws, validationParameters, out _); } @@ -56,7 +56,7 @@ public void ValidateToken_ExpectedTagsExist() // 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 }, + { TelemetryConstants.OperationStatusTag, TelemetryConstants.Protocols.Lkg }, }; Assert.Equal(expectedCounterTagList, testTelemetryClient.ExportedItems); From a7f85cfde3182c3fa389ea6debf90e168954f101 Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:04:10 -0700 Subject: [PATCH 14/15] Apply suggestions from code review Co-authored-by: Keegan --- .../Telemetry/IdentityModelTelemetry.cs | 1 - src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs index 94af3b2a1f..b41952ea03 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs @@ -12,7 +12,6 @@ internal class IdentityModelTelemetry /// Meter name for MicrosoftIdentityModel. /// private const string MeterName = "MicrosoftIdentityModel_Meter"; - //public const string ServiceName = "MicrosoftIdentityModel"; /// /// The meter responsible for creating instruments. diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs index 3839c56b89..6a8005fb2e 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs @@ -38,7 +38,6 @@ public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan operationDuration) { - var tagList = new TagList() { { TelemetryConstants.IdentityModelVersionTag, ClientVer }, From 63c019b4a0233e21b45c5a8917f3be4feba2741b Mon Sep 17 00:00:00 2001 From: Westin Musser <127992899+westin-m@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:58:31 -0700 Subject: [PATCH 15/15] change class name and add clarifying comments --- .../InternalAPI.Unshipped.txt | 21 ++++++++----------- .../Telemetry/TelemetryClient.cs | 11 ++++++---- ...lTelemetry.cs => TelemetryDataRecorder.cs} | 5 ++++- 3 files changed, 20 insertions(+), 17 deletions(-) rename src/Microsoft.IdentityModel.Tokens/Telemetry/{IdentityModelTelemetry.cs => TelemetryDataRecorder.cs} (92%) diff --git a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt index ff7360f7e2..d3311f516f 100644 --- a/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt @@ -8,11 +8,6 @@ const Microsoft.IdentityModel.Tokens.LogMessages.IDX10273 = "IDX10273: Algorithm const Microsoft.IdentityModel.Tokens.LogMessages.IDX10274 = "IDX10274: IssuerSigningKeyValidationDelegate threw an exception, see inner exception." -> string const Microsoft.IdentityModel.Tokens.LogMessages.IDX10275 = "IDX10275: TokenTypeValidationDelegate threw an exception, see inner exception." -> string const Microsoft.IdentityModel.Tokens.LogMessages.IDX10276 = "IDX10276: TokenReplayValidationDelegate threw an exception, see inner exception." -> string -const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string -const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManager" -> string -const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.MeterName = "MicrosoftIdentityModel_Meter" -> string -const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.ServiceName = "MicrosoftIdentityModel" -> string -const Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.ExceptionTypeTag = "ExceptionType" -> string const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.IdentityModelVersionTag = "IdentityModelVersion" -> string const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.MetadataAddressTag = "MetadataAddress" -> string @@ -24,6 +19,9 @@ const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.Firs const Microsoft.IdentityModel.Tokens.LogMessages.IDX10277 = "IDX10277: RequireAudience property on ValidationParameters is set to false. Exiting without validating the audience." -> string const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.Lkg = "LastKnownGood" -> string const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols.Manual = "Manual" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryDataRecorder.IdentityModelConfigurationManagerCounterDescription = "Counter capturing configuration manager operations." -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryDataRecorder.IdentityModelConfigurationManagerCounterName = "IdentityModelConfigurationManager" -> string +const Microsoft.IdentityModel.Tokens.Telemetry.TelemetryDataRecorder.TotalDurationHistogramName = "IdentityModelConfigurationRequestTotalDurationInMS" -> string Microsoft.IdentityModel.Tokens.AlgorithmValidationError Microsoft.IdentityModel.Tokens.AlgorithmValidationError.AlgorithmValidationError(Microsoft.IdentityModel.Tokens.MessageDetail messageDetail, Microsoft.IdentityModel.Tokens.ValidationFailureType validationFailureType, System.Type exceptionType, System.Diagnostics.StackFrame stackFrame, string invalidAlgorithm, System.Exception innerException = null) -> void Microsoft.IdentityModel.Tokens.AlgorithmValidationError.InvalidAlgorithm.get -> string @@ -64,11 +62,11 @@ Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.IncrementConfigurationR Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration) -> void Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.LogConfigurationRetrievalDuration(string metadataAddress, System.TimeSpan operationDuration, System.Exception exception) -> void Microsoft.IdentityModel.Tokens.Telemetry.TelemetryClient.TelemetryClient() -> void +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryDataRecorder +Microsoft.IdentityModel.Tokens.Telemetry.TelemetryDataRecorder.TelemetryDataRecorder() -> 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.TelemetryConstants Microsoft.IdentityModel.Tokens.Telemetry.TelemetryConstants.Protocols Microsoft.IdentityModel.Tokens.TokenTypeValidationError @@ -94,21 +92,20 @@ override Microsoft.IdentityModel.Tokens.TokenReplayValidationError.GetException( override Microsoft.IdentityModel.Tokens.TokenTypeValidationError.GetException() -> System.Exception static Microsoft.IdentityModel.Tokens.IssuerSigningKeyValidationError.NullParameter(string parameterName, System.Diagnostics.StackFrame stackFrame) -> Microsoft.IdentityModel.Tokens.IssuerSigningKeyValidationError static Microsoft.IdentityModel.Tokens.SignatureValidationError.NullParameter(string parameterName, System.Diagnostics.StackFrame stackFrame) -> Microsoft.IdentityModel.Tokens.SignatureValidationError +static Microsoft.IdentityModel.Tokens.Telemetry.TelemetryDataRecorder.IncrementConfigurationRefreshRequestCounter(in System.Diagnostics.TagList tagList) -> void +static Microsoft.IdentityModel.Tokens.Telemetry.TelemetryDataRecorder.RecordConfigurationRetrievalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void static Microsoft.IdentityModel.Tokens.TokenReplayValidationError.NullParameter(string parameterName, System.Diagnostics.StackFrame stackFrame) -> Microsoft.IdentityModel.Tokens.TokenReplayValidationError static Microsoft.IdentityModel.Tokens.TokenTypeValidationError.NullParameter(string parameterName, System.Diagnostics.StackFrame stackFrame) -> Microsoft.IdentityModel.Tokens.TokenTypeValidationError -static Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(in System.Diagnostics.TagList tagList) -> void -static Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(long requestDurationInMs, in System.Diagnostics.TagList tagList) -> void static Microsoft.IdentityModel.Tokens.Base64UrlEncoder.Decode(System.ReadOnlySpan strSpan, System.Span output) -> int static Microsoft.IdentityModel.Tokens.Utility.SerializeAsSingleCommaDelimitedString(System.Collections.Generic.IList strings) -> string static Microsoft.IdentityModel.Tokens.ValidationError.GetCurrentStackFrame(string filePath = "", int lineNumber = 0, int skipFrames = 1) -> System.Diagnostics.StackFrame static readonly Microsoft.IdentityModel.Tokens.LoggingEventId.TokenValidationFailed -> Microsoft.Extensions.Logging.EventId static readonly Microsoft.IdentityModel.Tokens.LoggingEventId.TokenValidationSucceeded -> Microsoft.Extensions.Logging.EventId +static readonly Microsoft.IdentityModel.Tokens.Telemetry.TelemetryDataRecorder.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter +static readonly Microsoft.IdentityModel.Tokens.Telemetry.TelemetryDataRecorder.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.AlgorithmValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.AudienceValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.IssuerSigningKeyValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType -static readonly Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.ConfigurationManagerCounter -> System.Diagnostics.Metrics.Counter -static readonly Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.IdentityModelMeter -> System.Diagnostics.Metrics.Meter -static readonly Microsoft.IdentityModel.Tokens.Telemetry.IdentityModelTelemetry.TotalDurationHistogram -> System.Diagnostics.Metrics.Histogram static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.IssuerValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.LifetimeValidatorThrew -> Microsoft.IdentityModel.Tokens.ValidationFailureType static readonly Microsoft.IdentityModel.Tokens.ValidationFailureType.NoTokenAudiencesProvided -> Microsoft.IdentityModel.Tokens.ValidationFailureType diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs index 6a8005fb2e..92026976cc 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs @@ -7,6 +7,9 @@ namespace Microsoft.IdentityModel.Tokens.Telemetry { + /// + /// Prepares s using the provided data and sends them to for recording. + /// internal class TelemetryClient : ITelemetryClient { public string ClientVer = IdentityModelTelemetryUtil.ClientVer; @@ -20,7 +23,7 @@ public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, { TelemetryConstants.OperationStatusTag, operationStatus } }; - IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(tagList); + TelemetryDataRecorder.IncrementConfigurationRefreshRequestCounter(tagList); } public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus, Exception exception) @@ -33,7 +36,7 @@ public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, { TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() } }; - IdentityModelTelemetry.IncrementConfigurationRefreshRequestCounter(tagList); + TelemetryDataRecorder.IncrementConfigurationRefreshRequestCounter(tagList); } public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan operationDuration) @@ -45,7 +48,7 @@ public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan o }; long durationInMilliseconds = (long)operationDuration.TotalMilliseconds; - IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(durationInMilliseconds, tagList); + TelemetryDataRecorder.RecordConfigurationRetrievalDurationHistogram(durationInMilliseconds, tagList); } public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan operationDuration, Exception exception) @@ -58,7 +61,7 @@ public void LogConfigurationRetrievalDuration(string metadataAddress, TimeSpan o }; long durationInMilliseconds = (long)operationDuration.TotalMilliseconds; - IdentityModelTelemetry.RecordConfigurationRetrievalDurationHistogram(durationInMilliseconds, tagList); + TelemetryDataRecorder.RecordConfigurationRetrievalDurationHistogram(durationInMilliseconds, tagList); } } } diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryDataRecorder.cs similarity index 92% rename from src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs rename to src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryDataRecorder.cs index b41952ea03..dbf449baf9 100644 --- a/src/Microsoft.IdentityModel.Tokens/Telemetry/IdentityModelTelemetry.cs +++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryDataRecorder.cs @@ -6,7 +6,10 @@ namespace Microsoft.IdentityModel.Tokens.Telemetry { - internal class IdentityModelTelemetry + /// + /// Pushes telemetry data to the configured or . + /// + internal class TelemetryDataRecorder { /// /// Meter name for MicrosoftIdentityModel.