slf4j: So protokollieren Sie formatierte Nachrichten, Objektarrays und Ausnahmen

274

Was ist der richtige Ansatz, um sowohl eine aufgefüllte Nachricht als auch eine Stapelverfolgung der Ausnahme zu protokollieren?

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

Ich möchte eine ähnliche Ausgabe erstellen:

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

slf4j Version 1.6.1

Rowe
quelle
3
Ich verstehe nicht, warum slf4j anstelle des Standardstils% s eine eigene Format-String-Syntax verwendet. Nervig.
Keith Tyler
@KeithTyler Ich mag {}mehr, die Frage des Geschmacks ...
Betlista
@KeithTyler Die toString()Methode der Argumente kann teuer sein. Mit dieser Syntax wird nur ein Verweis auf jedes Objekt übergeben und die toString()Methode wird nur aufgerufen, wenn die bestimmte Nachricht tatsächlich protokolliert wird. Bei Objekten, auf die in einem info()Protokollaufruf verwiesen wird, wird die toString()Methode nicht aufgerufen, wenn die Protokollstufe WARNoder höher ist. Die {}Syntax erinnert Benutzer daran, dass dies keine String.format()ähnliche Operation ist, dh sie sollten Objekte übergeben und keine Zeichenfolgendarstellungen davon.
user149408

Antworten:

426

Ab SLF4J 1.6.0 geht SLF4J bei Vorhandensein mehrerer Parameter und wenn das letzte Argument in einer Protokollierungsanweisung eine Ausnahme darstellt, davon aus, dass der Benutzer möchte, dass das letzte Argument als Ausnahme und nicht als einfacher Parameter behandelt wird. Siehe auch den entsprechenden FAQ-Eintrag .

Also schreiben (in SLF4J Version 1.7.x und höher)

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

oder schriftlich (in SLF4J Version 1.6.x)

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

wird nachgeben

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 ...

Die genaue Ausgabe hängt vom zugrunde liegenden Framework (z. B. Logback, log4j usw.) sowie von der Konfiguration des zugrunde liegenden Frameworks ab. Wenn der letzte Parameter jedoch eine Ausnahme darstellt, wird er unabhängig vom zugrunde liegenden Framework als solcher interpretiert.

Ceki
quelle
4
Welches zugrunde liegende Protokollierungsframework verwenden Sie? Wie in meiner obigen Antwort erwähnt, wird der letzte Parameter, wenn er eine Ausnahme darstellt, unabhängig vom zugrunde liegenden Framework als solcher interpretiert. (Getestet mit Logback, slf4j-log4j12, slf4j-jdk14 und slf4j-simple.)
Ceki
3
Entschuldigung, ich habe nicht erkannt, dass Sie in Ihrem Beispiel n = 3 Platzhalter in der Formatzeichenfolge und n + 1 = 4 Elemente im Objektarray verwendet haben. Ich hatte n Platzhalter in der Formatzeichenfolge und auch n Elemente im Objektarray sowie eine Ausnahme als dritten Parameter. Ich hatte erwartet, dass die Ausnahme mit Stacktrace gedruckt wird, aber das ist nie passiert. Funktioniert das wie geplant? Wenn ich n Platzhalter und n Elemente im Objektarray habe, mit Ausnahme des letzten Elements, sehe ich keine Stapelverfolgung. Vielleicht sollten die n Platzhalter mit n + 1 Objekten in einem Array etwas stärker hervorgehoben werden.
Rowe
7
Ich wollte es @Ceki schwer machen, nicht in den Javadocs zu sein, aber es steht an der Spitze der LoggerJavadoc-Klasse: slf4j.org/apidocs/org/slf4j/Logger.html
Adam Gent
1
Ich habe eine Verbesserungsanfrage erstellt . Sie können dafür stimmen, wenn es Ihnen gefällt.
Betlista
8

Zusätzlich zu @Cekis Antwort: Wenn Sie Logback verwenden und eine Konfigurationsdatei in Ihrem Projekt einrichten (normalerweise logback.xml), können Sie das Protokoll definieren, um auch den Stack-Trace zu zeichnen

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

Das% ex im Muster macht den Unterschied

Yaniv
quelle