slf4j: jak rejestrować sformatowaną wiadomość, tablicę obiektów, wyjątek

275

Jakie jest prawidłowe podejście do rejestrowania zarówno wypełnionego komunikatu, jak i śladu stosu wyjątku?

logger.error(
    "\ncontext info one two three: {} {} {}\n",
    new Object[] {"1", "2", "3"},
    new Exception("something went wrong"));

Chciałbym uzyskać wynik podobny do tego:

context info one two three: 1 2 3
java.lang.Exception: something went wrong
stacktrace 0
stacktrace 1
stacktrace ...

slf4j wersja 1.6.1

rowe
źródło
3
Nie rozumiem, dlaczego slf4j używa własnej składni ciągu formatu zamiast standardowego stylu% s. Denerwujący.
Keith Tyler
@KeithTyler Lubię {}bardziej, kwestia smaku ...
Betlista
@KeithTyler toString()Metoda argumentów może być droga. Dzięki tej składni przekazywane jest tylko odwołanie do każdego obiektu, a toString()metoda jest wywoływana tylko wtedy, gdy konkretny komunikat jest faktycznie rejestrowany. Do obiektów, do których odwołuje się info()wywołanie dziennika, nie zostanie wywołana ich toString()metoda, jeśli poziom dziennika jest WARNwyższy lub wyższy. {}Składnia jest przypomnieniem dla użytkowników, to nie jest String.format()-jak operacja, czyli powinny one przechodzić obiektów zamiast ich reprezentacje ciąg.
user149408

Odpowiedzi:

427

Począwszy od SLF4J 1.6.0, w obecności wielu parametrów i jeśli ostatni argument w instrukcji rejestrowania jest wyjątkiem, wówczas SLF4J zakłada, że ​​użytkownik chce, aby ostatni argument był traktowany jako wyjątek, a nie prosty parametr. Zobacz także odpowiedni wpis FAQ .

Pisanie (w SLF4J w wersji 1.7.xi nowszych)

 logger.error("one two three: {} {} {}", "a", "b", 
              "c", new Exception("something went wrong"));

lub pisanie (w wersji SLF4J 1.6.x)

 logger.error("one two three: {} {} {}", new Object[] {"a", "b", 
              "c", new Exception("something went wrong")});

ustąpi

one two three: a b c
java.lang.Exception: something went wrong
    at Example.main(Example.java:13)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at ...

Dokładne dane wyjściowe będą zależeć od bazowej struktury (np. Logback, log4j itp.), A także od konfiguracji podstawowej struktury. Jeśli jednak ostatni parametr jest wyjątkiem, zostanie on zinterpretowany jako taki niezależnie od podstawowych ram.

Ceki
źródło
4
Z jakich ram rejestrowania korzystasz? Jak wspomniano w mojej odpowiedzi powyżej, jeśli ostatni parametr jest wyjątkiem, będzie interpretowany jako taki bez względu na podstawowe ramy. (Testowane przy pomocy logback, slf4j-log4j12, slf4j-jdk14 i slf4j-simple.)
Ceki,
3
Niestety, nie rozpoznałem, że w twoim przykładzie użyłeś n = 3 symboli zastępczych w ciągu formatu i n + 1 = 4 elementy w tablicy obiektów. Miałem n symboli zastępczych w ciągu formatu, a także n elementów w tablicy obiektów plus wyjątek jako trzeci parametr. Oczekiwałem, że wyjątek zostanie wydrukowany za pomocą stacktrace, ale tak się nigdy nie stało. Czy to działa zgodnie z przeznaczeniem? Ponadto, jeśli mam n symboli zastępczych i n elementów w tablicy obiektów, z wyjątkiem tego, że ostatni element jest ostatnim elementem, nie widzę żadnego śledzenia stosu. Może n symboli zastępczych z obiektami n + 1 w tablicy powinno być nieco bardziej podkreślonych.
rowe
7
Nie mogłem dać @Ceki kłopotu z tym, że nie jest w Javadocs, ale jest na szczycie Loggerklasy javadoc: slf4j.org/apidocs/org/slf4j/Logger.html
Adam Gent
1
Stworzyłem prośbę o ulepszenie , możesz na nią głosować, jeśli ci się spodoba.
Betlista
8

Oprócz odpowiedzi @Ceki, jeśli używasz funkcji Logback i instalujesz plik konfiguracyjny w swoim projekcie (zwykle logback.xml), możesz zdefiniować dziennik, aby wykreślić również ślad stosu za pomocą

<encoder>
    <pattern>%date |%-5level| [%thread] [%file:%line] - %msg%n%ex{full}</pattern> 
</encoder>

% ex we wzorcu czyni różnicę

Janów
źródło