Quels sont certains modèles et anti-modèles de journalisation d'application? [fermé]

67

J'ai récemment eu à enquêter sur un problème de terrain pour notre application de grande entreprise. J'ai été horrifié par les journaux que j'ai dû parcourir pour tenter de trouver le problème et à la fin de la journée, ils ne nous ont pas du tout aidés à identifier / isoler le bogue.

Remarque: Je comprends que tous les bogues ne sont pas détectables via les journaux. Cela ne change pas le fait que les journaux sont horribles.

Notre journalisation présente des problèmes évidents que nous pouvons déjà tenter de résoudre. Je ne veux pas les énumérer ici et je ne peux pas simplement vous montrer nos fichiers de log afin que vous puissiez donner des conseils sur ce qu'il faut faire.

Au lieu de cela, afin d’évaluer l’état de notre situation en matière d’exploitation forestière, j'aimerais savoir:

  1. Quelles sont , le cas échéant, des instructions pour la journalisation d’une application, en particulier une application volumineuse.
  2. Existe-t-il des modèles à suivre ou des anti-modèles à connaître?
  3. Est-ce une chose importante à réparer ou peut-on même le faire ou bien tous les fichiers journaux sont simplement énormes et vous avez besoin de scripts supplémentaires pour les analyser?

Note latérale: nous utilisons log4j.

c_maker
la source

Réponses:

56

Quelques points que ma pratique s'est avérée utile:

  • Conservez tout le code de journalisation dans votre code de production. Avoir la capacité d'activer la consignation en production plus ou moins détaillée, de préférence par sous-système et sans redémarrer votre programme.

  • Rendez les journaux faciles à analyser petit à petit grep. S'en tenir à plusieurs champs communs au début de chaque ligne. Identifiez l'heure, la gravité et le sous-système dans chaque ligne. Formulez clairement le message. Rendez chaque message de journal facile à mapper à sa ligne de code source.

  • Si une erreur se produit, essayez de collecter et de consigner autant d'informations que possible. Cela peut prendre beaucoup de temps mais c'est correct car le traitement normal a de toute façon échoué. Ne pas avoir à attendre lorsque la même situation se produit en production avec un débogueur attaché est inestimable.

Les journaux sont principalement nécessaires pour la surveillance et le dépannage. Mettez-vous à la place du dépanneur et réfléchissez au type de journaux que vous aimeriez avoir lorsqu'un incident anormal se produit ou s'est produit en pleine nuit.

9000
la source
10
J'aime cette réponse, mais j'ajouterais qu'il est important de consigner le choix qui a été fait aux points de décision. J'ai vu de nombreux systèmes dans lesquels de nombreux fichiers indésirables étaient consignés, mais pas les décisions clés. Donc, 95% de l'exploitation forestière est fondamentalement inutile. De plus, pour les systèmes de type requête / réponse, il est plus important de pouvoir se connecter par requête plutôt que par sous-système.
Kevin
4
+1 J'aime ce que vous dites quand vous vous mettez à la place d'un dépanneur. Il semble que les instructions du journal doivent contenir beaucoup plus de messages de qualité que ce que nous avons fait auparavant ...
c_maker
1
Il est important de noter que la consignation des erreurs doit être consignée dans le journal des événements approprié ainsi que dans les journaux des applications.
Steven Evers
2
@SnOrfus: Il existe plusieurs façons de stocker les journaux, mais l'essentiel est que les messages de journal doivent être disponibles jusqu'à la dernière seconde où le système est tombé en panne, à la manière d'une boîte noire pour aéronef. Si vous utilisez un type de mise en mémoire tampon, fournissez une option pour le contourner / vider chaque message.
Rwong
1
@Rig: d'un autre côté, de nombreux enregistreurs locaux n'ont mis en œuvre aucune mise en mémoire tampon (et ont purgé consciencieusement chaque message), ce qui a entraîné des performances très médiocres. C'est pourquoi il faut le rendre facultatif.
Rwong
28

Je travaille avec des systèmes de sécurité en temps réel critiques et la journalisation est souvent le seul moyen d'attraper les bugs rares qui apparaissent une fois par lune bleue tous les 53 mardis, quand c'est la pleine lune, si vous voyez ce que je dérive. Cela vous rend obsédé par le sujet, alors je vais m'excuser si je commence à mousser à la bouche. Ce qui suit a été écrit pour les journaux de débogage de code natif, mais la plupart d'entre eux sont également applicables au monde géré ...

