Диагностика исключений в веб-приложениях с помощью Application Insights

Примечание.

В следующей документации используется классический API приложения Аналитика. Долгосрочный план приложения Аналитика заключается в сборе данных с помощью OpenTelemetry. Дополнительные сведения см. в разделе "Включить Azure Monitor OpenTelemetry" для приложений .NET, Node.js, Python и Java.

Исключения в веб-приложениях можно получить с помощью Application Insights. Для быстрого выявления причин неполадок можно сопоставлять неудачно завершенные запросы с исключениями и другими событиями на клиенте и на сервере. В этой статье вы узнаете, как настраивать отчеты об исключениях, сообщать об исключениях явным образом, диагностировать сбои и многое другое.

Настройка создания отчетов об исключениях

Вы можете настроить Application Insights для создания отчетов об исключениях, происходящих либо на сервере, либо на клиенте. В зависимости от платформы вашего приложения вам потребуется соответствующее расширение или пакет SDK.

На стороне сервера

Рассмотрите следующие сценарии для получения отчета об исключениях из приложения на стороне сервера:

На стороне клиента

Пакет SDK для JavaScript предоставляет возможность создания на стороне клиента отчетов об исключениях, возникших в веб-браузерах. Сведения о настройке отчетов об исключениях на клиенте см. в разделе Application Insights для веб-страниц.

Исполняющие среды

Для некоторых платформ приложений требуется дополнительная конфигурация. Можно использовать следующие технологии:

Внимание

В этой статье особое внимание уделяется приложениям .NET Framework с точки зрения примера кода. Некоторые методы, подходящие для .NET Framework, являются устаревшими в пакете SDK для .NET Core. Дополнительные сведения по сборке приложений с помощью .NET Core см. в документации пакета SDK для .NET Core.

Диагностика исключений с помощью Visual Studio

Откройте приложение в Visual Studio. Запустите приложение на сервере или на компьютере разработки, нажав клавишу F5. Повторно создайте исключение.

Откройте окно телеметрии Поиск Application Insights в Visual Studio. Во время отладки выберите раскрывающийся список Application Insights.

Screenshot that shows right-clicking the project and choosing Application Insights.

Щелкните отчет об исключении, чтобы отобразить его трассировку стека. Чтобы открыть соответствующий файл кода, щелкните строку ссылки в трассировке стека.

Если CodeLens включен, вы увидите данные об исключениях.

Screenshot that shows CodeLens notification of exceptions.

Диагностика сбоев с помощью портала Azure

В Application Insights входит курированный интерфейс Application Performance Management, который помогает диагностировать сбои в отслеживаемых приложениях. Чтобы начать, в меню ресурсов Application Insights слева в разделе Исследование выберите параметр Сбои.

Вы увидите тенденции частоты сбоев для ваших запросов, количество сбоев и количество затронутых пользователей. В представлении Общее показаны некоторые из наиболее полезные распределения, относящихся к выбранной операции сбоя. Вы увидите три основных кода отклика на ошибки, три основных типа исключений и три основных типа зависимостей с ошибками.

Screenshot that shows a failures triage view on the Operations tab.

Чтобы ознакомиться с репрезентативными примерами для каждого из этих подмножеств операций, выберите соответствующую ссылку. Например, для диагностики исключений можно выбрать счетчик числа нужных исключений, откроется вкладка сведений о сквозных транзакциях.

Screenshot that shows the End-to-end transaction details tab.

Кроме того, вместо просмотра исключений определенной операции со сбоем вы можете начать с общего представления исключений, перейдя на вкладку Исключения в верхней части страницы. Здесь вы увидите все исключения, собранные для отслеживаемого приложения.

Пользовательская трассировка и данные журналов

Для получения диагностических данных своего приложения вставьте код для отправки собственных данных телеметрии. Ваши данные телеметрии или журналов отображаются в результатах диагностического поиска вместе с запросом, представлением страницы и другими данными, которые собираются автоматически.

При использовании Microsoft.VisualStudio.ApplicationInsights.TelemetryClient у вас имеется несколько доступных API.

  • TelemetryClient.TrackEvent обычно используется для мониторинга шаблонов использования, но отправляемые с его помощью данные также отображаются в разделе пользовательских событий диагностического поиска. У событий есть имена, и они могут содержать строковые свойства и числовые метрики, по которым можно фильтровать результаты поиска диагностических данных.
  • TelemetryClient.TrackTrace позволяет отправлять более длинные данные, например данные POST.
  • TelemetryClient.TrackException отправляет сведения об исключении, такие как трассировки стека, в Application Insights.

Чтобы просмотреть эти события, в меню слева откройте Поиск. Выберите типы событий в раскрывающемся меню, а затем выберите Пользовательское событие, Трассировка или Исключение.

Screenshot that shows the Search screen.

Примечание.

Если приложение генерирует много телеметрических данных, модуль адаптивной выборки автоматически сокращает объем отправляемых на портал данных, пересылая только репрезентативную часть событий. События, составляющие часть той же операции, отбираются как группа, что позволяет перемещаться между связанными событиями. Дополнительные сведения см. в статье Выборка в Application Insights.

См. данные POST запроса

Сведения о запросе не содержат данные, отправляемые в приложение в вызове метода POST. Для внесения этих данных в отчет:

  • Установите пакет SDK в проект своего приложения.
  • Вставьте в свое приложение код для вызова Microsoft.ApplicationInsights.TrackTrace(). Передайте данные POST в параметр сообщения. На допустимый размер есть ограничение, поэтому следует передавать только самые необходимые данные.
  • При исследовании неудачно завершенных запросов найдите связанные трассировки.

Запись исключений и связанных диагностических данных

Сначала вы не увидите на портале все исключения, которые приводят к сбоям в приложении. Вы увидите все исключения браузера, если на веб-страницах используется пакет SDK для JavaScript. Но большинство серверных исключений перехватываются 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 один раз и повторно использовать его в течение всего времени существования приложения.

При наличии внедрения зависимостей (DI) в .NET, соответствующего пакета SDK для .NET и правильной настройки Application Insights для DI вы можете требовать TelemetryClient в качестве параметра конструктора.

public class ExampleController : ApiController
{
    private readonly TelemetryClient _telemetryClient;

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

В предыдущем примере TelemetryClient внедряется в класс ExampleController.

Веб-формы

Для веб-форм модуль HTTP сможет собирать исключения, если в CustomErrors не настроены перенаправления. Однако при наличии активных перенаправлений добавьте в функцию Application_Error в скрипте Global.asax.cs следующие строки.

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

В предыдущем примере _telemetryClient является переменной области класса с типом TelemetryClient.

MVC

Начиная с версии веб-пакета SDK 2.6 (бета-версии 3 и более поздних версий) для Application Insights в службе выполняется сбор необработанных исключений, автоматически созданных в методах контроллеров MVC 5+. Если для отслеживания таких исключений вы ранее добавили настраиваемый обработчик, можно удалить его, чтобы избежать двойного отслеживания исключений.

Существует несколько сценариев, в которых фильтр исключений не может правильно обрабатывать ошибки при возникновении исключений:

  • из конструкторов контроллера;
  • из обработчиков сообщений;
  • во время маршрутизации;
  • во время сериализации содержимого ответа;
  • во время запуска приложения;
  • в фоновых задачах.

Все исключения, которые обрабатывает приложение, по-прежнему должны отслеживаться вручную. Необработанные исключения, исходящие от контроллеров, приводят к ответу 500 — "Внутренняя ошибка сервера". Если такой ответ создан вручную как результат обработки исключения (или при отсутствии исключений), он будет отслеживаться в соответствующей телеметрии запросов с заданным для ResultCode значением 500. Однако пакет SDK Application Insights не может отслеживать соответствующее исключение.

Поддержка предыдущих версий

Примеры отслеживания исключений для MVC 4 (и более ранних версий) веб-пакета SDK 2.5 (и более ранних версий) для Application Insights приведены ниже.

Если для конфигурации 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

Зарегистрируйте AiHandleErrorAttribute в качестве глобального фильтра в Global.asax.cs.

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

Образец

MVC 4, MVC 5

Зарегистрируйте AiHandleErrorAttribute в качестве глобального фильтра в FilterConfig.cs.

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

Образец

Веб-интерфейс API

Начиная с версии веб-пакета SDK 2.6 (бета-версии 3 и более поздних версий) для службы Application Insights в службе выполняется сбор необработанных исключений, автоматически созданных в методах контроллеров для Web API 2+. Если ранее для отслеживания таких исключений вы добавляли настраиваемый обработчик (как указано в приведенных ниже примерах), можете удалить его, чтобы избежать двойного отслеживания исключений.

Существует несколько ситуаций, когда обработка фильтров исключений невозможна. Например:

  • Исключения выброшены из конструкторов контроллеров.
  • Исключения выброшены из обработчиков сообщений.
  • Исключения выброшены при маршрутизации.
  • Исключения выброшены при сериализации содержимого ответа.
  • Исключение, возникшее при запуске приложения.
  • исключение, возникшее в фоновых задачах.

Все исключения, которые обрабатывает приложение, по-прежнему должны отслеживаться вручную. Необработанные исключения, исходящие от контроллеров, приводят к ответу 500 — "Внутренняя ошибка сервера". Если такой ответ создан вручную как результат обработки исключения (или при отсутствии исключений), он будет отслеживаться в соответствующей телеметрии запросов с заданным для ResultCode значением 500. Однако пакет SDK Application Insights не может отслеживать соответствующее исключение.

Поддержка предыдущих версий

Примеры отслеживания исключений для WebAPI 1 (и более ранних версий) веб-пакета SDK 2.5 (и более ранних версий) для Application Insights приведены ниже.

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

Добавьте класс, который расширяет Attribute и реализует IErrorHandler и IServiceBehavior.

    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 подсчитывает число исключений в интервале и делит его на длину интервала.

Это число будет отличаться от значения счетчика Exceptions, вычисленного порталом Application Insights по количеству отчетов TrackException. Интервалы выборки различаются, а пакет SDK не отправляет отчеты TrackException для всех обработанных и необработанных исключений.

Следующие шаги