同步请求未调用中间件

3
我尝试使用SentryDotNet.AspNetCore将未处理的异常记录到sentry。
我的startup.cs文件中有以下内容:
   public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        var dsn = "[dsn]";


        services.AddSentryDotNet(
            new SentryClient(
                dsn,
                new SentryEventDefaults(
                    environment: "test",
                    release: typeof(Startup).Assembly.GetName().Version.ToString(3),
                    logger: "coremvcapp")));
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

        app.UseSentryDotNet(new SentryDotNetOptions { CaptureRequestBody = true });
 //app.Run(async context => { await DoSomethingAsync(context); });
    }

这里有一个示例调用中间件的代码,可以成功地将日志记录到Sentry。

private static async Task DoSomethingAsync(HttpContext context)
{
    if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("error"))
    {
        throw new InvalidOperationException("Boom");
    }
    await context.Response.WriteAsync("some stuff");
}

问题在于,如果控制器操作中抛出异常,则中间件不会被调用。
    public IActionResult LogError()
    {
        throw new Exception("mvc error");
    }

我在中间件的Invoke方法上设置了断点,但当操作中抛出异常时,断点没有被触发。

这个中间件有一个Invoke方法。

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next.Invoke(context);
        }
        catch (Exception e) when (_client != null)
        {
            // log stuff

            throw;
        }
    }

我发现它在应用程序启动时进行初始化。
public SentryDotNetMiddleware(RequestDelegate next, ISentryClient client, SentryDotNetOptions options)
{
    _next = next;
    _client = client;
    _options = options;

}

是否有遗漏导致中间件的调用方法未在操作中处理未处理的异常?

编辑

对于我来说,由Sentry.AspNetCore提供的实现可以直接使用。其他所有我尝试过的软件包都存在一些小问题。


1
值得注意的是,Sentry 官方支持 ASP.NET Core:https://docs.sentry.io/platforms/dotnet/aspnetcore/ (免责声明:我在 Sentry 工作)。 - Bruno Garcia
1个回答

4
你添加中间件的顺序很重要,因为它们按照添加到管道中的顺序被调用。
记录器和错误处理程序应该尽早添加到管道中。
请确保在拦截异常的任何中间件之后使用UseSentryDotNet()。否则,SentryDotNet中间件将无法看到异常。例如,app.UseDeveloperExceptionPage()应该在app.UseSentryDotNet()之前使用。
参考GitHub:SentryDotNet
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
    // Make sure middleware that catches exceptions without 
    // rethrowing them is added *before* SentryDotNet
    app.UseDeveloperExceptionPage();

    //Add sentry
    app.UseSentryDotNet(new SentryDotNetOptions { CaptureRequestBody = true });

    // Other middleware, e.g. app.UseMvc()

    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

你的示例之所以有效是因为你在添加Sentry中间件之后添加了它。
在其他调用中,错误发生在到达Sentry中间件之前,因此不会被捕获。
参考资料:ASP.NET Core Middleware 参考资料:处理ASP.NET Core中的错误

我一直在检查是否在 app.UseDeveloperExceptionPage() 后面添加了中间件,但没有意识到我还应该在其他中间件之前添加。现在这显然是很明显的。 - Mathias F

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接