Structured Logging — essence, formats de données et principe de fonctionnement dans les applications

Auteur : IT Sectr Publié le : 2026-05-28 Temps de lecture : 8 min

Structured Logging est une approche de journalisation où chaque message est représenté dans un format lisible par machine avec des paires clé-valeur, plutôt que sous forme de texte non structuré. Contrairement aux chaînes plates, les journaux structurés contiennent des métadonnées : timestamp, niveau, module, ID de requête — et peuvent être indexés par des systèmes d’analyse. Selon O'Reilly Effective Logging, le passage aux formats structurés réduit le temps de recherche d’incidents de plusieurs heures à quelques minutes grâce à la possibilité de filtrer par champs. C’est la norme de facto dans le développement mobile et serveur moderne : JSON et logfmt permettent de traiter les journaux par des programmes, pas par les yeux.

Points clés

  • Structured Logging — représentation des journaux au format clé-valeur au lieu de texte brut, adapté au traitement automatisé
  • JSON — le format de journal structuré le plus courant, pris en charge par tous les systèmes modernes de collecte et d’analyse
  • Logfmt — un format compact de Heroku, pratique pour la lecture humaine et l’analyse avec grep
  • ELK Stack — Elasticsearch, Logstash, Kibana — l’infrastructure standard pour stocker et visualiser les journaux structurés
  • Contexte — ID de requête, session utilisateur, version de l’application — champs obligatoires de chaque message structuré

Qu’est-ce que Structured Logging

Structured Logging est une méthode de journalisation où chaque message contient des champs nommés avec des valeurs typées. Au lieu d’une chaîne comme User 42 logged in from device ABC, un journal structuré ressemble à un ensemble de champs : user_id=42, event=login, device_id=ABC, timestamp=2026-07-04T10:30:00Z.

Le principal avantage des journaux structurés par rapport aux textuels est la possibilité de traitement programmatique. L’analyse des journaux textuels nécessite des expressions régulières et des hypothèses sur le format de la chaîne. Les journaux structurés sont analysés sans perte : chaque champ a un type et un nom connus, ce qui permet de construire des requêtes comme trouver toutes les erreurs d’authentification de la dernière heure pour l’utilisateur 42 sans traitement supplémentaire.

Selon Honeycomb.io (2023), les équipes utilisant structured logging en production détectent les incidents en moyenne 4 fois plus rapidement que les équipes qui comptent sur les journaux textuels et grep.

Formats des journaux structurés

Structured Logging prend en charge plusieurs formats de sérialisation. Le choix du format dépend de l’infrastructure : JSON est pratique pour l’intégration avec Elasticsearch et les systèmes cloud, logfmt pour l’affichage en console via tail et grep, Protocol Buffers pour les systèmes haute performance avec des limitations de bande passante.

FormatExempleQuand l’utiliser
JSON{"event":"login","user_id":42}ELK Stack, collecteurs cloud, microservices
Logfmtevent=login user_id=42 duration_ms=150Console, tail, heroku logs
MessagePackÉquivalent binaire de JSONSystèmes à forte charge, IoT

JSON — format universel

JSON est le format le plus courant pour les journaux structurés. Il est nativement pris en charge par tous les systèmes de collecte : Logstash, Fluentd, Amazon CloudWatch, Google Cloud Logging. Les journaux JSON sont faciles à lire par les humains et à analyser par n’importe quel langage de programmation sans bibliothèques supplémentaires. Le principal inconvénient est la verbosité : chaque paire clé-valeur nécessite des guillemets et des deux-points, ce qui augmente le volume de données stockées de 30 à 50% par rapport à logfmt.

Logfmt — format compact

Logfmt a été développé chez Heroku pour la visibilité en console. Il est plus compact que JSON, conserve la lisibilité humaine et peut être facilement traité avec cut et awk. Exemple : ts=2026-07-04T10:30:00Z level=error module=api status=500. Logfmt ne nécessite pas d’échappement de la plupart des caractères et convient bien pour la journalisation stdout dans les conteneurs.

Pourquoi Structured Logging dans le développement mobile

Dans les applications mobiles, Structured Logging résout trois problèmes clés : trouver les causes de crash sans reproduction sur un appareil, suivre les sessions utilisateur et analyser les performances par version de l’application.

