Mengapa tidak menggunakan java.util.logging?

351

Untuk pertama kalinya dalam hidup saya, saya menemukan diri saya dalam posisi di mana saya sedang menulis Java API yang akan bersumber terbuka. Semoga bisa dimasukkan dalam banyak proyek lainnya.

Untuk logging saya (dan memang orang yang bekerja dengan saya) selalu menggunakan JUL (java.util.logging) dan tidak pernah memiliki masalah dengan itu. Namun sekarang saya perlu memahami secara lebih rinci apa yang harus saya lakukan untuk pengembangan API saya. Saya telah melakukan beberapa penelitian tentang ini dan dengan informasi yang saya dapatkan saya menjadi semakin bingung. Karenanya pos ini.

Karena saya berasal dari JUL, saya bias dalam hal itu. Pengetahuan saya tentang sisanya tidak sebesar itu.

Dari penelitian yang saya lakukan, saya menemukan alasan mengapa orang tidak suka JUL:

  1. "Saya mulai berkembang di Jawa jauh sebelum Sun merilis JUL dan lebih mudah bagi saya untuk melanjutkan logging-framework-X daripada belajar sesuatu yang baru" . Hmm. Saya tidak bercanda, ini sebenarnya yang dikatakan orang. Dengan argumen ini kita semua bisa melakukan COBOL. (Namun saya pasti bisa menghubungkan ini menjadi cowok malas sendiri)

  2. "Saya tidak suka nama level logging di JUL" . Ok, serius, ini tidak cukup alasan untuk memperkenalkan ketergantungan baru.

  3. "Saya tidak suka format standar keluaran dari JUL" . Hmm. Ini hanya konfigurasi. Anda bahkan tidak perlu melakukan apapun secara bijaksana. (benar, di masa lalu Anda mungkin harus membuat kelas Formatter Anda sendiri untuk memperbaikinya).

  4. "Saya menggunakan perpustakaan lain yang juga menggunakan logging-framework-X jadi saya pikir lebih mudah hanya menggunakan yang itu" . Ini argumen melingkar, bukan? Mengapa 'semua orang' menggunakan logging-framework-X dan bukan JULI?

  5. "Semua orang menggunakan logging-framework-X" . Ini bagi saya hanyalah kasus khusus di atas. Mayoritas tidak selalu benar.

Jadi pertanyaan besar sebenarnya adalah mengapa tidak JULI? . Apa yang saya lewatkan? The raison d'être untuk fasad logging (SLF4J, JCL) adalah bahwa beberapa implementasi logging telah ada secara historis dan alasan untuk itu benar-benar kembali ke era sebelum JUL seperti yang saya lihat. Jika JUL sempurna maka fasad logging tidak akan ada, atau apa? Untuk membuat hal-hal yang lebih membingungkan, JUL adalah suatu fasad itu sendiri, memungkinkan Handler, Formatters dan bahkan LogManager untuk ditukar.

Daripada merangkul banyak cara untuk melakukan hal yang sama (logging), bukankah kita seharusnya mempertanyakan mengapa mereka diperlukan? (dan lihat apakah alasan itu masih ada)

