Contactez-nous

Logging structuré pour l'agrégation centralisée (ELK stack, Splunk)

Optimisez l'analyse de logs Spring Boot avec le logging structuré (JSON). Facilitez l'agrégation et la recherche dans ELK Stack (Elasticsearch, Logstash, Kibana) et Splunk.

Pourquoi passer au logging structuré ?

Dans les architectures modernes, notamment les microservices, les logs proviennent de nombreuses sources distribuées. Les logs textuels traditionnels, bien que lisibles par l'homme, deviennent rapidement difficiles à traiter et à analyser automatiquement à grande échelle. Chaque ligne de log peut avoir un format légèrement différent, rendant la recherche, le filtrage et l'agrégation complexes et coûteux en ressources.

Le logging structuré résout ce problème en enregistrant les informations de log dans un format de données cohérent et facilement analysable par des machines, le plus souvent en JSON (JavaScript Object Notation). Au lieu d'une simple chaîne de texte, chaque événement de log est représenté comme un objet avec des paires clé-valeur bien définies (par exemple, `{"timestamp": "...", "level": "INFO", "message": "..."}`).

L'adoption du logging structuré est particulièrement bénéfique lorsque les logs sont centralisés dans des systèmes d'agrégation comme la stack ELK (Elasticsearch, Logstash, Kibana) ou Splunk. Ces outils sont conçus pour ingérer, indexer et analyser des données structurées de manière beaucoup plus efficace que du texte libre.

Avantages clés pour l'agrégation centralisée

L'utilisation de logs structurés (JSON) offre des avantages majeurs pour les plateformes de centralisation :

  • Recherche et Filtrage Puissants : Les systèmes comme Elasticsearch peuvent indexer chaque champ JSON (timestamp, niveau, logger, ID utilisateur, ID de trace, etc.) séparément. Cela permet des requêtes très précises et rapides. Vous pouvez facilement filtrer tous les logs d'erreur (`level:ERROR`) pour un service spécifique (`service_name:order-service`) concernant un utilisateur particulier (`user_id:123`).
  • Analyse et Visualisation Facilitées : Une fois les données structurées indexées, des outils comme Kibana ou Splunk peuvent créer des visualisations et des tableaux de bord significatifs. Vous pouvez agréger des données pour compter les erreurs par type, visualiser la latence des requêtes par endpoint, ou suivre le parcours d'une requête à travers plusieurs services grâce à un ID de trace commun.
  • Parsing Simplifié et Efficace : Les agents de collecte de logs (Logstash, Fluentd, Filebeat avec module JSON) peuvent parser le format JSON nativement, ce qui est beaucoup plus simple et moins gourmand en CPU que d'utiliser des expressions régulières (regex) complexes pour extraire des informations de logs textuels non structurés.
  • Corrélation d'Evénements : En incluant des identifiants de contexte communs (comme un ID de transaction ou un ID de trace propagé via MDC) dans les logs structurés de différents microservices, il devient beaucoup plus facile de corréler les événements et de suivre une requête de bout en bout à travers le système.

Implémentation avec Logback et `logstash-logback-encoder`

Si vous utilisez Logback (l'implémentation par défaut de Spring Boot), une des bibliothèques les plus populaires pour générer des logs au format JSON (et spécifiquement compatible avec Logstash/ELK) est `logstash-logback-encoder`. Ajoutez d'abord la dépendance à votre projet :

Maven :


    net.logstash.logback
    logstash-logback-encoder
    7.4 

Gradle :

implementation 'net.logstash.logback:logstash-logback-encoder:7.4' // Utilisez une version récente

Ensuite, configurez Logback pour utiliser l'encodeur JSON. Créez ou modifiez votre fichier `src/main/resources/logback-spring.xml` :




    
    

    
    
        
            
            
            
        
    

    
    
        
        
        
    

Cette configuration de base remplace l'encodeur de texte par défaut de l'appender console par `LogstashEncoder`. Les logs seront désormais émis au format JSON sur la console, prêts à être collectés par un agent comme Filebeat ou Fluentd.

Implémentation avec Log4j2 (JSON Layout)

Si vous préférez utiliser Log4j2, celui-ci intègre nativement un `JsonLayout` qui produit des logs au format JSON. Assurez-vous d'avoir inclus `spring-boot-starter-log4j2` et exclu `spring-boot-starter-logging` comme décrit précédemment.

Configurez ensuite Log4j2 via un fichier `src/main/resources/log4j2-spring.xml` :



    
        
        
            
                
                
                
            
        

        
        
    

    
        
        
            
            
        

        
        
    

`JsonLayout` offre diverses options pour contrôler le format de sortie, comme `compact` (une ligne par événement JSON), `eventEol` (ajouter un retour chariot), `properties` (inclure les données MDC), `includeStacktrace`, etc.

Champs essentiels et bonnes pratiques

Pour un logging structuré efficace, assurez-vous d'inclure systématiquement certains champs clés :

  • Timestamp : Date et heure de l'événement, idéalement au format ISO 8601 et en UTC (par exemple, `@timestamp` pour ELK).
  • Log Level : (par ex., `level`, `severity`) INFO, WARN, ERROR, etc.
  • Logger Name : (par ex., `logger`) Le nom de la classe ou du package qui a émis le log.
  • Thread Name : (par ex., `thread`) Utile pour suivre l'exécution dans des environnements multithreadés.
  • Message : Le message de log principal.

Il est fortement recommandé d'enrichir ces logs avec du contexte applicatif via le MDC (Mapped Diagnostic Context) de SLF4J. Ajoutez des informations comme :

  • ID de Trace/Requête : (par ex., `traceId`, `requestId`) Pour suivre une requête à travers plusieurs services.
  • ID Utilisateur : (par ex., `userId`) Pour savoir quel utilisateur a déclenché l'action.
  • Nom du Service : (par ex., `service`, `application_name`) Pour identifier la source du log dans un système distribué (peut être ajouté statiquement par l'encodeur/layout).

Les stack traces d'exceptions doivent être incluses pour les erreurs, mais assurez-vous qu'elles sont correctement formatées dans le JSON (souvent comme une chaîne unique avec des `\n` ou un tableau de chaînes). Les encodeurs/layouts offrent généralement des options pour cela.

Adoptez une convention de nommage cohérente pour les champs JSON à travers toutes vos applications. Cela simplifie grandement l'écriture de requêtes et la création de dashboards dans votre système de centralisation.