Les journaux textuels sur les appareils mobiles sont presque inutiles — un développeur ne peut pas grep les journaux sur l’appareil de l’utilisateur. Les journaux structurés sont envoyés aux systèmes cloud (Firebase, Sentry, Datadog) et y sont indexés. Vous pouvez construire une requête comme afficher tous les crashes avec iOS 17.4, version de l’app 3.2, dans le module checkout et obtenir une sélection précise en quelques secondes.

Selon Sentry (2024), les applications utilisant des breadcrumbs structurés ont 60% plus de contexte dans chaque rapport de crash par rapport aux applications qui ne journalisent que le texte d’erreur. Cela affecte directement la vitesse de correction des bogues.

Outils de collecte et d’analyse

ELK Stack — Elasticsearch, Logstash, Kibana — reste l’infrastructure standard pour travailler avec les journaux structurés. Logstash reçoit les journaux en JSON, les transforme et les envoie à Elasticsearch pour indexation, Kibana fournit une interface visuelle pour les requêtes et les tableaux de bord.

Pour les applications mobiles, les solutions cloud sont populaires : Firebase Crashlytics avec des journaux personnalisés, Sentry avec des breadcrumbs, Datadog avec le suivi APM. Elles acceptent les journaux structurés directement depuis le SDK mobile et ne nécessitent pas de déploiement de backend propre. Firebase offre un package gratuit pour les rapports de crash, Sentry ajoute le tracing distribué et Datadog s’intègre à APM pour suivre les performances des requêtes à la fois sur le client et le serveur simultanément.

Grafana Loki — une alternative à Elasticsearch optimisée pour les journaux. Loki n’indexe pas le contenu des messages par défaut mais utilise des étiquettes (labels) pour le filtrage. C’est considérablement moins cher en stockage et plus rapide pour les requêtes sur un ensemble fixe de champs.

swift
// Journalisation structurée via Swift Logger en JSON
struct StructuredLog {
    let event: String
    let attributes: [String: Any]
    let level: String

    func serialize() -> String {
        var base = "event=\(event) level=\(level)"
        for (key, value) in attributes {
            base += " \(key)=\(value)"
        }
        return base
    }
}

Meilleures pratiques de Structured Logging

La première règle de la journalisation structurée : chaque message doit contenir un identifiant de requête ou de session. Sans contexte, un journal individuel est inutile — il est impossible de savoir à quel utilisateur ou requête il appartient. Ajoutez un correlation ID au début de la session et transmettez-le à travers toutes les couches de l’application.

La deuxième règle : typage des champs. Les champs numériques (duration_ms, status_code, retry_count) doivent être transmis comme des nombres, pas comme des chaînes. Elasticsearch et les systèmes similaires indexent les nombres et les chaînes différemment : les nombres peuvent être agrégés (moyenne, médiane, percentile), les chaînes prennent en charge la recherche en texte intégral. Un typage incorrect empêche la construction de tableaux de bord analytiques.

La troisième règle : évitez les objets imbriqués. Les journaux JSON avec une profondeur d’imbrication supérieure à 2 niveaux sont difficiles à filtrer et visualiser. Au lieu de {"user": {"name": "Alice", "role": "admin"}}, utilisez des clés plates : user_name=Alice user_role=admin.

kotlin
// Journalisation structurée sur Android via Timber + logfmt
class StructuredTree : Timber.Tree() {
    override fun log(priority: Int, tag: String?,
                  message: String?, t: Throwable?) {
        val level = priorityToLevel(priority)
        val logfmt = "level=$level tag=$tag message=$message"
        sendToRemote(logfmt)
    }
}

Champs obligatoires

L’ensemble minimal de champs pour chaque message structuré : timestamp au format ISO 8601, level (debug/info/warn/error/fatal), logger (nom du module ou de la classe), message (description lisible de l’événement). En complément : correlation_id, user_id (si connu), version (version de l’app), platform (iOS/Android), environment (dev/staging/prod).

Sans correlation_id, les journaux structurés deviennent un ensemble d’enregistrements déconnectés qui ne peuvent pas être liés en un seul scénario utilisateur. Générez un UUID à chaque lancement de l’application et ajoutez-le à tous les journaux de session. En pratique, le correlation_id doit être transmis à travers toutes les couches : des événements UI aux requêtes réseau et tâches d’arrière-plan — sinon certains journaux resteront sans contexte et ne participeront pas à l’analyse. Avec un suivi de bout en bout, un seul UUID permet de collecter l’image complète du parcours utilisateur.

