Parametrisiertes Logging
Effiziente Nachrichtenformatierung
Parametrisiertes Logging ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Das Problem mit der String-Verkettung
Beim Verketten einer Log-Nachricht wird der vollständige String vor dem Aufruf erstellt, selbst wenn das Level deaktiviert ist.
log.debug("id=" + id + " name=" + name) verbraucht CPU, wenn DEBUG deaktiviert ist, da der String unabhängig davon erstellt wird.
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);
}
}Platzhalter mit {}
SLF4J verwendet {} als Platzhalter. Übergeben Sie die Werte als zusätzliche Argumente.
Die Nachricht wird nur zusammengesetzt, wenn das Level aktiviert ist. Deaktiviertes Logging verursacht daher nahezu keine Kosten.
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);
}
}Mehrere Platzhalter
Platzhalter werden der Reihe nach gefüllt. Der erste {} nimmt das erste Argument auf, der zweite das zweite und so weiter.
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);
}
}Warum das effizient ist
Das Framework prüft zunächst das Level. Wenn es deaktiviert ist, wird sofort zurückgekehrt, ohne bei irgendeinem Argument toString() aufzurufen.
Der aufwendige Teil, die Formatierung, erfolgt verzögert und nur dann, wenn die Nachricht tatsächlich ausgegeben wird.
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});
}
}Rohobjekte statt vorformatierter Strings übergeben
Damit Sie vom verzögerten Auswerten profitieren, übergeben Sie das Rohobjekt und keinen Methodenaufruf, der es formatiert.
Wenn Sie log.debug("{}", buildReport()) schreiben, wird buildReport() trotzdem sofort ausgeführt. Übergeben Sie Argumente, die der Logger selbst formatieren kann.
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);
}
}Verzögerte Supplier für aufwendige Arbeit
Wenn die Formatierung wirklich aufwendig ist, verwenden Sie die Fluent-API von SLF4J 2.x mit einem Supplier, damit die Arbeit verzögert ausgeführt wird.
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();
}
}Eine geschweifte Klammer als Literal maskieren
Wenn Sie ein wörtliches {} in der Nachricht benötigen, maskieren Sie es mit einem Backslash: \\{}.
Das kommt selten vor, ist aber beim Protokollieren von JSON-ähnlichem Text nützlich.
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 plus Platzhalter
Sie können Platzhalter mit einer nachfolgenden Exception kombinieren. SLF4J erkennt, dass das letzte Argument ein Throwable ist, und gibt dessen Stacktrace aus.
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);
}
}
}Nicht zu viele Argumente übergeben
Wenn die Anzahl der Platzhalter nicht mit der Anzahl der Argumente übereinstimmt, gibt SLF4J sein Bestes, aber die Ausgabe kann falsch aussehen.
Achten Sie darauf, dass beide Anzahlen übereinstimmen. Bei mehr als ein paar Werten sollten Sie stattdessen strukturierten Kontext (MDC) in Betracht ziehen.
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");
}
}Kontext mit MDC hinzufügen
Für Werte, die über viele Zeilen hinweg gemeinsam verwendet werden (z. B. eine Request-ID), speichern Sie sie im MDC statt in jeder Nachricht.
Das Pattern-Layout kann den MDC-Wert dann automatisch in jeder Zeile ausgeben.
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();
}
}
}Zusammenfassung der Best Practices
Regeln für effizientes Logging:
- Verwenden Sie immer
{}-Platzhalter, niemals eine Verkettung mit+. - Übergeben Sie Rohobjekte statt vorab erstellter Strings.
- Verwenden Sie für wirklich aufwendige Arbeit Supplier oder
isXEnabled(). - Verwenden Sie MDC für querschnittlichen Kontext.
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);
}
}Kurzer Test
Testen Sie Ihr Wissen über parametrisiertes Logging.
Zusammenfassung
Sie haben parametrisiertes Logging kennengelernt:
- Verwenden Sie
{}-Platzhalter mit zusätzlichen Argumenten. - Nachrichten werden verzögert erstellt, nur wenn das Level aktiviert ist.
- Übergeben Sie Rohobjekte und verwenden Sie für aufwendige Arbeit Supplier.
- Verwenden Sie MDC für gemeinsam genutzte Kontextwerte.
Als Nächstes folgt die Konfiguration des Logback-Backends.
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");
}
}Häufig gestellte Fragen
Ist die Lektion „Parametrisiertes Logging“ kostenlos?
Ja — der vollständige Text von „Parametrisiertes Logging“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Parametrisiertes Logging“?
Effiziente Nachrichtenformatierung Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Java Academy zu starten?
Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Parametrisiertes Logging“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?
Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Warum strukturiertes Logging
- SLF4J-Fassade und Logger
- Parametrisiertes Logging
- Logback konfigurieren