Logging parametrizzato
Formattazione efficiente dei messaggi
Logging parametrizzato è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.
Il problema della concatenazione di stringhe
La concatenazione di una stringa per un messaggio di log costruisce l'intera stringa prima della chiamata, anche se il livello è disattivato.
log.debug("id=" + id + " name=" + name) spreca CPU quando DEBUG è disattivato, perché la stringa viene costruita comunque.
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);
}
}Segnaposto con {}
SLF4J utilizza {} come segnaposto. Passi i valori come argomenti aggiuntivi.
Il messaggio viene composto solo se il livello è attivo, quindi i log disattivati hanno un costo quasi nullo.
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);
}
}Più segnaposto
I segnaposto vengono sostituiti in ordine. Il primo {} riceve il primo argomento, il secondo riceve il secondo e così via.
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);
}
}Perché è efficiente
Il framework controlla innanzitutto il livello. Se è disattivato, restituisce immediatamente il controllo senza chiamare toString() su alcun argomento.
La parte costosa, cioè la formattazione, viene eseguita in modo differito solo quando il messaggio verrà effettivamente emesso.
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});
}
}Passare oggetti grezzi, non stringhe già formattate
Per ottenere il vantaggio dell'esecuzione differita, passi l'oggetto grezzo, non una chiamata di metodo che lo formatta.
Se scrive log.debug("{}", buildReport()), buildReport() viene comunque eseguito immediatamente. Passi argomenti che il logger possa formattare autonomamente.
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);
}
}Supplier per differire le operazioni costose
Quando la formattazione è effettivamente costosa, utilizzi la fluent API di SLF4J 2.x con un Supplier, in modo da differire l'operazione.
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();
}
}Eseguire l'escape di una parentesi graffa letterale
Se nel messaggio Le serve una coppia di {} letterale, esegua l'escape con una barra rovesciata: \\{}.
È raro, ma utile quando si registra testo simile a 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);
}
}Eccezione e segnaposto
È possibile combinare i segnaposto con un'eccezione finale. SLF4J rileva che l'ultimo argomento è un Throwable e ne stampa lo stack trace.
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);
}
}
}Evitare troppi argomenti
Se il numero di segnaposto e quello degli argomenti non coincidono, SLF4J fa del suo meglio, ma l'output potrebbe risultare errato.
Li mantenga sincronizzati. Per più di un paio di valori, valuti la possibilità di utilizzare il contesto strutturato (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");
}
}Aggiungere contesto con MDC
Per valori condivisi tra molte righe (come un ID richiesta), li inserisca nell'MDC invece che in ogni messaggio.
Il layout del pattern può quindi stampare automaticamente il valore MDC su ogni riga.
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();
}
}
}Riepilogo delle best practice
Regole per un logging efficiente:
- Utilizzi sempre i segnaposto
{}, mai la concatenazione con+. - Passi oggetti grezzi, non stringhe già costruite.
- Utilizzi supplier o
isXEnabled()per le operazioni realmente costose. - Utilizzi MDC per il contesto trasversale.
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);
}
}Verifica rapida
Verifichi le Sue conoscenze del logging parametrizzato.
Riepilogo
Ha appreso il logging parametrizzato:
- Utilizzi i segnaposto
{}con argomenti aggiuntivi. - I messaggi vengono costruiti in modo differito, solo quando il livello è attivo.
- Passi oggetti grezzi; utilizzi supplier per le operazioni costose.
- Utilizzi MDC per i valori di contesto condivisi.
Successivamente, la configurazione del backend 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");
}
}Domande Frequenti
La lezione «Logging parametrizzato» è gratuita?
Sì — il testo completo di «Logging parametrizzato» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.
Cosa imparerò in «Logging parametrizzato»?
Formattazione efficiente dei messaggi Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Java Academy?
Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Logging parametrizzato»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Java Academy?
Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Perché usare il logging strutturato
- Facade e logger SLF4J
- Logging parametrizzato
- Configurare Logback