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的自动记录:
- 创建自定义处理器:
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); } }
- 注册处理器:
- 若使用
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
相关产品推荐
相关产品推荐

