Comment tracer les informations de débogage dans le code ?
Mise à jour :
Le logging est un élément essentiel pour surveiller, déboguer et maintenir les applications en production. En Python, la bibliothèque de logging intégrée permet de créer et de gérer des journaux de manière flexible, facilitant ainsi la détection et la résolution des problèmes.
C’est quoi le logging ?
Le logging est le processus d’enregistrement des événements, des messages ou
des erreurs générées par un programme lors de son exécution. Ces enregistrements,
appelés logs, permettent de suivre le déroulement de l’application, de
comprendre le comportement du code et de détecter les problèmes ou les
anomalies. Contrairement aux simples impressions sur la console avec print()
,
le logging offre plus de contrôle et de flexibilité, comme la gestion des
niveaux de gravité des messages, l’enregistrement dans des fichiers et la
personnalisation du format des messages.
Les logs peuvent être utilisés pour :
- Surveiller l’application : suivre les actions importantes qui s’y déroulent, comme le traitement de données ou la réussite d’une opération.
- Déboguer : repérer et comprendre les erreurs en enregistrant les détails de leur apparition.
- Analyser la performance : examiner la durée et la fréquence de certaines opérations pour améliorer l’efficacité.
- Auditer : garder un historique des actions effectuées pour des raisons de conformité ou de sécurité.
Grâce à la bibliothèque de logging de Python, vous pouvez capturer et formater ces informations de manière organisée, les envoyer à plusieurs destinations (console, fichiers, etc.), et les gérer selon les besoins de votre application.
Configurer un logger basique
La bibliothèque de logging intégrée à Python est simple à utiliser pour créer un système de logs efficace. Pour démarrer, il est essentiel de comprendre comment configurer un logger de base qui permet d’enregistrer des messages de différentes gravités dans la console.
Utilisation de basicConfig
La méthode logging.basicConfig()
est le point de départ pour la configuration
rapide d’un logger. Elle permet de définir le niveau minimal de log, le
format des messages et la destination de sortie. Voici comment l’utiliser :
- Explication des paramètres :
-
level
: définit le niveau minimal de gravité des messages à enregistrer. Par exemple, silevel
est défini surlogging.INFO
, les messages de niveau DEBUG ne seront pas affichés. Les niveaux, par ordre croissant de gravité, sont :- DEBUG : détails de débogage (utilisés pour le diagnostic)
- INFO : messages d’information généraux
- WARNING : messages indiquant des problèmes potentiels
- ERROR : erreurs qui affectent le fonctionnement
- CRITICAL : erreurs graves nécessitant une intervention immédiate
-
format
: définit la mise en forme des messages de log. Les éléments communs incluent :%(asctime)s
: date et heure du message%(levelname)s
: niveau de gravité du message%(message)s
: contenu du message
- Exemple pratique :
Imaginez que vous souhaitez suivre le déroulement de votre programme et repérer des points spécifiques où des erreurs peuvent survenir. La configuration basique peut être suffisante pour surveiller les événements importants :
Dans cet exemple, un message est enregistré avant et après l’opération de division, et un message d’erreur est enregistré si une division par zéro est tentée.
Quand utiliser chaque niveau de logging
- DEBUG : Utilisé principalement lors de la phase de développement pour obtenir des informations détaillées sur le déroulement du code. Utile pour vérifier des valeurs de variables, l’exécution de boucles, etc.
- INFO : Utilisé pour consigner des étapes importantes du programme qui font partie du flux normal. Par exemple, le démarrage ou l’arrêt d’un service.
- WARNING : Signale un problème potentiel qui ne nécessite pas encore d’action immédiate mais qui doit être surveillé.
- ERROR : Employé pour capturer les erreurs qui empêchent une partie du programme de fonctionner correctement, comme des exceptions non gérées ou des échecs de traitement.
- CRITICAL : Réservé aux erreurs qui nécessitent une réponse urgente, comme l’arrêt complet d’un service essentiel.
Configuration via un fichier de configuration
Configurer le logging directement dans le code Python est pratique, mais cela peut rendre la maintenance difficile lorsque les besoins en logs évoluent. Pour une approche plus flexible et modifiable, il est préférable d’utiliser un fichier de configuration. Cette méthode permet de changer la configuration des logs sans modifier le code source de l’application.
Formats de fichiers de configuration
Python prend en charge deux formats principaux pour configurer le logging :
- Fichier de configuration INI (format
.ini
). - Fichier de configuration YAML (avec des bibliothèques tierces comme
PyYAML
).
Le format YAML est plus lisible et est souvent utilisé dans des applications
plus modernes. Vous aurez besoin de la bibliothèque PyYAML
pour le lire.
logging.yaml :
Pour utiliser ce fichier YAML, chargez-le comme suit :
Personnaliser le format des logs
La personnalisation du format des logs permet d’afficher les informations pertinentes de manière structurée et lisible. Python offre la possibilité de modifier le format des messages de log pour inclure des détails tels que la date, le niveau de gravité, le nom du module, et bien plus encore. Un format bien pensé peut faciliter le débogage et le suivi de votre application.
La méthode logging.basicConfig()
permet de spécifier un format personnalisé
pour vos messages de log grâce au paramètre format
. Voici un exemple de
configuration simple :
Voici quelques placeholders utiles pour personnaliser le format des logs :
%(asctime)s
: Affiche la date et l’heure du message.%(levelname)s
: Affiche le niveau de gravité du message (DEBUG, INFO, etc.).%(message)s
: Contenu du message de log.%(name)s
: Nom du logger qui enregistre le message.%(filename)s
: Nom du fichier source du message.%(funcName)s
: Nom de la fonction où le message est enregistré.%(lineno)d
: Numéro de la ligne où le log est appelé.
Journaliser dans des fichiers
Enregistrer les logs dans des fichiers plutôt que de les afficher uniquement sur la console permet de conserver un historique des événements et facilite l’analyse à long terme. Cette approche est particulièrement utile pour les applications en production, où il est indispensable de pouvoir retracer les erreurs et comprendre le comportement de l’application après coup.
Pour enregistrer les logs dans un fichier, il suffit de configurer un
Handler de type FileHandler
ou d’utiliser basicConfig
avec le paramètre
filename
. Voici un exemple simple de configuration :
Avec cette configuration, tous les messages de log seront enregistrés dans le
fichier app.log
et non dans la console. Si le fichier n’existe pas, Python le
créera automatiquement.
Mettre en place de la rotation de logs
Pour éviter que le fichier de log ne devienne trop volumineux et difficile à
gérer, il est conseillé d’utiliser un système de rotation. Python propose la
classe RotatingFileHandler
dans le module logging.handlers
, qui permet de
limiter la taille des fichiers de log et de créer de nouveaux fichiers
lorsqu’une taille maximale est atteinte.
Avec cette configuration, un nouveau fichier de log sera créé lorsque la taille
maximale de 5 Ko sera atteinte. Jusqu’à trois fichiers de sauvegarde seront
conservés (app_rotated.log.1
, app_rotated.log.2
, etc.).
D’autres Handlers
En utilisant différents Handlers, vous pouvez diversifier les sorties de vos logs en les envoyant simultanément vers plusieurs destinations, comme des bases de données, ou même des services distants.
-
SMTPHandler : Envoie les messages de log par e-mail via un serveur SMTP. Utile pour les notifications en cas d’erreurs critiques.
-
HTTPHandler : Envoie les messages de log à un serveur web via une requête HTTP. Utile pour intégrer les logs dans un système de gestion centralisée.
-
SysLogHandler : Permet d’envoyer des messages de log vers un serveur Syslog, couramment utilisé pour la collecte et la gestion centralisée des logs.
La documentation officielle de Python vous donne plus d’informations sur les Handlers disponibles ↗.
Utilisation des filtres
Les filtres dans le module logging de Python permettent d’affiner la sélection des messages à enregistrer ou à afficher en fonction de critères spécifiques. Cela vous offre un contrôle précis sur quels messages de log doivent être traités par un Handler.
Pour créer un filtre personnalisé, il suffit de définir une classe qui hérite de
logging.Filter
et de redéfinir la méthode filter()
:
Dans cet exemple, seul le message contenant le mot “spécial” sera affiché, car il passe le filtre.
Outre les filtres personnalisés, Python offre la possibilité d’utiliser des
filtres intégrés, comme logging.Filter()
pour restreindre les logs à un module
spécifique :
Dans cet exemple, le Handler n’enregistrera que les messages provenant du
module module_filtré
.
Les filtres peuvent également être utilisés pour ajouter des métadonnées aux logs ou pour modifier légèrement les messages avant leur enregistrement :
Ce filtre ajoute un champ user_id
aux messages de log, ce qui est utile pour
enrichir les journaux avec des détails contextuels sans modifier le code
principal de l’application.
Logging pour les modules de l’application
Dans les applications complexes composées de plusieurs modules, il est important de configurer des loggers distincts pour chaque module afin de mieux suivre et diagnostiquer les événements. Chaque logger peut être configuré indépendamment pour capturer des informations spécifiques à un module, offrant ainsi une vue plus détaillée et organisée des logs.
Pour créer des loggers pour différents modules, il suffit d’utiliser
logging.getLogger()
avec le nom du module. Voici comment configurer des
loggers dans une application composée de plusieurs modules.
fichier principal (main.py) :
fichier module_a.py :
fichier module_b.py :
Ajuster les niveaux de log pour chaque module
Il est possible de définir des niveaux de log différents pour chaque logger afin de mieux contrôler la quantité d’informations enregistrées :
Dans cet exemple, module_a
n’enregistrera que les messages de niveau
WARNING et supérieur, tandis que module_b
enregistrera tous les messages
de niveau DEBUG et supérieur.
Logging des exceptions
Lors du développement d’applications, il est nécessaire de consigner non seulement les messages informatifs mais aussi les exceptions qui surviennent. En enregistrant les exceptions, vous pouvez obtenir des informations détaillées sur les erreurs, y compris les stack traces, ce qui facilite le débogage et la correction des problèmes.
Utiliser logger.exception()
La méthode logger.exception()
est particulièrement utile pour consigner les
exceptions avec une stack trace complète. Cette méthode est similaire à
logger.error()
, mais elle ajoute automatiquement les détails de l’exception au
message de log. Elle doit être utilisée uniquement dans un bloc except
.
Exemple simple d’utilisation :
Dans cet exemple, le log contiendra un message de type ERROR avec la stack trace détaillant l’endroit où l’exception a été déclenchée.
Utiliser exc_info=True
Si vous utilisez des méthodes comme logger.error()
ou logger.critical()
,
vous pouvez toujours inclure la stack trace en ajoutant exc_info=True
:
Conclusion
La gestion des logs en Python est indispensable pour surveiller, déboguer et maintenir des applications de manière efficace. Qu’il s’agisse de consigner des événements importants, de capturer des erreurs ou de suivre le déroulement de votre code, la bibliothèque logging intégrée offre toute la flexibilité nécessaire. En comprenant et en maîtrisant les différentes configurations, niveaux de gravité et destinations des logs, vous pouvez construire un système de journalisation robuste qui facilite le diagnostic et l’amélioration continue de votre application.