Exemples de logging structuré en Swift et Kotlin

Sur iOS, le logging structuré peut être implémenté via une surcouche d’os_log qui sérialise les champs au format logfmt. Sur Android, via Timber avec un Tree personnalisé qui convertit les messages en JSON ou logfmt avant l’envoi au serveur.

swift
import OSLog

struct StructuredLogger {
    let subsystem: String
    let category: String

    func log(level: OSLogType,
              event: String,
              context: [String: Any]) {
        let oslogger = Logger(
            subsystem: subsystem,
            category: category
        )
        let fields = context.map {
            "\($0.key)=\($0.value)"
        }.joined(separator: " ")
        oslogger.log(level: level,
                     "\(event) \(fields)")
    }
}

Structured vs Unstructured : comparaison des approches

Le choix entre les journaux structurés et textuels dépend du stade du projet. Aux premiers stades de développement, les journaux textuels sont plus simples et plus rapides — le développeur écrit un message directement sans surcouches supplémentaires. Mais dès que le projet dépasse les limites d’une seule équipe ou d’un seul serveur, les journaux structurés deviennent obligatoires.

CritèreJournaux textuelsJournaux structurés
LisibilitéHaute en consoleMoyenne (nécessite pretty-print)
Recherchegrep par sous-chaîneRequêtes par champs et valeurs
AgrégationNon supportéeMoyenne, médiane, percentiles
IntégrationNécessite analyseNative dans ELK/Loki/Datadog
Volume de stockagePlus faible (sans métadonnées)Plus élevé (champs + valeurs)

Questions fréquentes

Quel format est le meilleur pour la journalisation mobile ?

Pour l’envoi au serveur, utilisez JSON — il est nativement pris en charge par Firebase Crashlytics, Sentry et Datadog. Pour l’affichage local dans les logs Xcode ou Android Studio, utilisez logfmt — il est plus compact et lisible sans formatage.

Faut-il journaliser au format structuré sur le client ?

Oui, les journaux structurés sur le client permettent d’ajouter du contexte à chaque rapport de crash : version de l’OS, état du réseau, dernières actions de l’utilisateur. Sans breadcrumbs structurés, un rapport de crash ne contient que la pile d’appels sans le scénario utilisateur.

En quoi logfmt diffère-t-il de JSON ?

Logfmt est plus compact (30 à 50% de volume en moins) et plus facile à lire dans un terminal. JSON prend en charge les objets et tableaux imbriqués mais nécessite l’échappement des guillemets. Le choix dépend de l’infrastructure : pour ELK — JSON, pour l’affichage en console — logfmt.

Comment ajouter un correlation ID à tous les logs ?

Créez une instance unique d’UUID au démarrage de l’application, stockez-la dans un singleton ou un conteneur DI et transmettez-la à tous les logger via le constructeur. Alternative — utilisez le stockage local de thread ou Continuation Local Storage dans les coroutines Kotlin.

Peut-on mélanger les journaux structurés et textuels ?

On peut, mais ce n’est pas recommandé — le mélange fait perdre la capacité d’indexation automatique. Si certains journaux sont textuels, ils doivent être analysés avec des expressions régulières, ce qui réduit les performances et la fiabilité de la recherche. Il est préférable de migrer tous les journaux vers un format structuré.

Résumé

  • Structured Logging — format de journal avec paires clé-valeur, adapté à l’indexation et aux requêtes automatiques, contrairement aux chaînes de texte
  • JSON et logfmt — les principaux formats : JSON est universel pour les systèmes de collecte, logfmt est compact pour l’affichage en console et les logs docker
  • Correlation ID — champ obligatoire de chaque message structuré, sans lui les journaux ne peuvent pas être liés en session utilisateur
  • ELK Stack et Grafana Loki — solutions d’infrastructure standard pour stocker, indexer et visualiser les journaux structurés
  • Performances — les équipes avec structured logging détectent les incidents 4 fois plus vite grâce aux requêtes par champs plutôt qu’au grep par texte
  • Typage — les nombres doivent être transmis comme nombres, pas comme chaînes, pour permettre les agrégations (moyenne, médiane, percentiles) dans les systèmes d’analyse

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi