Skip to content

Commit f478bbd

Browse files
committed
Add test for logging registration, add try/catch around sending error to telemetry
1 parent 9801f4a commit f478bbd

File tree

2 files changed

+43
-18
lines changed

2 files changed

+43
-18
lines changed

src/Aspire.Dashboard/Telemetry/TelemetryLoggerProvider.cs

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,13 @@ public void Dispose()
2828

2929
private sealed class TelemetryLogger : ILogger
3030
{
31-
private readonly DashboardTelemetryService? _telemetryService;
31+
private readonly IServiceProvider _serviceProvider;
32+
private readonly bool _isCircuitHostLogger;
3233

3334
public TelemetryLogger(IServiceProvider serviceProvider, string categoryName)
3435
{
35-
if (categoryName == CircuitHostLogCategory)
36-
{
37-
// Set this lazily to avoid a circular reference between resolving telemetry service and logging.
38-
_telemetryService = serviceProvider.GetRequiredService<DashboardTelemetryService>();
39-
}
36+
_serviceProvider = serviceProvider;
37+
_isCircuitHostLogger = categoryName == CircuitHostLogCategory;
4038
}
4139

4240
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
@@ -45,19 +43,30 @@ public TelemetryLogger(IServiceProvider serviceProvider, string categoryName)
4543

4644
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
4745
{
48-
if (_telemetryService != null && eventId == CircuitUnhandledExceptionEventId && exception != null)
46+
if (_isCircuitHostLogger && eventId == CircuitUnhandledExceptionEventId && exception != null)
4947
{
50-
_telemetryService.PostFault(
51-
TelemetryEventKeys.Error,
52-
$"{exception.GetType().FullName}: {exception.Message}",
53-
FaultSeverity.Critical,
54-
new Dictionary<string, AspireTelemetryProperty>
55-
{
56-
[TelemetryPropertyKeys.ExceptionType] = new AspireTelemetryProperty(exception.GetType().FullName!),
57-
[TelemetryPropertyKeys.ExceptionMessage] = new AspireTelemetryProperty(exception.Message),
58-
[TelemetryPropertyKeys.ExceptionStackTrace] = new AspireTelemetryProperty(exception.StackTrace ?? string.Empty)
59-
}
60-
);
48+
try
49+
{
50+
// Get the telemetry service lazily to avoid a circular reference between resolving telemetry service and logging.
51+
var telemetryService = _serviceProvider.GetRequiredService<DashboardTelemetryService>();
52+
53+
telemetryService.PostFault(
54+
TelemetryEventKeys.Error,
55+
$"{exception.GetType().FullName}: {exception.Message}",
56+
FaultSeverity.Critical,
57+
new Dictionary<string, AspireTelemetryProperty>
58+
{
59+
[TelemetryPropertyKeys.ExceptionType] = new AspireTelemetryProperty(exception.GetType().FullName!),
60+
[TelemetryPropertyKeys.ExceptionMessage] = new AspireTelemetryProperty(exception.Message),
61+
[TelemetryPropertyKeys.ExceptionStackTrace] = new AspireTelemetryProperty(exception.StackTrace ?? string.Empty)
62+
}
63+
);
64+
}
65+
catch
66+
{
67+
// We should never throw an error out of logging.
68+
// Logging the error to telemetry shouldn't throw. But, for extra safety, send error to telemetry is inside a try/catch.
69+
}
6170
}
6271
}
6372
}

tests/Aspire.Dashboard.Tests/Integration/StartupTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Text.Json.Nodes;
77
using Aspire.Dashboard.Configuration;
88
using Aspire.Dashboard.Otlp.Http;
9+
using Aspire.Dashboard.Telemetry;
910
using Aspire.Hosting;
1011
using Aspire.Tests.Shared.Telemetry;
1112
using Google.Protobuf;
@@ -15,6 +16,7 @@
1516
using Microsoft.Extensions.DependencyInjection;
1617
using Microsoft.Extensions.Logging;
1718
using Microsoft.Extensions.Logging.Abstractions;
19+
using Microsoft.Extensions.Logging.Console;
1820
using Microsoft.Extensions.Logging.Testing;
1921
using Microsoft.Extensions.Options;
2022
using Microsoft.Net.Http.Headers;
@@ -765,6 +767,20 @@ public async Task Configuration_DisableResourceGraph_EnsureValueSetOnOptions(boo
765767
// Assert
766768
Assert.Equal(value, app.DashboardOptionsMonitor.CurrentValue.UI.DisableResourceGraph);
767769
}
770+
[Fact]
771+
public async Task ServiceProvider_AppCreated_LoggerProvidersRegistered()
772+
{
773+
// Arrange
774+
await using var app = IntegrationTestHelpers.CreateDashboardWebApplication(testOutputHelper);
775+
776+
// Act
777+
var loggerProviders = app.Services.GetServices<ILoggerProvider>();
778+
var loggerProviderTypes = loggerProviders.Select(p => p.GetType()).ToList();
779+
780+
// Assert
781+
Assert.Contains(typeof(TelemetryLoggerProvider), loggerProviderTypes);
782+
Assert.Contains(typeof(ConsoleLoggerProvider), loggerProviderTypes);
783+
}
768784

769785
private static void AssertIPv4OrIPv6Endpoint(Func<EndpointInfo> endPointAccessor)
770786
{

0 commit comments

Comments
 (0)