slf4j: cara mencatat pesan yang diformat, array objek, pengecualian

275

Apa pendekatan yang benar untuk mencatat pesan terpopulasi dan jejak stack pengecualian?

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

Saya ingin menghasilkan keluaran yang mirip dengan ini:

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

slf4j versi 1.6.1

rowe
sumber
3
Saya tidak mengerti mengapa slf4j menggunakan sintaks string format sendiri alih-alih gaya% s standar. Mengganggu.
Keith Tyler
@KeithTyler Saya suka {}lebih banyak, soal selera ...
Betlista
@KeithTyler toString()Metode argumen mungkin mahal. Dengan sintaks ini, hanya referensi ke setiap objek yang diteruskan dan toString()metode ini hanya dipanggil jika pesan tertentu benar-benar dicatat. Objek yang direferensikan dalam info()panggilan log tidak akan memanggil toString()metode mereka jika tingkat log WARNlebih tinggi. The {}sintaks adalah pengingat kepada pengguna bahwa ini bukan String.format()operasi -seperti, yaitu mereka harus lulus objek daripada representasi string yang daripadanya.
user149408

Jawaban:

427

Pada SLF4J 1.6.0, di hadapan beberapa parameter dan jika argumen terakhir dalam pernyataan logging adalah pengecualian, maka SLF4J akan menganggap bahwa pengguna ingin argumen terakhir diperlakukan sebagai pengecualian dan bukan parameter sederhana. Lihat juga entri FAQ yang relevan .

Jadi, menulis (dalam SLF4J versi 1.7.x dan yang lebih baru)

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

atau tulisan (dalam SLF4J versi 1.6.x)

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

akan menghasilkan

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

Output yang tepat akan tergantung pada kerangka kerja yang mendasarinya (misalnya logback, log4j, dll) juga pada bagaimana kerangka kerja yang mendasarinya dikonfigurasi. Namun, jika parameter terakhir adalah pengecualian maka akan diinterpretasikan seperti itu terlepas dari kerangka kerja yang mendasarinya.

Ceki
sumber
4
Kerangka dasar pendataan mana yang Anda gunakan? Seperti yang disebutkan dalam jawaban saya di atas, jika parameter terakhir adalah pengecualian akan ditafsirkan seperti itu terlepas dari kerangka kerja yang mendasarinya. (Diuji dengan logback, slf4j-log4j12, slf4j-jdk14 dan slf4j-simple.)
Ceki
3
Maaf, saya tidak mengenali bahwa dalam contoh Anda, Anda menggunakan n = 3 placeholder dalam format string dan n + 1 = 4 elemen dalam array objek. Saya memiliki n penampung dalam string format dan juga n elemen dalam array objek plus pengecualian sebagai parameter ketiga. Harapan saya adalah bahwa pengecualian akan dicetak dengan stacktrace tetapi ini tidak pernah terjadi. Apakah ini berfungsi seperti yang dirancang? Juga, jika saya memiliki n placeholder dan elemen n dalam array objek dengan pengecualian sebagai elemen terakhir saya tidak melihat stacktrace. Mungkin n placeholder dengan n +1 objek dalam array harus sedikit lebih ditekankan.
rowe
7
Saya akan memberikan @Ceki waktu yang sulit tentang itu tidak berada di Javadocs tetapi di bagian atas Loggerkelas javadoc: slf4j.org/apidocs/org/slf4j/Logger.html
Adam Gent
1
Saya membuat permintaan peningkatan , Anda dapat memilihnya jika Anda suka.
Betlista
8

Selain jawaban @Ceki, Jika Anda menggunakan logback dan menyiapkan file konfigurasi di proyek Anda (biasanya logback.xml), Anda dapat menentukan log untuk memplot jejak stack juga menggunakan

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

% ex dalam pola adalah apa yang membuat perbedaan

Yaniv
sumber