Диагностика исключений в веб-приложениях с помощью Application Insights
Примечание.
В следующей документации используется классический API Application Insights. Долгосрочный план Application Insights — сбор данных с помощью OpenTelemetry. Дополнительные сведения см. в статье "Включение Azure Monitor OpenTelemetry для .NET", Node.js, приложений Python и Java и нашей стратегии OpenTelemetry. Рекомендации по миграции доступны для .NET, Node.js и Python.
Исключения в веб-приложениях можно получить с помощью Application Insights. Для быстрого выявления причин неполадок можно сопоставлять неудачно завершенные запросы с исключениями и другими событиями на клиенте и на сервере. В этой статье вы узнаете, как настраивать отчеты об исключениях, сообщать об исключениях явным образом, диагностировать сбои и многое другое.
Настройка создания отчетов об исключениях
Вы можете настроить Application Insights для создания отчетов об исключениях, происходящих либо на сервере, либо на клиенте. В зависимости от платформы вашего приложения вам потребуется соответствующее расширение или пакет SDK.
На стороне сервера
Рассмотрите следующие сценарии для получения отчета об исключениях из приложения на стороне сервера:
- Добавьте веб-приложения расширение Application Insights для Azure.
- Добавьте расширение мониторинга приложений для виртуальных машин Azure и приложений масштабируемых наборов виртуальных машин Azure, размещенные в службах IIS.
- Установите пакет SDK Application Insights в коде приложения, запустите агент Application Insights для веб-серверов IIS или включите агент Java для веб-приложений Java.
На стороне клиента
Пакет 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.
Щелкните отчет об исключении, чтобы отобразить его трассировку стека. Чтобы открыть соответствующий файл кода, щелкните строку ссылки в трассировке стека.
Если CodeLens включен, вы увидите данные об исключениях.
Диагностика сбоев с помощью портала Azure
В Application Insights входит курированный интерфейс Application Performance Management, который помогает диагностировать сбои в отслеживаемых приложениях. Чтобы начать, в меню ресурсов Application Insights слева в разделе Исследование выберите параметр Сбои.
Вы увидите тенденции частоты сбоев для ваших запросов, количество сбоев и количество затронутых пользователей. В представлении Общее показаны некоторые из наиболее полезные распределения, относящихся к выбранной операции сбоя. Вы увидите три основных кода отклика на ошибки, три основных типа исключений и три основных типа зависимостей с ошибками.
Чтобы ознакомиться с репрезентативными примерами для каждого из этих подмножеств операций, выберите соответствующую ссылку. Например, для диагностики исключений можно выбрать счетчик числа нужных исключений, откроется вкладка сведений о сквозных транзакциях.
Кроме того, вместо просмотра исключений определенной операции со сбоем вы можете начать с общего представления исключений, перейдя на вкладку Исключения в верхней части страницы. Здесь вы увидите все исключения, собранные для отслеживаемого приложения.
Пользовательская трассировка и данные журналов
Для получения диагностических данных своего приложения вставьте код для отправки собственных данных телеметрии. Ваши данные телеметрии или журналов отображаются в результатах диагностического поиска вместе с запросом, представлением страницы и другими данными, которые собираются автоматически.
При использовании Microsoft.VisualStudio.ApplicationInsights.TelemetryClient у вас имеется несколько доступных API.
- TelemetryClient.TrackEvent обычно используется для мониторинга шаблонов использования, но отправляемые с его помощью данные также отображаются в разделе пользовательских событий диагностического поиска. У событий есть имена, и они могут содержать строковые свойства и числовые метрики, по которым можно фильтровать результаты поиска диагностических данных.
- TelemetryClient.TrackTrace позволяет отправлять более длинные данные, например данные POST.
- TelemetryClient.TrackException отправляет сведения об исключении, такие как трассировки стека, в Application Insights.
Чтобы просмотреть эти события, в меню слева откройте Поиск. Выберите типы событий в раскрывающемся меню, а затем выберите Пользовательское событие, Трассировка или Исключение.
Примечание.
Если приложение генерирует много телеметрических данных, модуль адаптивной выборки автоматически сокращает объем отправляемых на портал данных, пересылая только репрезентативную часть событий. События, составляющие часть той же операции, отбираются как группа, что позволяет перемещаться между связанными событиями. Дополнительные сведения см. в статье Выборка в 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
для всех обработанных и необработанных исключений.