Logger kumparan Slf4j alternatif

Salam, teman-teman terkasih!

Saya ingin berbagi pemikiran saya tentang topik logging dan apa yang mereka tuju.

Mungkin karena kurangnya penelitian teoritis, penebangan selalu menjadi zona turbulensi di dunia Jawa. Seiring waktu, ini telah menyebabkan munculnya beberapa perpustakaan untuk penebangan, seperti:

  • Log4j
  • Java Util Logging
  • Pembalakan bersama
  • Logback
  • Log4j2

Mencoba mempersempit sisanya, sayangnya masing-masing memperkenalkan kekurangannya sendiri.

Dan jika, dari sudut pandang standardisasi kode, situasi membaik setelah kemunculan Slf4j - sebagai lapisan abstraksi untuk logging, masalah yang belum terselesaikan masih ada dalam implementasi yang ada.

Sebagai komunitas Open Source, kami mengambil inisiatif untuk membuat pendekatan revolusioner yang baru - dan membuat logger yang ringan (tetapi pada saat yang sama kaya secara fungsional), menggunakan perkembangan terkini, seperti scripting.

Masalahnya


- Implementasi yang ada hanya menyediakan dukungan parsial untuk skrip dalam pengaturan


Ini mengarah ke pemrograman deklaratif dalam file konfigurasi logger (XML, JSON, YAML), meskipun akan jauh lebih mudah untuk secara dinamis menafsirkan nilai-nilai konfigurasi saat runtime menggunakan skrip imperatif.

Mari kita ambil contoh konfigurasi filter di Logback, untuk mencatat hanya pesan dengan INFO tingkat logging:

<filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> 

Ini adalah contoh khas pemrograman XML deklaratif.

(ya, Logback mendukung filter menggunakan Groovy, tetapi hanya berlaku untuk appenders tertentu, bukan ke logger)

Tetapi dukungan skrip untuk memformat string sama sekali tidak ada.

- Konfigurasi yang rumit dan panjang


Ambil Logback dan Log4j2:

Tidak ada cara untuk mengkonfigurasi level logging untuk appender tertentu.

Appenders dikonfigurasikan secara terpisah dari penebang dan penebang merujuk ke appenders menggunakan atribut "AppenderRef" - sementara hanya penebang yang mendukung pengaturan tingkat pencatatan dan nama kelas.

Misalkan kita perlu mengecualikan pesan Debug dari satu kelas Foo dari file log tertentu tanpa mempengaruhi file dan kelas log lainnya.

Di Logback, ini dimungkinkan menggunakan filter Skrip Groovy pada appender - tetapi jika kita memiliki banyak appenders, ukuran konfigurasi tumbuh secara eksponensial.

- Untuk setiap tingkat logging - file terpisah!


Kami tidak dapat menemukan kemungkinan pengaturan seperti itu di mana pesan dikelompokkan ke dalam file berdasarkan tingkat pesan (debug, info, dll.)

Fitur-fitur yang ada membutuhkan duplikasi appenders di setiap level logging.

- Pengaturan pemfilteran menurut nama kelas di Root logger itu sendiri


Root logger hanya mendukung pengaturan tingkat logging, tetapi tidak ada kemungkinan kontrol terpusat dari kelas mana yang harus dicatat.

- Ada pemutusan konseptual antara bagaimana data log dihasilkan dalam aplikasi dan bagaimana data ini dikonsumsi oleh logger


Praktik historis sedemikian rupa sehingga logger (dan konfigurasinya) lebih berpusat pada kelas daripada jika mereka berpusat pada file.

Ini bertentangan dengan persepsi manusia, yang secara lebih logis merasakan harapan di sekitar isi akhir dari file log, daripada khawatir tentang pengaturan setiap kelas individu.

Dalam praktiknya, paradoks ini adalah alasan keterbatasan fungsional implementasi yang ada:

  • Konfigurasi nama file yang rumit
  • Konfigurasi logger yang tidak rasional, misalnya:

Logback mendukung maksimal 1 "diskriminator" di "SiftingAppender".
SiftingAppender memiliki batasan dalam pengaturan kebijakan untuk pengarsipan
Redesain RoutingAppender di Log4j2

Solusi


- Dukungan skrip penuh dalam konfigurasi


Bobbin menggunakan konfigurasi sebagai locator untuk skrip Groovy yang menentukan perilaku logger dalam runtime aplikasi.

Seperti inilah contoh "filter":

 { "levels": "['info'].contains(level)" } 

Setiap aspek logger mendukung penyesuaian menggunakan skrip:

  • Level pembalakan
  • Nama kelas
  • Format pesan
  • Nama file

- Pengaturan sederhana dan ringkas


Bobbin tidak memerlukan penyandi, pola, filter, pembeda, dan banyak hal lain yang tidak perlu.

Ini dikonfigurasi hanya dengan beberapa parameter dasar:

  • Tingkat
  • Kelas
  • File
  • Format garis

Pisahkan file untuk setiap level logging: cukup masukkan "$ {level}" di mask nama file di Bobbin.json (file konfigurasi).

Contoh file konfigurasi:

 { "levels": "['debug', 'info', 'warn', 'error'].contains(level)", "destinations": [ { "name": "io.infinite.bobbin.destinations.FileDestination", "properties": { "fileName": "\"./LOGS/PLUGINS/INPUT/${className}/${level}/${className}_${level}.log\"" }, "classes": "className.contains('conf.plugins.input')" }, { "name": "io.infinite.bobbin.destinations.FileDestination", "properties": { "fileName": "\"./LOGS/PLUGINS/OUTPUT/${className}/${level}/${threadName}_${level}_${date}.log\"" }, "classes": "className.contains('conf.plugins.output')" }, { "name": "io.infinite.bobbin.destinations.FileDestination", "properties": { "fileName": "\"./LOGS/THREADS/${threadGroupName}/${threadName}/${level}/${threadName}_${level}_${date}.log\"" }, "classes": "className.contains('io.infinite.')" }, { "name": "io.infinite.bobbin.destinations.FileDestination", "properties": { "fileName": "\"./LOGS/ALL/WARNINGS_AND_ERRORS_${date}.log\"" }, "levels": "['warn', 'error'].contains(level)" }, { "name": "io.infinite.bobbin.destinations.ConsoleDestination", "levels": "['warn', 'error'].contains(level)" } ] } 

Coba Bobbin sekarang:

 Gradle: compile "io.infinite:bobbin:2.0.0" 

* Bobbin adalah proyek Open Source yang dilisensikan di bawah Apache.

Source: https://habr.com/ru/post/id442232/


All Articles