Browse Source

Merge pull request #25464 from abpframework/maliming/fix-blazor-wasm-stackoverflow-logging

Avoid stack overflow when logging exceptions in Blazor WebAssembly
pull/25477/head
Engincan VESKE 1 month ago
committed by GitHub
parent
commit
4265df0dcf
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs
  2. 62
      framework/test/Volo.Abp.AspNetCore.Components.Web.Theming.Tests/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLogger_Tests.cs

3
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs

@ -48,7 +48,8 @@ public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule
context.Services.AddHttpClient();
context.Services
.GetHostBuilder().Logging
.AddProvider(new AbpExceptionHandlingLoggerProvider(context.Services));
.AddProvider(new AbpExceptionHandlingLoggerProvider(context.Services))
.AddFilter<AbpExceptionHandlingLoggerProvider>(typeof(UserExceptionInformer).FullName, LogLevel.None);
if (!context.Services.ExecutePreConfiguredActions<AbpAspNetCoreComponentsWebOptions>().IsBlazorWebApp)
{

62
framework/test/Volo.Abp.AspNetCore.Components.Web.Theming.Tests/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/AbpExceptionHandlingLogger_Tests.cs

@ -0,0 +1,62 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Shouldly;
using Volo.Abp.AspNetCore.Components.ExceptionHandling;
using Xunit;
namespace Volo.Abp.AspNetCore.Components.Web.ExceptionHandling;
public class AbpExceptionHandlingLogger_Tests
{
[Fact]
public void Should_Not_Recurse_When_Informer_Writes_To_Same_Logger_Pipeline()
{
var services = new ServiceCollection();
var informer = new RecordingUserExceptionInformer();
services.AddSingleton<IUserExceptionInformer>(informer);
var provider = new AbpExceptionHandlingLoggerProvider(services);
services.AddLogging(builder => builder
.AddProvider(provider)
.AddFilter<AbpExceptionHandlingLoggerProvider>(typeof(UserExceptionInformer).FullName, LogLevel.None));
var accessor = services.AddObjectAccessor<IServiceProvider>();
var sp = services.BuildServiceProvider();
accessor.Value = sp;
informer.Logger = sp.GetRequiredService<ILoggerFactory>()
.CreateLogger(typeof(UserExceptionInformer).FullName!);
var entryLogger = sp.GetRequiredService<ILogger<AbpExceptionHandlingLogger_Tests>>();
entryLogger.LogError(new InvalidOperationException("boom"), "entry");
informer.InformCalls.ShouldBe(1);
}
private sealed class RecordingUserExceptionInformer : IUserExceptionInformer
{
private const int RecursionCircuitBreaker = 50;
public int InformCalls;
public ILogger? Logger;
public void Inform(UserExceptionInformerContext context)
{
InformCalls++;
if (InformCalls > RecursionCircuitBreaker)
{
return;
}
Logger?.LogError(context.Exception, context.Exception.Message);
}
public Task InformAsync(UserExceptionInformerContext context)
{
Inform(context);
return Task.CompletedTask;
}
}
}
Loading…
Cancel
Save