| File: Circuits\RemoteErrorBoundaryLogger.cs | Web Access |
| Project: src\aspnetcore\src\Components\Server\src\Microsoft.AspNetCore.Components.Server.csproj (Microsoft.AspNetCore.Components.Server) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.AspNetCore.Components.Web; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.JSInterop; namespace Microsoft.AspNetCore.Components.Server.Circuits; internal sealed partial class RemoteErrorBoundaryLogger : IErrorBoundaryLogger { private readonly ILogger _logger; private readonly IJSRuntime _jsRuntime; private readonly CircuitOptions _options; public RemoteErrorBoundaryLogger(ILogger<ErrorBoundary> logger, IJSRuntime jsRuntime, IOptions<CircuitOptions> options) { _logger = logger; _jsRuntime = jsRuntime; _options = options.Value; } public ValueTask LogErrorAsync(Exception exception) { // We always log detailed information to the server-side log Log.ExceptionCaughtByErrorBoundary(_logger, exception.Message, exception); // We log to the client only if the browser is connected interactively, and even then // we may suppress the details var shouldLogToClient = (_jsRuntime as RemoteJSRuntime)?.IsInitialized == true; if (shouldLogToClient) { var message = _options.DetailedErrors ? exception.ToString() : $"For more details turn on detailed exceptions in '{nameof(CircuitOptions)}.{nameof(CircuitOptions.DetailedErrors)}'"; return _jsRuntime.InvokeVoidAsync("console.error", message); } else { return ValueTask.CompletedTask; } } private static partial class Log { [LoggerMessage(100, LogLevel.Warning, "Unhandled exception rendering component: {Message}", EventName = "ExceptionCaughtByErrorBoundary")] public static partial void ExceptionCaughtByErrorBoundary(ILogger logger, string message, Exception exception); } }