0Pricing
Java Academy · Lekcja

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

  1. Dlaczego logowanie strukturalne
  2. Fasada SLF4J i loggery
  3. Logowanie parametryzowane
  4. Konfigurowanie Logback
← Powrót do Java Academy