Diagnostic des exceptions dans les applications web avec Application Insights

Remarque

La documentation suivante s’appuie sur l’API classique d’Application Insights. Le plan à long terme pour Application Insights est de collecter des données en utilisant OpenTelemetry. Pour plus d’informations, consultez la section Activer Azure Monitor OpenTelemetry pour les applications .NET, Node.js, Python et Java.

Les exceptions dans les applications Web peuvent être signalées avec Application Insights. Vous pouvez associer les demandes ayant échoué à des exceptions et à d’autres événements sur le client et le serveur, ce qui vous permet de diagnostiquer rapidement les causes. Dans cet article, vous allez apprendre à configurer la création de rapports d’exceptions, à signaler les exceptions explicitement, à diagnostiquer les échecs et bien plus encore.

Configurer les rapports d’exceptions

Vous pouvez configurer Application Insights pour signaler les exceptions qui se produisent dans le serveur ou le client. Selon la plateforme dont dépend l’application, vous aurez besoin de l’extension ou du Kit de développement logiciel (SDK) approprié.

Côté serveur

Pour que les exceptions soient signalées à partir de votre application côté serveur, tenez compte des scénarios suivants :

Côté client

Le Kit de développement logiciel (SDK) JavaScript offre la possibilité de générer des rapports côté client sur les exceptions qui se produisent dans des navigateurs web. Pour configurer la création de rapports d’exceptions sur le client, consultez Application Insights pour pages web.

Frameworks d’application

Avec certaines infrastructures d’application, une configuration supplémentaire est requise. Considérez les technologies suivantes :

Important

Cet article se concentre spécifiquement sur les applications .NET Framework du point de vue d’un exemple de code. Certaines des méthodes qui fonctionnent pour .NET Framework sont obsolètes dans le kit SDK .NET Core. Pour plus d’informations, consultez la documentation du Kit SDK .NET Core lors de la création d’applications avec .NET Core.

Diagnostic des exceptions à l’aide de Visual Studio

Ouvrez la solution d'application dans Visual Studio. Exécutez l’application sur votre serveur ou sur votre ordinateur de développement à l’aide de la touche F5. Recréez l’exception.

Ouvrez la fenêtre de télémétrie de recherche Application Insights dans Visual Studio. Pendant le débogage, sélectionnez la liste déroulante Application Insights.

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

Sélectionnez un rapport d’exception pour afficher son arborescence des appels de procédure. Pour ouvrir le fichier de code approprié, sélectionnez une référence de ligne dans l’arborescence des appels de procédure.

Si CodeLens est activé, vous verrez des données sur les exceptions :

Screenshot that shows CodeLens notification of exceptions.

Diagnostic des défaillances à l’aide du portail Azure

Application Insights est fourni avec une expérience Application Performance Management organisée pour vous aider à diagnostiquer les échecs dans les applications surveillées. Pour commencer, dans le menu de ressources Application Insights à gauche, sous Examiner, sélectionnez l’option Défaillances.

Vous verrez les tendances du taux de défaillance de vos requêtes, le nombre d’entre elles qui échouent et le nombre d’utilisateurs affectés. La vue globale affiche certaines des distributions les plus utiles spécifiques de l’opération défaillante sélectionnée. Vous verrez les trois principaux codes de réponse, les trois principaux types d’exception et les trois principaux types de dépendances défaillantes.

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

Pour examiner des exemples représentatifs pour chacun de ces sous-ensembles d’opérations, sélectionnez le lien correspondant. À titre d’exemple, pour diagnostiquer les exceptions, vous pouvez sélectionner le nombre d’occurrences d’une exception spécifique à présenter sous l’onglet Détails de la transaction de bout en bout.

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

Sinon, au lieu de rechercher les exceptions relatives à une opération défaillante spécifique, vous pouvez partir de la vue d’ensemble des exceptions, en basculant vers l’onglet Exceptions en haut. Sur cette page, vous pouvez voir toutes les exceptions collectées pour votre application analysée.

Suivi personnalisé et données du journal

Pour obtenir des données de diagnostic propres à votre application, vous pouvez insérer le code pour envoyer vos propres données de télémétrie. Vos données de télémétrie ou de journal personnalisées sont affichées dans la recherche de diagnostic en même temps que la requête, la vue de page et d’autres données collectées automatiquement.

À l’aide de Microsoft.VisualStudio.ApplicationInsights.TelemetryClient, vous avez plusieurs API disponibles :

  • TelemetryClient.TrackEvent sert généralement à surveiller les modèles d’utilisation, mais les données qu’il envoie apparaissent également sous Événements personnalisés dans Recherche de diagnostic. Les événements sont nommés et peuvent contenir des propriétés de type chaîne et des métriques numériques sur lesquels vous pouvez filtrer vos recherches de diagnostic.
  • TelemetryClient.TrackTrace vous permet d’envoyer des données plus longues telles que des informations POST.
  • TelemetryClient.TrackException envoie les détails de l’exception, tels que les arborescences des appels de procédure, à Application Insights.

