使用 Application Insights 诊断 Web 应用中的异常

注意

建议为新应用程序或客户提供 Azure Monitor OpenTelemetry 发行版 ,以便为 Azure Monitor Application Insights 提供支持。 Azure Monitor OpenTelemetry 发行版提供与 Application Insights SDK 类似的功能和体验。 可以使用 适用于 .NETNode.jsPython 的迁移指南从 Application Insights SDK 迁移,但我们仍在努力添加 更多功能 以实现向后兼容性。

可以使用 Application Insights 报告 Web 应用程序中的异常。 可将失败的请求与客户端和服务器上的异常和其他事件相关联,从而快速诊断原因。 本文介绍如何设置异常报告、显式报告异常、诊断故障等。

设置异常报告

可以设置 Application Insights 以报告服务器或客户端中发生的异常。 根据应用程序所依赖的平台,你将需要添加相应的扩展或 SDK。

服务器端

若要从服务器端应用程序报告异常,请考虑以下方案:

客户端

JavaScript SDK 提供让客户端报告 Web 浏览器中发生的异常的功能。 若要在客户端上设置异常报告,请参阅 Application Insights 网页

应用程序框架

对于某些应用程序框架,需要进行更多配置。 请考虑以下技术:

重要

本文从代码示例的角度着重介绍 .NET Framework 应用。 用于 .NET Framework 的某些方法在 .NET Core SDK 中已过时。 有关详细信息,请参阅 使用 .NET Core 生成应用时的 .NET Core SDK 文档

使用 Visual Studio 诊断异常

在 Visual Studio 中打开应用程序解决方案。 使用 F5 在服务器或开发计算机上运行应用。 重新创建异常。

打开 Visual Studio 中的“Application Insights 搜索”遥测窗口。 调试时,选择“Application Insights”下拉框。

选择异常报告,显示器堆栈跟踪。 若要打开相关代码文件,请选择堆栈跟踪中的行引用。

如果已启用 CodeLens,你将看到有关异常的数据:

显示 CodeLens 异常通知的屏幕截图。

使用 Azure 门户诊断失败

Application Insights 随附了特选的应用程序性能管理体验,可帮助你诊断受监视应用程序中发生的故障。 若要开始,请在左侧 Application Insights 资源菜单中的“调查”下,选择“失败”选项。

你将看到请求的失败率趋势、其中失败的请求数,以及受影响的用户数。 “总体”视图显示特定于所选失败操作的一些最有用的分布情况。 你将看到排名前三的响应代码、排名前三的异常类型以及排名前三的失败依赖项类型。

显示“操作”选项卡上“故障分类”视图的屏幕截图。

若要查看其中每个操作子集的具有代表性的示例,请选择相应链接。 例如,若要诊断异常,可以选择要在“端到端事务详细信息”选项卡中显示的特定异常的计数。

显示“端到端事务详细信息”选项卡的屏幕截图。

或者,可以切换到顶部的“异常”选项卡,从异常的“总体”视图开始,而不是查看特定失败操作的异常。 这里可以看到为所监视的应用收集的所有异常。

自定义跟踪和日志数据

要获取特定于应用的诊断数据,可在插入代码后发送自己的遥测数据。 自定义遥测或日志数据与请求、页面视图和其他自动收集的数据一起显示在诊断搜索中。

使用 Microsoft.VisualStudio.ApplicationInsights.TelemetryClient,你可以使用多个 API:

  • TelemetryClient.TrackEvent 通常用于监视使用模式,但它发送的数据还显示在诊断搜索的“自定义事件”下。 事件可以命名,并可以携带字符串属性和数值指标,可用于筛选诊断搜索。
  • TelemetryClient.TrackTrace 允许发送较长的数据,例如 POST 信息。
  • TelemetryClient.TrackException 将异常详细信息(例如堆栈跟踪)发送到 Application Insights。

若要查看这些事件,请在左侧菜单中打开“搜索”。 选择下拉菜单“事件类型”,然后选择“自定义事件”、“跟踪”或“异常”。

显示“搜索”屏幕的屏幕截图。

