0Pricing
Java Academy · Leçon

Journalisation paramétrée

Formatage efficace des messages

Journalisation paramétrée est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.

Le problème de la concaténation de chaînes

La concaténation d'un message de journalisation construit la chaîne complète avant l'appel, même si le niveau est désactivé.

log.debug("id=" + id + " name=" + name) gaspille du temps CPU lorsque DEBUG est désactivé, car la chaîne est construite dans tous les cas.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        String name = "Ada"; int id = 7;
        // Bad: string is built even if DEBUG is disabled
        log.debug("id=" + id + " name=" + name);
    }
}

Paramètres de substitution avec {}

SLF4J utilise {} comme paramètre de substitution. Transmettez les valeurs comme arguments supplémentaires.

Le message n'est assemblé que si le niveau est activé, de sorte que les journaux désactivés ne coûtent presque rien.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        String name = "Ada"; int id = 7;
        // Good: no string built unless DEBUG is on
        log.debug("id={} name={}", id, name);
    }
}

Plusieurs paramètres de substitution

Les paramètres de substitution sont remplis dans l'ordre. Le premier {} reçoit le premier argument, le deuxième reçoit le deuxième, et ainsi de suite.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.info("order {} for user {} totaling {} cents", "A-1", 42, 1599);
    }
}

Pourquoi est-ce efficace ?

L'infrastructure vérifie d'abord le niveau. S'il est désactivé, elle retourne immédiatement sans appeler toString() sur le moindre argument.

La partie coûteuse, le formatage, n'a lieu de manière différée que lorsque le message sera réellement émis.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    static String describe(Object o) { System.out.println("toString called"); return o.toString(); }
    public static void main(String[] args) {
        // Note: passing describe(...) still evaluates eagerly; pass the raw object instead
        log.trace("value={}", new int[]{1, 2, 3});
    }
}

Transmettre des objets bruts plutôt que des chaînes déjà formatées

Pour bénéficier de l'évaluation différée, transmettez l'objet brut, et non un appel de méthode qui le formate.

Si vous écrivez log.debug("{}", buildReport()), buildReport() s'exécute tout de même immédiatement. Transmettez des arguments que le journaliseur peut formater lui-même.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        Object user = new Object();
        // Logger calls user.toString() only if DEBUG is enabled
        log.debug("current user: {}", user);
    }
}

Fournisseurs différés pour les tâches lourdes

Lorsque le formatage est réellement coûteux, utilisez l'API fluide de SLF4J 2.x avec un Supplier afin de différer le travail.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    static String heavyReport() { return "...expensive..."; }
    public static void main(String[] args) {
        log.atDebug()
           .setMessage("report: {}")
           .addArgument(() -> heavyReport())
           .log();
    }
}

Échapper une accolade littérale

Si vous avez besoin d'un {} littéral dans le message, échappez-le avec une barre oblique inverse : \\{}.

C'est rare, mais utile lors de la journalisation d'un texte ressemblant à du JSON.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        // Logs a literal {} then the value
        log.info("empty object is \\{} and id is {}", 7);
    }
}

Exception et paramètres de substitution

Vous pouvez combiner des paramètres de substitution avec une exception finale. SLF4J détecte que le dernier argument est un Throwable et affiche sa trace de pile.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        int id = 99;
        try {
            throw new RuntimeException("db down");
        } catch (Exception e) {
            log.error("failed processing record {}", id, e);
        }
    }
}

Éviter trop d'arguments

Si le nombre de paramètres de substitution et le nombre d'arguments ne correspondent pas, SLF4J fait de son mieux, mais la sortie peut sembler incorrecte.

Veillez à les maintenir synchronisés. Pour plus de quelques valeurs, envisagez plutôt le contexte structuré (MDC).

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        // Two placeholders, two arguments: correct
        log.info("user {} did {}", "ada", "login");
    }
}

Ajouter du contexte avec MDC

Pour les valeurs partagées par de nombreuses lignes, comme un identifiant de requête, placez-les dans le MDC plutôt que dans chaque message.

Le motif de formatage peut alors afficher automatiquement la valeur du MDC sur chaque ligne.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        MDC.put("requestId", "req-1234");
        try {
            log.info("handling request");
            log.info("request done");
        } finally {
            MDC.clear();
        }
    }
}

Récapitulatif des bonnes pratiques

Règles pour une journalisation efficace :

  • Utilisez toujours les paramètres de substitution {}, jamais la concaténation avec +.
  • Transmettez des objets bruts, et non des chaînes déjà construites.
  • Utilisez des fournisseurs ou isXEnabled() pour les tâches réellement lourdes.
  • Utilisez MDC pour le contexte transversal.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.info("processed {} items in {} ms", 1000, 42);
    }
}

Vérification rapide

Testez vos connaissances de la journalisation paramétrée.

Récapitulatif

Vous avez découvert la journalisation paramétrée :

  • Utilisez les paramètres de substitution {} avec des arguments supplémentaires.
  • Les messages sont construits de manière différée, uniquement lorsque le niveau est activé.
  • Transmettez des objets bruts ; utilisez des fournisseurs pour les tâches lourdes.
  • Utilisez MDC pour les valeurs de contexte partagées.

Ensuite, la configuration de l'infrastructure Logback.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.info("Parameterized logging recap: {}", "done");
    }
}

Questions Fréquemment Posées

La leçon « Journalisation paramétrée » est-elle gratuite ?

Oui — le texte complet de « Journalisation paramétrée » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Journalisation paramétrée » ?

Formatage efficace des messages Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Java Academy ?

Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Journalisation paramétrée » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?

Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Pourquoi utiliser la journalisation structurée
  2. Façade SLF4J et journaliseurs
  3. Journalisation paramétrée
  4. Configurer Logback
← Retour à Java Academy