Ok, penelitian saya sejauh ini telah mengarah pada beberapa hal yang dapat saya lihat mungkin masalah nyata dengan JUL:

  1. Performa . Ada yang mengatakan bahwa kinerja di SLF4J lebih unggul dari yang lain. Bagi saya ini adalah optimasi yang prematur. Jika Anda perlu mencatat ratusan megabyte per detik maka saya tidak yakin Anda berada di jalur yang benar. JUL juga telah berevolusi dan tes yang Anda lakukan di Java 1.4 mungkin tidak lagi benar. Anda dapat membacanya di sini dan perbaikan ini telah membuatnya menjadi Java 7. Banyak juga yang berbicara tentang overhead dari penggabungan string dalam metode logging. Namun logging berbasis template menghindari biaya ini dan ada juga di JUL. Secara pribadi saya tidak pernah benar-benar menulis logging berbasis template. Terlalu malas untuk itu. Sebagai contoh jika saya melakukan ini dengan JULI:

    log.finest("Lookup request from username=" + username 
       + ", valueX=" + valueX
       + ", valueY=" + valueY));
    

    IDE saya akan memperingatkan saya dan meminta izin untuk mengubahnya menjadi:

    log.log(Level.FINEST, "Lookup request from username={0}, valueX={1}, valueY={2}", 
       new Object[]{username, valueX, valueY});
    

    .. yang tentu saja akan saya terima. Izin diberikan ! Terima kasih untuk bantuannya.

    Jadi saya tidak benar-benar menulis pernyataan seperti itu sendiri, yang dilakukan oleh IDE.

    Kesimpulannya pada masalah kinerja saya belum menemukan apa pun yang menunjukkan bahwa kinerja JUL tidak ok dibandingkan dengan kompetisi.

  2. Konfigurasi dari classpath . JUL out-of-the-box tidak dapat memuat file konfigurasi dari classpath. Ini adalah beberapa baris kode untuk membuatnya melakukannya. Saya bisa melihat mengapa ini mungkin mengganggu tetapi solusinya pendek dan sederhana.

  3. Ketersediaan penangan keluaran . JUL hadir dengan 5 penangan keluaran out-of-the-box: konsol, aliran file, soket dan memori. Ini dapat diperpanjang atau yang baru dapat ditulis. Misalnya, ini dapat ditulis ke UNIX / Linux Syslog dan Windows Event Log. Saya pribadi tidak pernah memiliki persyaratan ini atau saya melihatnya digunakan tetapi saya pasti bisa menghubungkan mengapa itu mungkin fitur yang berguna. Logback dilengkapi dengan appender untuk Syslog misalnya. Masih saya akan membantah itu

    1. 99,5% dari kebutuhan untuk destinasi keluaran dicakup oleh apa yang ada di JUL out-of-the-box.
    2. Kebutuhan khusus dapat dipenuhi oleh penangan khusus di atas JUL daripada di atas sesuatu yang lain. Tidak ada bagi saya yang menunjukkan bahwa dibutuhkan lebih banyak waktu untuk menulis handler keluaran Syslog untuk JUL daripada yang dilakukan untuk kerangka kerja logging lain.

Saya benar-benar khawatir ada sesuatu yang saya abaikan. Penggunaan fasad penebangan dan implementasi penebangan selain JUL sangat luas sehingga saya harus sampai pada kesimpulan bahwa saya yang tidak mengerti. Itu bukan pertama kalinya, saya khawatir. :-)

Jadi apa yang harus saya lakukan dengan API saya? Saya ingin menjadi sukses. Tentu saja saya bisa hanya "mengikuti arus" dan menerapkan SLF4J (yang tampaknya paling populer akhir-akhir ini) tetapi demi saya sendiri, saya masih perlu memahami persis apa yang salah dengan JULI hari ini yang menjamin semua fuzz? Apakah saya akan menyabot diri dengan memilih JUL untuk perpustakaan saya?

Menguji kinerja

(bagian ditambahkan oleh nolan600 pada 07-JUL-2012)

Ada referensi di bawah ini dari Ceki tentang parametri SLF4 menjadi 10 kali atau lebih cepat daripada JUL. Jadi saya sudah mulai melakukan beberapa tes sederhana. Sepintas klaim itu tentu benar. Berikut adalah hasil awal (tapi baca terus!):

  • Waktu pelaksanaan SLF4J, backend Logback: 1515
  • Waktu eksekusi SLF4J, backend JUL: 12938
  • Waktu eksekusi JUL: 16911

Angka-angka di atas adalah msec jadi lebih sedikit lebih baik. Jadi perbedaan kinerja 10 kali dengan yang pertama sebenarnya cukup dekat. Reaksi awal saya: Banyak sekali!

Inilah inti dari tes ini. Seperti dapat dilihat integer dan string dibangun dalam satu loop yang kemudian digunakan dalam pernyataan log:

    for (int i = 0; i < noOfExecutions; i++) {
        for (char x=32; x<88; x++) {
            String someString = Character.toString(x);
            // here we log 
        }
    }

(Saya ingin pernyataan log memiliki tipe data primitif (dalam hal ini int) dan tipe data yang lebih kompleks (dalam hal ini sebuah String). Tidak yakin itu penting tetapi Anda memilikinya.)

Pernyataan log untuk SLF4J:

logger.info("Logging {} and {} ", i, someString);

Pernyataan log untuk JUL:

logger.log(Level.INFO, "Logging {0} and {1}", new Object[]{i, someString});

JVM 'menghangat' dengan tes yang sama dilakukan sekali sebelum pengukuran yang sebenarnya dilakukan. Java 1.7.03 digunakan pada Windows 7. Versi terbaru SLF4J (v1.6.6) dan Logback (v1.0.6) digunakan. Stdout dan stderr dialihkan ke perangkat nol.