Utilisez des fichiers journaux de texte. Cela semble évident, mais certaines personnes essaient de générer des fichiers journaux binaires: c'est idiot, car je n'ai pas besoin de rechercher un outil de lecture lorsque je suis sur le terrain. De plus, si c'est du texte et que le débogage est prolixe, l'ingénieur de terrain a de bonnes chances de lire le fichier et de diagnostiquer le problème sans jamais revenir à moi. Tout le monde gagne.

Je conçois des systèmes capables de tout enregistrer, mais je ne les allume pas par défaut. Les informations de débogage sont envoyées à une boîte de dialogue de débogage masquée qui les horodate et les envoie dans une zone de liste (limitée à environ 500 lignes avant suppression). Cette boîte de dialogue me permet de les arrêter, de les enregistrer automatiquement dans un fichier journal ou de les rediriger vers un débogueur attaché. Ce détournement me permet de voir la sortie de débogage de plusieurs applications parfaitement sérialisées, ce qui peut parfois sauver la vie. J'avais l' habitude d'utiliser des niveaux de journalisation numériques (plus vous définissez le niveau, plus vous en capturez):

off
errors only
basic
detailed
everything

mais ceci est trop inflexible - au fur et à mesure que vous avancez vers un bogue, il est beaucoup plus efficace de pouvoir vous connecter en vous connectant exactement à ce dont vous avez besoin sans avoir à parcourir des tonnes de détritus, et il peut s'agir d'un type de transaction ou d'opération particulier cela cause l'erreur. Si cela vous oblige à tout activer, vous ne faites que rendre votre travail plus difficile. Vous avez besoin de quelque chose de plus fin.

Alors maintenant, je suis en train de passer à la journalisation basée sur un système de drapeau. Tout ce qui est consigné a un drapeau détaillant son type d’opération, et un ensemble de cases à cocher me permettant de définir ce qui est consigné. Typiquement cette liste ressemble à ceci:

#define DEBUG_ERROR          1
#define DEBUG_BASIC          2
#define DEBUG_DETAIL         4
#define DEBUG_MSG_BASIC      8
#define DEBUG_MSG_POLL       16
#define DEBUG_MSG_STATUS     32
#define DEBUG_METRICS        64
#define DEBUG_EXCEPTION      128
#define DEBUG_STATE_CHANGE   256
#define DEBUG_DB_READ        512
#define DEBUG_DB_WRITE       1024
#define DEBUG_SQL_TEXT       2048
#define DEBUG_MSG_CONTENTS   4096

Ce système de journalisation est livré avec la version validée, activée et sauvegardée dans un fichier par défaut. Il est trop tard pour savoir que vous auriez dû vous connecter APRÈS le bogue, si ce bogue ne se produit que tous les six mois en moyenne et que vous ne pouvez pas le reproduire. La journalisation qui fonctionne uniquement avec les versions de débogage est juste. plaine. stupide.

Le logiciel est généralement livré avec ERROR, BASIC, STATE_CHANGE et EXCEPTION activé, mais cela peut être modifié dans le champ via la boîte de dialogue de débogage (ou un paramètre registry / ini / cfg, où ces éléments sont enregistrés).

Oh et une chose - mon système de débogage génère un fichier par jour. Vos exigences peuvent être différentes. Mais assurez-vous que votre code de débogage commence chaque fichier avec la date, la version du code que vous utilisez, et si possible un marqueur pour l'ID client, l'emplacement du système ou autre. Vous pouvez obtenir un méli-mélo de fichiers journaux provenant du terrain, et vous avez besoin de savoir ce qui vient d'où et quelle version du système qu'ils utilisaient qui est réellement dans les données elles-mêmes, et vous ne pouvez pas faire confiance au client. / ingénieur de terrain pour vous dire quelle version ils ont - ils peuvent simplement vous dire quelle version ils pensent. Pire, ils peuvent signaler la version exe présente sur le disque, mais l'ancienne version est toujours en cours d'exécution car ils ont oublié de redémarrer après le remplacement. Demandez à votre code de vous dire lui-même.

Enfin, vous ne voulez pas que votre code génère ses propres problèmes, installez donc une fonction de minuterie pour purger les fichiers journaux après tant de jours ou de semaines (vérifiez simplement la différence entre l'heure actuelle et l'heure de création du fichier). Cela convient pour une application serveur qui fonctionne tout le temps. Sur une application côté client, vous pouvez vous en servir pour purger les anciennes données au démarrage. Nous purgeons généralement après 30 jours environ, sur un système ne nécessitant pas de visites d'ingénieur fréquentes, vous souhaiterez peut-être le laisser plus longtemps. Évidemment, cela dépend également de la taille de vos fichiers journaux.

Bob Moore
la source
1
+1 En général, excellente réponse, mais surtout pour l'insertion de l'identifiant de l'application et des informations de version dans le fichier journal. Malheureusement, c'est souvent oublié.
Binary Worrier
27

