Introduction : Pourquoi la journalisation est cruciale en Rust
La journalisation ne se résume pas à écrire des événements dans un fichier. Dans les systèmes à forte charge et sécurisés, où Rust trouve son utilisation principale (serveurs web, utilitaires CLI, systèmes embarqués), les logs sont la seule source de vérité lors du débogage et de la surveillance. Rust propose un écosystème où le choix de la bonne approche de journalisation peut avoir un impact significatif sur les performances et la maintenabilité du code.
Dans cet article, nous allons détailler les principes fondamentaux de la journalisation en Rust, en commençant par la crate de base log et en terminant par des outils avancés comme tracing. Vous apprendrez à éviter les erreurs typiques, à configurer les niveaux de journalisation et à structurer la sortie pour l'analyse.
Les bases : La crate log et l'architecture façade
En Rust, le standard de facto est la crate log. Elle fournit une façade (abstraction) qui ne dépend d'aucun backend spécifique. Vous écrivez le code en utilisant les macros log::info!, log::error!, et le choix de l'implémentation (où écrire : dans un fichier, la console, syslog) revient à l'utilisateur de la bibliothèque.
Installation et configuration de base
Ajoutez dans Cargo.toml :
[dependencies]
log = "0.4"
env_logger = "0.11"
env_logger est le backend le plus populaire pour la sortie vers stderr. Il se configure via la variable d'environnement RUST_LOG.
Exemple de journalisation simple
use log::{info, warn, error};
fn main() {
env_logger::init();
info!("Application démarrée");
warn!("Ceci est un avertissement");
error!("Erreur critique : {}", 42);
}
Exécutez avec le niveau : RUST_LOG=info cargo run. Vous ne verrez que les messages info et supérieurs. Si la variable n'est pas définie, les logs ne seront pas affichés.
Niveaux de journalisation
Dans log, 5 niveaux sont définis (par ordre de priorité croissante) :
trace— informations de débogage extrêmement détaillées (par exemple, entrée/sortie de fonction).debug— utile pour le développeur lors du débogage.info— événements importants du fonctionnement de l'application (démarrage, arrêt, opérations réussies).warn— situations potentiellement dangereuses qui ne cassent pas le fonctionnement.error— erreurs irrécupérables nécessitant une intervention.
Conseil : En production, utilisez le niveau info ou warn. trace et debug sont mieux réservés au développement.
Bonnes pratiques : Comment écrire des logs correctement
Il ne suffit pas d'insérer info!("Something"). Pour que les logs soient utiles, suivez ces règles.
1. Logs structurés plutôt que chaînes de caractères
Évitez la concaténation manuelle de chaînes. Utilisez des champs nommés. Dans log, cela se fait via le formatage :
let user_id = 123;
let action = "login";
info!("Utilisateur {} a effectué {}", user_id, action);
Pour une structuration avancée (JSON), utilisez la crate slog ou tracing.
2. Contexte et identifiants
Ajoutez toujours du contexte : request_id, user_id, session_id. Cela permet de lier les logs dans les systèmes distribués.
warn!("Erreur de validation",
user_id = user_id,
field = "email",
reason = "format incorrect"
);
3. Évitez la journalisation dans les boucles critiques
La journalisation est une opération coûteuse (entrées-sorties). Ne placez pas trace! à l'intérieur de boucles avec des millions d'itérations. Utilisez la journalisation conditionnelle ou des compteurs de métriques.
4. Utilisez RUST_LOG pour une configuration flexible
Vous pouvez filtrer les logs par modules et crates :
RUST_LOG="warn,my_crate=debug,othe