Mise à jour : Pour des extensions de System.Diagnostics, fournissant certains des listeners manquants que vous pourriez vouloir, voir Essential.Diagnostics sur CodePlex ( http://essentialdiagnostics.codeplex.com/ )
Cadres de travail
Q : Quels cadres de travail utilisez-vous ?
R : System.Diagnostics.TraceSource, intégré à .NET 2.0.
Il fournit une journalisation puissante, flexible et performante pour les applications. Cependant, de nombreux développeurs ne sont pas conscients de ses capacités et ne les utilisent pas pleinement.
Il y a certains domaines où une fonctionnalité supplémentaire est utile, ou parfois la fonctionnalité existe mais n'est pas bien documentée, cependant cela ne signifie pas que l'ensemble du cadre de journalisation (qui est conçu pour être extensible) devrait être jeté et complètement remplacé comme certaines alternatives populaires (NLog, log4net, Common.Logging, et même EntLib Logging).
Plutôt que de changer la façon dont vous ajoutez les déclarations de journalisation à votre application et de réinventer la roue, il suffit d'étendre le cadre System.Diagnostics aux quelques endroits où vous en avez besoin.
Il me semble que les autres frameworks, même EntLib, souffrent tout simplement du syndrome du "Not Invented Here", et je pense qu'ils ont perdu du temps à réinventer les bases qui fonctionnent déjà parfaitement bien dans System.Diagnostics (comme la façon d'écrire les déclarations de journal), plutôt que de combler les quelques lacunes qui existent. En bref, ne les utilisez pas - ils ne sont pas nécessaires.
Des caractéristiques que vous ne connaissiez peut-être pas :
- L'utilisation des surcharges TraceEvent qui prennent une chaîne de format et des arguments peut améliorer les performances car les paramètres sont conservés comme références séparées jusqu'à ce que Filter.ShouldTrace() ait réussi. Cela signifie qu'il n'y a pas d'appels coûteux à ToString() sur les valeurs des paramètres jusqu'à ce que le système ait confirmé que le message sera effectivement enregistré.
- Le gestionnaire de corrélation Trace.CorrelationManager permet de mettre en corrélation les déclarations de journal concernant la même opération logique (voir ci-dessous).
- VisualBasic.Logging.FileLogTraceListener permet d'écrire dans des fichiers journaux et prend en charge la rotation des fichiers. Bien qu'il se trouve dans l'espace de noms VisualBasic, il peut être utilisé tout aussi facilement dans un projet C# (ou autre langage) en incluant simplement la DLL.
- Lorsque vous utilisez EventLogTraceListener, si vous appelez TraceEvent avec plusieurs arguments et avec une chaîne de format vide ou nulle, les arguments sont transmis directement à EventLog.WriteEntry() si vous utilisez des ressources de message localisées.
- L'outil Service Trace Viewer (de WCF) est utile pour visualiser les graphiques des fichiers journaux corrélés à l'activité (même si vous n'utilisez pas WCF). Cela peut vraiment aider à déboguer des problèmes complexes où plusieurs threads/activités sont impliqués.
- Évitez les surcharges en effaçant tous les listeners (ou en supprimant Default) ; sinon Default transmettra tout au système de suivi (et subira toutes les surcharges de ToString()).
Les domaines que vous pourriez envisager d'étendre (si nécessaire) :
- Écoute de la trace de la base de données
- Écouteur de trace de console coloré
- Écouteurs de traces MSMQ / Email / WMI (si nécessaire)
- Implémenter un FileSystemWatcher pour appeler Trace.Refresh pour les changements de configuration dynamique
Autres recommandations :
Utilisez des identifiants d'événements structurés et conservez une liste de référence (par exemple, documentez-les dans une énumération).
Le fait de disposer d'un identifiant unique pour chaque événement (significatif) de votre système est très utile pour établir des corrélations et trouver des problèmes spécifiques. Il est facile de remonter jusqu'au code spécifique qui enregistre/utilise les identifiants d'événements et de fournir des conseils pour les erreurs courantes, par exemple, l'erreur 5178 signifie que la chaîne de connexion à la base de données est incorrecte, etc.
Les identifiants d'événements doivent suivre une certaine structure (similaire à la théorie des codes de réponse utilisée dans le courrier électronique et le protocole HTTP), qui vous permet de les traiter par catégorie sans connaître les codes spécifiques.
Par exemple, le premier chiffre peut indiquer la classe générale : 1xxx peut être utilisé pour les opérations de "démarrage", 2xxx pour le comportement normal, 3xxx pour le suivi des activités, 4xxx pour les avertissements, 5xxx pour les erreurs, 8xxx pour les opérations d'arrêt, 9xxx pour les erreurs fatales, etc.
Le deuxième chiffre peut détailler la zone, par exemple 21xx pour les informations relatives à la base de données (41xx pour les avertissements relatifs à la base de données, 51xx pour les erreurs relatives à la base de données), 22xx pour le mode de calcul (42xx pour les avertissements relatifs aux calculs, etc.), 23xx pour un autre module, etc.
Les identifiants d'événements attribués et structurés vous permettent également de les utiliser dans des filtres.
Q : Si vous utilisez le traçage, faites-vous usage de Trace.Correlation.StartLogicalOperation ?
R : Trace.CorrelationManager est très utile pour corréler les déclarations de journal dans n'importe quel type d'environnement multithread (c'est-à-dire à peu près tout de nos jours).
Vous devez au moins définir l'ActivityId une fois pour chaque opération logique afin d'établir une corrélation.
Start/Stop et le LogicalOperationStack peuvent alors être utilisés pour un contexte simple basé sur la pile. Pour des contextes plus complexes (par exemple, des opérations asynchrones), l'utilisation de TraceTransfer vers le nouvel ActivityId (avant de le modifier), permet la corrélation.
L'outil Service Trace Viewer peut être utile pour visualiser les graphiques d'activité (même si vous n'utilisez pas WCF).
Q : Écrivez-vous ce code manuellement ou utilisez-vous une forme de programmation orientée aspect pour le faire ? Vous voulez partager un extrait de code ?
R : Vous pouvez créer une classe d'étendue, par exemple LogicalOperationScope, qui (a) définit le contexte lors de sa création et (b) réinitialise le contexte lors de sa destruction.
Cela vous permet d'écrire un code tel que le suivant pour envelopper automatiquement les opérations :
using( LogicalOperationScope operation = new LogicalOperationScope("Operation") )
{
// .. do work here
}
Lors de sa création, l'étendue pourrait d'abord définir ActivityId si nécessaire, appeler StartLogicalOperation, puis enregistrer un message TraceEventType.Start. Lors de la suppression, elle peut enregistrer un message Stop, puis appeler StopLogicalOperation.
Q : Fournissez-vous une forme de granularité sur les sources de trace ? Par exemple, les TraceSources de WPF vous permettent de les configurer à différents niveaux.
R : Oui, les sources de traçage multiples sont utiles/importantes lorsque les systèmes deviennent plus grands.
Bien que vous souhaitiez probablement consigner systématiquement tous les messages d'avertissement et plus, ou tous les messages d'information et plus, pour tout système de taille raisonnable, le volume du suivi des activités (démarrage, arrêt, etc.) et de la consignation Verbose devient tout simplement trop important.
Plutôt que d'avoir un seul interrupteur pour tout activer ou désactiver, il est utile de pouvoir activer ces informations pour une section de votre système à la fois.
De cette façon, vous pouvez localiser les problèmes importants à partir de la journalisation habituelle (tous les avertissements, erreurs, etc.), puis "zoomer" sur les sections que vous souhaitez et les définir sur des niveaux de suivi d'activité ou même de débogage.
Le nombre de sources de traçage dont vous avez besoin dépend de votre application. Par exemple, vous pouvez vouloir une source de traçage par assemblage ou par section majeure de votre application.
Si vous avez besoin d'un contrôle encore plus précis, ajoutez des interrupteurs booléens individuels pour activer/désactiver le traçage de gros volumes spécifiques, par exemple les vidages de messages bruts. (Ou une source de traçage séparée pourrait être utilisée, comme pour WCF/WPF).
Vous pouvez également envisager des sources de traçage distinctes pour le suivi des activités et la journalisation générale (autre), car cela peut faciliter la configuration des filtres exactement comme vous le souhaitez.
Notez que les messages peuvent toujours être corrélés via ActivityId même si différentes sources sont utilisées, alors utilisez-en autant que nécessaire.
Auditeurs
Q : Quelles sorties de journaux utilisez-vous ?
Cela peut dépendre du type d'application que vous écrivez, et des éléments qui sont enregistrés. En général, différentes choses vont à différents endroits (c'est-à-dire des sorties multiples).
Je classe généralement les sorties en trois groupes :
(1) Événements - Journal des événements de Windows (et fichiers de trace)
Par exemple, si vous écrivez un serveur/service, la meilleure pratique sous Windows est d'utiliser le journal des événements de Windows (vous n'avez pas d'interface utilisateur à laquelle faire rapport).
Dans ce cas, tous les événements fatals, d'erreur, d'avertissement et d'information (au niveau du service) doivent aller dans le journal des événements de Windows. Le niveau Information doit être réservé à ce type d'événements de haut niveau, ceux que vous voulez voir apparaître dans le journal des événements, par exemple "Service démarré", "Service arrêté", "Connecté à Xyz", et peut-être même "Planification initiée", "Utilisateur connecté", etc.
Dans certains cas, vous pouvez souhaiter que l'écriture dans le journal des événements fasse partie intégrante de votre application et ne passe pas par le système de suivi (c'est-à-dire écrire directement les entrées du journal des événements). Cela signifie qu'elle ne peut pas être accidentellement désactivée. (Notez que vous souhaitez toujours noter le même événement dans votre système de suivi afin de pouvoir établir une corrélation).
En revanche, une application Windows GUI les signale généralement à l'utilisateur (bien qu'elles puissent également être enregistrées dans le journal des événements de Windows).
Les événements peuvent également être associés à des compteurs de performance (par exemple, le nombre d'erreurs par seconde). Il peut être important de coordonner l'écriture directe dans le journal des événements, les compteurs de performance, l'écriture dans le système de suivi et les rapports à l'utilisateur, de manière à ce qu'ils se produisent en même temps.
Par exemple, si un utilisateur voit un message d'erreur à un moment donné, vous devriez pouvoir trouver le même message d'erreur dans le journal des événements de Windows, puis le même événement avec le même horodatage dans le journal de suivi (avec d'autres détails de suivi).
(2) Activités - Fichiers journaux de l'application ou table de la base de données (et fichiers de trace)
Il s'agit de l'activité régulière d'un système, par exemple une page web servie, une transaction boursière effectuée, un ordre pris, un calcul effectué, etc.
Le suivi des activités (démarrage, arrêt, etc.) est utile ici (à la bonne granularité).
Il est également très courant d'utiliser un journal d'application spécifique (parfois appelé journal d'audit). Il s'agit généralement d'une table de base de données ou d'un fichier journal d'application qui contient des données structurées (c'est-à-dire un ensemble de champs).
Les choses peuvent devenir un peu floues ici en fonction de votre application. Un bon exemple pourrait être un serveur web qui écrit chaque requête dans un journal web ; des exemples similaires pourraient être un système de messagerie ou un système de calcul où chaque opération est enregistrée avec des détails spécifiques à l'application.
Un moins bon exemple est celui des transactions boursières ou d'un système de commande des ventes. Dans ces systèmes, vous enregistrez probablement déjà l'activité car elle a une valeur commerciale importante, mais le principe de la corrélation avec d'autres actions reste important.
Outre les journaux d'application personnalisés, les activités sont souvent associées à des compteurs de performance, par exemple le nombre de transactions par seconde.
En général, vous devez coordonner l'enregistrement des activités sur différents systèmes, c'est-à-dire écrire dans le journal de votre application en même temps que vous augmentez votre compteur de performance et que vous enregistrez dans votre système de suivi. Si vous faites tout en même temps (ou directement l'un après l'autre dans le code), le débogage des problèmes est plus facile (que s'ils se produisent tous à des moments/emplacements différents dans le code).
(3) Debug Trace - Fichier texte, ou peut-être XML ou base de données.
Il s'agit d'informations de niveau Verbose et inférieur (par exemple, des interrupteurs booléens personnalisés pour activer/désactiver les vidages de données brutes). Elles fournissent les détails de ce que fait un système au niveau de la sous-activité.
Il s'agit du niveau que vous souhaitez pouvoir activer/désactiver pour des sections individuelles de votre application (d'où les sources multiples). Vous ne voulez pas que ces éléments encombrent le journal des événements de Windows. Parfois, une base de données est utilisée, mais il est plus probable qu'il s'agisse de fichiers journaux roulants qui sont purgés après un certain temps.
Une grande différence entre ces informations et un fichier journal d'application est qu'elles ne sont pas structurées. Alors qu'un journal d'application peut comporter des champs pour les valeurs To, From, Amount, etc., les traces de débogage verbeuses peuvent être constituées de ce que le programmeur y inscrit, par exemple "vérification des valeurs X={valeur}, Y=faux", ou de commentaires/marqueurs aléatoires tels que "Terminé, réessayer".
Une pratique importante consiste à s'assurer que les éléments que vous consignez dans les fichiers journaux des applications ou dans le journal des événements de Windows sont également enregistrés dans le système de suivi avec les mêmes détails (par exemple, l'horodatage). Cela vous permet de corréler les différents journaux lors de vos recherches.
Si vous envisagez d'utiliser un visualisateur de journaux particulier parce que vous avez une corrélation complexe, par exemple le visualisateur de traces de service, vous devez utiliser un format approprié, c'est-à-dire XML. Sinon, un simple fichier texte est généralement suffisant - aux niveaux inférieurs, l'information est en grande partie non structurée, de sorte que vous pouvez trouver des vidages de tableaux, de piles, etc. Pour autant que vous puissiez établir une corrélation avec des journaux plus structurés aux niveaux supérieurs, tout devrait bien se passer.
Q : Si vous utilisez des fichiers, utilisez-vous des journaux continus ou un seul fichier ? Comment mettez-vous les journaux à la disposition des gens ?
R : Pour les fichiers, vous voulez généralement des fichiers de logs roulants du point de vue de la gestion (avec System.Diagnostics, utilisez simplement VisualBasic.Logging.FileLogTraceListener).
La disponibilité dépend à nouveau du système. Si vous ne parlez que de fichiers, alors pour un serveur/service, les fichiers roulants sont accessibles uniquement lorsque cela est nécessaire. (Le journal des événements de Windows ou les journaux des applications de base de données auraient leurs propres mécanismes d'accès).
Si vous ne disposez pas d'un accès facile au système de fichiers, il peut être plus facile d'effectuer un suivi de débogage vers une base de données. [Pour ce faire, il suffit d'implémenter un TraceListener de base de données.]
Une solution intéressante que j'ai vue pour une application Windows GUI consistait à enregistrer des informations de traçage très détaillées dans un "enregistreur de vol" pendant qu'elle fonctionnait, puis, lorsque vous l'arrêtiez, si elle ne présentait aucun problème, elle supprimait simplement le fichier.
Si, toutefois, il s'est écrasé ou a rencontré un problème, le fichier n'a pas été supprimé. S'il détecte l'erreur, ou la prochaine fois qu'il s'exécute, il remarquera le fichier, et pourra alors prendre des mesures, par exemple le compresser (par exemple avec 7zip) et l'envoyer par courrier électronique ou le rendre disponible.
De nos jours, de nombreux systèmes intègrent le signalement automatique des défaillances à un serveur central (après vérification auprès des utilisateurs, par exemple pour des raisons de confidentialité).
Visualisation de
Q : Quels outils utilisez-vous pour visualiser les journaux ?
R : Si vous avez plusieurs journaux pour différentes raisons, vous utiliserez plusieurs visionneurs.
Notepad/vi/Notepad++ ou tout autre éditeur de texte est la base pour les journaux en texte brut.
Si vous avez des opérations complexes, par exemple des activités avec des transferts, alors vous utiliserez évidemment un outil spécialisé comme le Service Trace Viewer. (Mais si vous n'en avez pas besoin, un éditeur de texte est plus simple).
Comme je consigne généralement les informations de haut niveau dans le journal des événements de Windows, il s'agit d'un moyen rapide d'obtenir une vue d'ensemble, de manière structurée (recherchez les jolies icônes d'erreur/d'avertissement). Il vous suffit de commencer à chercher dans les fichiers texte si le journal n'en contient pas suffisamment, mais au moins le journal vous donne un point de départ. (À ce stade, il est utile de s'assurer que vos journaux ont des entiers coordonnés).
En général, le journal des événements de Windows met également ces événements importants à la disposition d'outils de surveillance comme MOM ou OpenView.
Autres --
Si vous vous connectez à une base de données, il peut être facile de filtrer et de trier les informations (par exemple, zoomer sur un identifiant d'activité particulier) (avec les fichiers texte, vous pouvez utiliser Grep/PowerShell ou un outil similaire pour filtrer sur le GUID partiel que vous souhaitez).
MS Excel (ou un autre tableur). Cela peut s'avérer utile pour analyser des informations structurées ou semi-structurées si vous pouvez les importer avec les bons délimiteurs afin que des valeurs différentes soient placées dans des colonnes différentes.
Lorsque j'exécute un service en débogage/test, je l'héberge généralement dans une application console ; pour plus de simplicité, je trouve utile d'avoir un logger console coloré (par exemple rouge pour les erreurs, jaune pour les avertissements, etc). Vous devez implémenter un écouteur de trace personnalisé.
Notez que le framework n'inclut pas de collecteur de console coloré ou de collecteur de base de données. Pour l'instant, vous devez donc les écrire si vous en avez besoin (ce n'est pas trop difficile).
Cela m'ennuie vraiment que plusieurs frameworks (log4net, EntLib, etc.) aient perdu du temps à réinventer la roue et à réimplémenter l'enregistrement de base, le filtrage et l'enregistrement dans des fichiers texte, le journal des événements de Windows et les fichiers XML, chacun à sa manière (les instructions d'enregistrement sont différentes dans chacun) ; chacun a ensuite implémenté sa propre version, par exemple, d'un enregistreur de base de données, alors que la plupart de ces éléments existaient déjà et que tout ce qui était nécessaire était quelques écouteurs de trace supplémentaires pour System.Diagnostics. Vous parlez d'un grand gaspillage d'efforts redondants.
Q : Si vous construisez une solution ASP.NET, utilisez-vous également la surveillance de la santé d'ASP.NET ? Incluez-vous la sortie de trace dans les événements de surveillance de la santé ? Qu'en est-il de Trace.axd ?
Ces éléments peuvent être activés ou désactivés selon les besoins. Je trouve Trace.axd assez utile pour déboguer la façon dont un serveur répond à certaines choses, mais il n'est généralement pas utile dans un environnement très utilisé ou pour un traçage à long terme.
Q : Qu'en est-il des compteurs de performance personnalisés ?
Pour une application professionnelle, en particulier un serveur/service, je m'attends à ce qu'elle soit entièrement instrumentée à l'aide des compteurs de Performance Monitor et de l'enregistrement dans le journal des événements de Windows. Ce sont les outils standard de Windows et ils doivent être utilisés.
Vous devez vous assurer que vous incluez des installateurs pour les compteurs de performance et les journaux d'événements que vous utilisez ; ceux-ci doivent être créés au moment de l'installation (lors de l'installation en tant qu'administrateur). Lorsque votre application fonctionne normalement, elle ne devrait pas avoir besoin de privilèges d'administration (et ne pourra donc pas créer les journaux manquants).
C'est une bonne raison de s'entraîner à développer en tant que non-administrateur (ayez un compte administrateur distinct pour les cas où vous devez installer des services, etc.) Si vous écrivez dans le journal des événements, .NET créera automatiquement un journal manquant la première fois que vous écrirez dans ce journal. Si vous développez en tant que non-administrateur, vous vous en apercevrez rapidement et éviterez une mauvaise surprise lorsqu'un client installera votre système et ne pourra pas l'utiliser parce qu'il n'est pas exécuté en tant qu'administrateur.