| File: Telemetry\TelemetryLoggerProvider.cs | Web Access |
| Project: src\src\Aspire.Dashboard\Aspire.Dashboard.csproj (Aspire.Dashboard) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace Aspire.Dashboard.Telemetry; /// <summary> /// Log an error to dashboard telemetry when there is an unhandled Blazor error. /// </summary> public sealed class TelemetryLoggerProvider : ILoggerProvider { // Log when an unhandled error is caught by Blazor. // https://github.com/dotnet/aspnetcore/blob/0230498dfccaef6f782a5e37c60ea505081b72bf/src/Components/Server/src/Circuits/CircuitHost.cs#L695 public const string CircuitHostLogCategory = "Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost"; public static readonly EventId CircuitUnhandledExceptionEventId = new EventId(111, "CircuitUnhandledException"); private readonly IServiceProvider _serviceProvider; public TelemetryLoggerProvider(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public ILogger CreateLogger(string categoryName) => new TelemetryLogger(_serviceProvider, categoryName); public void Dispose() { } private sealed class TelemetryLogger : ILogger { private readonly IServiceProvider _serviceProvider; private readonly bool _isCircuitHostLogger; public TelemetryLogger(IServiceProvider serviceProvider, string categoryName) { _serviceProvider = serviceProvider; _isCircuitHostLogger = categoryName == CircuitHostLogCategory; } public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null; public bool IsEnabled(LogLevel logLevel) => true; public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) { if (_isCircuitHostLogger && eventId == CircuitUnhandledExceptionEventId && exception != null) { try { // Get the telemetry service lazily to avoid a circular reference between resolving telemetry service and logging. var errorRecorder = _serviceProvider.GetRequiredService<ITelemetryErrorRecorder>(); errorRecorder.RecordError("Blazor global error", exception); } catch { // We should never throw an error out of logging. // Logging the error to telemetry shouldn't throw. But, for extra safety, send error to telemetry is inside a try/catch. } } } } }