Logowanie parametryzowane
Wydajne formatowanie komunikatów
Logowanie parametryzowane to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.
Problem z konkatenacją ciągów znaków
Konkatenowanie komunikatu logu tworzy cały ciąg znaków przed wywołaniem, nawet jeśli dany poziom jest wyłączony.
log.debug("id=" + id + " name=" + name) niepotrzebnie zużywa procesor, gdy DEBUG jest wyłączony, ponieważ ciąg znaków i tak zostaje utworzony.
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);
}
}Placeholdery z użyciem {}
SLF4J używa {} jako placeholdera. Przekaż wartości jako dodatkowe argumenty.
Komunikat jest składany tylko jeśli dany poziom jest włączony, dlatego wyłączone logowanie prawie nic nie kosztuje.
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);
}
}Wiele placeholderów
Placeholdery są wypełniane w kolejności. Pierwszy {} otrzymuje pierwszy argument, drugi — drugi argument itd.
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);
}
}Dlaczego jest to wydajne
Framework najpierw sprawdza poziom. Jeśli jest wyłączony, natychmiast kończy działanie bez wywoływania toString() dla żadnego argumentu.
Kosztowna część, czyli formatowanie, odbywa się leniwie i tylko wtedy, gdy komunikat zostanie rzeczywiście wysłany.
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});
}
}Przekazuj surowe obiekty, nie wstępnie sformatowane ciągi
Aby skorzystać z leniwego działania, przekaż surowy obiekt, a nie wywołanie metody, która go formatuje.
Jeśli napiszesz log.debug("{}", buildReport()), metoda buildReport() i tak zostanie wykonana od razu. Przekazuj argumenty, które logger może sformatować samodzielnie.
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);
}
}Leniwe Suppliery dla kosztownych operacji
Gdy formatowanie jest rzeczywiście kosztowne, użyj fluent API SLF4J 2.x wraz z Supplier, aby odroczyć wykonanie tej pracy.
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();
}
}Escapowanie dosłownych nawiasów klamrowych
Jeśli potrzebujesz dosłownego {} w komunikacie, poprzedź go backslashem: \\{}.
Zdarza się to rzadko, ale jest przydatne podczas logowania tekstu przypominającego 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);
}
}Wyjątek i placeholdery
Możesz połączyć placeholdery z wyjątkiem umieszczonym na końcu. SLF4J rozpoznaje, że ostatni argument jest typu Throwable, i wyświetla jego ślad stosu.
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);
}
}
}Unikaj zbyt wielu argumentów
Jeśli liczba placeholderów nie odpowiada liczbie argumentów, SLF4J robi, co może, ale dane wyjściowe mogą wyglądać nieprawidłowo.
Zadbaj o ich zgodność. W przypadku więcej niż kilku wartości rozważ użycie kontekstu strukturalnego (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");
}
}Dodawanie kontekstu za pomocą MDC
Wartości wspólne dla wielu wierszy, takie jak identyfikator żądania, umieść w MDC zamiast dodawać je do każdego komunikatu.
Układ wzorca może następnie automatycznie wyświetlać wartość MDC w każdym wierszu.
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();
}
}
}Podsumowanie dobrych praktyk
Zasady wydajnego logowania:
- Zawsze używaj placeholderów
{}, nigdy konkatenacji z użyciem+. - Przekazuj surowe obiekty, a nie wstępnie utworzone ciągi znaków.
- W przypadku rzeczywiście kosztownych operacji używaj supplierów lub
isXEnabled(). - Używaj MDC do przechowywania kontekstu przekrojowego.
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);
}
}Szybki test
Sprawdź swoją wiedzę o logowaniu z parametrami.
Podsumowanie
Poznali Państwo logowanie z parametrami:
- Używaj placeholderów
{}wraz z dodatkowymi argumentami. - Komunikaty są tworzone leniwie, tylko wtedy, gdy poziom jest włączony.
- Przekazuj surowe obiekty, a w przypadku kosztownych operacji używaj supplierów.
- Używaj MDC do przechowywania współdzielonych wartości kontekstu.
W następnej części omówiono konfigurację backendu 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");
}
}Często zadawane pytania
Czy lekcja „Logowanie parametryzowane” jest bezpłatna?
Tak — pełny tekst „Logowanie parametryzowane” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Logowanie parametryzowane”?
Wydajne formatowanie komunikatów Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Java Academy?
Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Logowanie parametryzowane”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?
Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Dlaczego logowanie strukturalne
- Fasada SLF4J i loggery
- Logowanie parametryzowane
- Konfigurowanie Logback