Mise à jour: pour les extensions de System.Diagnostics, fournissant certains des écouteurs manquants que vous pourriez souhaiter, voir Essential.Diagnostics sur CodePlex ( http://essentialdiagnostics.codeplex.com/ )
Cadres
Q: Quels cadres utilisez-vous?
R: System.Diagnostics.TraceSource, intégré à .NET 2.0.
Il fournit une journalisation puissante, flexible et hautes performances pour les applications, mais de nombreux développeurs ne connaissent pas ses capacités et ne les utilisent pas pleinement.
Il existe des domaines dans lesquels des fonctionnalités supplémentaires sont utiles, ou parfois elles existent mais ne sont pas bien documentées, mais cela ne signifie pas que l'ensemble du cadre de journalisation (conçu pour être extensible) doit ê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 des instructions de journalisation à votre application et de réinventer la roue, il vous suffit d'étendre le cadre System.Diagnostics aux rares endroits où vous en avez besoin.
Il me semble que les autres frameworks, même EntLib, souffrent simplement du syndrome de 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 dont vous écrivez des instructions 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 fonctionnalités que vous ne connaissiez peut-être pas:
- L'utilisation des surcharges TraceEvent qui prennent une chaîne de format et des arguments peuvent améliorer les performances car les paramètres sont conservés en tant que références distinctes jusqu'à ce que Filter.ShouldTrace () réussisse. Cela signifie qu'aucun appel coûteux à ToString () sur les valeurs des paramètres tant que le système n'a pas confirmé le message sera réellement enregistré.
- Le Trace.CorrelationManager vous permet de corréler les instructions de journal concernant la même opération logique (voir ci-dessous).
- VisualBasic.Logging.FileLogTraceListener est bon pour écrire dans des fichiers journaux et prend en charge la rotation de fichiers. Bien que dans l'espace de noms VisualBasic, il peut être tout aussi facilement utilisé dans un projet C # (ou autre langage) simplement en incluant 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 afficher des graphiques de fichiers journaux d'activité corrélés (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 frais généraux en effaçant tous les écouteurs (ou en supprimant Default); sinon Default passera tout au système de trace (et encourra tous ces frais généraux ToString ()).
Domaines que vous pourriez envisager d'étendre (si nécessaire):
- Écouteur de trace de base de données
- Écouteur de trace de console colorée
- Écouteurs de trace MSMQ / Email / WMI (si nécessaire)
- Implémentez un FileSystemWatcher pour appeler Trace.Refresh pour les changements de configuration dynamiques
Autres recommandations:
Utilisez des identifiants d'événement structurés et conservez une liste de références (par exemple, documentez-les dans une énumération).
Avoir des ID d'événement uniques pour chaque événement (significatif) dans votre système est très utile pour corréler et trouver des problèmes spécifiques. Il est facile de retracer le code spécifique qui enregistre / utilise les identifiants d'événement et peut faciliter la fourniture de conseils pour les erreurs courantes, par exemple l'erreur 5178 signifie que votre chaîne de connexion à la base de données est incorrecte, etc.
Les ID d'événement doivent suivre une sorte de structure (similaire à la théorie des codes de réponse utilisés dans les e-mails et HTTP), qui vous permet de les traiter par catégorie sans connaître de codes spécifiques.
Par exemple, le premier chiffre peut détailler la classe générale: 1xxx peut être utilisé pour les opérations «Démarrer», 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 «Arrêter», 9xxx pour les erreurs fatales, etc.
Le deuxième chiffre peut détailler la zone, par exemple 21xx pour les informations de base de données (41xx pour les avertissements de base de données, 51xx pour les erreurs de base de données), 22xx pour le mode de calcul (42xx pour les avertissements de calcul, etc.), 23xx pour un autre module, etc.
Les ID d'événement structurés et attribués vous permettent également de les utiliser dans des filtres.
Q: Si vous utilisez le traçage, utilisez-vous Trace.Correlation.StartLogicalOperation?
R: Trace.CorrelationManager est très utile pour corréler les instructions de journal dans n'importe quel type d'environnement multi-thread (ce qui est à peu près n'importe quoi de nos jours).
Vous devez au moins définir le ActivityId une fois pour chaque opération logique afin de corréler.
Start / Stop et LogicalOperationStack peuvent ensuite être utilisés pour un contexte basé sur une pile simple. Pour les contextes plus complexes (par exemple les 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 afficher les graphiques d'activité (même si vous n'utilisez pas WCF).
Q: Ecrivez-vous ce code manuellement ou utilisez-vous une forme de programmation orientée aspect pour le faire? Vous souhaitez partager un extrait de code?
R: Vous souhaiterez peut-être créer une classe d'étendue, par exemple LogicalOperationScope, qui (a) configure le contexte lors de sa création et (b) réinitialise le contexte lorsqu'il est supprimé.
Cela vous permet d'écrire du code tel que le suivant pour encapsuler automatiquement les opérations:
using( LogicalOperationScope operation = new LogicalOperationScope("Operation") )
{
// .. do work here
}
Lors de la création, la portée peut d'abord définir ActivityId si nécessaire, appeler StartLogicalOperation, puis enregistrer un message TraceEventType.Start. Sur Dispose, il peut enregistrer un message d'arrêt, puis appeler StopLogicalOperation.
Q: Fournissez-vous une forme de granularité sur les sources de trace? Par exemple, WPF TraceSources vous permet de les configurer à différents niveaux.
R: Oui, plusieurs sources de trace sont utiles / importantes à mesure que les systèmes s'agrandissent.
Bien que vous souhaitiez probablement consigner de manière cohérente tous les messages d'avertissement et ci-dessus, ou tous les messages d'information et ci-dessus, pour tout système de taille raisonnable, le volume de suivi d'activité (démarrage, arrêt, etc.) et de journalisation détaillée devient tout simplement trop.
Plutôt que d'avoir un seul commutateur qui active ou désactive tout, 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 souhaitées et les définir sur le suivi d'activité ou même sur les niveaux de débogage.
Le nombre de sources de trace dont vous avez besoin dépend de votre application, par exemple, vous pouvez vouloir une source de trace par assemblage ou par section principale de votre application.
Si vous avez besoin d'un contrôle encore plus précis, ajoutez des commutateurs booléens individuels pour activer / désactiver le traçage spécifique à haut volume, par exemple les vidages de messages bruts. (Ou une source de trace distincte pourrait être utilisée, similaire à WCF / WPF).
Vous pouvez également envisager des sources de trace distinctes pour la trace d'activité par rapport à 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, utilisez-en autant que vous en avez besoin.
Les auditeurs
Q: Quelles sorties de journal utilisez-vous?
Cela peut dépendre du type d'application que vous écrivez et des éléments enregistrés. Habituellement, des choses différentes vont à différents endroits (c'est-à-dire plusieurs sorties).
Je classe généralement les sorties en trois groupes:
(1) Événements - Journal des événements Windows (et fichiers de trace)
Par exemple, si vous écrivez un serveur / service, la meilleure pratique sous Windows consiste à utiliser le journal des événements Windows (vous n'avez pas d'interface utilisateur pour faire rapport).
Dans ce cas, tous les événements Fatal, Error, Warning et (service-level) Information doivent être enregistrés dans le journal des événements Windows. Le niveau Information doit être réservé à ce type d'événements de haut niveau, ceux que vous souhaitez afficher dans le journal des événements, par exemple "Service Started", "Service Stopped", "Connected to Xyz", et peut-être même "Schedule Initiated" , "Utilisateur connecté", etc.
Dans certains cas, vous souhaiterez peut-être faire de l'écriture dans le journal des événements une partie intégrée de votre application et non via le système de suivi (c'est-à-dire écrire directement les entrées du journal des événements). Cela signifie qu'il ne peut pas être désactivé accidentellement. (Notez que vous souhaitez également noter le même événement dans votre système de trace afin de pouvoir corréler).
En revanche, une application d'interface graphique Windows les signale généralement à l'utilisateur (bien qu'ils puissent également se connecter au journal des événements Windows).
Les événements peuvent également avoir des compteurs de performances associés (par exemple, nombre d'erreurs / s), et il peut être important de coordonner toute écriture directe dans le journal des événements, les compteurs de performances, l'écriture dans le système de suivi et la notification à l'utilisateur afin qu'ils se produisent à le 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 Windows, puis le même événement avec le même horodatage dans le journal de trace (avec d'autres détails de trace).
(2) Activités - Fichiers journaux d'application ou table de base de données (et fichiers de trace)
Il s'agit de l'activité régulière d'un système, par exemple la page Web servie, le marché boursier déposé, la prise de commande, le calcul effectué, etc.
Le suivi d'activité (démarrage, arrêt, etc.) est utile ici (à la bonne granularité).
En outre, il est 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 et contenant des données structurées (c'est-à-dire un ensemble de champs).
Les choses peuvent devenir un peu floues selon votre application. Un bon exemple pourrait être un serveur Web qui écrit chaque demande dans un journal Web; des exemples similaires peuvent ê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 exemple pas si bon est les transactions boursières ou un système d'ordres de vente. Dans ces systèmes, vous enregistrez probablement déjà l'activité car ils ont une valeur commerciale importante, mais le principe de la corrélation avec d'autres actions est toujours important.
En plus des journaux d'applications personnalisés, les activités ont souvent des compteurs de performances associés, par exemple le nombre de transactions par seconde.
En général, vous devez coordonner la journalisation 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 performances et connectez-vous à votre système de trace. Si vous faites tout en même temps (ou directement les uns après les autres dans le code), les problèmes de débogage sont plus faciles (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 au niveau détaillé et inférieur (par exemple, des commutateurs booléens personnalisés pour activer / désactiver les vidages de données brutes). Cela fournit les tripes ou les détails de ce qu'un système fait au niveau d'une sous-activité.
Il s'agit du niveau que vous souhaitez pouvoir activer / désactiver pour des sections individuelles de votre application (d'où les multiples sources). Vous ne voulez pas que ces trucs encombrent le journal des événements Windows. Parfois, une base de données est utilisée, mais il est plus probable que des fichiers journaux roulants soient purgés après un certain temps.
Une grande différence entre ces informations et un fichier journal d'application est qu'il n'est pas structuré. Alors qu'un journal d'application peut avoir des champs pour À, De, Montant, etc., les traces de débogage détaillées peuvent être tout ce qu'un programmeur insère, par exemple "vérifier les valeurs X = {valeur}, Y = faux", ou des commentaires / marqueurs aléatoires comme " Fait, réessayant ".
Une pratique importante consiste à vous assurer que les éléments que vous placez dans les fichiers journaux des applications ou le journal des événements Windows sont également enregistrés dans le système de suivi avec les mêmes détails (par exemple, l'horodatage). Cela vous permet ensuite de corréler les différents journaux lors de l'enquête.
Si vous prévoyez d'utiliser une visionneuse de journaux particulière parce que vous avez une corrélation complexe, par exemple la visionneuse de trace de service, vous devez utiliser un format approprié, c'est-à-dire XML. Sinon, un simple fichier texte est généralement assez bon - aux niveaux inférieurs, les informations sont en grande partie non structurées, vous pouvez donc trouver des vidages de tableaux, des vidages de pile, etc. Pourvu que vous puissiez établir une corrélation avec des journaux plus structurés à des niveaux supérieurs, les choses devraient ça va.
Q: Si vous utilisez des fichiers, utilisez-vous des journaux de roulement ou un seul fichier? Comment mettez-vous les journaux à la disposition des utilisateurs?
R: Pour les fichiers, vous voulez généralement rouler les fichiers journaux 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 déroulants ne sont accessibles que lorsque cela est nécessaire. (Le journal des événements Windows ou les journaux d'application de base de données auraient leurs propres mécanismes d'accès).
Si vous n'avez pas facilement accès au système de fichiers, le suivi du débogage vers une base de données peut être plus facile. [c'est-à-dire implémenter une base de données TraceListener].
Une solution intéressante que j'ai vue pour une application Windows GUI était qu'elle enregistrait des informations de traçage très détaillées sur un "enregistreur de vol" lors de son exécution, puis lorsque vous la fermiez si elle n'avait aucun problème, elle supprimait simplement le fichier.
Si toutefois il tombait en panne ou rencontrait un problème, le fichier n'était pas supprimé. Soit s'il détecte l'erreur, soit la prochaine fois qu'il s'exécute, il remarquera le fichier, puis il peut prendre des mesures, par exemple le compresser (par exemple 7zip) et l'envoyer par e-mail ou autrement le rendre disponible.
De nos jours, de nombreux systèmes intègrent le signalement automatisé des pannes à un serveur central (après vérification auprès des utilisateurs, par exemple pour des raisons de confidentialité).
Visualisation
Q: Quels outils utilisez-vous pour afficher les journaux?
R: Si vous avez plusieurs journaux pour différentes raisons, vous utiliserez plusieurs visualiseurs.
Notepad / vi / Notepad ++ ou tout autre éditeur de texte est la base des journaux de texte brut.
Si vous avez des opérations complexes, par exemple des activités avec des transferts, 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 facile).
Comme je connecte généralement des informations de haut niveau au journal des événements de Windows, cela fournit un moyen rapide d'obtenir une vue d'ensemble, de manière structurée (recherchez les jolies icônes d'erreur / d'avertissement). Vous n'avez besoin de commencer à rechercher des fichiers texte que s'il n'y en a pas assez dans le journal, bien qu'au moins le journal vous donne un point de départ. (À ce stade, il est utile de vous assurer que vos journaux ont des entrées coordonnées).
Généralement, le journal des événements Windows met également ces événements importants à la disposition d'outils de surveillance tels que 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 ID d'activité particulier. (Avec les fichiers texte, vous pouvez utiliser Grep / PowerShell ou similaire pour filtrer le GUID particulier que vous souhaitez)
MS Excel (ou un autre tableur). Cela peut être utile pour analyser des informations structurées ou semi-structurées si vous pouvez les importer avec les bons délimiteurs afin que différentes valeurs se retrouvent dans différentes colonnes.
Lors de l'exécution d'un service en débogage / test, je l'héberge généralement dans une application console pour plus de simplicité. Je trouve un enregistreur de console coloré utile (par exemple rouge pour les erreurs, jaune pour les avertissements, etc.). Vous devez implémenter un écouteur de trace personnalisé.
Notez que le cadre n'inclut pas un enregistreur de console coloré ou un enregistreur de base de données, donc pour le moment, vous devrez les écrire si vous en avez besoin (ce n'est pas trop difficile).
Cela m'énerve vraiment que plusieurs cadres (log4net, EntLib, etc.) aient perdu du temps à réinventer la roue et à réimplémenter la journalisation, le filtrage et la journalisation de base dans des fichiers texte, le journal des événements Windows et des fichiers XML, chacun dans leur propre manière différente (les instructions de journal 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 ceux-ci existaient déjà et qu'il ne fallait plus que quelques écouteurs de trace pour System.Diagnostics. Parlez d'un gros gaspillage d'efforts en double.
Q: Si vous créez une solution ASP.NET, utilisez-vous également ASP.NET Health Monitoring? Incluez-vous la sortie de trace dans les événements du moniteur d'intégrité? Qu'en est-il de Trace.axd?
Ces choses peuvent être activées / désactivées au besoin. Je trouve Trace.axd très 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 suivi à long terme.
Q: Qu'en est-il des compteurs de performances personnalisés?
Pour une application professionnelle, en particulier un serveur / service, je m'attends à le voir entièrement instrumenté avec les deux compteurs de l'Analyseur de performances et la connexion au journal des événements Windows. Ce sont les outils standard de Windows et doivent être utilisés.
Vous devez vous assurer d'inclure les programmes d'installation pour les compteurs de performances 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 s'exécute normalement, elle ne devrait pas avoir besoin de privilèges d'administration (et ne pourra donc pas créer de journaux manquants).
C'est une bonne raison de pratiquer le développement en tant que non-administrateur (ayez un compte administrateur séparé pour quand 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 y écrivez; si vous vous développez en tant que non-administrateur, vous attraperez cela tôt et éviterez une mauvaise surprise lorsqu'un client installe votre système et ne peut pas l'utiliser car il ne fonctionne pas en tant qu'administrateur.