Ma ressource publique préférée pour les consignes de journalisation est Apache JCL Best Practices .

Les meilleures pratiques pour JCL sont présentées dans deux catégories: Général et Entreprise. Les principes généraux sont assez clairs. Les pratiques d'entreprise sont un peu plus impliquées et la raison pour laquelle elles sont importantes n'est pas toujours claire.

Les principes de meilleures pratiques d'entreprise s'appliquent aux composants et outils middleware censés s'exécuter dans un environnement de niveau "Entreprise". Ces problèmes concernent la journalisation en tant qu'internationalisation et la détection des pannes. Les entreprises requièrent plus d’efforts et de planification, mais sont fortement encouragées (si non requises) dans les systèmes au niveau de la production. Différentes entreprises / environnements ont des exigences différentes, donc être flexible aide toujours ...

Malgré le ciblage de JCL, ceux-ci semblent être suffisamment génériques pour être adoptés pour la journalisation en général.

  • Mes "directives" personnelles pour la journalisation sont les suivantes: au niveau du débogage, j'essaie de faire en sorte que mes journaux se lisent comme une histoire - avec une logique compréhensible et des détails suffisants (mais non surchargés).

Le plus célèbre des anti-modèles est probablement "l'avaleur des exceptions" - il suffit de chercher sur le Web pour le trouver.

En ce qui concerne les gros fichiers de journalisation, dans ma pratique, c’était surtout le cas normal. Et oui, les scripts supplémentaires comme vous les appelez et / ou des outils tels que Chainsaw me semblent également normaux.

  • Ce qui précède ne signifie pas pour autant que vous devez toujours mettre aveuglément tous les journaux dans un seul fichier. Parfois, il peut être utile d’écrire / copier certains journaux dans des fichiers séparés. Par exemple, dans mon projet récent, les responsables de l'assurance qualité ont demandé des fichiers dédiés pour les métriques et les données de synchronisation, ainsi que des rapports succincts sur les opérations du système. Ils ont dit qu’ils en tireraient parti et que c’est ce qu’a fait l’enquête (l’avantage des fichiers de rapports brefs s’est avéré très important).

PS En ce qui concerne les anti-modèles, d'autres qui viennent à l'esprit sont les "inondations" et les messages insensés.

  • Je l'appelle inondation lorsque je vois plusieurs messages similaires provenant d'une boucle comportant de nombreuses itérations. Pour moi, l’inondation est suffisamment agaçante pour essayer de l’éliminer lorsque je le détecte dans le code source. Généralement, l’améliorer nécessite un peu d’art - parce que les choses qui se passent dans la boucle peuvent être intéressantes. Quand je n'ai pas le temps de l'améliorer, j'essaie au moins de changer le niveau de consignation de ces messages au plus bas pour faciliter le filtrage.

  • Les messages insensés semblent être des déchets très populaires. Celles-ci ont l'air inoffensives lorsqu'elles sont lues dans le code source - je suppose qu'il faut passer par la douleur d'analyser la sortie de débogage ressemblant à ...

    step #1
    step #2
    step #3
    

    ... d'apprécier profondément leur laideur inhérente. Mon heuristique préférée pour détecter ce type de problèmes au niveau du code source (proposé par collègue dans l'un de mes projets antérieurs) consiste à calculer le nombre d' occurrences de symboles d'espace dans les littéraux de chaîne utilisés dans la journalisation. D'après mon expérience, zéro espace garantit fondamentalement que la déclaration de journalisation est insensée, un espace est également un bon indicateur du problème potentiel.

moucheron
la source
4
Pour éviter les inondations, je rassemble généralement les heuristiques de la boucle et les affiche après la boucle. Cela signifie que tout ce qui est intéressant dans la boucle doit être stocké dans une variable (comme somethingSpecialHappenedCount), puis exporté vers le consignateur.
Spoike
@Spoike bon point! le stockage dans une variable est en effet l' un de mes trucs préférés personnels pour lutter contre les inondations
moucheron
1
Je fais sortir tous les différents compteurs vers le logger sous forme de table ASCII dans le journal après la fin de la boucle afin qu'ils puissent être facilement comparés. L'idée de la table a été inspirée par celle générée par StopWatch.prettyPrint () de Spring . Autre que cela, rendre le texte du journal lisible et pertinent est toujours un "art" comme mentionné précédemment dans la réponse.
Spoike
@Spoike: (et @gnat) C'est intéressant. Donc, fondamentalement, vous ajoutez du code réel à la logique métier uniquement dans le but de la journalisation? Je n'ai jamais entendu parler de cela ni fait cela auparavant et je ne sais pas comment je pourrais le justifier à mes collègues. Je crains que si nous commençons à le faire, certains de nos développeurs vont encombrer le code source à un point tel que la logique métier devient compliquée et difficile à lire. Le simple fait de consigner une déclaration rend déjà la source plus laide.
c_maker
2
@c_maker votre point de vue sur le mélange de la journalisation avec la logique métier mérite une question dédiée. Personnellement, je n'ai pas encore d'opinion forte sur ces questions. En théorie, on peut imaginer des améliorations de la séparation utilisant AOP et iirc. Il existe même des applications pratiques pour cette approche. Dans la pratique, cependant, je reste fidèle à une approche «mixte» et je n’y ai pas eu jusqu’à présent de problème majeur. Encombrer le code source est un réel danger, mais, encore une fois, j’ai réussi jusqu’à présent à le faire coexister avec le code de journalisation plutôt «pacifiquement». Cela nécessite bien sûr un certain effort.
moucher
11