备注

如果应用生成大量遥测数据,自适应采样模块将通过仅发送具有代表性的事件部分来自动减少发送到门户的数据量。 属于同一操作的事件将以组为单位进行选择或取消选择,以便你可以在相关事件之间导航。 有关详细信息,请参阅 Application Insights 中的采样

查看请求 POST 数据

请求详细信息不包含在 POST 调用中发送到应用的数据。 若要报告此数据:

捕获异常和相关的诊断数据

首先,不会在门户中看到在应用中导致失败的所有异常。 如果在网页中使用 JavaScript SDK,你会看到所有浏览器异常。 但大多数服务器异常由 IIS 导致,必须编写几行代码才能看到它们。

方法:

  • 显式记录异常,通过在异常处理程序中插入代码来报告这些异常。
  • 通过配置 ASP.NET 框架自动捕获异常。 框架类型不同,必要的附加内容也不同。

显式报告异常

最简单的报告方法是在异常处理程序中插入对 trackException() 的调用。

try
{
    // ...
}
catch (ex)
{
    appInsights.trackException(ex, "handler loc",
    {
        Game: currentGame.Name,
        State: currentGame.State.ToString()
    });
}
var telemetry = new TelemetryClient();

try
{
    // ...
}
catch (Exception ex)
{
    var properties = new Dictionary<string, string>
    {
        ["Game"] = currentGame.Name
    };

    var measurements = new Dictionary<string, double>
    {
        ["Users"] = currentGame.Users.Count
    };

    // Send the exception telemetry:
    telemetry.TrackException(ex, properties, measurements);
}
Dim telemetry = New TelemetryClient

Try
    ' ...
Catch ex as Exception
    ' Set up some properties:
    Dim properties = New Dictionary (Of String, String)
    properties.Add("Game", currentGame.Name)

    Dim measurements = New Dictionary (Of String, Double)
    measurements.Add("Users", currentGame.Users.Count)

    ' Send the exception telemetry:
    telemetry.TrackException(ex, properties, measurements)
End Try

属性和度量参数是可选的,但它们可用于 筛选和添加 额外信息。 例如,如果有一个可运行多个游戏的应用,可查找与特定游戏相关的所有异常报表。 可向每个字典添加任意数量的项。

浏览器异常

报告大多数浏览器异常。

如果网页包含来自内容分发网络或其他域的脚本文件,请确保脚本标记具有属性 crossorigin="anonymous" ,并且服务器发送 CORS 标头。 此行为允许从这些资源中获取有关未处理的 JavaScript 异常的堆栈跟踪和详细信息。

重用遥测客户端

备注

建议实例化 TelemetryClient 一次,并在应用程序的整个生命周期内重复使用它。

在使用 .NET 中的依赖项注入 (DI)、相应的 .NET SDK 并为 DI 正确配置了 Application Insights 的情况下,可以要求将 TelemetryClient 用作构造函数参数。

public class ExampleController : ApiController
{
    private readonly TelemetryClient _telemetryClient;

    public ExampleController(TelemetryClient telemetryClient)
    {
        _telemetryClient = telemetryClient;
    }
}

在前面的示例中,已将 TelemetryClient 注入到 ExampleController 类中。

Web 窗体

在 Web 窗体中,当不存在通过 CustomErrors 配置的重定向时,HTTP 模块能够收集异常。 但是,如果有活动重定向,在 Global.asax.cs 中将以下行添加到 Application_Error 函数。

void Application_Error(object sender, EventArgs e)
{
    if (HttpContext.Current.IsCustomErrorEnabled &&
        Server.GetLastError () != null)
    {
        _telemetryClient.TrackException(Server.GetLastError());
    }
}

在前面的示例中,_telemetryClient 是类型 TelemetryClient 的类范围内变量。

MVC

从 Application Insights Web SDK 2.6 版(beta3 及更高版本)开始,Application Insights 会自动收集 MVC 5+ 控制器方法中引发的未经处理异常。 如果之前已添加自定义处理程序以跟踪此类异常,可将其删除以避免对异常进行双重跟踪。

