Contactez-nous

Formatage des logs (patterns, JSON)

Maîtrisez le formatage des logs dans Spring Boot : personnalisez les patterns pour la lisibilité humaine ou utilisez le format JSON pour une analyse automatisée efficace.

L'importance du formatage des logs

Le format dans lequel vos logs sont écrits est aussi important que les informations qu'ils contiennent. Un format bien choisi facilite grandement la lecture, la recherche, le filtrage et l'analyse des logs, que ce soit par un humain ou par des outils automatisés. A l'inverse, un format incohérent ou peu clair peut rendre le débogage et la surveillance extrêmement pénibles.

Spring Boot, en s'appuyant sur des frameworks comme Logback, offre principalement deux approches pour le formatage des logs :

  • Formatage par Patterns (Layouts) : C'est l'approche traditionnelle où vous définissez un modèle textuel (pattern) pour structurer chaque ligne de log. C'est généralement optimisé pour la lecture humaine directe dans une console ou un fichier texte.
  • Formatage Structuré (JSON) : Cette approche consiste à écrire chaque événement de log sous forme d'objet JSON. C'est idéal pour les systèmes de gestion de logs centralisés (comme ELK Stack, Splunk, Grafana Loki, Datadog) qui peuvent facilement parser, indexer et requêter des données structurées.

Le choix entre ces formats dépend de vos besoins, de vos outils et de votre environnement.

Formatage par patterns : lisibilité humaine avant tout

Comme vu précédemment, Spring Boot permet de définir facilement des patterns de formatage via les propriétés logging.pattern.console et logging.pattern.file dans application.properties ou application.yml.

Ces patterns utilisent des "spécificateurs de conversion" (commençant par %) pour indiquer quelles informations inclure et comment les formater. Voici quelques spécificateurs courants (syntaxe Logback) :

  • %d ou %date : Affiche la date et l'heure de l'événement. Le format peut être précisé entre accolades (ex: %d{yyyy-MM-dd HH:mm:ss.SSS}) ou via logging.pattern.dateformat.
  • %p ou %le ou %level : Affiche le niveau de log (DEBUG, INFO, WARN, ERROR).
  • %t ou %thread : Affiche le nom du thread qui a généré l'événement.
  • %c ou %lo ou %logger : Affiche le nom du logger (généralement le nom de la classe). On peut limiter la longueur avec des accolades (ex: %logger{36} affiche les 36 derniers caractères du nom complet).
  • %m ou %msg ou %message : Affiche le message de log fourni par l'application.
  • %n : Insère un séparateur de ligne dépendant de la plateforme.
  • %M : Affiche le nom de la méthode où l'appel de log a eu lieu (peut impacter les performances).
  • %L : Affiche le numéro de ligne (peut impacter les performances).
  • %X{key} ou %mdc{key} : Affiche la valeur associée à la clé 'key' dans le contexte de diagnostic mappé (MDC), utile pour tracer des requêtes spécifiques.
  • %clr(pattern){color} : (Spécifique à Spring Boot pour Logback) Permet d'appliquer une couleur à un pattern dans la console (ex: %clr(%5p){faint}).
  • %ex ou %exception ou %throwable : Affiche la trace de pile (stack trace) d'une exception, si présente.

Exemple de pattern et de configuration :

# application.properties
logging.pattern.console=%d{HH:mm:ss.SSS} %clr(%-5level){blue} --- [%15.15t] %clr(%-40.40logger{39}){cyan} : %m%n%wEx
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{50} - %message%n%exception
# application.yml
logging:
  pattern:
    console: "'%d{HH:mm:ss.SSS} %clr(%-5level){blue} --- [%15.15t] %clr(%-40.40logger{39}){cyan} : %m%n%wEx'"
    file: "'%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{50} - %message%n%exception'"

Un message de log formaté avec le pattern console ci-dessus pourrait ressembler à :

14:35:10.123 INFO  --- [       main] c.e.MonApplication                     : Démarrage de MonApplication...