Pour afficher ces événements, dans le menu de gauche, ouvrez Recherche. Sélectionnez le menu déroulant Types d’événements, puis choisissez Événement personnalisé, Trace ou Exception.

Screenshot that shows the Search screen.

Remarque

Si votre application génère un volume important de télémétrie, le module d’échantillonnage adaptatif réduit automatiquement le volume qui est envoyé au portail en envoyant uniquement une fraction représentative des événements. Les événements qui font partie de la même opération seront activés ou désactivés en tant que groupe, afin que vous puissiez naviguer entre des événements connexes. Pour plus d’informations, consultez l’article Échantillonnage dans Application Insights.

Afficher les données POST de requête

Les détails de la demande n'incluent pas les données envoyées à votre application dans un appel POST. Pour que ces données soient signalées :

  • Installez le SDK dans votre projet d’application.
  • Insérez du code dans votre application pour appeler Microsoft.ApplicationInsights.TrackTrace(). Envoyez les données POST dans le paramètre du message. Étant donné qu’il existe une limite à la taille autorisée, vous deviez essayer de n’envoyer que les données essentielles.
  • Lorsque vous examinez une demande ayant échoué, recherchez les traces associées.

Capturer les exceptions et les données de diagnostic connexes

Dans un premier temps, vous ne verrez pas dans le portail toutes les exceptions qui entraînent des défaillances dans votre application. Vous verrez les exceptions du navigateur si vous utilisez le SDK JavaScript dans vos pages web. Mais la plupart des exceptions de serveur sont interceptées par IIS et vous devez écrire un peu de code afin de les afficher.

Vous pouvez :

  • Enregistrer explicitement des exceptions en insérant le code dans les gestionnaires d'exceptions pour signaler ces exceptions.
  • Capturer automatiquement des exceptions en configurant votre infrastructure ASP.NET. Les ajouts nécessaires sont différents selon les différents types d’infrastructure.

Signaler explicitement des exceptions

La façon la plus simple de signaler consiste à insérer un appel à trackException() dans un gestionnaire d’exceptions.

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

Les paramètres de propriétés et de mesures sont facultatifs, mais sont utiles pour filtrer et ajouter des informations supplémentaires. Par exemple, si vous avez une application qui peut exécuter plusieurs jeux, vous pouvez rechercher tous les rapports d'exception liés à un jeu particulier. Vous pouvez ajouter autant d’éléments que vous le souhaitez à chaque dictionnaire.

Exceptions du navigateur

La plupart des exceptions de navigateur sont signalées.

Si votre page web inclut des fichiers de script à partir de réseaux de distribution de contenu ou d’autres domaines, vérifiez que votre balise de script possède l’attribut crossorigin="anonymous"et que le serveur envoie des en-têtes CORS. Ce comportement vous permettra d’obtenir une arborescence des appels de procédure et les détails des exceptions JavaScript non gérées à partir de ces ressources.

Réutiliser votre client de télémétrie

Notes

Nous vous recommandons d’instancier le TelemetryClient une fois, et de le réutiliser tout au long de la vie d’une application.

Avec l'injection de dépendances (DI) dans .NET, le kit de développement logiciel (SDK) .NET approprié et la configuration correcte d’Application Insights pour l’injection de dépendance, vous pouvez exiger le TelemetryClient comme paramètre de constructeur.

public class ExampleController : ApiController
{
    private readonly TelemetryClient _telemetryClient;

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

Dans l’exemple précédent, TelemetryClient est injecté dans la classe ExampleController.

Formulaires web

Pour les formulaires web, le module HTTP pourra collecter les exceptions si aucune redirection n’est configurée avec CustomErrors. Cependant, quand vous avez des redirections actives, ajoutez les lignes suivantes à la fonction Application_Error dans Global.asax.cs.

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

Dans l’exemple précédent, _telemetryClient est une variable de portée de classe de type TelemetryClient.

MVC

À partir de la version 2.6 (version bêta 3 et versions ultérieures) du Kit de développement logiciel (SDK) web d’Application Insights, Application Insights collecte automatiquement les exceptions non prises en charge qui sont levées dans les méthodes des contrôleurs MVC 5+. Si vous avez déjà ajouté un gestionnaire personnalisé pour suivre ces exceptions, vous pouvez le supprimer afin d’éviter un double suivi.

Il existe plusieurs scénarios dans lesquels un filtre d’exception ne peut pas gérer correctement les erreurs quand des exceptions sont levées :

