From e94fddc64b5eb95609128f9fb37d8c61d09f9f7c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 29 Sep 2025 21:16:43 +0000
Subject: [PATCH 1/8] Initial plan
From 01a7ffd41e757bd34221382040eafcff9e9e32e4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 29 Sep 2025 21:39:20 +0000
Subject: [PATCH 2/8] Add telemetry domain extraction feature with AppContext
switch
Co-authored-by: westin-m <127992899+westin-m@users.noreply.github.com>
---
.../AppContextSwitches.cs | 11 ++
.../Telemetry/TelemetryClient.cs | 42 ++++-
.../TelemetryClientDomainExtractionTests.cs | 171 ++++++++++++++++++
3 files changed, 219 insertions(+), 5 deletions(-)
create mode 100644 test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
diff --git a/src/Microsoft.IdentityModel.Tokens/AppContextSwitches.cs b/src/Microsoft.IdentityModel.Tokens/AppContextSwitches.cs
index 7f32a2fb85..97dc7fcceb 100644
--- a/src/Microsoft.IdentityModel.Tokens/AppContextSwitches.cs
+++ b/src/Microsoft.IdentityModel.Tokens/AppContextSwitches.cs
@@ -98,6 +98,14 @@ internal static class AppContextSwitches
private static bool? _useCapitalizedXMLTypeAttr;
internal static bool UseCapitalizedXMLTypeAttr => _useCapitalizedXMLTypeAttr ??= (AppContext.TryGetSwitch(UseCapitalizedXMLTypeAttrSwitch, out bool useCapitalizedXMLTypeAttr) && useCapitalizedXMLTypeAttr);
+ ///
+ /// When enabled, telemetry will use the full metadata address instead of just the domain name for IdentityModelConfiguration metrics.
+ /// By default (when disabled), only the domain name is used for successful operations to reduce OpenTelemetry cardinality.
+ ///
+ internal const string UseFullMetadataAddressForTelemetrySwitch = "Switch.Microsoft.IdentityModel.UseFullMetadataAddressForTelemetry";
+ private static bool? _useFullMetadataAddressForTelemetry;
+ internal static bool UseFullMetadataAddressForTelemetry => _useFullMetadataAddressForTelemetry ??= (AppContext.TryGetSwitch(UseFullMetadataAddressForTelemetrySwitch, out bool useFullMetadataAddressForTelemetry) && useFullMetadataAddressForTelemetry);
+
///
/// Used for testing to reset all switches to its default value.
///
@@ -123,6 +131,9 @@ internal static void ResetAllSwitches()
_useCapitalizedXMLTypeAttr = null;
AppContext.SetSwitch(UseCapitalizedXMLTypeAttrSwitch, false);
+
+ _useFullMetadataAddressForTelemetry = null;
+ AppContext.SetSwitch(UseFullMetadataAddressForTelemetrySwitch, false);
}
}
}
diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
index 2a56774454..2af7f87e72 100644
--- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
+++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
@@ -22,12 +22,44 @@ internal class TelemetryClient : ITelemetryClient
AppContextSwitches.UpdateConfigAsBlocking.ToString()
);
+ ///
+ /// Extracts the domain name from a metadata address for telemetry purposes.
+ /// Returns the full address if domain extraction fails or if the UseFullMetadataAddressForTelemetry switch is enabled.
+ /// In error cases, always returns the full address for better debugging.
+ ///
+ /// The full metadata address
+ /// True if this is a successful operation, false for error cases
+ /// Domain name for success cases (when switch is disabled), full address otherwise
+ private static string GetMetadataAddressForTelemetry(string metadataAddress, bool isSuccessCase = true)
+ {
+ // Always use full address for error cases or when the switch is enabled
+ if (!isSuccessCase || AppContextSwitches.UseFullMetadataAddressForTelemetry || string.IsNullOrEmpty(metadataAddress))
+ return metadataAddress;
+
+ try
+ {
+ var uri = new Uri(metadataAddress, UriKind.Absolute);
+
+ // Extract domain, removing 'www.' prefix if present
+ string host = uri.Host;
+ if (host.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
+ host = host.Substring(4);
+
+ return host;
+ }
+ catch (UriFormatException)
+ {
+ // If parsing fails, return the original address
+ return metadataAddress;
+ }
+ }
+
public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus, string configurationSource)
{
var tagList = new TagList()
{
{ TelemetryConstants.IdentityModelVersionTag, ClientVer },
- { TelemetryConstants.MetadataAddressTag, metadataAddress },
+ { TelemetryConstants.MetadataAddressTag, GetMetadataAddressForTelemetry(metadataAddress, isSuccessCase: true) },
{ TelemetryConstants.OperationStatusTag, operationStatus },
{ TelemetryConstants.ConfigurationSourceTag, configurationSource },
_blockingTagValue
@@ -41,7 +73,7 @@ public void IncrementConfigurationRefreshRequestCounter(string metadataAddress,
var tagList = new TagList()
{
{ TelemetryConstants.IdentityModelVersionTag, ClientVer },
- { TelemetryConstants.MetadataAddressTag, metadataAddress },
+ { TelemetryConstants.MetadataAddressTag, GetMetadataAddressForTelemetry(metadataAddress, isSuccessCase: false) },
{ TelemetryConstants.OperationStatusTag, operationStatus },
{ TelemetryConstants.ConfigurationSourceTag, configurationSource },
{ TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() },
@@ -56,7 +88,7 @@ public void LogConfigurationRetrievalDuration(string metadataAddress, string con
var tagList = new TagList()
{
{ TelemetryConstants.IdentityModelVersionTag, ClientVer },
- { TelemetryConstants.MetadataAddressTag, metadataAddress },
+ { TelemetryConstants.MetadataAddressTag, GetMetadataAddressForTelemetry(metadataAddress, isSuccessCase: true) },
{ TelemetryConstants.ConfigurationSourceTag, configurationSource },
};
@@ -69,7 +101,7 @@ public void LogConfigurationRetrievalDuration(string metadataAddress, string con
var tagList = new TagList()
{
{ TelemetryConstants.IdentityModelVersionTag, ClientVer },
- { TelemetryConstants.MetadataAddressTag, metadataAddress },
+ { TelemetryConstants.MetadataAddressTag, GetMetadataAddressForTelemetry(metadataAddress, isSuccessCase: false) },
{ TelemetryConstants.ConfigurationSourceTag, configurationSource },
{ TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() },
_blockingTagValue
@@ -87,7 +119,7 @@ public void LogBackgroundConfigurationRefreshFailure(
var tagList = new TagList()
{
{ TelemetryConstants.IdentityModelVersionTag, ClientVer },
- { TelemetryConstants.MetadataAddressTag, metadataAddress },
+ { TelemetryConstants.MetadataAddressTag, GetMetadataAddressForTelemetry(metadataAddress, isSuccessCase: false) },
{ TelemetryConstants.ConfigurationSourceTag, configurationSource },
{ TelemetryConstants.ExceptionTypeTag, exception.GetType().ToString() },
_blockingTagValue
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
new file mode 100644
index 0000000000..16a3138add
--- /dev/null
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
@@ -0,0 +1,171 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Diagnostics;
+using Microsoft.IdentityModel.TestUtils;
+using Microsoft.IdentityModel.Tokens;
+using Xunit;
+
+namespace Microsoft.IdentityModel.Telemetry.Tests
+{
+ public class TelemetryClientDomainExtractionTests
+ {
+ [Fact]
+ public void DebugMethodCall()
+ {
+ // Debug what's happening with reflection
+ var telemetryClientType = typeof(TelemetryClient);
+ var methods = telemetryClientType.GetMethods(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
+
+ var foundMethods = new List();
+ foreach (var m in methods)
+ {
+ foundMethods.Add($"{m.Name}({string.Join(", ", m.GetParameters().Select(p => p.ParameterType.Name))})");
+ }
+
+ // This should help us see what methods are available
+ Assert.True(foundMethods.Count > 0, $"Available methods: {string.Join(", ", foundMethods)}");
+
+ var method = telemetryClientType.GetMethod("GetMetadataAddressForTelemetry",
+ System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
+
+ Assert.NotNull(method); // This should pass if the method exists
+
+ // Test the method directly
+ var testUrl = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
+ var result = (string)method.Invoke(null, new object[] { testUrl, true });
+
+ // For now, let's just ensure it doesn't throw and see what we get
+ Assert.NotNull(result);
+ }
+
+ [Theory]
+ [InlineData("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration")]
+ [InlineData("https://accounts.google.com/.well-known/openid-configuration")]
+ [InlineData("https://login.windows.net/common/.well-known/openid-configuration")]
+ public void GetMetadataAddressForTelemetry_ErrorCase_ReturnsFullAddress(string fullAddress)
+ {
+ // Arrange
+ var telemetryClient = new TelemetryClient();
+
+ // Act - using reflection to call the private method with isSuccessCase = false
+ var method = typeof(TelemetryClient).GetMethod("GetMetadataAddressForTelemetry",
+ System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
+ var result = (string)method.Invoke(null, new object[] { fullAddress, false });
+
+ // Assert
+ Assert.Equal(fullAddress, result);
+ }
+
+ [Theory]
+ [InlineData("invalid-url")]
+ [InlineData("")]
+ [InlineData(null)]
+ public void GetMetadataAddressForTelemetry_InvalidUrl_ReturnsOriginalString(string invalidUrl)
+ {
+ // Arrange
+ var telemetryClient = new TelemetryClient();
+
+ // Act - using reflection to call the private method
+ var method = typeof(TelemetryClient).GetMethod("GetMetadataAddressForTelemetry",
+ System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
+ var result = (string)method.Invoke(null, new object[] { invalidUrl, true });
+
+ // Assert
+ Assert.Equal(invalidUrl, result);
+ }
+
+ [Fact]
+ public void GetMetadataAddressForTelemetry_WithAppContextSwitch_ReturnsFullAddress()
+ {
+ // Arrange
+ var fullAddress = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
+ var telemetryClient = new TelemetryClient();
+
+ try
+ {
+ // Enable the switch to use full metadata address
+ AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
+
+ // Act - using reflection to call the private method
+ var method = typeof(TelemetryClient).GetMethod("GetMetadataAddressForTelemetry",
+ System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
+ var result = (string)method.Invoke(null, new object[] { fullAddress, true });
+
+ // Assert
+ Assert.Equal(fullAddress, result);
+ }
+ finally
+ {
+ // Cleanup
+ AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, false);
+ }
+ }
+
+ [Fact]
+ public void TelemetryClient_Methods_DoNotThrow()
+ {
+ // This test ensures that the modified telemetry methods don't break existing functionality
+ // We cannot easily verify the exact values sent to the telemetry system without complex setup,
+ // but we can ensure the methods don't throw exceptions when called with valid parameters.
+
+ // Arrange
+ var telemetryClient = new TelemetryClient();
+ var testAddress = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
+ var testDuration = TimeSpan.FromMilliseconds(100);
+ var testException = new InvalidOperationException("Test exception");
+
+ // Act & Assert - these should not throw
+ var ex1 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration));
+ var ex2 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration, testException));
+ var ex3 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "FirstRefresh", "Retriever"));
+ var ex4 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "ConfigurationRetrievalFailed", "Retriever", testException));
+ var ex5 = Record.Exception(() => telemetryClient.LogBackgroundConfigurationRefreshFailure(testAddress, "Retriever", testException));
+
+ Assert.Null(ex1);
+ Assert.Null(ex2);
+ Assert.Null(ex3);
+ Assert.Null(ex4);
+ Assert.Null(ex5);
+ }
+
+ [Fact]
+ public void TelemetryClient_WithAppContextSwitch_DoesNotThrow()
+ {
+ // Test that telemetry methods work correctly when the backward compatibility switch is enabled
+
+ try
+ {
+ // Enable the switch to use full metadata address
+ AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
+
+ // Arrange
+ var telemetryClient = new TelemetryClient();
+ var testAddress = "https://accounts.google.com/.well-known/openid-configuration";
+ var testDuration = TimeSpan.FromMilliseconds(150);
+ var testException = new InvalidOperationException("Test exception");
+
+ // Act & Assert - these should not throw even with the switch enabled
+ var ex1 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration));
+ var ex2 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration, testException));
+ var ex3 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "FirstRefresh", "Retriever"));
+ var ex4 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "ConfigurationRetrievalFailed", "Retriever", testException));
+ var ex5 = Record.Exception(() => telemetryClient.LogBackgroundConfigurationRefreshFailure(testAddress, "Retriever", testException));
+
+ Assert.Null(ex1);
+ Assert.Null(ex2);
+ Assert.Null(ex3);
+ Assert.Null(ex4);
+ Assert.Null(ex5);
+ }
+ finally
+ {
+ // Cleanup
+ AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, false);
+ }
+ }
+ }
+}
\ No newline at end of file
From 8d873974c83d237ec7b8392b572484b808fe9d9e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 29 Sep 2025 21:48:32 +0000
Subject: [PATCH 3/8] Complete telemetry domain extraction feature
implementation with tests
Co-authored-by: westin-m <127992899+westin-m@users.noreply.github.com>
---
.../TelemetryClientDomainExtractionTests.cs | 50 ++++++++++++-------
1 file changed, 31 insertions(+), 19 deletions(-)
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
index 16a3138add..a740063e39 100644
--- a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
@@ -13,33 +13,42 @@ namespace Microsoft.IdentityModel.Telemetry.Tests
{
public class TelemetryClientDomainExtractionTests
{
+ [Theory]
+ [InlineData("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "login.microsoftonline.com")]
+ [InlineData("https://www.login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "login.microsoftonline.com")]
+ [InlineData("https://accounts.google.com/.well-known/openid-configuration", "accounts.google.com")]
+ [InlineData("https://login.windows.net/common/.well-known/openid-configuration", "login.windows.net")]
+ [InlineData("http://localhost:8080/.well-known/openid-configuration", "localhost")]
+ [InlineData("https://example.com/path/to/config", "example.com")]
+ [InlineData("https://subdomain.example.org/config.json", "subdomain.example.org")]
+ public void GetMetadataAddressForTelemetry_SuccessCase_ReturnsExpectedDomain(string fullAddress, string expectedDomain)
+ {
+ // Act - using reflection to call the private method
+ var method = typeof(TelemetryClient).GetMethod("GetMetadataAddressForTelemetry",
+ System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
+ var result = (string)method.Invoke(null, new object[] { fullAddress, true });
+
+ // Assert
+ Assert.Equal(expectedDomain, result);
+ }
+
[Fact]
- public void DebugMethodCall()
+ public void DebugAppContextSwitch()
{
- // Debug what's happening with reflection
- var telemetryClientType = typeof(TelemetryClient);
- var methods = telemetryClientType.GetMethods(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
-
- var foundMethods = new List();
- foreach (var m in methods)
- {
- foundMethods.Add($"{m.Name}({string.Join(", ", m.GetParameters().Select(p => p.ParameterType.Name))})");
- }
-
- // This should help us see what methods are available
- Assert.True(foundMethods.Count > 0, $"Available methods: {string.Join(", ", foundMethods)}");
+ // Check if the AppContext switch is causing issues
+ var switchValue = AppContextSwitches.UseFullMetadataAddressForTelemetry;
+ // Test a simple call
+ var telemetryClientType = typeof(TelemetryClient);
var method = telemetryClientType.GetMethod("GetMetadataAddressForTelemetry",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
- Assert.NotNull(method); // This should pass if the method exists
-
- // Test the method directly
var testUrl = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
var result = (string)method.Invoke(null, new object[] { testUrl, true });
- // For now, let's just ensure it doesn't throw and see what we get
- Assert.NotNull(result);
+ // The switch should be false by default, so we should get the host name
+ Assert.False(switchValue, $"Switch value: {switchValue}");
+ Assert.Equal("login.microsoftonline.com", result);
}
[Theory]
@@ -87,6 +96,9 @@ public void GetMetadataAddressForTelemetry_WithAppContextSwitch_ReturnsFullAddre
try
{
+ // Reset switches first to clear any cached values
+ AppContextSwitches.ResetAllSwitches();
+
// Enable the switch to use full metadata address
AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
@@ -101,7 +113,7 @@ public void GetMetadataAddressForTelemetry_WithAppContextSwitch_ReturnsFullAddre
finally
{
// Cleanup
- AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, false);
+ AppContextSwitches.ResetAllSwitches();
}
}
From 4827171925327d9bf3e2a9ad5ca959665ad1e426 Mon Sep 17 00:00:00 2001
From: Westin Musser <127992899+westin-m@users.noreply.github.com>
Date: Tue, 30 Sep 2025 10:27:40 -0700
Subject: [PATCH 4/8] internal method, no reflection in tests
---
.../Telemetry/TelemetryClient.cs | 2 +-
.../TelemetryClientDomainExtractionTests.cs | 69 ++++++-------------
2 files changed, 23 insertions(+), 48 deletions(-)
diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
index 2af7f87e72..fd6d17bc5d 100644
--- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
+++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
@@ -30,7 +30,7 @@ internal class TelemetryClient : ITelemetryClient
/// The full metadata address
/// True if this is a successful operation, false for error cases
/// Domain name for success cases (when switch is disabled), full address otherwise
- private static string GetMetadataAddressForTelemetry(string metadataAddress, bool isSuccessCase = true)
+ internal static string GetMetadataAddressForTelemetry(string metadataAddress, bool isSuccessCase = true)
{
// Always use full address for error cases or when the switch is enabled
if (!isSuccessCase || AppContextSwitches.UseFullMetadataAddressForTelemetry || string.IsNullOrEmpty(metadataAddress))
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
index a740063e39..f6098dbb5e 100644
--- a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
@@ -2,10 +2,6 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Diagnostics;
-using Microsoft.IdentityModel.TestUtils;
using Microsoft.IdentityModel.Tokens;
using Xunit;
@@ -17,16 +13,14 @@ public class TelemetryClientDomainExtractionTests
[InlineData("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "login.microsoftonline.com")]
[InlineData("https://www.login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "login.microsoftonline.com")]
[InlineData("https://accounts.google.com/.well-known/openid-configuration", "accounts.google.com")]
- [InlineData("https://login.windows.net/common/.well-known/openid-configuration", "login.windows.net")]
+ [InlineData("https://login.windows.net/common/.well-known/openid-configuration", "login.windows.net")]
[InlineData("http://localhost:8080/.well-known/openid-configuration", "localhost")]
[InlineData("https://example.com/path/to/config", "example.com")]
[InlineData("https://subdomain.example.org/config.json", "subdomain.example.org")]
public void GetMetadataAddressForTelemetry_SuccessCase_ReturnsExpectedDomain(string fullAddress, string expectedDomain)
{
- // Act - using reflection to call the private method
- var method = typeof(TelemetryClient).GetMethod("GetMetadataAddressForTelemetry",
- System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
- var result = (string)method.Invoke(null, new object[] { fullAddress, true });
+ // Act
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(fullAddress, true);
// Assert
Assert.Equal(expectedDomain, result);
@@ -37,15 +31,10 @@ public void DebugAppContextSwitch()
{
// Check if the AppContext switch is causing issues
var switchValue = AppContextSwitches.UseFullMetadataAddressForTelemetry;
-
- // Test a simple call
- var telemetryClientType = typeof(TelemetryClient);
- var method = telemetryClientType.GetMethod("GetMetadataAddressForTelemetry",
- System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
-
+
var testUrl = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
- var result = (string)method.Invoke(null, new object[] { testUrl, true });
-
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(testUrl);
+
// The switch should be false by default, so we should get the host name
Assert.False(switchValue, $"Switch value: {switchValue}");
Assert.Equal("login.microsoftonline.com", result);
@@ -57,13 +46,8 @@ public void DebugAppContextSwitch()
[InlineData("https://login.windows.net/common/.well-known/openid-configuration")]
public void GetMetadataAddressForTelemetry_ErrorCase_ReturnsFullAddress(string fullAddress)
{
- // Arrange
- var telemetryClient = new TelemetryClient();
-
- // Act - using reflection to call the private method with isSuccessCase = false
- var method = typeof(TelemetryClient).GetMethod("GetMetadataAddressForTelemetry",
- System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
- var result = (string)method.Invoke(null, new object[] { fullAddress, false });
+ // Act
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(fullAddress, false);
// Assert
Assert.Equal(fullAddress, result);
@@ -75,13 +59,8 @@ public void GetMetadataAddressForTelemetry_ErrorCase_ReturnsFullAddress(string f
[InlineData(null)]
public void GetMetadataAddressForTelemetry_InvalidUrl_ReturnsOriginalString(string invalidUrl)
{
- // Arrange
- var telemetryClient = new TelemetryClient();
-
- // Act - using reflection to call the private method
- var method = typeof(TelemetryClient).GetMethod("GetMetadataAddressForTelemetry",
- System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
- var result = (string)method.Invoke(null, new object[] { invalidUrl, true });
+ // Act
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(invalidUrl, true);
// Assert
Assert.Equal(invalidUrl, result);
@@ -92,20 +71,17 @@ public void GetMetadataAddressForTelemetry_WithAppContextSwitch_ReturnsFullAddre
{
// Arrange
var fullAddress = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
- var telemetryClient = new TelemetryClient();
-
+
try
{
// Reset switches first to clear any cached values
AppContextSwitches.ResetAllSwitches();
-
+
// Enable the switch to use full metadata address
AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
-
- // Act - using reflection to call the private method
- var method = typeof(TelemetryClient).GetMethod("GetMetadataAddressForTelemetry",
- System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
- var result = (string)method.Invoke(null, new object[] { fullAddress, true });
+
+ // Act
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(fullAddress, true);
// Assert
Assert.Equal(fullAddress, result);
@@ -123,20 +99,20 @@ public void TelemetryClient_Methods_DoNotThrow()
// This test ensures that the modified telemetry methods don't break existing functionality
// We cannot easily verify the exact values sent to the telemetry system without complex setup,
// but we can ensure the methods don't throw exceptions when called with valid parameters.
-
+
// Arrange
var telemetryClient = new TelemetryClient();
var testAddress = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
var testDuration = TimeSpan.FromMilliseconds(100);
var testException = new InvalidOperationException("Test exception");
-
+
// Act & Assert - these should not throw
var ex1 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration));
var ex2 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration, testException));
var ex3 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "FirstRefresh", "Retriever"));
var ex4 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "ConfigurationRetrievalFailed", "Retriever", testException));
var ex5 = Record.Exception(() => telemetryClient.LogBackgroundConfigurationRefreshFailure(testAddress, "Retriever", testException));
-
+
Assert.Null(ex1);
Assert.Null(ex2);
Assert.Null(ex3);
@@ -148,25 +124,24 @@ public void TelemetryClient_Methods_DoNotThrow()
public void TelemetryClient_WithAppContextSwitch_DoesNotThrow()
{
// Test that telemetry methods work correctly when the backward compatibility switch is enabled
-
try
{
// Enable the switch to use full metadata address
AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
-
+
// Arrange
var telemetryClient = new TelemetryClient();
var testAddress = "https://accounts.google.com/.well-known/openid-configuration";
var testDuration = TimeSpan.FromMilliseconds(150);
var testException = new InvalidOperationException("Test exception");
-
+
// Act & Assert - these should not throw even with the switch enabled
var ex1 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration));
var ex2 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration, testException));
var ex3 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "FirstRefresh", "Retriever"));
var ex4 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "ConfigurationRetrievalFailed", "Retriever", testException));
var ex5 = Record.Exception(() => telemetryClient.LogBackgroundConfigurationRefreshFailure(testAddress, "Retriever", testException));
-
+
Assert.Null(ex1);
Assert.Null(ex2);
Assert.Null(ex3);
@@ -180,4 +155,4 @@ public void TelemetryClient_WithAppContextSwitch_DoesNotThrow()
}
}
}
-}
\ No newline at end of file
+}
From e36a9b9953b5104f04bb96d83080632d689af502 Mon Sep 17 00:00:00 2001
From: Westin Musser <127992899+westin-m@users.noreply.github.com>
Date: Tue, 30 Sep 2025 11:12:05 -0700
Subject: [PATCH 5/8] remove unnecessary operation
---
.../Telemetry/TelemetryClient.cs | 8 +-------
.../Telemetry/TelemetryClientDomainExtractionTests.cs | 2 +-
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
index fd6d17bc5d..3c3019e725 100644
--- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
+++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
@@ -39,13 +39,7 @@ internal static string GetMetadataAddressForTelemetry(string metadataAddress, bo
try
{
var uri = new Uri(metadataAddress, UriKind.Absolute);
-
- // Extract domain, removing 'www.' prefix if present
- string host = uri.Host;
- if (host.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
- host = host.Substring(4);
-
- return host;
+ return uri.Host;
}
catch (UriFormatException)
{
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
index f6098dbb5e..2c6c63811f 100644
--- a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
@@ -11,7 +11,7 @@ public class TelemetryClientDomainExtractionTests
{
[Theory]
[InlineData("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "login.microsoftonline.com")]
- [InlineData("https://www.login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "login.microsoftonline.com")]
+ [InlineData("https://www.login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "www.login.microsoftonline.com")]
[InlineData("https://accounts.google.com/.well-known/openid-configuration", "accounts.google.com")]
[InlineData("https://login.windows.net/common/.well-known/openid-configuration", "login.windows.net")]
[InlineData("http://localhost:8080/.well-known/openid-configuration", "localhost")]
From eee75f3e26972b710f29ffec793c7c354dbfb45b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 30 Sep 2025 22:56:08 +0000
Subject: [PATCH 6/8] Fix AppContext switch test interference with
ResetAppContextSwitches attribute
Co-authored-by: westin-m <127992899+westin-m@users.noreply.github.com>
---
.../Telemetry/TelemetryClientDomainExtractionTests.cs | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
index 2c6c63811f..0b8468660f 100644
--- a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
@@ -2,11 +2,13 @@
// Licensed under the MIT License.
using System;
+using Microsoft.IdentityModel.TestUtils;
using Microsoft.IdentityModel.Tokens;
using Xunit;
namespace Microsoft.IdentityModel.Telemetry.Tests
{
+ [ResetAppContextSwitches]
public class TelemetryClientDomainExtractionTests
{
[Theory]
@@ -74,9 +76,6 @@ public void GetMetadataAddressForTelemetry_WithAppContextSwitch_ReturnsFullAddre
try
{
- // Reset switches first to clear any cached values
- AppContextSwitches.ResetAllSwitches();
-
// Enable the switch to use full metadata address
AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
@@ -88,8 +87,8 @@ public void GetMetadataAddressForTelemetry_WithAppContextSwitch_ReturnsFullAddre
}
finally
{
- // Cleanup
- AppContextSwitches.ResetAllSwitches();
+ // Cleanup is handled by ResetAppContextSwitches attribute
+ AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, false);
}
}
From 27828deabee1765a4dc1aa456345abd26f3cf806 Mon Sep 17 00:00:00 2001
From: Westin Musser <127992899+westin-m@users.noreply.github.com>
Date: Tue, 7 Oct 2025 13:09:23 -0700
Subject: [PATCH 7/8] avoid tast failures causes by app context switch
interference
---
.../ClaimsIdentityFactoryTests.cs | 10 +-
.../TelemetryClientDomainExtractionTests.cs | 220 +++++++++---------
2 files changed, 113 insertions(+), 117 deletions(-)
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/ClaimsIdentityFactoryTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/ClaimsIdentityFactoryTests.cs
index f1878a638b..1a1cf0da39 100644
--- a/test/Microsoft.IdentityModel.Tokens.Tests/ClaimsIdentityFactoryTests.cs
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/ClaimsIdentityFactoryTests.cs
@@ -9,14 +9,10 @@
namespace Microsoft.IdentityModel.Tokens.Tests
{
- [Collection(nameof(ClaimsIdentityFactoryTests))]
+ [ResetAppContextSwitches]
+ [Collection("AppContextSwitches")]
public class ClaimsIdentityFactoryTests
{
- public ClaimsIdentityFactoryTests()
- {
- AppContextSwitches.ResetAllSwitches();
- }
-
[Theory]
[InlineData(true)]
[InlineData(false)]
@@ -47,7 +43,7 @@ public void Create_FromTokenValidationParameters_ReturnsCorrectClaimsIdentity(bo
Assert.Equal(jsonWebToken, ((CaseSensitiveClaimsIdentity)actualClaimsIdentity).SecurityToken);
}
- AppContextSwitches.ResetAllSwitches();
+ AppContext.SetSwitch(AppContextSwitches.UseClaimsIdentityTypeSwitch, false);
}
[Theory]
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
index 0b8468660f..4cba8625b5 100644
--- a/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/Telemetry/TelemetryClientDomainExtractionTests.cs
@@ -6,106 +6,136 @@
using Microsoft.IdentityModel.Tokens;
using Xunit;
-namespace Microsoft.IdentityModel.Telemetry.Tests
+namespace Microsoft.IdentityModel.Telemetry.Tests;
+
+[ResetAppContextSwitches]
+[Collection("AppContextSwitches")]
+public class TelemetryClientDomainExtractionTests
{
- [ResetAppContextSwitches]
- public class TelemetryClientDomainExtractionTests
+ [Theory]
+ [InlineData("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "login.microsoftonline.com")]
+ [InlineData("https://www.login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "www.login.microsoftonline.com")]
+ [InlineData("https://accounts.google.com/.well-known/openid-configuration", "accounts.google.com")]
+ [InlineData("https://login.windows.net/common/.well-known/openid-configuration", "login.windows.net")]
+ [InlineData("http://localhost:8080/.well-known/openid-configuration", "localhost")]
+ [InlineData("https://example.com/path/to/config", "example.com")]
+ [InlineData("https://subdomain.example.org/config.json", "subdomain.example.org")]
+ public void GetMetadataAddressForTelemetry_SuccessCase_ReturnsExpectedDomain(string fullAddress, string expectedDomain)
{
- [Theory]
- [InlineData("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "login.microsoftonline.com")]
- [InlineData("https://www.login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "www.login.microsoftonline.com")]
- [InlineData("https://accounts.google.com/.well-known/openid-configuration", "accounts.google.com")]
- [InlineData("https://login.windows.net/common/.well-known/openid-configuration", "login.windows.net")]
- [InlineData("http://localhost:8080/.well-known/openid-configuration", "localhost")]
- [InlineData("https://example.com/path/to/config", "example.com")]
- [InlineData("https://subdomain.example.org/config.json", "subdomain.example.org")]
- public void GetMetadataAddressForTelemetry_SuccessCase_ReturnsExpectedDomain(string fullAddress, string expectedDomain)
- {
- // Act
- var result = TelemetryClient.GetMetadataAddressForTelemetry(fullAddress, true);
+ // Act
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(fullAddress, true);
- // Assert
- Assert.Equal(expectedDomain, result);
- }
+ // Assert
+ Assert.Equal(expectedDomain, result);
+ }
- [Fact]
- public void DebugAppContextSwitch()
- {
- // Check if the AppContext switch is causing issues
- var switchValue = AppContextSwitches.UseFullMetadataAddressForTelemetry;
+ [Fact]
+ public void DebugAppContextSwitch()
+ {
+ // Check if the AppContext switch is causing issues
+ var switchValue = AppContextSwitches.UseFullMetadataAddressForTelemetry;
- var testUrl = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
- var result = TelemetryClient.GetMetadataAddressForTelemetry(testUrl);
+ var testUrl = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(testUrl);
- // The switch should be false by default, so we should get the host name
- Assert.False(switchValue, $"Switch value: {switchValue}");
- Assert.Equal("login.microsoftonline.com", result);
- }
+ // The switch should be false by default, so we should get the host name
+ Assert.False(switchValue, $"Switch value: {switchValue}");
+ Assert.Equal("login.microsoftonline.com", result);
+ }
- [Theory]
- [InlineData("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration")]
- [InlineData("https://accounts.google.com/.well-known/openid-configuration")]
- [InlineData("https://login.windows.net/common/.well-known/openid-configuration")]
- public void GetMetadataAddressForTelemetry_ErrorCase_ReturnsFullAddress(string fullAddress)
- {
- // Act
- var result = TelemetryClient.GetMetadataAddressForTelemetry(fullAddress, false);
+ [Theory]
+ [InlineData("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration")]
+ [InlineData("https://accounts.google.com/.well-known/openid-configuration")]
+ [InlineData("https://login.windows.net/common/.well-known/openid-configuration")]
+ public void GetMetadataAddressForTelemetry_ErrorCase_ReturnsFullAddress(string fullAddress)
+ {
+ // Act
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(fullAddress, false);
- // Assert
- Assert.Equal(fullAddress, result);
- }
+ // Assert
+ Assert.Equal(fullAddress, result);
+ }
- [Theory]
- [InlineData("invalid-url")]
- [InlineData("")]
- [InlineData(null)]
- public void GetMetadataAddressForTelemetry_InvalidUrl_ReturnsOriginalString(string invalidUrl)
+ [Theory]
+ [InlineData("invalid-url")]
+ [InlineData("")]
+ [InlineData(null)]
+ public void GetMetadataAddressForTelemetry_InvalidUrl_ReturnsOriginalString(string invalidUrl)
+ {
+ // Act
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(invalidUrl, true);
+
+ // Assert
+ Assert.Equal(invalidUrl, result);
+ }
+
+ [Fact]
+ public void GetMetadataAddressForTelemetry_WithAppContextSwitch_ReturnsFullAddress()
+ {
+ // Arrange
+ var fullAddress = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
+
+ try
{
+ // Enable the switch to use full metadata address
+ AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
+
// Act
- var result = TelemetryClient.GetMetadataAddressForTelemetry(invalidUrl, true);
+ var result = TelemetryClient.GetMetadataAddressForTelemetry(fullAddress, true);
// Assert
- Assert.Equal(invalidUrl, result);
+ Assert.Equal(fullAddress, result);
}
-
- [Fact]
- public void GetMetadataAddressForTelemetry_WithAppContextSwitch_ReturnsFullAddress()
+ finally
{
- // Arrange
- var fullAddress = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
-
- try
- {
- // Enable the switch to use full metadata address
- AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
-
- // Act
- var result = TelemetryClient.GetMetadataAddressForTelemetry(fullAddress, true);
-
- // Assert
- Assert.Equal(fullAddress, result);
- }
- finally
- {
- // Cleanup is handled by ResetAppContextSwitches attribute
- AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, false);
- }
+ // Cleanup is handled by ResetAppContextSwitches attribute
+ AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, false);
}
+ }
+
+ [Fact]
+ public void TelemetryClient_Methods_DoNotThrow()
+ {
+ // This test ensures that the modified telemetry methods don't break existing functionality
+ // We cannot easily verify the exact values sent to the telemetry system without complex setup,
+ // but we can ensure the methods don't throw exceptions when called with valid parameters.
+
+ // Arrange
+ var telemetryClient = new TelemetryClient();
+ var testAddress = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
+ var testDuration = TimeSpan.FromMilliseconds(100);
+ var testException = new InvalidOperationException("Test exception");
+
+ // Act & Assert - these should not throw
+ var ex1 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration));
+ var ex2 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration, testException));
+ var ex3 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "FirstRefresh", "Retriever"));
+ var ex4 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "ConfigurationRetrievalFailed", "Retriever", testException));
+ var ex5 = Record.Exception(() => telemetryClient.LogBackgroundConfigurationRefreshFailure(testAddress, "Retriever", testException));
+
+ Assert.Null(ex1);
+ Assert.Null(ex2);
+ Assert.Null(ex3);
+ Assert.Null(ex4);
+ Assert.Null(ex5);
+ }
- [Fact]
- public void TelemetryClient_Methods_DoNotThrow()
+ [Fact]
+ public void TelemetryClient_WithAppContextSwitch_DoesNotThrow()
+ {
+ // Test that telemetry methods work correctly when the backward compatibility switch is enabled
+ try
{
- // This test ensures that the modified telemetry methods don't break existing functionality
- // We cannot easily verify the exact values sent to the telemetry system without complex setup,
- // but we can ensure the methods don't throw exceptions when called with valid parameters.
+ // Enable the switch to use full metadata address
+ AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
// Arrange
var telemetryClient = new TelemetryClient();
- var testAddress = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
- var testDuration = TimeSpan.FromMilliseconds(100);
+ var testAddress = "https://accounts.google.com/.well-known/openid-configuration";
+ var testDuration = TimeSpan.FromMilliseconds(150);
var testException = new InvalidOperationException("Test exception");
- // Act & Assert - these should not throw
+ // Act & Assert - these should not throw even with the switch enabled
var ex1 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration));
var ex2 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration, testException));
var ex3 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "FirstRefresh", "Retriever"));
@@ -118,40 +148,10 @@ public void TelemetryClient_Methods_DoNotThrow()
Assert.Null(ex4);
Assert.Null(ex5);
}
-
- [Fact]
- public void TelemetryClient_WithAppContextSwitch_DoesNotThrow()
+ finally
{
- // Test that telemetry methods work correctly when the backward compatibility switch is enabled
- try
- {
- // Enable the switch to use full metadata address
- AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, true);
-
- // Arrange
- var telemetryClient = new TelemetryClient();
- var testAddress = "https://accounts.google.com/.well-known/openid-configuration";
- var testDuration = TimeSpan.FromMilliseconds(150);
- var testException = new InvalidOperationException("Test exception");
-
- // Act & Assert - these should not throw even with the switch enabled
- var ex1 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration));
- var ex2 = Record.Exception(() => telemetryClient.LogConfigurationRetrievalDuration(testAddress, "Retriever", testDuration, testException));
- var ex3 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "FirstRefresh", "Retriever"));
- var ex4 = Record.Exception(() => telemetryClient.IncrementConfigurationRefreshRequestCounter(testAddress, "ConfigurationRetrievalFailed", "Retriever", testException));
- var ex5 = Record.Exception(() => telemetryClient.LogBackgroundConfigurationRefreshFailure(testAddress, "Retriever", testException));
-
- Assert.Null(ex1);
- Assert.Null(ex2);
- Assert.Null(ex3);
- Assert.Null(ex4);
- Assert.Null(ex5);
- }
- finally
- {
- // Cleanup
- AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, false);
- }
+ // Cleanup
+ AppContext.SetSwitch(AppContextSwitches.UseFullMetadataAddressForTelemetrySwitch, false);
}
}
}
From 6c190a8aafb858a6a4653eb493ab4c69388d0ada Mon Sep 17 00:00:00 2001
From: Westin Musser <127992899+westin-m@users.noreply.github.com>
Date: Wed, 8 Oct 2025 09:46:21 -0700
Subject: [PATCH 8/8] pr feedback
---
.../Telemetry/TelemetryClient.cs | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
index 3c3019e725..73ad2100a1 100644
--- a/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
+++ b/src/Microsoft.IdentityModel.Tokens/Telemetry/TelemetryClient.cs
@@ -36,16 +36,11 @@ internal static string GetMetadataAddressForTelemetry(string metadataAddress, bo
if (!isSuccessCase || AppContextSwitches.UseFullMetadataAddressForTelemetry || string.IsNullOrEmpty(metadataAddress))
return metadataAddress;
- try
- {
- var uri = new Uri(metadataAddress, UriKind.Absolute);
- return uri.Host;
- }
- catch (UriFormatException)
- {
- // If parsing fails, return the original address
- return metadataAddress;
- }
+
+ if (Uri.TryCreate(metadataAddress, UriKind.Absolute, out Uri result))
+ return result.Host;
+
+ return metadataAddress;
}
public void IncrementConfigurationRefreshRequestCounter(string metadataAddress, string operationStatus, string configurationSource)