在某些情况下,当引发异常时,异常筛选器无法正确处理错误:

  • 从控制器构造函数引发异常时
  • 从消息处理程序引发异常时
  • 在路由期间引发异常时
  • 在响应内容序列化期间引发异常时
  • 在应用程序启动期间引发异常时
  • 在后台任务中引发异常时

应用程序 处理 的所有异常仍需手动跟踪。 源自控制器的未经处理异常通常会导致 500“内部服务器错误”响应。 如果此类响应是由于已处理的异常或根本没有任何异常而手动构造的,则它是通过 ResultCode 500 在相应请求遥测数据中进行跟踪的。 但是,Application Insights SDK 无法跟踪相应异常。

以前版本支持

如果使用 Application Insights Web SDK 2.5(及更低版本)的 MVC 4(及更低版本),请参照以下示例跟踪异常。

如果 CustomErrors 配置是 Off,则 HTTP 模块 可以收集异常。 但是,如果它是 RemoteOnly(默认值)或 On,异常将被清除,并且 Application Insights 无法自动收集它。 可通过替代 System.Web.Mvc.HandleErrorAttribute 类和应用该被替代类来修复该行为,如以下针对不同 MVC 版本的方式所示(请参阅 GitHub 源):

using System;
using System.Web.Mvc;
using Microsoft.ApplicationInsights;

namespace MVC2App.Controllers
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AiHandleErrorAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            if (filterContext != null && filterContext.HttpContext != null && filterContext.Exception != null)
            {
                //The attribute should track exceptions only when CustomErrors setting is On
                //if CustomErrors is Off, exceptions will be caught by AI HTTP Module
                if (filterContext.HttpContext.IsCustomErrorEnabled)
                {   //Or reuse instance (recommended!). See note above.
                    var ai = new TelemetryClient();
                    ai.TrackException(filterContext.Exception);
                }
            }
            base.OnException(filterContext);
        }
    }
}

MVC 2

将 HandleError 属性替换为控制器中的新属性:

    namespace MVC2App.Controllers
    {
        [AiHandleError]
        public class HomeController : Controller
        {
            // Omitted for brevity
        }
    }

样本

MVC 3

在 Global.asax.cs 中将 AiHandleErrorAttribute 注册为全局筛选器:

public class MyMvcApplication : System.Web.HttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new AiHandleErrorAttribute());
    }
}

样本

MVC 4、MVC 5

在 FilterConfig.cs 中将 AiHandleErrorAttribute 注册为全局筛选器:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        // Default replaced with the override to track unhandled exceptions
        filters.Add(new AiHandleErrorAttribute());
    }
}

样本

网络应用程序接口

从 Application Insights Web SDK 2.6 版(beta3 及更高版本)开始,Application Insights 会自动收集 WebAPI 2+ 控制器方法中引发的未经处理异常。 如果之前已添加自定义处理程序以跟踪此类异常(如下面的示例中所述),则可以删除该处理程序以避免对异常进行双重跟踪。

存在一些无法处理异常筛选器的情况。 例如:

  • 从控制器构造函数引发的异常。
  • 从消息处理程序引发的异常。
  • 在路由过程中引发的异常。
  • 在响应内容序列化期间引发的异常。
  • 在应用程序启动过程中引发的异常。
  • 在后台任务中引发的异常。

应用程序 处理 的所有异常仍需手动跟踪。 源自控制器的未经处理异常通常会导致 500“内部服务器错误”响应。 如果此类响应是由于已处理的异常或根本没有任何异常而手动构造的,则它是通过 ResultCode 500 在相应请求遥测数据中进行跟踪的。 但是,Application Insights SDK 无法跟踪相应异常。

以前版本支持

如果使用 Application Insights Web SDK 2.5(及更低版本)的 WebAPI 1(及更低版本),请参照以下示例跟踪异常。

Web API 1.x

替代 System.Web.Http.Filters.ExceptionFilterAttribute

using System.Web.Http.Filters;
using Microsoft.ApplicationInsights;