Connectez l'exception une seule fois!

L’un des points douloureux que j’ai le plus souvent remarqué est la journalisation et la modification d’une exception. Par conséquent, les fichiers journaux contiennent les mêmes exceptions plusieurs fois sur plusieurs niveaux de pile.

Nayaki
la source
5

Voici un anti-modèle: créer deux douzaines de champs "variable générique" dans une table de base de données pour suivre tout ce qui est imaginable, puis avoir 88 valeurs (en comptant) différentes enum pour différents types de journaux.

Wayne Molina
la source
+1 - J'ai vu ça. "Tables d'erreur" ayant des colonnes telles que chaîne1, chaîne2, chaîne3, chaîne4, chaîne5, où la concaténation de toutes les colonnes entraîne un code d'erreur qui n'est référencé dans aucune des documentations. Le résultat est une journalisation à la fois déroutante et inutile; également connu sous le nom de "tierce partie entreprise-app-avec-custom-development-debugging-hell".
Morgan Herlocker
Dans mon cas, il s'agit "d'un système d'exploitation forestière à la main sans aucune idée de ce que l'exploitation forestière implique réellement"
Wayne Molina
4

Mon expérience avec les journaux est d' autant plus grande que les journaux sont volumineux, mais suffisamment cohérents pour pouvoir les filtrer par machine et pour pouvoir configurer individuellement un niveau de gravité pour chaque composant de votre application.

En outre, il est très difficile de prédire de quelle journalisation vous aurez besoin pour trouver un futur bogue. La plupart des endroits évidents pour identifier les bogues sont corrigés avant que le produit ne sorte. Il n'est pas rare que le résultat d'un rapport de bogue soit que vous venez d'ajouter une journalisation pour aider à diagnostiquer si cela se reproduit.

Karl Bielefeldt
la source
2

Quelques notes du côté des opérations de la maison ici:

1) Assurez-vous que les journaux sont configurables localement, de préférence avec un outil pas plus lourd qu'un éditeur de texte. La plupart du temps, nous ne voulons pas obtenir de journalisation au niveau TRACE, mais nous aimons pouvoir l’activer.

2) Dans la mesure du possible, assurez-vous que les journaux peuvent être lus avec un outil pas plus lourd qu'un éditeur de texte. Rien n’est pire que de partir à la chasse aux outils à une heure inconnue lorsque le système de production est défaillant.

Wyatt Barnett
la source
1

De ma propre expérience de travail avec des applications Web:

(& considérant le stockage est très bon marché de nos jours)

  • Connectez-vous autant d'informations disponibles (à ce moment précis) que vous pouvez.
  • J'inclus toujours DateTime.Now dans mes chaînes de connexion.
  • Je me connecte toujours (si cela est possible) à la durée d'une "action" spécifique.
  • Soyez cohérent avec vos chaînes de connexion. Depuis toujours j'utilise ce genre de motif:

    • "[Info X] [Info Y] [Info Z] [etc.]"
Sabiland
la source
1

En dehors du stacktrace, enregistrez l'état actuel de l'application et l'entrée.

Le logiciel est déterministe, ces deux éléments sont généralement la seule chose dont vous avez besoin pour reproduire le bogue. Dans certains cas, le stockage de l'état complet peut être gênant. Par conséquent, les méthodes de reproduction de l'état actuel, par exemple les entrées précédentes, sont également utiles.

Bien sûr, plus de données est toujours préférable, mais au minimum, ces deux solutions sont un bon début pour les accidents les plus faciles.

ladida
la source
3
"Le logiciel est déterministe" => pas toujours malheureusement. Pensez aux bugs de concurrence, par exemple.
Assylias