Parameterisert logging
Effektiv formatering av meldinger
Parameterisert logging er en gratis leksjon i Java Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Java Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Java Academy inneholder totalt 4 leksjoner.
Problemet med strengsammenslåing
Når du slår sammen en loggmelding, bygges hele strengen før kallet, selv om nivået er deaktivert.
log.debug("id=" + id + " name=" + name) bruker unødvendig CPU når DEBUG er deaktivert, fordi strengen bygges uansett.
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);
}
}Plassholdere med {}
SLF4J bruker {} som plassholder. Send verdiene som ekstra argumenter.
Meldingen settes bare sammen hvis nivået er aktivert, så deaktiverte logger har nesten ingen kostnad.
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 plassholdere
Plassholdere fylles ut i rekkefølge. Den første {} får det første argumentet, den andre får det andre, 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 dette er effektivt
Rammeverket sjekker først nivået. Hvis det er deaktivert, returnerer det umiddelbart uten å kalle toString() på noen av argumentene.
Den kostbare delen, formateringen, skjer først når meldingen faktisk skal skrives ut.
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 forhåndsformaterte strenger
For å dra nytte av utsettelsen bør du sende råobjektet, ikke et metodekall som formaterer det.
Hvis du skriver log.debug("{}", buildReport()), kjøres buildReport() fortsatt umiddelbart. Send argumenter som loggeren kan formatere selv.
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);
}
}Lazy Supplier-objekter for tungt arbeid
Når formateringen faktisk er kostbar, kan du bruke SLF4J 2.x sitt fluent API med en Supplier, slik at arbeidet utsettes.
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();
}
}Escape en bokstavelig krøllparentes
Hvis du trenger en bokstavelig {} i meldingen, bruker du en omvendt skråstrek som escape-tegn: \\{}.
Dette er sjelden nødvendig, men nyttig når du logger 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);
}
}Unntak pluss plassholdere
Du kan kombinere plassholdere med et unntak til slutt. SLF4J oppdager at det siste argumentet er en Throwable, og skriver ut stacktracen.
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);
}
}
}Unngå for mange argumenter
Hvis antallet plassholdere og argumenter ikke stemmer overens, gjør SLF4J så godt det kan, men utskriften kan se feil ut.
Hold dem synkronisert. Hvis du har mer enn et par verdier, bør du heller vurdere strukturert 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");
}
}Legge til kontekst med MDC
For verdier som deles av mange linjer, for eksempel en forespørsels-ID, legger du dem i MDC i stedet for i hver melding.
Deretter kan mønsteroppsettet skrive ut MDC-verdien på hver linje automatisk.
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();
}
}
}Oppsummering av beste praksis
Regler for effektiv logging:
- Bruk alltid
{}-plassholdere, aldri+-sammenslåing. - Send råobjekter, ikke ferdigbygde strenger.
- Bruk suppliers eller
isXEnabled()for virkelig tungt arbeid. - Bruk MDC for kontekst som går på tvers av komponenter.
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);
}
}Kort sjekk
Test kunnskapen din om parameterisert logging.
Oppsummering
Du har lært om parameterisert logging:
- Bruk
{}-plassholdere med ekstra argumenter. - Meldinger bygges ved behov, bare når nivået er aktivert.
- Send råobjekter, og bruk suppliers for tungt arbeid.
- Bruk MDC for delte kontekstverdier.
Deretter ser vi på hvordan du konfigurerer Logback-backenden.
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 deg Java med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 104
- Leksjoner
- 374
Ofte stilte spørsmål
Er leksjonen «Parameterisert logging» gratis?
Ja – hele teksten i «Parameterisert logging» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Java Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Java Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Parameterisert logging»?
Effektiv formatering av meldinger Du øver på Java Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Java Academy?
Ingen tidligere erfaring er nødvendig. Java Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.
Hvor lang tid tar leksjonen «Parameterisert logging»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Java Academy-leksjonen?
Ja. Alle Java Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Hvorfor strukturert logging
- SLF4J-fasade og loggere
- Parameterisert logging
- Konfigurere Logback