Parametrisoitu lokitus
Tehokas viestien muotoilu.
Parametrisoitu lokitus on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.
Merkkijonojen yhdistämisen ongelma
Lokiviestin yhdistäminen muodostaa koko merkkijonon ennen kutsua, vaikka taso olisi poistettu käytöstä.
log.debug("id=" + id + " name=" + name) kuluttaa suorittimen aikaa, kun DEBUG ei ole käytössä, koska merkkijono muodostetaan joka tapauksessa.
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);
}
}Paikkamerkit muodossa {}
SLF4J käyttää {}-merkintää paikkamerkkinä. Välittäkää arvot ylimääräisinä argumentteina.
Viesti kootaan vain jos taso on käytössä, joten käytöstä poistetut lokit aiheuttavat lähes olemattoman kustannuksen.
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);
}
}Useita paikkamerkkejä
Paikkamerkit täytetään järjestyksessä. Ensimmäinen {} saa ensimmäisen argumentin, toinen toisen ja niin edelleen.
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);
}
}Miksi tämä on tehokasta
Framework tarkistaa ensin tason. Jos taso ei ole käytössä, se palaa heti kutsumatta minkään argumentin toString()-metodia.
Kallis osa eli muotoilu tehdään laiskasti vasta, kun viesti todella lähetetään.
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});
}
}Raakaobjektien käyttäminen valmiiksi muotoiltujen merkkijonojen sijaan
Jotta laiskasta käsittelystä saadaan hyöty, välittäkää raakaobjekti sen sijaan, että kutsuisitte sitä muotoilevaa metodia.
Jos kirjoitatte log.debug("{}", buildReport()), buildReport() suoritetaan silti heti. Välittäkää argumentit, jotka loggeri voi muotoilla itse.
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);
}
}Laiskat supplierit raskasta työtä varten
Kun muotoilu on todella kallista, käyttäkää SLF4J 2.x:n fluent APIa ja Supplier-tyyppiä työn lykkäämiseen.
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();
}
}Kirjaimellisen aaltosulkeen merkitseminen
Jos viestissä tarvitaan kirjaimellinen {}, escapettakaa se kenoviivalla: \\{}.
Tätä tarvitaan harvoin, mutta siitä on hyötyä JSON-tyyppistä tekstiä lokitettaessa.
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);
}
}Poikkeus ja paikkamerkit
Paikkamerkkejä voi käyttää yhdessä viimeisenä annettavan poikkeuksen kanssa. SLF4J tunnistaa, että viimeinen argumentti on Throwable, ja tulostaa sen pinonjäljityksen.
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);
}
}
}Liian monien argumenttien välttäminen
Jos paikkamerkkien ja argumenttien määrät eivät täsmää, SLF4J yrittää parhaansa, mutta tuloste voi näyttää virheelliseltä.
Huolehtikaa siitä, että määrät vastaavat toisiaan. Jos arvoja on enemmän kuin pari, harkitkaa sen sijaan rakenteisen kontekstin (MDC) käyttöä.
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");
}
}Kontekstin lisääminen MDC:llä
Jos sama arvo, kuten pyynnön tunnus, toistuu monilla riveillä, sijoittakaa se MDC:hen jokaisen viestin sijaan.
Pattern-asettelu voi silloin tulostaa MDC-arvon automaattisesti jokaiselle riville.
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();
}
}
}Parhaiden käytäntöjen yhteenveto
Tehokkaan lokituksen säännöt:
- Käyttäkää aina
{}-paikkamerkkejä, älkää koskaan+-merkkijonojen yhdistämistä. - Välittäkää raakaobjekteja, älkää valmiiksi muodostettuja merkkijonoja.
- Käyttäkää suppliereita tai
isXEnabled()-metodia todella raskasta työtä varten. - Käyttäkää MDC:tä poikittaisen kontekstin välittämiseen.
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);
}
}Pikatarkistus
Testatkaa parametrisoidun lokituksen tuntemustanne.
Kertaus
Opitte parametrisoidun lokituksen:
- Käyttäkää
{}-paikkamerkkejä ylimääräisten argumenttien kanssa. - Viestit muodostetaan laiskasti vain, kun taso on käytössä.
- Välittäkää raakaobjekteja ja käyttäkää suppliereita raskasta työtä varten.
- Käyttäkää MDC:tä jaettujen kontekstiarvojen välittämiseen.
Seuraavaksi määritetään Logback-backend.
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");
}
}Opi Java tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 104
- Oppitunnit
- 374
Usein kysytyt kysymykset
Onko oppitunti ”Parametrisoitu lokitus” ilmainen?
Kyllä – oppitunnin ”Parametrisoitu lokitus” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Parametrisoitu lokitus”?
Tehokas viestien muotoilu. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.
Kuinka kauan ”Parametrisoitu lokitus”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?
Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Miksi rakenteinen lokitus
- SLF4J-julkisivu ja lokittimet
- Parametrisoitu lokitus
- Logbackin määrittäminen