From f55a12938605c5b239267f782ea4b881283e8d31 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 14 May 2025 22:26:38 +0800 Subject: [PATCH 1/2] Don't throw from component telemetry context dispose if not initialized --- .../Pages/ComponentTelemetryContext.cs | 11 +++++++---- .../ComponentTelemetryContextTests.cs | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/Aspire.Dashboard/Components/Pages/ComponentTelemetryContext.cs b/src/Aspire.Dashboard/Components/Pages/ComponentTelemetryContext.cs index 6d95fb71791..14d13cc1e4b 100644 --- a/src/Aspire.Dashboard/Components/Pages/ComponentTelemetryContext.cs +++ b/src/Aspire.Dashboard/Components/Pages/ComponentTelemetryContext.cs @@ -41,8 +41,6 @@ public ComponentTelemetryContext(string componentType) // Internal for testing internal Dictionary Properties { get; } = []; - private DashboardTelemetryService TelemetryService => _telemetryService ?? throw new ArgumentNullException(nameof(_telemetryService), "InitializeAsync has not been called"); - public void Initialize(DashboardTelemetryService telemetryService, string? browserUserAgent) { _telemetryService = telemetryService; @@ -92,7 +90,12 @@ public bool UpdateTelemetryProperties(ReadOnlySpan m private void PostProperties() { - TelemetryService.PostOperation( + if (_telemetryService == null) + { + throw new InvalidOperationException("InitializeAsync has not been called"); + } + + _telemetryService.PostOperation( TelemetryEventKeys.ParametersSet, TelemetryResult.Success, properties: Properties, @@ -103,7 +106,7 @@ public void Dispose() { if (!_disposed) { - TelemetryService.PostOperation( + _telemetryService?.PostOperation( TelemetryEventKeys.ComponentDispose, TelemetryResult.Success, properties: new Dictionary diff --git a/tests/Aspire.Dashboard.Tests/Telemetry/ComponentTelemetryContextTests.cs b/tests/Aspire.Dashboard.Tests/Telemetry/ComponentTelemetryContextTests.cs index 8e87c0e9792..cfb1702ee14 100644 --- a/tests/Aspire.Dashboard.Tests/Telemetry/ComponentTelemetryContextTests.cs +++ b/tests/Aspire.Dashboard.Tests/Telemetry/ComponentTelemetryContextTests.cs @@ -13,6 +13,7 @@ public class ComponentTelemetryContextTests [Fact] public async Task ComponentTelemetryContext_TelemetryEnabled_EndToEnd() { + // Arrange var telemetryContext = new ComponentTelemetryContext(nameof(ComponentTelemetryContextTests)); var telemetrySender = new TestDashboardTelemetrySender { IsTelemetryEnabled = true }; var telemetryService = new DashboardTelemetryService(NullLogger.Instance, telemetrySender); @@ -20,6 +21,7 @@ public async Task ComponentTelemetryContext_TelemetryEnabled_EndToEnd() telemetryContextProvider.SetBrowserUserAgent("mozilla"); await telemetryService.InitializeAsync(); + // Act & assert initialize telemetryContextProvider.Initialize(telemetryContext); for (var i = 0; i < telemetryService.GetDefaultProperties().Count; i++) { @@ -35,6 +37,7 @@ public async Task ComponentTelemetryContext_TelemetryEnabled_EndToEnd() OperationContext? parametersUpdateOperation; + // Act & assert update properties telemetryContext.UpdateTelemetryProperties([new ComponentTelemetryProperty("Test", new AspireTelemetryProperty("Value"))]); Assert.Equal(3, telemetryContext.Properties.Count); Assert.True(telemetrySender.ContextChannel.Reader.TryRead(out parametersUpdateOperation)); @@ -50,6 +53,7 @@ public async Task ComponentTelemetryContext_TelemetryEnabled_EndToEnd() Assert.Equal(3, telemetryContext.Properties.Count); Assert.True(telemetrySender.ContextChannel.Reader.TryRead(out parametersUpdateOperation)); + // Act & assert dispose telemetryContext.Dispose(); Assert.True(telemetrySender.ContextChannel.Reader.TryRead(out var disposeOperation)); Assert.Equal("/telemetry/operation - $aspire/dashboard/component/dispose", disposeOperation.Name); @@ -58,6 +62,7 @@ public async Task ComponentTelemetryContext_TelemetryEnabled_EndToEnd() [Fact] public async Task ComponentTelemetryContext_TelemetryDisabled_EndToEnd() { + // Arrange var telemetryContext = new ComponentTelemetryContext(nameof(ComponentTelemetryContextTests)); var telemetrySender = new TestDashboardTelemetrySender { IsTelemetryEnabled = false }; var telemetryService = new DashboardTelemetryService(NullLogger.Instance, telemetrySender); @@ -65,14 +70,27 @@ public async Task ComponentTelemetryContext_TelemetryDisabled_EndToEnd() telemetryContextProvider.SetBrowserUserAgent("mozilla"); await telemetryService.InitializeAsync(); + // Act & assert initialize telemetryContextProvider.Initialize(telemetryContext); Assert.False(telemetrySender.ContextChannel.Reader.TryRead(out _)); + // Act & assert update properties telemetryContext.UpdateTelemetryProperties([new ComponentTelemetryProperty("Test", new AspireTelemetryProperty("Value"))]); Assert.Equal(3, telemetryContext.Properties.Count); Assert.False(telemetrySender.ContextChannel.Reader.TryRead(out _)); + // Act & assert dispose telemetryContext.Dispose(); Assert.False(telemetrySender.ContextChannel.Reader.TryRead(out _)); } + + [Fact] + public void ComponentTelemetryContext_DisposeWithoutInitialize_NoThrow() + { + // Arrange + var telemetryContext = new ComponentTelemetryContext(nameof(ComponentTelemetryContextTests)); + + // Act + telemetryContext.Dispose(); + } } From 6554bdf225f1b60f43932904978e63b22d7d3341 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Wed, 14 May 2025 22:29:17 +0800 Subject: [PATCH 2/2] Clean up --- .../Components/Pages/ComponentTelemetryContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Aspire.Dashboard/Components/Pages/ComponentTelemetryContext.cs b/src/Aspire.Dashboard/Components/Pages/ComponentTelemetryContext.cs index 14d13cc1e4b..4726aafca14 100644 --- a/src/Aspire.Dashboard/Components/Pages/ComponentTelemetryContext.cs +++ b/src/Aspire.Dashboard/Components/Pages/ComponentTelemetryContext.cs @@ -92,7 +92,7 @@ private void PostProperties() { if (_telemetryService == null) { - throw new InvalidOperationException("InitializeAsync has not been called"); + throw new InvalidOperationException("InitializeAsync has not been called."); } _telemetryService.PostOperation(