Avantages : Très lisible pour un humain consultant directement les logs. Configuration simple via les propriétés Spring Boot pour les cas courants.
Inconvénients : Plus difficile à parser de manière fiable par des outils automatisés, surtout si le format change ou si les messages contiennent des caractères qui pourraient être confondus avec la structure du pattern.

Formatage JSON : optimisé pour les machines et l'analyse

Le formatage JSON transforme chaque événement de log en un objet JSON structuré, avec des champs dédiés pour chaque information (timestamp, niveau, message, logger, thread, MDC, stack trace, etc.). C'est le format idéal pour l'ingestion dans des systèmes de logging centralisés qui peuvent ensuite facilement indexer, rechercher et analyser ces données.

Spring Boot ne fournit pas de propriété simple comme logging.pattern.json=true. Pour activer le logging JSON, vous devez généralement :

  1. Ajouter une dépendance spécifique qui fournit un encodeur JSON pour votre framework de logging (Logback par défaut). La bibliothèque la plus populaire pour cela est logstash-logback-encoder.
  2. Configurer le framework de logging (via logback-spring.xml ou log4j2-spring.xml) pour utiliser cet encodeur JSON avec un appender approprié (console, fichier, ou un appender réseau envoyant directement vers Logstash/Fluentd).

1. Ajouter la dépendance (exemple Maven) :



    net.logstash.logback
    logstash-logback-encoder
    7.4 

2. Créer un fichier src/main/resources/logback-spring.xml :



    

    
    
        
            
            
                @timestamp
                @version
                level_value 
            
            
            true
            true
        
    

    
    
        /var/log/mon-app/app.log.json
        
            /var/log/mon-app/app.log.json.%d{yyyy-MM-dd}.%i.gz
            100MB
            30
            3GB
        
        
    

    
    
        
         
        
        
    

    
    


Dans cet exemple, on définit un appender console `CONSOLE_JSON` qui utilise `LogstashEncoder`. On pourrait également définir un appender fichier `FILE_JSON` et l'activer dans le logger `root`.

Un événement de log formaté en JSON pourrait ressembler à ceci :

{
  "@timestamp": "2023-10-27T15:45:20.123+02:00",
  "@version": "1",
  "message": "Traitement de la requête ID: req-123",
  "logger_name": "com.example.service.TraitementService",
  "thread_name": "http-nio-8080-exec-1",
  "level": "INFO",
  "level_value": 20000,
  "mdc": {
    "requestId": "req-123",
    "userId": "user-abc"
  }
}

Avantages : Facilement parsable par les machines. Idéal pour l'agrégation, la recherche et l'analyse dans les systèmes de gestion de logs. Structure claire et cohérente.
Inconvénients : Moins lisible directement par un humain sans outils spécifiques (visionneuse JSON). Peut introduire un léger surcoût de performance par rapport au formatage texte simple (généralement négligeable). Nécessite une configuration plus avancée (fichier XML) et des dépendances supplémentaires.

Choisir le bon format pour le bon usage

Le choix entre le formatage par pattern et le formatage JSON dépend largement de votre cas d'usage :

  • Développement local / Console : Le formatage par pattern est souvent préféré pour sa lisibilité immédiate dans la console de l'IDE ou le terminal. Les couleurs (via %clr) peuvent améliorer encore la clarté.
  • Environnements de production / Logging centralisé : Le formatage JSON est fortement recommandé. Il simplifie l'ingestion, l'indexation et l'analyse par des outils comme ELK, Splunk, Loki, etc., ce qui est crucial pour la surveillance et le dépannage en production.
  • Fichiers logs simples : Si vous loggez dans des fichiers simples sans système centralisé, le format pattern peut suffire si la lisibilité humaine est la priorité. Cependant, même dans ce cas, un format JSON peut faciliter l'utilisation d'outils comme jq pour des analyses en ligne de commande.

Il est également possible d'adopter une approche hybride : utiliser un appender console avec un format pattern pour le développement et un appender fichier ou réseau avec un format JSON pour la production, le tout configuré dans le même fichier logback-spring.xml en utilisant les profils Spring (via les balises ) pour activer les appenders appropriés selon l'environnement.