Namun, hati-hati sekarang, ternyata JUL menghabiskan sebagian besar waktunya getSourceClassName()karena JUL secara default mencetak nama kelas sumber dalam output, sementara Logback tidak. Jadi kami membandingkan apel dan jeruk. Saya harus melakukan tes lagi dan mengkonfigurasi implementasi logging dengan cara yang sama sehingga mereka benar-benar menghasilkan hal yang sama. Namun saya menduga bahwa SLF4J + Logback masih akan keluar di atas tetapi jauh dari angka awal seperti yang diberikan di atas. Tetap disini.

Btw: Tes ini pertama kali saya benar-benar bekerja dengan SLF4J atau Logback. Pengalaman yang menyenangkan. JUL tentu jauh lebih tidak ramah ketika Anda memulai.

Menguji kinerja (bagian 2)

(bagian ditambahkan oleh nolan600 pada 08-JUL-2012)

Ternyata tidak masalah untuk kinerja bagaimana Anda mengkonfigurasi pola Anda di JUL, yaitu apakah itu termasuk nama sumber atau tidak. Saya mencoba dengan pola yang sangat sederhana:

java.util.logging.SimpleFormatter.format="%4$s: %5$s [%1$tc]%n"

dan itu tidak mengubah timing di atas sama sekali. Profiler saya mengungkapkan bahwa logger masih menghabiskan banyak waktu dalam panggilan getSourceClassName()bahkan jika ini bukan bagian dari pola saya. Polanya tidak masalah.

Oleh karena itu saya menyimpulkan pada masalah kinerja bahwa setidaknya untuk pernyataan log berbasis template yang diuji tampaknya ada kira-kira faktor 10 dalam perbedaan kinerja nyata antara JUL (lambat) dan SLF4J + Logback (cepat). Seperti kata Ceki.

Saya juga bisa melihat hal lain yaitu bahwa getLogger()panggilan SLF4J jauh lebih mahal daripada JUL. (95 ms vs 0,3 ms jika profiler saya akurat). Ini masuk akal. SLF4J harus melakukan beberapa waktu untuk mengikat implementasi logging yang mendasarinya. Ini tidak membuatku takut. Panggilan ini harus agak jarang terjadi dalam masa aplikasi. Tahan luntur harus dalam panggilan log yang sebenarnya.

Kesimpulan akhir

(bagian ditambahkan oleh nolan600 pada 08-JUL-2012)

Terima kasih atas semua jawaban Anda. Bertentangan dengan apa yang awalnya saya pikir saya akhirnya memutuskan untuk menggunakan SLF4J untuk API saya. Ini didasarkan pada sejumlah hal dan masukan Anda:

  1. Ini memberikan fleksibilitas untuk memilih implementasi log pada waktu penyebaran.

  2. Masalah dengan kurangnya fleksibilitas konfigurasi JUL saat dijalankan di dalam server aplikasi.

  3. SLF4J tentu jauh lebih cepat seperti yang dijelaskan di atas khususnya jika Anda memasangkannya dengan Logback. Bahkan jika ini hanya tes kasar saya punya alasan untuk percaya bahwa lebih banyak upaya telah dilakukan untuk optimasi pada SLF4J + Logback daripada pada JUL.

  4. Dokumentasi. Dokumentasi untuk SLF4J jauh lebih komprehensif dan tepat.

  5. Fleksibilitas pola. Ketika saya melakukan tes saya menetapkan untuk JUL meniru pola default dari Logback. Pola ini termasuk nama utas. Ternyata JULI tidak bisa melakukan ini di luar kotak. Ok, saya belum melewatkannya sampai sekarang, tetapi saya tidak berpikir itu adalah hal yang harus hilang dari kerangka log. Titik!

  6. Sebagian besar (atau banyak) proyek Java saat ini menggunakan Maven sehingga menambahkan ketergantungan bukanlah hal yang besar terutama jika ketergantungan itu agak stabil, yaitu tidak selalu mengubah API-nya. Ini tampaknya berlaku untuk SLF4J. Gelas dan teman SLF4J juga berukuran kecil.