namespace WebAPI.App_Start
{
    public class AiExceptionFilterAttribute : ExceptionFilterAttribute
    {
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext != null && actionExecutedContext.Exception != null)
        {  //Or reuse instance (recommended!). See note above.
            var ai = new TelemetryClient();
            ai.TrackException(actionExecutedContext.Exception);
        }
        base.OnException(actionExecutedContext);
    }
    }
}

可将此替换属性添加到特定控制器,或者将其添加到 WebApiConfig 类中的全局筛选器配置:

using System.Web.Http;
using WebApi1.x.App_Start;

namespace WebApi1.x
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });
    
            // ...
            config.EnableSystemDiagnosticsTracing();
    
            // Capture exceptions for Application Insights:
            config.Filters.Add(new AiExceptionFilterAttribute());
        }
    }
}

样本

Web API 2.x

添加 IExceptionLogger 的实现:

using System.Web.Http.ExceptionHandling;
using Microsoft.ApplicationInsights;

namespace ProductsAppPureWebAPI.App_Start
{
    public class AiExceptionLogger : ExceptionLogger
    {
        public override void Log(ExceptionLoggerContext context)
        {
            if (context != null && context.Exception != null)
            {
                //or reuse instance (recommended!). see note above
                var ai = new TelemetryClient();
                ai.TrackException(context.Exception);
            }
            base.Log(context);
        }
    }
}

将此代码片段添加到服务的 WebApiConfig 中:

using System.Web.Http;
using System.Web.Http.ExceptionHandling;
using ProductsAppPureWebAPI.App_Start;

namespace WebApi2WithMVC
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
    
            // Web API routes
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });

            config.Services.Add(typeof(IExceptionLogger), new AiExceptionLogger());
        }
    }
}

样本

作为替代项,可以:

  • 仅将 ExceptionHandler 实例替换为 IExceptionHandler 的自定义实现。 此异常处理程序仅在框架仍能够选择要发送哪个响应消息时(而不是在终止了连接等情况下)调用。
  • 使用异常筛选器(如上述有关 Web API 1.x 控制器的部分中所述),这些筛选器并非在所有情况下都调用。

WCF(Windows Communication Foundation)

添加一个用来扩展 Attribute 并实现 IErrorHandlerIServiceBehavior 的类。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    using System.Web;
    using Microsoft.ApplicationInsights;

    namespace WcfService4.ErrorHandling
    {
      public class AiLogExceptionAttribute : Attribute, IErrorHandler, IServiceBehavior
      {
        public void AddBindingParameters(ServiceDescription serviceDescription,
            System.ServiceModel.ServiceHostBase serviceHostBase,
            System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
            System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
            System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher disp in serviceHostBase.ChannelDispatchers)
            {
                disp.ErrorHandlers.Add(this);
            }
        }

        public void Validate(ServiceDescription serviceDescription,
            System.ServiceModel.ServiceHostBase serviceHostBase)
        {
        }

        bool IErrorHandler.HandleError(Exception error)
        {//or reuse instance (recommended!). see note above
            var ai = new TelemetryClient();

            ai.TrackException(error);
            return false;
        }

        void IErrorHandler.ProvideFault(Exception error,
            System.ServiceModel.Channels.MessageVersion version,
            ref System.ServiceModel.Channels.Message fault)
        {
        }
      }
    }

将属性添加到服务实现:

namespace WcfService4
{
    [AiLogException]
    public class Service1 : IService1
    {
        // Omitted for brevity
    }
}

样本

异常性能计数器

如果已在服务器上 安装了 Azure Monitor Application Insights 代理 ,则可以获取由 .NET 测量的异常率图表。 已经处理和未经处理的 .NET 异常均会包括在内。

打开指标资源管理器选项卡,添加新图表。 在“性能计数器”下,选择“异常率”。

.NET Framework 通过对间隔中的异常数进行计数并除以间隔长度计算异常率。

此计数与 Application Insights 门户通过对 TrackException 报告计数计算得出的“异常”计数不同。 采样间隔不同,并且 SDK 不会为所有已经处理和未经处理的异常发送 TrackException 报告。

后续步骤