-
Notifications
You must be signed in to change notification settings - Fork 403
Add MsalRemainingTokenLifetime histogram for token expiry #5920
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
9b26a89
01805a2
3742b3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,7 @@ internal class OtelInstrumentation : IOtelInstrumentation | |
| private const string DurationInL2CacheHistogramName = "MsalDurationInL2Cache.1A"; | ||
| private const string DurationInHttpHistogramName = "MsalDurationInHttp.1A"; | ||
| private const string DurationInExtensionInMsHistogram = "MsalDurationInExtensionInMs.1B"; | ||
| private const string RemainingTokenLifetimeHistogramName = "MsalRemainingTokenLifetime.1A"; | ||
|
|
||
| /// <summary> | ||
| /// Meter to hold the MSAL metrics. | ||
|
|
@@ -88,6 +89,14 @@ internal class OtelInstrumentation : IOtelInstrumentation | |
| unit: "us", | ||
| description: "Performance of token acquisition calls extension latency.")); | ||
|
|
||
| /// <summary> | ||
| /// Histogram to record the remaining lifetime of acquired tokens in seconds. | ||
| /// </summary> | ||
| internal static readonly Lazy<Histogram<long>> s_remainingTokenLifetime = new(() => Meter.CreateHistogram<long>( | ||
| RemainingTokenLifetimeHistogramName, | ||
| unit: "s", | ||
| description: "Remaining lifetime of acquired tokens at the time of acquisition.")); | ||
|
neha-bhargava marked this conversation as resolved.
Comment on lines
+92
to
+98
|
||
|
|
||
| public OtelInstrumentation() | ||
| { | ||
| // Needed to fail fast if the runtime, like in-process Azure Functions, doesn't support OpenTelemetry | ||
|
|
@@ -103,7 +112,8 @@ public void LogSuccessMetrics( | |
| CacheLevel cacheLevel, | ||
| long totalDurationInUs, | ||
| AuthenticationResultMetadata authResultMetadata, | ||
| ILoggerAdapter logger) | ||
| ILoggerAdapter logger, | ||
| DateTimeOffset expiresOn) | ||
| { | ||
| IncrementSuccessCounter( | ||
| platform, | ||
|
|
@@ -171,6 +181,19 @@ public void LogSuccessMetrics( | |
| new(TelemetryConstants.CacheLevel, authResultMetadata.CacheLevel), | ||
| new(TelemetryConstants.TokenType, authResultMetadata.TelemetryTokenType)); | ||
| } | ||
|
|
||
| if (s_remainingTokenLifetime.Value.Enabled) | ||
| { | ||
| long remainingSeconds = Math.Max(0, (long)(expiresOn - DateTimeOffset.UtcNow).TotalSeconds); | ||
|
|
||
| s_remainingTokenLifetime.Value.Record(remainingSeconds, | ||
| new(TelemetryConstants.MsalVersionPlatform, $"{MsalIdHelper.GetMsalVersion()},{platform}"), | ||
| new(TelemetryConstants.ApiId, apiId), | ||
| new(TelemetryConstants.TokenSource, authResultMetadata.TokenSource), | ||
| new(TelemetryConstants.CacheLevel, cacheLevel), | ||
| new(TelemetryConstants.CacheRefreshReason, authResultMetadata.CacheRefreshReason), | ||
| new(TelemetryConstants.TokenType, authResultMetadata.TelemetryTokenType)); | ||
|
Comment on lines
+189
to
+195
|
||
| } | ||
| } | ||
|
|
||
| public void IncrementSuccessCounter(string platform, | ||
|
|
@@ -218,5 +241,6 @@ public void LogFailureMetrics(string platform, | |
| new(TelemetryConstants.TokenType, tokenType)); | ||
| } | ||
| } | ||
|
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -76,7 +76,7 @@ public async Task AcquireTokenOTelTestAsync() | |
| await AcquireTokenMsalClientExceptionAsync().ConfigureAwait(false); | ||
|
|
||
| s_meterProvider.ForceFlush(); | ||
| VerifyMetrics(6, _exportedMetrics, 2, 2); | ||
| VerifyMetrics(7, _exportedMetrics, 2, 2); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -91,7 +91,7 @@ public async Task AcquireTokenOTelTestWithExtensionAsync() | |
| await AcquireTokenMsalClientExceptionAsync().ConfigureAwait(false); | ||
|
|
||
| s_meterProvider.ForceFlush(); | ||
| VerifyMetrics(6, _exportedMetrics, 2, 2); | ||
| VerifyMetrics(7, _exportedMetrics, 2, 2); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -147,7 +147,7 @@ public async Task ProactiveTokenRefresh_ValidResponse_ClientCredential_Async() | |
| Assert.AreEqual(CacheRefreshReason.NotApplicable, result.AuthenticationResultMetadata.CacheRefreshReason); | ||
|
|
||
| s_meterProvider.ForceFlush(); | ||
| VerifyMetrics(5, _exportedMetrics, 4, 0); | ||
| VerifyMetrics(6, _exportedMetrics, 4, 0); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -222,7 +222,7 @@ public async Task ProactiveTokenRefresh_ValidResponse_MSI_Async() | |
| Assert.AreEqual(CacheRefreshReason.NotApplicable, result.AuthenticationResultMetadata.CacheRefreshReason); | ||
|
|
||
| s_meterProvider.ForceFlush(); | ||
| VerifyMetrics(5, _exportedMetrics, 4, 0); | ||
| VerifyMetrics(6, _exportedMetrics, 4, 0); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -279,7 +279,7 @@ public async Task ProactiveTokenRefresh_ValidResponse_OBO_Async() | |
| Assert.AreEqual(CacheRefreshReason.NotApplicable, result.AuthenticationResultMetadata.CacheRefreshReason); | ||
|
|
||
| s_meterProvider.ForceFlush(); | ||
| VerifyMetrics(5, _exportedMetrics, 4, 0); | ||
| VerifyMetrics(6, _exportedMetrics, 4, 0); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -329,7 +329,7 @@ public async Task ProactiveTokenRefresh_AadUnavailableResponse_Async() | |
| Thread.Sleep(1000); | ||
|
|
||
| s_meterProvider.ForceFlush(); | ||
| VerifyMetrics(4, _exportedMetrics, 3, 1); | ||
| VerifyMetrics(5, _exportedMetrics, 3, 1); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -577,6 +577,26 @@ private void VerifyMetrics(int expectedMetricCount, List<Metric> exportedMetrics | |
| AssertTags(metricPoint.Tags, expectedTags); | ||
| } | ||
|
|
||
| break; | ||
|
|
||
| case "MsalRemainingTokenLifetime.1A": | ||
| Trace.WriteLine("Verify the metrics captured for MsalRemainingTokenLifetime.1A histogram."); | ||
| Assert.AreEqual(MetricType.Histogram, exportedItem.MetricType); | ||
|
|
||
| expectedTags.Add(TelemetryConstants.MsalVersionPlatform); | ||
| expectedTags.Add(TelemetryConstants.ApiId); | ||
| expectedTags.Add(TelemetryConstants.TokenSource); | ||
| expectedTags.Add(TelemetryConstants.CacheLevel); | ||
| expectedTags.Add(TelemetryConstants.CacheRefreshReason); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test validates tags but never asserts the recorded histogram value |
||
| expectedTags.Add(TelemetryConstants.TokenType); | ||
|
|
||
| foreach (var metricPoint in exportedItem.GetMetricPoints()) | ||
| { | ||
| AssertTags(metricPoint.Tags, expectedTags); | ||
| Assert.IsGreaterThan((long)0, metricPoint.GetHistogramCount(), "Histogram should have at least one recorded value."); | ||
| Assert.IsGreaterThanOrEqualTo(0.0, metricPoint.GetHistogramSum(), "Remaining token lifetime should be non-negative."); | ||
| } | ||
|
|
||
| break; | ||
| default: | ||
| Assert.Fail("Unexpected metrics logged."); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.