Jadi hal aneh yang terjadi adalah saya benar-benar kesal dengan JUL setelah bekerja sedikit dengan SLF4J. Saya masih menyesal bahwa ini harus dengan JUL. Juli memang jauh dari sempurna, tetapi jenis pekerjaan yang dilakukannya. Tidak cukup baik. Hal yang sama dapat dikatakan tentang Propertiessebagai contoh tetapi kami tidak berpikir tentang abstrak sehingga orang dapat menyambungkan pustaka konfigurasi mereka sendiri dan apa pun yang Anda miliki. Saya pikir alasannya adalah yang Propertiesdatang tepat di atas bar sementara yang sebaliknya berlaku untuk JUL hari ini ... dan di masa lalu itu datang pada nol karena tidak ada.

peterh
sumber
8
Saya tidak akan meminta penutupan, karena pertanyaan yang disajikan dengan baik ini menarik, tetapi ini merupakan batas jika Anda membaca FAQ: akan sulit untuk menemukan jawaban unik yang pasti tidak berdasarkan pada pendapat.
Denys Séguret
Apa yang mungkin Anda lewatkan adalah bahwa banyak penulis kerangka menyerah mencoba menggunakan JUL dan karenanya seringkali lebih sulit untuk menggunakannya jika Anda tidak hanya membuat vanilla java.
Denys Séguret
3
Adalah keliru untuk menggunakan istilah umum "logging-framework-X" ketika merujuk pada kerangka kerja penebangan populer yang ada sebelum jul. Anda harus menggunakan "log4j" dalam kasus ini. Kerangka kerja populer lainnya seperti SLF4J dan logback datang dengan baik setelah jul dirilis.
Ceki
1
@Acuariano. Proyek Netty hanya menggunakan Refleksi untuk menguji kerangka logging apa yang tersedia di classpath. Lihat di sini untuk sumbernya. Lihat InternalLoggerFactory.java.
peterh
1
@xenoterracide bahkan yang lebih penting adalah pembaruan ke Java 9, seperti yang diperkenalkan java.lang.System.Logger, yang merupakan antarmuka , yang dapat diarahkan ke kerangka kerja logging aktual apa pun yang Anda inginkan, selama kerangka itu berhasil dan menyediakan implementasi antarmuka itu. Dikombinasikan dengan modularisasi, Anda bahkan bisa menggunakan aplikasi dengan JRE yang dibundel tidak berisi java.util.logging, jika Anda lebih suka kerangka kerja yang berbeda.
Holger

Jawaban:

207

Penafian : Saya adalah pendiri proyek log4j, SLF4J dan logback.

Ada alasan obyektif untuk memilih SLF4J. Pertama, SLF4J memungkinkan pengguna akhir kebebasan untuk memilih kerangka kerja logging yang mendasarinya . Selain itu, pengguna yang berpengalaman cenderung lebih suka logback yang menawarkan kemampuan di luar log4j , dengan jul yang jauh tertinggal. Fitur-fitur jul mungkin cukup untuk beberapa pengguna tetapi bagi banyak orang lain tidak. Singkatnya, jika logging penting bagi Anda, Anda ingin menggunakan SLF4J dengan logback sebagai implementasi yang mendasarinya. Jika logging tidak penting, jul baik-baik saja.

Namun, sebagai pengembang oss, Anda harus memperhitungkan preferensi pengguna dan bukan hanya preferensi Anda. Oleh karena itu Anda harus mengadopsi SLF4J bukan karena Anda yakin bahwa SLF4J lebih baik daripada jul tetapi karena sebagian besar pengembang Java saat ini (Juli 2012) lebih memilih SLF4J sebagai API logging mereka. Jika pada akhirnya Anda memutuskan untuk tidak peduli dengan pendapat umum, pertimbangkan fakta-fakta berikut:

  1. mereka yang memilih jul melakukannya karena kenyamanan karena jul dibundel dengan JDK. Setahu saya tidak ada argumen objektif yang mendukung jul
  2. preferensi Anda sendiri untuk jul hanya itu, preferensi .

Dengan demikian, memegang "fakta keras" di atas opini publik, meskipun tampak berani, adalah kekeliruan logis dalam kasus ini.

Jika masih tidak yakin, JB Nizet membuat argumen tambahan dan kuat:

Kecuali pengguna akhir bisa melakukan kustomisasi ini untuk kodenya sendiri, atau pustaka lain yang menggunakan log4j atau logback. jul bisa diperluas, tetapi harus memperluas logback, jul, log4j dan hanya Tuhan yang tahu kerangka kerja logging yang lain karena ia menggunakan empat pustaka yang menggunakan empat kerangka kerja logging berbeda rumit. Dengan menggunakan SLF4J, Anda mengizinkannya untuk mengkonfigurasi kerangka kerja logging yang dia inginkan, bukan yang Anda pilih. Ingatlah bahwa proyek tipikal menggunakan berjuta perpustakaan, dan bukan hanya milik Anda .

Jika karena alasan apa pun Anda membenci API SLF4J dan menggunakannya akan memadamkan kesenangan dari pekerjaan Anda, maka tentu saja berlaku untuk jul. Bagaimanapun, ada cara untuk mengarahkan jul ke SLF4J .

Omong-omong, parametri jul setidaknya 10 kali lebih lambat dari SLF4J yang akhirnya membuat perbedaan nyata.

Ceki
sumber
2
@ Ceki Anda mungkin ingin menjelaskan sedikit tentang disclaimer Anda sehingga menyebutkan peran Anda saat ini di proyek log4j, slf4j dan logback. Alasannya adalah untuk menjelaskan bias Anda secara alami.
Thorbjørn Ravn Andersen
2
Apakah ada dukungan untuk klaim bahwa sebagian besar pengembang Java lebih memilih SLF4J sebagai API logging mereka?
Olivier Cailloux
3
Inti dari posting saya adalah bahwa pengembang yang berbeda memiliki preferensi yang berbeda yang tampaknya tidak dapat diperdebatkan. Iya?
Ceki
1
jujur, saya ingin melihat 2018 tolok ukur di Java 11 (atau apa pun yang akhirnya menjadi), dan terhadap log4j2 dalam mode async.
xenoterracide
5
Inilah saya, menggunakan SLF4J, dan saya masih harus berurusan dengan semua kerangka kerja logging lainnya yang digunakan perpustakaan lain. Menggunakan SLF4J tidak memecahkan masalah penebang heterogen, itu hanya membuatnya lebih buruk. xkcd.com/927
Charlie
34
  1. java.util.loggingdiperkenalkan di Jawa 1.4. Ada kegunaan untuk logging sebelum itu, itu sebabnya banyak API logging lain ada. API mana yang banyak digunakan sebelum Java 1.4 dan karenanya memiliki pangsa pasar yang hebat yang tidak hanya turun ke 0 saat 1.4 dirilis.

  2. JULI tidak memulai semua yang hebat, banyak hal yang Anda sebutkan di mana jauh lebih buruk di 1,4 dan hanya menjadi lebih baik di 1,5 (dan saya kira di 6 juga, tapi saya tidak terlalu yakin).

  3. JUL tidak cocok untuk beberapa aplikasi dengan konfigurasi berbeda di JVM yang sama (pikirkan beberapa aplikasi web yang tidak boleh berinteraksi). Tomcat perlu melompati beberapa rintangan untuk membuatnya bekerja (mengimplementasikan kembali JUL secara efektif jika saya memahaminya dengan benar).

  4. Anda tidak selalu dapat memengaruhi kerangka kerja pencatatan yang digunakan perpustakaan Anda. Oleh karena itu menggunakan SLF4J (yang sebenarnya hanya lapisan API yang sangat tipis di atas pustaka lainnya) membantu menjaga gambaran yang agak konsisten dari seluruh dunia logging (sehingga Anda dapat memutuskan kerangka kerja logging yang mendasarinya sementara masih memiliki library logging di sistem yang sama).

  5. Perpustakaan tidak dapat dengan mudah diubah. Jika versi sebelumnya dari perpustakaan yang digunakan untuk menggunakan logging-library-X, ia tidak dapat dengan mudah beralih ke logging-library-Y (misalnya JUL), bahkan jika yang terakhir jelas superious: setiap pengguna perpustakaan itu perlu belajar kerangka kerja logging baru dan (setidaknya) mengkonfigurasi ulang logging mereka. Itu sangat tidak boleh, terutama ketika itu tidak membawa keuntungan bagi kebanyakan orang.

Setelah mengatakan semua yang saya pikir JUL setidaknya merupakan alternatif yang valid untuk kerangka kerja logging lainnya hari ini.

