You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Web API 2如何避免自定义异常被Application Insights重复记录

ASP.NET Web API中避免Application Insights重复记录自定义异常

问题描述

在ASP.NET Web API应用中已安装Application Insights,并实现了全局异常处理器AppExceptionHandler,将AppSessionException这类特定异常记录为自定义事件到App Insights。代码如下:

public class AppExceptionHandler : ExceptionHandler
{
    private readonly IAuthEventLogger _authEventLogger;

    public AppExceptionHandler()
    {
        _authEventLogger = DependencyResolver.Current.GetService<IAuthEventLogger>();
    }

    public override void Handle(ExceptionHandlerContext context)
    {
        Exception ex = context.Exception;
        IHttpActionResult newResult = null;

        while (ex != null)
        {
            if (ex is AppSessionException)
            {
                newResult = new StatusCodeResult(HttpStatusCode.Unauthorized, context.Request);
                _authEventLogger.TrackUnauthorizedRequestEvent(context.Request.RequestUri.PathAndQuery);

                break;
            }      
        }

        if (newResult != null)
        {
            context.Result = newResult;
        }
        else
        {
            base.Handle(context);
        }
    }
}

目前功能正常,但存在异常重复记录的问题:自定义事件已通过日志器写入,同时该异常还会被自动记录到Application Insights的「Failures」板块。尝试清除ExceptionHandlerContext.Exception属性但发现其为只读,希望实现自定义异常不被自动记录为Failures,仅记录其他异常。

解决方案

方法1:标记异常为已处理

在处理完AppSessionException后,设置context.ExceptionHandled = true,告知后续异常处理管道(包括Application Insights的默认异常收集)该异常已被处理,无需再记录:

public override void Handle(ExceptionHandlerContext context)
{
    Exception ex = context.Exception;
    IHttpActionResult newResult = null;

    while (ex != null)
    {
        if (ex is AppSessionException)
        {
            newResult = new StatusCodeResult(HttpStatusCode.Unauthorized, context.Request);
            _authEventLogger.TrackUnauthorizedRequestEvent(context.Request.RequestUri.PathAndQuery);
            // 标记异常已处理,阻止后续自动记录
            context.ExceptionHandled = true;
            break;
        }      
        ex = ex.InnerException; // 补充遍历内部异常逻辑,避免遗漏嵌套的目标异常
    }

    if (newResult != null)
    {
        context.Result = newResult;
    }
    else
    {
        base.Handle(context);
    }
}

方法2:使用自定义TelemetryProcessor过滤异常

如果方法1无法生效,可通过自定义TelemetryProcessor全局过滤掉AppSessionException的自动记录:

  1. 创建自定义处理器:
public class CustomExceptionFilter : ITelemetryProcessor
{
    private readonly ITelemetryProcessor _next;

    public CustomExceptionFilter(ITelemetryProcessor next)
    {
        _next = next;
    }

    public void Process(ITelemetry telemetry)
    {
        if (telemetry is ExceptionTelemetry exceptionTelemetry)
        {
            // 检查异常是否为AppSessionException或包含该类型的内部异常
            var currentEx = exceptionTelemetry.Exception;
            while (currentEx != null)
            {
                if (currentEx is AppSessionException)
                {
                    // 跳过该异常的记录
                    return;
                }
                currentEx = currentEx.InnerException;
            }
        }
        // 其他遥测正常处理
        _next.Process(telemetry);
    }
}
  1. 注册处理器:
  • 若使用ApplicationInsights.config,添加以下配置:
<TelemetryProcessors>
  <Add Type="你的命名空间.CustomExceptionFilter, 你的程序集名称" />
</TelemetryProcessors>
  • 若使用代码注册(如Startup.cs):
using Microsoft.ApplicationInsights.Extensibility;

public void Configuration(IAppBuilder app)
{
    var telemetryConfiguration = TelemetryConfiguration.Active;
    telemetryConfiguration.TelemetryProcessorChainBuilder
        .Use((next) => new CustomExceptionFilter(next))
        .Build();
    // 其他Web API配置逻辑...
}

说明

  • 方法1更直接,适合在异常处理器内完成标记;方法2是全局过滤,适合需要在多个场景排除特定异常的情况。
  • 建议优先尝试方法1,若因管道顺序等问题导致不生效,再使用方法2。

内容的提问来源于stack exchange,提问作者Mikhail Kostiuchenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 10:45:46