Parameteriseret logging
Effektiv formatering af meddelelser
Parameteriseret logging er en gratis Java Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Java Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Java Academy-kurset indeholder 4 lektioner i alt.
Problemet med sammenkædning af strenge
Når du sammenkæder en logmeddelelse, bygges hele strengen før kaldet, også selvom niveauet er deaktiveret.
log.debug("id=" + id + " name=" + name) spilder CPU, når DEBUG er slået fra, fordi strengen bygges uanset hvad.
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);
}
}Pladsholdere med {}
SLF4J bruger {} som pladsholder. Angiv værdierne som ekstra argumenter.
Meddelelsen sammensættes kun hvis niveauet er aktiveret, så deaktiverede logkald næsten ikke koster noget.
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);
}
}Flere pladsholdere
Pladsholdere udfyldes i rækkefølge. Den første {} får det første argument, den anden får det andet, og så videre.
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);
}
}Hvorfor det er effektivt
Frameworket tjekker først niveauet. Hvis det er deaktiveret, returnerer det straks uden at kalde toString() på noget argument.
Den dyre del, formateringen, sker først ved behov, når meddelelsen faktisk skal udsendes.
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});
}
}Send rå objekter, ikke præformaterede strenge
For at få fordelene ved udsættelse skal du sende det rå objekt, ikke et metodekald, der formaterer det.
Hvis du skriver log.debug("{}", buildReport()), kører buildReport() stadig med det samme. Send argumenter, som loggeren selv kan formatere.
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);
}
}Udskyd tungt arbejde med Supplier
Når formatering reelt er dyr, skal du bruge SLF4J 2.x's fluent API med en Supplier, så arbejdet udskydes.
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();
}
}Undvigelse af en bogstavelig klammeparentes
Hvis du har brug for et bogstaveligt {} i meddelelsen, skal du undvige det med en omvendt skråstreg: \\{}.
Det er sjældent nødvendigt, men nyttigt ved logning af JSON-lignende tekst.
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);
}
}Undtagelser sammen med pladsholdere
Du kan kombinere pladsholdere med en afsluttende undtagelse. SLF4J registrerer, at det sidste argument er en Throwable, og udskriver dens stacktrace.
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);
}
}
}Undgå for mange argumenter
Hvis antallet af pladsholdere og argumenter ikke stemmer overens, gør SLF4J sit bedste, men resultatet kan se forkert ud.
Sørg for, at de stemmer overens. Ved mere end et par værdier kan du i stedet overveje struktureret kontekst (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");
}
}Tilføj kontekst med MDC
For værdier, der deles på tværs af mange linjer, f.eks. et request-id, skal du placere dem i MDC i stedet for i hver meddelelse.
Layoutet kan derefter automatisk udskrive MDC-værdien på hver linje.
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();
}
}
}Opsummering af bedste praksis
Regler for effektiv logning:
- Brug altid pladsholdere med
{}, aldrig sammenkædning med+. - Send rå objekter, ikke færdigbyggede strenge.
- Brug Supplier-objekter eller
isXEnabled()til virkelig tungt arbejde. - Brug MDC til tværgående kontekst.
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);
}
}Hurtigt tjek
Test din viden om parametriseret logning.
Opsummering
Du lærte om parametriseret logning:
- Brug pladsholdere med
{}sammen med ekstra argumenter. - Meddelelser bygges udskudt, kun når niveauet er aktiveret.
- Send rå objekter, og brug Supplier til tungt arbejde.
- Brug MDC til delte kontekstværdier.
Næste emne er konfiguration af Logback-backendet.
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");
}
}Lær Java med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 104
- Lektioner
- 374
Ofte stillede spørgsmål
Er lektionen “Parameteriseret logging” gratis?
Ja — hele teksten til “Parameteriseret logging” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Java Academy-kurset, skal du opgradere til CoddyKit PRO. Java Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Parameteriseret logging”?
Effektiv formatering af meddelelser Du øver dig i Java Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Java Academy?
Der kræves ingen tidligere erfaring. Java Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Parameteriseret logging”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Java Academy-lektion?
Ja. Alle Java Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Hvorfor structured logging
- SLF4J-facade og loggere
- Parameteriseret logging
- Konfiguration af Logback