Joachim Sauer
sumber
1
Terima kasih Joachim, saya menghargai posting Anda. (1) dan (2) Anda hanya bagi saya sejarah. Dahulu kala. (4) Anda adalah konsekuensi dari itu dan kemudian menjadi apa yang saya sebut argumen siklik. (3) Anda sangat menarik. Mungkin Anda tertarik pada sesuatu? Tetapi ini hanya akan mempengaruhi mereka yang membangun wadah aplikasi yang pada akhirnya sangat sedikit orang. Atau apa?
peterh
3
Nah, siapa yang mengabaikan sejarah ditakdirkan untuk mengulanginya ;-) Sejarah sangat relevan dalam pengembangan perangkat lunak. Orang tidak bergerak terlalu cepat dan mengganti pustaka pihak ketiga yang ada dengan API standar hanya berfungsi dengan baik jika API standar berfungsi setidaknya sebaik pustaka pihak ketiga. Dan mereka awalnya tidak (dan bisa dibilang masih tidak dalam beberapa kasus).
Joachim Sauer
Joachim, saya tertarik pada "masih bisa dibilang tidak dalam beberapa kasus" yang Anda sebutkan. Itu tadi dagingnya. Mengganti perpustakaan logger dalam kode Anda yang ada cukup sepele dan dapat otomatis hari ini. SLF4J memiliki alat untuk itu yang membuktikan maksud saya. Jadi saya akan berpikir bahwa perpustakaan besar yang ditulis pada tahun 2002 dengan log4j dapat dikonversi menjadi JUL dalam hitungan menit dengan alat otomatis. (Tapi saya tidak tahu kalau ada). Jadi mengapa itu tidak terjadi?
peterh
3
@ nolan6000: Saya tidak cukup tahu tentang hal-hal spesifik untuk merinci frasa itu, dan bukan itu maksud saya. Bahkan jika JUL sekarang setara dengan kerangka kerja pihak ketiga, kelembaman dan infrastruktur yang ada masih merupakan alasan kuat untuk tidak beralih. Sebagai contoh jika library X menggunakan slf4j di Versi 1.1, beralih ke JUL di 1.2 (atau bahkan 2.0) akan menjadi masalah besar bagi banyak pengguna (yang sudah mengkonfigurasi sistem lama dengan benar dan harus melakukan kembali itu tanpa keuntungan nyata) .
Joachim Sauer
@ nolan6000 bahkan jika Anda tidak peduli tentang sejarah, perpustakaan yang Anda gunakan di aplikasi Anda pasti akan melakukannya. Tidak menyenangkan karena harus membuang perpustakaan hanya karena menggunakan kerangka logging yang berbeda dari Anda.
Thorbjørn Ravn Andersen
29

IMHO, keuntungan utama dalam menggunakan fasad logging seperti slf4j adalah Anda membiarkan pengguna akhir dari perpustakaan memilih implementasi logging logging yang ia inginkan, daripada memaksakan pilihan Anda kepada pengguna akhir.

Mungkin dia telah menginvestasikan waktu dan uang di Log4j atau LogBack (formatters khusus, appenders, dll.) Dan lebih suka terus menggunakan Log4j atau LogBack, daripada mengkonfigurasi jul. Tidak masalah: slf4j memungkinkan itu. Apakah ini pilihan bijak untuk menggunakan Log4j daripada jul? Mungkin tidak. Tapi kamu tidak peduli. Biarkan pengguna akhir memilih apa yang diinginkannya.

JB Nizet
sumber
Terima kasih JB. Pertanyaan saya adalah apakah saya benar-benar memaksakan itu pada pengguna / pelaksana perpustakaan saya dengan memaksa JUL padanya? Jika dia tidak senang dengan contoh handler keluaran standar JUL dia hanya bisa menukar mereka sendiri pada waktu penempatan seperti yang saya lihat. Saya tidak benar-benar melihat JUL sebagai jaket pelindung. Bagi saya kelihatannya sefleksibel dan dapat diperluas seperti yang lainnya.
peterh
12
Kecuali pengguna akhir bisa melakukan kustomisasi ini untuk kodenya sendiri, atau pustaka lain yang menggunakan log4j atau LogBack. jul bisa diperluas, tetapi harus memperluas LogBack, jul, log4j dan hanya Tuhan yang tahu kerangka kerja logging yang lain karena ia menggunakan 4 pustaka yang menggunakan 4 kerangka kerja logging berbeda rumit. Dengan menggunakan slf4j, Anda mengizinkannya untuk mengkonfigurasi kerangka kerja logging yang ia inginkan. bukan yang telah Anda pilih. Ingat bahwa proyek tipikal menggunakan berjuta perpustakaan, dan bukan hanya milik Anda.
JB Nizet
6