  • À partir de constructeurs de contrôleur.
  • À partir de gestionnaires de messages.
  • Lors du routage.
  • Lors de la sérialisation du contenu de la réponse.
  • Lors du démarrage de l’application.
  • Dans des tâches en arrière-plan.

Toutes les exceptions prises en charge par l’application doivent toujours faire l’objet d’un suivi manuel. Les exceptions non prises en charge provenant de contrôleurs aboutissent généralement à une réponse « Erreur interne du serveur » 500. Si cette réponse est construite manuellement à la suite d’une exception prise en charge (ou d’aucune exception), elle est suivie dans la télémétrie de la demande correspondante avec le ResultCode 500. Toutefois, le Kit de développement logiciel (SDK) Application Insights n’est pas en mesure de suivre l’exception associée.

Prise en charge des versions antérieures

Si vous utilisez MVC 4 (ou une version antérieure) du Kit SDK web 2.5 d’Application Insights (ou une version antérieure), référez-vous aux exemples suivants pour effectuer le suivi des exceptions.

Si la configuration de CustomErrors est Off, les exceptions seront alors disponibles pour être collectées par le module HTTP. Toutefois, si elle est RemoteOnly (valeur par défaut), ou On, l’exception ne sera alors pas disponible pour être collectée automatiquement par Application Insights. Vous pouvez corriger ce comportement en remplaçant la classe System.Web.Mvc.HandleErrorAttribute et en appliquant la classe remplacée comme indiqué pour les différentes versions MVC ici (source 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

Remplacez l’attribut HandleError par votre nouvel attribut dans vos contrôleurs :

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

Exemple

MVC 3

Enregistrez AiHandleErrorAttribute en tant que filtre global dans Global.asax.cs :

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

Exemple

MVC 4, MVC 5

Enregistrez AiHandleErrorAttribute en tant que filtre global dans Global.asax.cs :

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

Exemple

API Web

À partir de la version 2.6 (bêta 3 et versions ultérieures) du Kit de développement logiciel (SDK) web d’Application Insights, Application Insights collecte automatiquement les exceptions non prises en charge qui sont levées dans les méthodes de contrôleurs pour l’API Web 2+. Si vous avez déjà ajouté un gestionnaire personnalisé pour suivre ces exceptions, comme décrit dans les exemples suivants, vous pouvez le supprimer afin d’éviter un double suivi.

Il existe des cas que les filtres d’exception ne peuvent pas gérer. Par exemple :

  • Les exceptions lancées à partir des constructeurs de contrôleur.
  • Les exceptions lancées à partir des gestionnaires de messages.
  • Les exceptions lancées pendant le routage.
  • Les exceptions lancées pendant la sérialisation du contenu de réponse.
  • Exception levée lors du démarrage d’application.
  • Exception levée dans les tâches en arrière-plan.

Toutes les exceptions prises en charge par l’application doivent toujours faire l’objet d’un suivi manuel. Les exceptions non prises en charge provenant de contrôleurs aboutissent généralement à une réponse « Erreur interne du serveur » 500. Si une telle réponse est construite manuellement à la suite d’une exception prise en charge (ou d’aucune exception), elle est suivie dans la télémétrie de la demande correspondante avec le ResultCode 500. Toutefois, le Kit de développement logiciel (SDK) Application Insights n’est pas en mesure de suivre une exception associée.

Prise en charge des versions antérieures

Si vous utilisez l’API Web 1 (ou une version antérieure) du Kit SDK web 2.5 d’Application Insights (ou une version antérieure), référez-vous aux exemples suivants pour effectuer le suivi des exceptions.

API Web 1.x

Écrasez 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);
    }
    }
}

Vous pouvez ajouter cet attribut remplacé à des contrôleurs spécifiques ou l’ajouter à la configuration du filtre global dans la classe 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());
        }
    }
}

Exemple

API Web 2.x

Ajoutez une implémentation de 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);
        }
    }
}

Ajoutez cet extrait de code aux services dans 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());
        }
    }
}

Exemple

Alternativement, vous pouvez :

  • Remplacez la seule instance ExceptionHandler par une implémentation personnalisée de IExceptionHandler. Ce gestionnaire d’exceptions est appelé uniquement lorsque l’infrastructure est toujours en mesure de choisir le message de réponse à envoyer, mais pas quand la connexion est abandonnée, par exemple.
  • Utilisez des filtres d’exception, comme décrit dans la section précédente sur les contrôleurs de l’API Web 1.x, qui ne sont pas appelés dans tous les cas.

WCF

Ajoutez une classe qui étend Attribute et implémente IErrorHandler et 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)
        {
        }
      }
    }

Ajoutez l'attribut aux implémentations de service :

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

Exemple

Compteurs de performance des exceptions

Si vous avez installé l’agent Application Insights d’Azure Monitor sur votre serveur, vous pouvez obtenir un graphique du taux d’exceptions, mesuré par .NET. Les exceptions .NET gérées et non gérées sont incluses.

Ouvrez un onglet d’explorateur de métriques et ajoutez un nouveau graphique. Sous Compteurs de performances, sélectionnez Taux d’exception.

Le .NET Framework calcule le taux en comptant le nombre d’exceptions sur un intervalle et en divisant ce nombre par la longueur de l’intervalle.

Ce nombre sera différent du nombre d’« exceptions » calculé par le portail Application Insights, qui est basé sur les rapports TrackException. Les intervalles d’échantillonnage sont différents et le Kit de développement logiciel (SDK) n’envoie pas de rapports TrackException pour toutes les exceptions gérées et non gérées.

Étapes suivantes