Logs applicatives - les bonnes pratiques
En tant que développeur, travaille dans une Tierce Maintenance Application et Évolutive (TMA). Cette expérience m’a permis de prendre l’importance du nommage des variables, des méthodes, des classes etc, et de comprendre que nous les développeurs, passons plus de temps à lire du code qu’à en écrire. Tout au long du cycle de vie d’une application Java EE par exemple, c’est une nécessité de détenir des traces (logs) de qualités :
- Au cours du développement, afin de suivre l’exécution pas à pas et de détecter d’éventuelles anomalies.
- Au cours de la recette, afin de corréler les anomalies fonctionnelles et exécution du programme.
- Au cours de l’exploitation, afin de surveiller la « bonne santé » de l’application.
Obtenir des logs de qualités ce n’est pas si facile. Au cours d’un suivi d’exploitation, nous avons besoin des traces (logs) nous permettant d’orienter les alertes vers des symptômes plutôt que des causes, et permettre à tous les acteurs intervenant lors de ces différentes phases de pouvoir interagir efficacement.
Il y a plusieurs choses à prendre en compte :
-
Les logs sont un outil collaboratif issu d’un processus itératif.
Les messages de logs sont destinés à tous les acteurs du projet. Il est essentiel de garder à l’esprit, lors de tout développement, qu’une application est vouée à être développée, puis testée, puis exploitée (et éventuellement corrigée). Les logs doivent prendre en compte ces 3 phases de la vie d’application, et permettre à tous les acteurs intervenant lors de ces différentes phases de pouvoir interagir efficacement. C’est pourquoi chaque méthode devrait au minimum contenir des traces de niveau INFO, WARN et ERROR, chaque niveau ciblant un des acteurs intervenant sur l’application. De plus, il est difficile de réaliser une bonne log du premier coup. La pertinence de celle-ci sera renforcée par des échanges constants entre exploitation et développement (ciblage spécifique d’un problème de performance, anomalie non remontée initialement…). Chaque correction d’anomalie devrait entraîner l’ajout de traces de niveau DEBUG, qui permettront un diagnostic plus fin en cas de nouvelle occurrence.
-
Les logs sont paramétrées en fonction des besoins.
L’écriture d’une log a un coût qu’il ne faut pas négliger. Les performances d’une application en production ne doivent pas être plombées par la génération de lignes de log inutiles. Et il est inenvisageable de demander à chaque développeur d’effacer systématiquement les logs qu’il ajoute (si ces logs ont été utiles à un moment de la vie du projet, il y a de grandes chances qu’elles puissent resservir plus tard.). Il est donc impératif de choisir un framework de logs facilement administrable autant en développement qu’en production :
Pour le développement : Une configuration de logs par défaut quand on fait un checkout du code. La possibilité de modifier à chaud la configuration des logs lors de l’éxécution de l’application dans l’IDE.
Pour l’exploitation : Une configuration par fichier, séparée du WAR, ce qui permet de livrer/modifier l’application indépendamment de sa configuration (et vice et versa).Des mécanismes de reconfiguration à chaud par modification de fichier et/ou par API (JMX).
- Les logs doivent avoir un impact minimal sur les performances globales de l’application.
- Une utilisation correcte du logger est la première source d’information.
Chaque niveau de log a ses spécificités. Bien définir l’utilisation de chacun de ces niveaux permet de s’affranchir du risque de logger trop, ou trop peu, aux différentes étapes du cycle de vie de l’application. Utiliser des niveaux de log cohérents et pertinents donne donc un premier niveau d’information essentiel. Voici les niveaux existants dans les différents frameworks, et leur utilisation communément admise (Log4J/Apache Commons Logging – java.util.logging) :
- TRACE / FINE : niveau d’information ultra fin.
- DEBUG / CONFIG : information détaillée pour le suivi d’exécution du programme (identification et résolution d’éventuelles anomalies).
- INFO : information essentielle sur le programme, suivi de l’exécution d’un point de vue global.
- WARN / WARNING : situation d’exécution non-idéale (utilisation d’API dépréciée, ressource non critique absente…).
- ERROR / <pas d’équivalent> : situation d’erreur ou inattendue, qui n’entraine pas forcément une situation de blocage (accès à un service externe non critique et dont l’accès est re-testé périodiquement).
- FATAL / SEVERE : situation d’erreur critique, qui entraîne un blocage voire un arrêt du système (problème de connexion à la DB par exemple).
-
Une log efficace doit remplacer le debugger