Saya mulai, seperti Anda saya kira, menggunakan JULI karena itu yang paling mudah untuk segera dilakukan. Namun, selama bertahun-tahun, saya berharap saya telah menghabiskan lebih banyak waktu untuk memilih.

Masalah utama saya sekarang adalah bahwa kita memiliki sejumlah besar kode 'perpustakaan' yang digunakan di banyak aplikasi dan mereka semua menggunakan JUL. Setiap kali saya menggunakan alat ini dalam aplikasi jenis layanan web, pencatatan hanya menghilang atau pergi ke suatu tempat yang tidak terduga atau aneh.

Solusi kami adalah menambahkan fasad ke kode perpustakaan yang berarti bahwa panggilan log perpustakaan tidak berubah tetapi dialihkan secara dinamis ke mekanisme log apa pun yang tersedia. Ketika dimasukkan dalam alat POJO mereka diarahkan ke JUL tetapi ketika digunakan sebagai aplikasi web mereka diarahkan ke LogBack.

Penyesalan kami - tentu saja - adalah bahwa kode pustaka tidak menggunakan pencatatan parameter tetapi sekarang ini dapat dipasang kembali saat dan ketika dibutuhkan.

Kami menggunakan slf4j untuk membangun fasad.

OldCurmudgeon
sumber
1
Apa alasan Anda tidak hanya menggunakan paket "redirect java.util.logging to slf4j" dalam distribusi slf4j?
Thorbjørn Ravn Andersen
2
Kami melakukannya, tetapi sedikit nilainya karena manfaat utama pindah ke slf4j adalah logging parameterised yang efisien. Jika kita menggunakannya sejak awal, kita tidak akan memiliki pekerjaan yang harus dilakukan sekarang.
OldCurmudgeon
1
Saya setuju bahwa ini adalah buah slf4j yang rendah.
Thorbjørn Ravn Andersen
3

Saya menjalankan jul terhadap slf4j-1.7.21 melalui logback-1.1.7, output ke SSD, Java 1.8, Win64

Juli berlari 48449 ms, logback 27185 ms untuk loop 1M.

Namun, sedikit lebih cepat dan API yang sedikit lebih baik tidak bernilai 3 perpustakaan dan 800 ribu untuk saya.

package log;

import java.util.logging.Level;
import java.util.logging.Logger;

public class LogJUL
{
    final static Logger logger = Logger.getLogger(LogJUL.class.getSimpleName());

    public static void main(String[] args) 
    {
        int N = 1024*1024;

        long l = System.currentTimeMillis();

        for (int i = 0; i < N; i++)
        {
            Long lc = System.currentTimeMillis();

            Object[] o = { lc };

            logger.log(Level.INFO,"Epoch time {0}", o);
        }

        l = System.currentTimeMillis() - l;

        System.out.printf("time (ms) %d%n", l);
    }
}

dan

package log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogSLF
{
    static Logger logger = LoggerFactory.getLogger(LogSLF.class);


    public static void main(String[] args) 
    {
        int N = 1024*1024;

        long l = System.currentTimeMillis();

        for (int i = 0; i < N; i++)
        {
            Long lc = System.currentTimeMillis();

            logger.info("Epoch time {}", lc);
        }

        l = System.currentTimeMillis() - l;

        System.out.printf("time (ms) %d%n", l);
    }

}
weberjn
sumber
3
Anda tidak membandingkan suka untuk suka. Mengapa Anda secara eksplisit membuat array untuk jul? Saya kira itu karena slf4j tidak memiliki satu argumen yang berlebihan logger.info(). Jadi Anda sengaja melumpuhkan kinerja jul untuk mengkompensasi kekurangan pada antarmuka slf4j. Anda sebaiknya mengkode kedua metode dengan cara mereka dikodekan secara idiomatis.
Klitos Kyriacou
2
Anda salah paham. Anda tidak harus menggunakan 800 ribu tambahan. Konsensusnya adalah bahwa api SLF4J yang sangat tipis layak digunakan karena Anda (atau orang lain yang mungkin menggunakan kembali kode Anda suatu hari nanti!) Dapat beralih bebas di antara JUL, Logback, Log4j dll. SLF4J hanya ~ 28K. Jembatan SLF4J ke JUL (slf4j-jdk ... jar) hanya ~ 9K.
Riskop