Partager via


Diagnostics des nuages

Contrôler la journalisation et le suivi dans Windows Azure

Mike Kelly

Télécharger l'exemple de code

À l'instar de nombreux programmeurs, j'utilisais les instructions print pour le débogage lorsque j'ai commencé à écrire du code. J'ignorais comment utiliser un débogueur et les instructions print étaient un moyen rudimentaire mais efficace de voir ce que faisait mon programme lors de son exécution. J'ai ensuite appris à utiliser un véritable débogueur et j'ai cessé de me servir des instructions print comme outil de débogage.

Venons-en à l'époque où j'ai commencé à écrire du code exécuté sur les serveurs. J'ai découvert que ces instructions print entraient désormais dans la catégorie plus sophistiquée de la « journalisation et du suivi », des techniques essentielles pour tout programmeur d'application serveur.

Même si vous parvenez à attacher un débogueur à une application serveur de production, ce qui est souvent impossible en raison des restrictions de sécurité sur les machines qui hébergent l'application, les types de problèmes rencontrés par les applications serveur ne sont pas révélés aisément avec les débogueurs traditionnels. De nombreuses applications serveur sont distribuées et exécutées sur plusieurs machines. C'est pourquoi le débogage de ce qui se passe sur une machine ne suffit pas toujours à diagnostiquer les problèmes réels.

De plus, les applications serveurs sont souvent exécutées sous le contrôle du personnel d'exploitation qui ignore comment utiliser un débogueur traditionnel. Et il n'est ni souhaitable, ni pratique de faire appel à un développeur pour chaque problème rencontré.

Dans cet article, je vous expliquerai des techniques de journalisation, de suivi et de débogage de base utilisées pour les applications serveur. J'explorerai ensuite la façon dont ces techniques peuvent être utilisées pour vos projets Windows Azure. Chemin faisant, vous découvrirez comment la journalisation et le suivi sont utilisés avec certaines applications réelles et je vous montrerai comment utiliser Windows PowerShell pour gérer les diagnostics d'un service exécuté.

Une stratégie de journalisation

Idéalement, une stratégie de journalisation et de suivi est conçue dès le départ pour toute application serveur, et à peu près toute application Web (y compris celles exécutées sous Windows Azure). Les informations de journalisation doivent être suffisamment solides pour décrire presque tout ce qui se produit dans chaque composant. Cependant, la journalisation peut générer beaucoup de sorties, au même titre que ces instructions print que j'ajoutais à mes tout premiers programmes. Une journalisation et un suivi bien conçus comprennent donc des méthodes permettant d'ajuster le type et le volume de journalisation provenant de n'importe quel composant. Cela permet au personnel d'exploitation et aux développeurs de se concentrer sur un composant qui présente un comportement incorrect, peut-être même sur une machine particulière, afin d'obtenir beaucoup plus d'informations sur ce qui se passe exactement à l'intérieur, sans générer dans le journal un bruit trop important qui risquerait d'être distrayant, voire de ralentir l'application de façon significative.

De plus, dans la mesure où les applications serveur sont couramment distribuées, les informations doivent être recueillies et regroupées à partir de plusieurs machines (peut-être dans des rôles d'application différents) pour obtenir une image complète de ce qui se passait au moment où un problème donné s'est produit. Il est donc important de disposer d'une façon d'identifier un thread de transaction dans les machines car cela permet le regroupement après les faits.

La journalisation disponible dans Windows Azure a évolué au fil des versions CTP (Community Technology Preview). La première technique de journalisation n'était guère plus sophistiquée qu'une instruction print, capturée sous forme de texte dans le stockage par table de Windows Azure. En commençant par la version PDC09, Windows Azure s'est mis à offrir une infrastructure de journalisation et de suivi plus complète en matière de fonctionnalités, reposant sur la plateforme de suivi d'événements Windows (ETW).

Cette plateforme ETW est prise en charge dans ASP.NET via les classes de l'espace de noms System.Diagnostics. L'espace de noms Microsoft.WindowsAzure.Diagnostics, qui hérite des classes standard System.Diagnostics et les développe, permet l'utilisation de System.Diagnostics comme plateforme de journalisation dans l'environnement Windows Azure. La figure 1 illustre la façon dont ETW est implémentée par Windows Azure Diagnostics.

Figure 1 High-Level Overview of Windows Azure Diagnostics
Figure 1 Vue d'ensemble de haut niveau de Windows Azure Diagnostics

ETW fournit un modèle dans lequel le code est journalisé dans une ou plusieurs sources TraceSource. Le niveau de journalisation autorisé dans chaque source est contrôlé par un commutateur SourceSwitch. Les sources sont à leur tour connectées à un ou plusieurs consommateurs qui conservent les informations de journalisation de plusieurs façons.

Windows Azure fournit un consommateur ou un écouteur standard pour conserver les informations de journalisation que vous générez soit dans le stockage par table Windows Azure, soit dans le stockage BLOB. Vous pouvez également écrire votre propre consommateur si vous souhaitez faire quelque chose de différent avec les données d'événement ou utiliser un consommateur disponible dans le commerce (bien que certains aient besoin d'être modifiés dans l'environnement Windows Azure).

La plateforme ETW associe un type TraceEventType à chaque événement, comme illustré à la figure 2. Les cinq premières lignes de gravité sont les valeurs les plus couramment utilisées et elles indiquent l'importance relative de la sortie de suivi. Notez que les types Suspend, Resume et Transfer sont utilisés par la fondation WCF (Windows Communication Foundation).

Figure 2 Types d'événement de suivi

TraceEventType Valeur Signification
Critical 0x0001 Erreur irrécupérable ou panne d'application
Error 0x0002 Erreur récupérable
Warning 0x0004 Problème non-critique, peut indiquer des problèmes futurs plus sérieux
Information 0x0008 Message d'informations
Verbose 0x0010 Suivi de débogage (par exemple, des informations détaillées sur le flux d'exécution, des paramètres, etc.)
Start 0x0100 Démarrage d'une opération logique
Stop 0x0200 Arrêt d'une opération logique
Suspend 0x0400 Suspension d'une opération logique
Resume 0x0800 Reprise d'une opération logique
Transfer 0x1000 Transfert vers une nouvelle activité

Si vous recherchez uniquement les très mauvaises choses, veillez à capturer les valeurs de type Critical, et probablement Error. Si vous souhaitez obtenir de nombreuses informations sur ce qui se passe, recherchez tout ce qui est au-dessus de Verbose.

Votre stratégie de journalisation doit inclure une utilisation cohérente du type d'événement et une multitude d'entrées de journalisation avec les valeurs situées plus bas dans la hiérarchie. Il devrait être possible de suivre virtuellement le flux d'exécution de votre application si la journalisation de toutes les valeurs en surbrillance est activée dans votre application. Cette fonctionnalité peut s'avérer précieuse pour dépanner une erreur ou un problème au niveau de la production.

Vous pouvez raccorder des écouteurs, les sources et les commutateurs pour activer différents niveaux de sortie par programme, mais cette opération est généralement effectuée via les fichiers de configuration. Vous pouvez configurer la sortie dans app.config (pour les rôles worker de Windows Azure) ou dans web.config (pour les rôles Web de Windows Azure). Cependant, comme je l'expliquerai plus loin dans cet article, le fait d'intégrer cela dans ServiceConfiguration.cscfg vous permet d'ajuster les options de journalisation et de suivi pendant l'exécution du service Windows Azure sans avoir à redéployer les mises à jour du code exécuté, ni même à arrêter le service. Windows Azure expose également une interface RESTful afin de permettre le contrôle de certaines options de journalisation à distance. Windows PowerShell peut se servir de l'interface RESTful.

Journalisation, suivi et sortie de débogage

Les termes journalisation, suivi et sortie de débogage peuvent parfois être utilisés indifféremment. Dans cet article, je ferai la distinction entre quatre types différents de ce qui peut généralement être nommé diagnosticoutput dans votre code. Ils sont grossièrement classés du plus bavard au moins bavard.

  • Sortie de débogage : ce sont les informations qui apparaissent uniquement dans les versions de débogage de votre application et qui sont exclues des versions de publication lors de la compilation (tout dépend si le symbole du préprocesseur DEBUG a été défini lors de la compilation, ce que Visual Studio ne fait que dans les versions de débogage par défaut). En règle générale, la sortie de débogage inclut par exemple des affirmations que vous ajoutez afin de faciliter la recherche de cas où le code ne respecte pas les préconditions spécifiées, créant ainsi des bogues, voire des vidages de structures de données. Ces ajouts vous permettent de déboguer des algorithmes lors du débogage et du test.
  • Suivi : il s'agit des instructions destinées à faciliter le suivi du flux de contrôle et d'état du programme au cours de son exécution. Imaginez que vous exécutez un débogueur, que vous examinez le code et que vous vérifiez les valeurs des variables clés dans la fenêtre Espion. Les instructions de suivi permettent de répliquer cette expérience dans les situations où il est impossible de raccorder un débogueur. Idéalement, elles offrent suffisamment de contexte pour que vous puissiez voir le chemin choisi à chaque point de contrôle de l'application et suivre en quelque sorte le code grâce à la lecture des instructions de suivi. Le suivi est activé lorsque le symbole de préprocesseur TRACE est défini au moment de la compilation et il peut se trouver à la fois dans les versions de publication et de débogage. Par défaut, Visual Studio définit TRACE dans les versions de débogage et de publication, mais vous pouvez bien évidemment modifier ce paramètre.
  • Journalisation des événements : ces instructions permettent de capturer les événements principaux pendant l'exécution de l'application, par exemple, le début d'une transaction ou l'ajout d'un élément dans une base de données. La journalisation des événements diffère du suivi en ce sens qu'elle capture les états principaux au lieu du flux de contrôle détaillé.
  • Journalisation des erreurs : il s'agit de cas spéciaux de journalisation des événements au cours desquels vous capturez des situations exceptionnelles ou potentiellement dangereuses. Parmi les exemples de ces situations, citons notamment toute exception interceptée, les cas où il est impossible d'accéder à une ressource sur un autre ordinateur auquel vous devriez pouvoir accéder (ce que votre application gérera bien évidemment avec grâce, mais qu'il est important de noter), et les cas où les erreurs reviennent des API alors que vous n'en attendez aucune.

La journalisation des erreurs peut également être utile au personnel d'exploitation dans les cas il n'y a pas encore de problèmes, mais que certaines choses indiquent qu'il y en aura bientôt, par exemple un quota qui approche de son maximum ou une transaction réussie, mais plus longue que d'habitude. Ces types d'événements de journalisation peuvent aider le personnel d'exploitation à traiter les problèmes de façon proactive avant qu'ils ne se produisent et éviter ainsi les interruptions de l'application.

La plupart des bons développeurs se sont habitués à inclure la sortie de débogage dans leur application pour les aider à diagnostiquer les problèmes pendant le développement et nombre d'entre eux ont développé une solution plus ou moins approximative pour la journalisation des erreurs.

Cependant, vous devez veiller à ne pas tenir compte uniquement des options de sortie de débogage et de journalisation des erreurs, mais également avoir une stratégie solide de suivi et de journalisation des événements, ce qui peut véritablement faciliter le diagnostic des problèmes qui se produisent uniquement en cas de chargements lourds dans les environnements de production.

De plus, réfléchissez attentivement à ce que vous considérez aujourd'hui majoritairement comme sortie de débogage afin de voir si cela ne devrait pas plutôt être du suivi et disponible dans les versions de publication et de débogage. Une application au comportement indésirable au stade de production exécutera généralement la version de publication. Si les instructions de suivi sont présentes mais désactivées (j'expliquerai plus loin comment procéder), vous pouvez les activer de manière sélective afin d'obtenir une sortie très riche similaire au débogage à partir de la version de publication, ce qui facilite le diagnostic des problèmes.

Suivi et journalisation dans Windows Azure

Vous pouvez utiliser la journalisation Windows Azure directement puisqu'elle fait partie de Windows Azure SDK. Il y a des avantages à utiliser une plateforme de journalisation telle que Logger.NET, Enterprise Library, log4net ou Ukadc.Diagnostics. Celles-ci ajoutent une structure aux messages de journalisation et permettent également d'apporter une partie de la configurabilité mentionnée précédemment. Cependant, la plupart d'entre elles n'ont pas été modifiées afin de permettre leur fonctionnement dans l'environnement Windows Azure et certaines sont bien plus qu'une simple plateforme de journalisation.

En ce qui concerne l'exemple de code présenté dans cet article, j'ai décidé d'utiliser uniquement les API standard de journalisation et de suivi de Windows Azure avec une mince couche au-dessus, afin d'offrir une configuration dynamique. Vous trouverez probablement qu'il est également utile de créer des classes d'assistance et une plateforme pour votre stratégie de journalisation et de suivi ou de demander aux autres plateformes de fournir les versions Windows Azure.

Lorsque vous créez un nouveau service dans Windows Azure à l'aide de Visual Studio, il est déjà activé pour la journalisation de base. L'écouteur de diagnostics est déjà configuré et activé dans le code standard de rôle worker et de rôle Web généré par les modèles de Windows Azure.

Pour activer la journalisation simple dans un service Windows Azure, commencez un nouveau projet dans Visual Studio à l'aide du module Windows Azure Cloud Service (Visual C#). Nommez le projet. Pour mon exemple, j'ai utilisé MSDNSampleLoggingService. Cliquez sur OK.

L'Assistant New Cloud Service Project sera exécuté. Dans l'Assistant, ajoutez un rôle worker et un rôle Web au projet. Remplacez le nom du rôle worker par LoggingWorkerRole et celui du rôle Web par LoggingWebRole, puis cliquez sur OK. Visual Studio crée alors le projet.

À ce stade, vous pouvez explorer le code généré. Observez le fichier app.config du projet LoggingWorkerRole et notez que le code suivant apparaît :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace autoflush="false" indentsize="4">
      <listeners>
        <add name="AzureDiagnostics" type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Mi-crosoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

Il permet de raccorder l'écouteur de diagnostics standard de Windows Azure à votre code, ce qui signifie que toute journalisation et tout suivi effectués à partir du rôle worker seront dirigés vers l'écouteur de Windows Azure (DiagnosticMonitorTraceListener), à moins que vous ne changiez ce fonctionnement. Vous trouverez une entrée similaire dans web.config pour le rôle Web créé pour ce service.

Si vous observez le fichier WorkerRole.cs dans le projet du rôle worker, vous verrez également la ligne suivante dans la méthode OnStart :

DiagnosticMonitor.Start("DiagnosticsConnectionString");

Puis, dans la méthode Run, vous verrez un appel de suivi :

// This is a sample worker implementation. Replace with your logic.
Trace.WriteLine("LoggingWorkerRole entry point called", "Information");

En dernier lieu, si vous observez le fichier ServiceConfiguration.cscfg dans la racine Service, vous verrez la ligne suivante pour le rôle worker et le rôle Web :

<Setting name="DiagnosticsConnectionString" 
         value="UseDevelopmentStorage=true" />

Ce code indique à l'écouteur de Windows Azure quel compte de stockage utiliser pour conserver les informations de journalisation et de suivi. Dans ce cas, les informations de journalisation seront stockées dans le stockage de développement sur votre ordinateur local. En faisant passer cela dans un compte de stockage nuage Windows Azure, les journaux peuvent aller dans le stockage nuage. Voici un exemple du format associé provenant de l'exemple de code fourni avec cet article :

<Setting name="DiagnosticsConnectionString" 
  value="DefaultEndpointsProtocol=https;AccountName=Xxxxxx;AccountKey=Yyyyyy" />

Les valeurs AccountName et AccountKey doivent être personnalisées en fonction de vos compte et clé Azure. Vous obtenez ces informations auprès du portail de compte de stockage de votre service sur windows.azure.com. AccountName correspond à la première partie de l'URL pour les points de terminaison de stockage par table et BLOB (il s'agit de la partie précédant « .table.core.windows.net »). AccountKey correspond à la clé d'accès principale codée base64 pour votre compte de stockage.

Notez que dans la mesure où un compte de stockage distinct est utilisé pour les diagnostics, vous pouvez choisir de stocker vos informations de diagnostics à un emplacement différent de celui des autres données de l'application. Pour cela, définissez un compte de stockage distinct en cliquant sur New Service dans la page de portail, en sélectionnant Storage Account, puis en nommant le compte (MesJournauxApp, par exemple). Vous pouvez définir un groupe d'affinité pour que le stockage de vos journaux se trouve dans la même zone que votre service.

Maintenant que vous avez lu cette présentation rapide du code de suivi dans les services Windows Azure, vous pouvez exécuter le projet simple de rôle Web que vous avez créé. Notez que l'écouteur par défaut fourni par Windows Azure dirige également la sortie dans la fenêtre de sortie de Visual Studio pour les versions de débogage. Vous verrez donc le message OnStart apparaître dans la fenêtre de débogage :

Information: LoggingWorkerRole entry point called

Que se passe-t-il si vous souhaitez consulter les journaux après l'exécution du service ? Par défaut, Windows Azure ne conserve pas les journaux dans un emplacement de stockage. Vous pouvez cependant lui demander de le faire en ajoutant quelques lignes de code à la méthode OnStart de votre rôle :

TimeSpan tsOneMinute = TimeSpan.FromMinutes(1);
DiagnosticMonitorConfiguration dmc =
DiagnosticMonitor.GetDefaultInitialConfiguration();

// Transfer logs to storage every minute
dmc.Logs.ScheduledTransferPeriod = tsOneMinute;
// Transfer verbose, critical, etc. logs
dmc.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;    
// Start up the diagnostic manager with the given configuration
DiagnosticMonitor.Start("DiagnosticsConnectionString", dmc);

Si vous ajoutez ce code à WorkerRole.cs et que vous réexécutez, Windows Azure transfère les journaux vers le stockage de développement toutes les minutes. Vous pouvez également choisir d'effectuer un transfert des journaux à la demande (pour plus d'informations sur la façon de procéder, voir le code disponible dans admin.aspx.cs dans mon exemple d'application) ou utiliser les commandes Windows PowerShell décrites plus loin dans cet article. N'oubliez pas qu'une fois que les journaux ont été transférés dans l'emplacement de stockage, vous êtes facturé pour l'espace de stockage correspondant et qu'il vous incombe de supprimer les informations lorsqu'elles ne vous sont plus nécessaires.

Une fois que les journaux se trouvent dans le stockage de Windows Azure, vous avez besoin d'un outil pour consulter les tables de stockage et avoir accès aux journaux. Pour ma part, j'ai utilisé Cloud Storage Studio proposé par Cerebrata (cerebrata.com). Depuis, Cerebrata a conçu un outil nommé Azure Diagnostics Manager et des outils gratuits sont également disponibles sur CodePlex (codeplex.com) pour permettre la consultation du stockage nuage et des diagnostics. Les journaux sont mis dans une table nommée WADLogsTable, que vous pouvez observer à la figure 3.

Figure 3 Logs Persisted in Development Storage
Figure 3 Journaux conservés dans le stockage de développement

Vous remarquerez deux points en observant les journaux du stockage. Tout d'abord, Windows Azure associe automatiquement des informations à chaque événement consigné : un horodatage, un nombre de cycles (qui fournit une évaluation du temps plus détaillée avec une précision de 100 nanosecondes) et des informations sur le déploiement, le rôle et l'instance de rôle. Cela vous permet, si vous le souhaitez, de limiter les journaux à des instances particulières.

Deuxièmement, un niveau et un eventId sont associés à chaque événement. Le niveau correspond aux valeurs de la figure 2. Les événements de suivi consignés comme informations auront une valeur de niveau égale à 4, tandis que les événements consignés comme erreur auront un niveau égal à 2. Les événements génériques envoyés via Trace.WriteLine (comme le fait le code standard) auront un niveau de 5 (Verbose).

L'EventId est une valeur que vous spécifiez. L'appel de base Trace.WriteLine présenté plus tôt ne vous permet pas de la spécifier. Vous devez utiliser d'autres méthodes Trace pour passer l'EventId.

Activation du suivi et de la journalisation de façon sélective

Une application type est composée de plusieurs composants logiques. Par exemple, vous pouvez avoir un composant de base de données qui gère le modèle de données dans le stockage de Windows Azure. Votre rôle Web peut à son tour être divisé en un composant administratif et un composant utilisateur (qui peuvent même être encore divisés en composants logiques selon les besoins de votre application).

Vous pouvez lier les options de journalisation et de suivi (le type de journalisation activé et le niveau de détail correspondant) à ces composants. Cela vous permet d'activer le suivi de façon sélective uniquement dans les composants pour lesquels vous en avez besoin et d'éviter ainsi beaucoup d'encombrements.

La meilleure solution ici consiste à ne pas appeler Trace directement, mais à utiliser plusieurs instances TraceSource, généralement une par espace de noms. Une source TraceSource est associée à un commutateur SourceSwitch qui vérifie si la source est activée, ainsi que le niveau de sortie souhaité. Il est important de noter que les valeurs SourceSwitch ne sont pas définies lors de la compilation, mais de l'exécution. Vous pouvez donc activer ou désactiver la sortie de diagnostics à partir de différentes parties de votre application sans avoir à la recompiler, ni même à redéployer une version différente.

WorkerDiagnostics.cs et WebDiagnostics.cs contiennent la configuration des sources et des commutateurs de suivi dans l'exemple de code. Voici un extrait :

// Trace sources
public TraceSource ConfigTrace;
public TraceSource WorkerTrace;
// Add additional sources here

// Corresponding trace switches to control 
// level of output for each source
public SourceSwitch ConfigTraceSwitch { get; set; }
public SourceSwitch WorkerTraceSwitch { get; set; }
// Add additional switches 1:1 with trace sources here

Ensuite, dans le fichier de configuration de votre rôle, vous les raccordez aux écouteurs, comme illustré à la figure 4. L'écouteur de diagnostics standard de Windows Azure est d'abord défini comme écouteur partagé afin de pouvoir y faire référence dans les éléments <sources>. Deux sources sont ensuite configurées : une source WorkerTrace et une source ConfigTrace. Les commutateurs correspondants sont également définis afin de vous permettre d'ajuster le niveau de sortie. ConfigTrace donne la sortie la plus bavarde, tandis que WorkerTrace donne uniquement les erreurs.

Figure 4 Configuration des sources de suivi et des écouteurs

<configuration>
  <system.diagnostics>
    <sharedListeners>
      <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        name="AzureDiagnostics">
        <filter type="" />
      </add>
    </sharedListeners>
    <sources>
      <source name="ConfigTrace">
        <listeners>
          <add name="AzureDiagnostics" />
        </listeners>
      </source>
      <source name="WorkerTrace">
        <listeners>
          <add name="AzureDiagnostics" />
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="ConfigTrace" value="Verbose"/>
      <add name="WorkerTrace" value="Error"/>
    </switches>
    <trace>
      <listeners>
        <add name="AzureDiagnostics" />
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

Les commutateurs ne doivent pas nécessairement porter le même nom que les sources, mais cela vous facilitera la vie. Si vous optez pour deux noms différents, vous devez ajouter un attribut switchName à l'élément source pour indiquer le nom du commutateur qui contrôle la sortie de cette source. Cela vous permet de partager un seul commutateur entre plusieurs sources de suivi. Notez que le nom de la source de suivi et du commutateur est sensible à la casse et qu'il doit correspondre exactement à la casse passée dans le constructeur de votre code.

Si vous le souhaitez, vous pouvez éviter totalement le commutateur en ajoutant simplement un attribut switchValue à l'élément source, sans oublier d'indiquer la valeur de commutateur souhaitée pour cette source. Les valeurs de commutateur que vous utilisez sont en fait analysées à partir du fichier de configuration comme l'un des niveaux SourceLevel définis à la figure 5, qui indique également comment le type TraceEventType que vous passez aux appels TraceSource interagit avec le niveau SourceLevel défini pour la source afin de déterminer ce qui passe.

Figure 5 Suivi des niveaux de source et TraceEventType

Figure 5 Tracing Source Levels and TraceEventType

Vous avez peut-être remarqué que SourceLevel est un simple masque de bits auquel AND est ajouté lors de l'exécution à TraceEventType afin de déterminer si l'événement doit être consigné. Pour obtenir des combinaisons telles que Avertissement et Suivi des activités, spécifiez la valeur numérique du champ de bits comme valeur de commutateur au lieu d'utiliser les valeurs symboliques indiquées.

Outre les commutateurs, un écouteur peut avoir un filtre TraceFilter qui ajoute une logique d'exécution plus sophistiquée permettant de définir si un message donné doit être autorisé à passer. L'écriture d'un filtre TraceFilter personnalisé dépasse le cadre de cet article, mais vous trouverez un exemple utile dans la documentation du projet Ukadc.Diagnostics sur CodePlex (ukadcdiagnostics.codeplex.com/wikipage?title=LoggingPrimer).

Modification des informations consignées lors de l'exécution

Il s'agit de la façon dont le suivi ASP.NET fonctionne par défaut. Cette méthode peut aussi être appliquée aux services déployés sur Windows Azure. Le problème est que vous aimeriez pouvoir changer les valeurs du commutateur lors de l'exécution et que Windows Azure ne vous permet pas de remplacer simplement web.config ou app.config sans redéployer le service. Dans ce cas de figure, la solution générique ASP.NET consiste à utiliser WebConfigurationManager pour modifier les valeurs de configuration mais, à l'heure actuelle, Windows Azure ne permet pas non plus cette opération pour les services déployés dans le nuage.

La solution est de mettre en miroir les valeurs de ces commutateurs dans ServiceConfiguration.cscfg. Windows Azure vous permet de modifier ce fichier (ou d'en télécharger un nouveau) via le portail de développement pendant que le service est exécuté. Vous devrez cependant écrire du code supplémentaire pour que cela fonctionne.

Le code par défaut System.Diagnostics connaît uniquement les paramètres de app.config ou web.config, mais vos rôles reçoivent des notifications d'exécution à propos des modifications de ServiceConfiguration.cscfg via les événements RoleEnvironmentChanging et RoleEnvironmentChanged. Vous pouvez ensuite décider de recycler (redémarrer) le rôle ou de mettre simplement à jour une valeur de configuration. La dernière solution convient au suivi des commutateurs. Le redémarrage du rôle peut faire disparaître les problèmes intermittents. L'exemple de code de cet article montre comment procéder en ajoutant deux valeurs à ServiceConfiguration.cscfg (notez que vous devez également modifier ServiceDefinition.csdef, qui fournit le schéma) et en ajoutant du code à vos rôles.

Test dans Development Fabric

Qu'en est-il des tests sur Development Fabric, là où vous ne disposez pas du portail Windows Azure afin de modifier la configuration comme vous pouvez le faire pour les services déployés dans le nuage ? Commencez par déterminer l'ID du déploiement attribué par Windows Azure au service Development Fabric exécuté. Vous le trouverez en affichant l'interface utilisateur de Development Fabric dans la barre d'état système pendant l'exécution du système. Cet identificateur ressemble à un numéro similaire à 177.

  1. Allez dans le répertoire où les binaires de votre service ont été mis par version, généralement \bin\debug ou \bin\release sous le code du service. Vous trouverez la copie du fichier ServiceConfiguration.cscfg créé lors de la création de l'application.
  2. Ensuite, à l'aide d'un éditeur de texte, modifiez ce fichier de façon à utiliser le commutateur de suivi souhaité. Ainsi, dans l'exemple de code, remplacez la valeur Off de WebTrace par Verbose.
  3. Puis, dans une invite de commande du kit de développement logiciel (SDK) de Windows Azure (Démarrer | Tous les programmes | Windows Azure SDK v1.1 | Windows Azure SDK Command Prompt), exécutez la commande suivante :
csrun /update:NNN;ServiceConfiguration.cscfg

NNN correspond à l'ID de déploiement de Windows Azure que vous avez recherché précédemment. Ce code aura dans Development Fabric le même effet qu'un clic sur le bouton Configurer dans le portail de développement Windows Azure pour les services déployés dans le nuage, c'est-à-dire mettre à jour les paramètres de configuration et déclencher les événements.

Autres informations de diagnostic

Bien que cet article se soit concentré sur les données tabulaires consignées par votre application à l'aide de System.Diagnostics, Windows Azure peut également capturer les journaux IIS et ceux du suivi des requêtes en échec (précédemment connu sous le nom de mise en mémoire tampon des requêtes en échec, ou FREB), etc. Certains de ces journaux sont placés dans le stockage BLOB de Windows Azure, d'autres dans son stockage par table. La figure 6 répertorie les journaux disponibles ainsi que leur emplacement de stockage. Notez que pour les journaux qui ne sont pas activés par défaut, vous devez généralement effectuer une modification dans web.config ou app.config pour que Windows Azure puisse les collecter. Examinons maintenant un exemple qui n'est pas collecté par défaut afin d'illustrer la façon dont cela fonctionne. 

Figure 6 Options de journalisation Azure standard

Type de journal Format de stockage Windows Azure Collecté par défaut ? Remarques
Journaux Windows Azure générés à partir de votre code Table 4 L'écouteur de suivi d'événements doit être ajouté au fichier web.config ou app.config, comme illustré dans l'exemple de code. Stocké dans WADLogsTable.
Journaux IIS 7.0 BLOB 4 Rôles Web uniquement. Stockés dans un conteneur BLOB sous le chemin wad-iis-logfiles\<ID de déploiement>\<nom du rôle web>\<instance de rôle>\W3SVC1.
Journaux d'infrastructure des diagnostics Windows Table 4 Informations sur le service de diagnostics lui-même. Stockés dans WADDiagnosticInfrastructureLogsTable.
Journaux de suivi des requêtes BLOB   Rôles Web uniquement. Activés en paramétrant les options de suivi sous les paramètres system.WebServer du fichier web.config. Stockés dans un conteneur BLOB sous le chemin wad-iis-failedreqlogfiles\<ID de déploiement>\<nom du rôle web>\<instance de rôle>\W3SVC1.
Journaux des événements Windows Table   Activés en modifiant DiagnosticMonitor Configuration.WindowsEventLog lors du paramétrage de la configuration initiale. Stockés dans la table WADWindowsEventLogsTable. Le blog de Steve Marx (blog.smarx.com/posts/capturing-filtered-windows-events-with-windows-azure-diagnostics) explique comment les utiliser.
Compteurs de performances Table   Activés en modifiant DiagnosticMonitor Configuration. PerformanceCounters. Stockés dans la table WADPerformanceCountersTable. Le rôle worker de l'exemple de code définit un compteur de performances.
Vidages sur incident BLOB   Activés en appelant CrashDumps.EnableCollection. Stockés dans un conteneur BLOB sous le chemin wad-crash-dumps. Dans la mesure où ASP.NET gère la plupart des exceptions, ils sont généralement utiles dans le cadre d'un rôle worker.
Journaux d'erreurs personnalisés BLOB   Bien qu'il dépasse le cadre de cet article, le blog de Neil Mackenzie (nmackenzie.spaces.live.com/blog/cns!B863FF075995D18A!537.entry) propose un exemple intéressant sur leur utilisation.

À titre d'exemple, observons l'activation de la journalisation FREB à partir d'IIS sur votre rôle Web. Pour voir cette activation en action, téléchargez l'exemple de code du service MSDNSampleLoggingService fourni avec cet article. Ouvrez web.config pour le rôle LoggingWebRole et recherchez la section nommée <system.webServer>. Remarquez que les lignes illustrées à la figure 7 ont été ajoutées au fichier par défaut Windows Azure web.config. Cela provoque l'échec de la journalisation pour toutes les requêtes qui durent plus de 15 secondes ou qui ont un code d'état compris entre 400 et 599 (l'élément failureDefinitions).

Figure 7 Échec de la journalisation des requêtes pour LoggingWebRole

<tracing>
  <traceFailedRequests>
    <add path="*">
      <traceAreas>
        <add provider="ASP" verbosity="Verbose" />
        <add provider="ASPNET" 
             areas="Infrastructure,Module,Page,AppServices"
             verbosity="Verbose" />
        <add provider="ISAPI Extension" verbosity="Verbose" />
        <add provider="WWW Server"
             areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module" 
             verbosity="Verbose" />
      </traceAreas>
      <failureDefinitions timeTaken="00:00:15" statusCodes="400-599" />
    </add>
  </traceFailedRequests>
</tracing>

Si vous ouvrez about.aspx.cs dans le projet LoggingWebRole, vous remarquerez qu'un délai arbitraire de 18 secondes a été ajouté à la méthode PageLoad avec la ligne de code suivante :

System.Threading.Thread.Sleep(18000);

Avec ce code, le chargement de la page est considéré comme une requête en échec d'après la définition spécifiée précédemment.

Pour consulter le journal FREB, reconstruisez et déployez l'application dans Development Fabric, puis recherchez le contrôleur dans la zone de notification de la barre des tâches (vous devrez peut-être cliquer sur le bouton Afficher les icônes cachées dans la barre des tâches parce que cette icône est souvent masquée car inactive). Cliquez dessus avec le bouton droit de la souris et sélectionnez Show Development Fabric UI. Les informations sur l'application seront alors affichées pendant son exécution.

Développez le rôle Web et cliquez avec le bouton droit de la souris sur l'instance de rôle (0). Sélectionnez Open local store pour ouvrir le dossier sur l'ordinateur local où les journaux ont été enregistrés (voir la figure 8). Dans ce dossier, les journaux se trouvent dans le dossier \directory\DiagnosticStore. En effet, le rôle Web de l'exemple de code est configuré de façon à stocker les informations de diagnostic dans le stockage de développement. Si vous définissez en revanche la chaîne DiagnosticsConnectionString dans un compte de stockage du nuage, les journaux conservés se trouveront dans le stockage BLOB associé à ce compte de stockage. Vous pouvez utiliser Cloud Storage Studio pour examiner les conteneurs de stockage BLOB et consulter les journaux.

Figure 8 Opening Logs Saved to Local Development Fabric Storage
Figure 8 Ouverture des journaux enregistrés dans Local Development Fabric Storage

Gestion des diagnostics pour un service exécuté

Bien que vous puissiez ajouter beaucoup de journalisation dans votre code, il n'est pas recommandé de conserver toutes les informations de journalisation dans les emplacements de stockage pendant l'exécution du service de production. Vous pouvez par exemple souhaiter conserver dans les journaux les informations de type Error et Critical, tout en supprimant les informations plus détaillées (consignées sous Verbose ou Information).

Mais que se passera-t-il en cas de problème ? Vous n'allez pas redéployer une nouvelle version de votre service ou le problème peut disparaître comme par magie. Vous savez très certainement à quel point un redémarrage peut être efficace pour faire disparaître les problèmes insaisissables.

En revanche, il est plus efficace d'accroître la quantité d'informations allant dans les tables de journalisation ou le stockage BLOB, tout en permettant la poursuite de l'exécution du code au comportement incorrect. Vous aurez ainsi plus de chances de trouver l'origine du problème dans votre application pendant son exécution.

J'ai décrit précédemment comment peaufiner les détails de la sélection des journalisations passées aux diagnostics de Windows Azure pour une source TraceSource donnée. Il s'agit en quelque sorte d'une révision en amont des informations qui seront consignées. Dans cette section, je vais expliquer les paramètres généraux de diagnostic Windows Azure qui déterminent comment les informations qui passent via une TraceSource arrivent dans le stockage permanent.

Les applets de commande Windows PowerShell peuvent gérer un certain nombre d'aspects relatifs à l'exécution des services Windows Azure, dont les diagnostics. Vous exécutez ces applets à partir de votre ordinateur local et elles se connectent via Internet aux serveurs en nuage qui exécutent votre service en fournissant les informations et en ajustant les paramètres. Windows PowerShell est installé avec Windows 7 et peut être téléchargé pour Windows Vista sur microsoft.com/powershell. Téléchargez les applets de commande de la gestion des services Windows Azure sur code.msdn.microsoft.com/azurecmdlets et suivez les instructions d'installation. Les commandes Windows Azure associées aux diagnostics sont illustrées à la figure 9.

Figure 9 Applets de commande des diagnostics de gestion Windows Azure

Nom Description
Get-ActiveTransfers Renvoie l'ensemble des transferts de diagnostics actifs avec les informations de transfert associées.
Get-CommonConfigurationLogs Obtient les valeurs de configuration courantes pour toutes les mémoires tampon de journalisation. Cela inclut l'intervalle de temps au cours duquel les changements de configuration sont interrogés et la taille de la mémoire tampon est allouée pour les journaux en mémoire.
Get-DiagnosticAwareRoleInstances Renvoie une liste d'ID des instances de rôle actives dont le contrôle de diagnostic est en cours d'exécution.
Get-DiagnosticAwareRoles Répertorie l'ensemble de rôles ayant lancé au moins un contrôle de diagnostic.
Get-DiagnosticConfiguration Obtient la configuration de la mémoire tampon pour le nom de mémoire tampon spécifié (Logs, Directories, PerformanceCounters, WindowsEventLogs ou DiagnosticInfrastructureLogs).
Set-CommonConfigurationLogs Définit les valeurs de configuration courantes pour toutes les mémoires tampon de journalisation.
Set-FileBasedLog Définit la configuration de la mémoire tampon pour les journaux basés sur un fichier.
Set-InfrastructureLog Définit la configuration de la mémoire tampon pour les journaux générés par l'infrastructure de diagnostic Windows Azure sous-jacente. Les journaux de l'infrastructure de diagnostic permettent de dépanner le système de diagnostics lui-même.
Set-PerformanceCounter Définit la configuration de la mémoire tampon pour les données du compteur de performances collectées par votre service.
Set-WindowsAzureLog Définit la configuration de la mémoire tampon pour les journaux de base Windows Azure générés par votre service.
Set-WindowsEventLog Définit la configuration de la mémoire tampon pour les journaux d'événements Windows Azure générés par votre service.
Start-OnDemandTransfer Démarre un transfert à la demande de la mémoire tampon de données spécifiée. Les données sont alors transférées dans le stockage de Windows Azure (par table ou BLOB).
Stop-ActiveTransfer Arrête un transfert à la demande actif, pour un ID de transfert.

Par exemple, pour rechercher les paramètres de transfert actuels d'une instance de rôle donnée, passez l'ID de déploiement (à partir du portail de développement Windows Azure sur lequel vous déployez le service), le nom du compte de stockage et la clé que vous avez utilisés pour la chaîne DiagnosticsConnectionString dans le fichier app.config ou web.config du rôle de service (voir la figure 10). Remarquez que Windows PowerShell demande deux paramètres obligatoires manquants, l'instance de rôle et le nom de la mémoire tampon que vous souhaitez. Logs correspond aux journaux Windows Azure standard. Le résultat montre que le niveau de filtre est Verbose et un transfert est prévu toutes les minutes.

Figure 10 Diagnostics Configuration for a Running Service Using Windows PowerShell
Figure 10 Configuration des diagnostics pour un service exécuté à l'aide de Windows PowerShell

Pour modifier la configuration de ce rôle, utilisez l'applet de commande Set-DiagnosticConfiguration, comme illustré à la figure 11. Notez que j'ai fait passer la période de transfert d'une à deux minutes et que la valeur du filtre Error a été remplacée par Verbose, ce qui signifie que seuls les événements consignés sous Error et Critical seront envoyés en stockage permanent.

Figure 11 Changing Diagnostics Configuration from Windows PowerShell
Figure 11 Changement de la configuration des diagnostics à partir de Windows PowerShell

L'opération la plus utile que vous puissiez effectuer à distance à partir de Windows PowerShell est probablement de forcer un transfert des informations de journal immédiatement. La figure 12 vous indique comment procéder.

Figure 12 Using Windows PowerShell to Initiate a Transfer of IIS Logs
Figure 12 Utilisation de Windows PowerShell pour commencer un transfert de journaux IIS

J'effectue d'abord une requête pour savoir s'il existe un transfert de journaux à la demande. Une restriction a été définie lors de l'implémentation actuelle des diagnostics dans Windows Azure : un seul transfert à la demande d'un type particulier peut avoir lieu à un moment donné. Je constate qu'aucun transfert n'est en cours et j'en demande donc un en passant l'ID de déploiement du service, le rôle et l'instance, le type de journal à transférer et l'intervalle de temps des données à transférer. Dans le cadre du type de journal, Directories fait référence aux journaux basés sur les fichiers, dont les journaux IIS. En revanche, les Logs sont les journaux Windows Azure basés sur les tables et envoyés via TraceSource.

Je passe également un nom de file d'attente de notification, là où les diagnostics Windows Azure enverront une notification indiquant que le transfert est terminé. En expérimentant, j'ai découvert que si je ne passais pas de file d'attente de notification, le transfert semblait ne pas se produire. J'obtiens en retour un GUID qui identifie la demande de transfert. Je demande ensuite l'état de la requête et je vois qu'elle est publiée, ce qui signifie qu'elle est en cours.

La version actuelle des applets de commande de la gestion des services Windows Azure ne semble pas indiquer le moment où la requête s'est terminée, mais si vous demandez le stockage des diagnostics BLOB, vous verrez les journaux apparaître dans la hiérarchie des conteneurs rapidement (ou dans le stockage par table de Windows Azure si vous avez demandé un transfert d'informations stockées dans le stockage par table).

Synthèse

En utilisant une combinaison des paramètres d'ajustement de la configuration des sources TraceSource définies dans votre code et en utilisant les applets de commande de la gestion des services Windows Azure pour déplacer les informations dans le stockage permanent, vous devriez pouvoir contrôler totalement la sortie de diagnostics obtenue à partir des services Windows Azure.

Il est évident que l'opération la plus importante que vous puissiez effectuer pour dépanner votre code de production est de développer une stratégie solide pour la sortie des diagnostics dès les premières étapes du développement, puis de suivre cette stratégie au cours du codage. L'utilisation des sources TraceSource et des outils fournis par Windows Azure pour configurer la prolixité de la sortie des diagnostics qui passe de votre application au stockage vous aidera à exploiter ces informations afin d'obtenir la quantité exacte d'informations dont vous avez besoin en cas de problème.

Il n'y a rien de pire que de sentir que le code qui se comporte de façon irrégulière sur un serveur est une boîte noire, totalement opaque pour vous. Le code de diagnostic solide et les outils décrits ici vous permettront d'ouvrir les couvercles de cette boîte et d'examiner ce qu'il y a à l'intérieur.  

Mike Kelly est un consultant qui se consacre au développement de logiciels et permet l'intégration d'acquisitions dans des entreprises importantes. Il a travaillé pour Microsoft pendant 15 ans et a occupé différents rôles dans le cadre du développement de produits. Il y a également été directeur des pratiques émergentes au sein de l'équipe Engineering Excellence. Vous pouvez le joindre à l'adresse himself@mikekellyconsulting.com.

Je remercie les experts techniques suivants qui ont participé à la révision de cet article : Sumit Mehrotra, Michael Levin et Matthew Kerner de Microsoft, ainsi que Neil Mackenzie et Steven Nagy