JavaRush /Java Blog /Random-ID /Logging di Java: apa, bagaimana, dimana dan dengan apa?

Logging di Java: apa, bagaimana, dimana dan dengan apa?

Dipublikasikan di grup Random-ID
Halo semuanya, komunitas JavaRush! Hari ini kita akan berbicara tentang logging Java:
  1. Apa ini, mengapa demikian. Kapan lebih baik digunakan, kapan tidak?
  2. Apa saja perbedaan penerapan logging di Jawa dan apa yang harus kita lakukan terhadap keberagaman ini?
  3. Tingkat pencatatan. Mari kita bahas apa itu appender dan cara mengkonfigurasinya dengan benar.
  4. Pencatatan node dan cara mengkonfigurasinya dengan benar agar semuanya berjalan sesuai keinginan kita.
Materi ini ditujukan untuk khalayak luas. Ini akan menjadi jelas bagi mereka yang baru mengenal Java, dan bagi mereka yang sudah bekerja, tetapi baru mengetahuinya dengan logger.info(“log something”); Let's Go!

Mengapa logging diperlukan?

Mari kita lihat kasus nyata di mana logging dapat memecahkan masalah tersebut. Ini adalah contoh dari pekerjaan saya. Ada titik aplikasi yang terintegrasi dengan layanan lain. Saya menggunakan pencatatan poin-poin ini sebagai “alibi” : jika integrasi tidak berhasil, maka akan mudah untuk mengetahui dari sisi mana masalahnya berasal. Dianjurkan juga untuk mencatat informasi penting yang disimpan ke database. Misalnya membuat pengguna administrator. Ini adalah hal yang baik untuk dicatat.

Alat Pencatatan Java

Penebangan: apa, bagaimana, dimana dan dengan apa?  - 2Solusi terkenal untuk masuk ke Java meliputi:
  • log4j
  • JUL - java.util.logging
  • JCL - jakarta commons penebangan
  • Masuk kembali
  • SLF4J - fasad logging sederhana untuk java
Mari kita lihat sekilas masing-masingnya, dan di bagian praktis materi ini kita akan menggunakan koneksi Slf4j - log4j sebagai dasar . Ini mungkin tampak aneh sekarang, tapi jangan khawatir: di akhir artikel semuanya akan menjadi jelas.

Sistem.err.println

Awalnya tentu saja ada System.err.println (merekam keluaran ke konsol). Itu masih digunakan untuk mendapatkan log dengan cepat selama debugging. Tentu saja, tidak perlu membicarakan pengaturan apa pun di sini, jadi ingatlah saja dan lanjutkan.

Log4j

Ini sudah merupakan solusi lengkap, yang diciptakan berdasarkan kebutuhan pengembang. Ternyata ini adalah alat yang sangat menarik untuk digunakan. Karena berbagai keadaan, solusi ini tidak pernah berhasil masuk ke JDK, yang membuat seluruh komunitas kecewa. log4j memiliki opsi konfigurasi sehingga logging dapat diaktifkan dalam sebuah paket com.example.typedan dimatikan dalam subpaket com.example.type.generic. Hal ini memungkinkan untuk dengan cepat memisahkan apa yang perlu dicatat dari apa yang tidak diperlukan. Penting untuk dicatat di sini bahwa ada dua versi log4j: 1.2.x dan 2.x.x, yang tidak kompatibel satu sama lain . log4j menambahkan konsep seperti appender , yaitu alat yang dapat digunakan untuk mencatat log dan tata letak - pemformatan log. Ini memungkinkan Anda mencatat hanya apa yang Anda butuhkan dan bagaimana Anda membutuhkannya. Kita akan berbicara lebih banyak tentang appender nanti.

JUL - java.util.logging

Salah satu keunggulan utama adalah solusinya - JUL disertakan dalam JDK (Java Development Kit). Sayangnya, dalam perkembangannya, bukan log4j populer yang dijadikan dasar, melainkan solusi dari IBM yang mempengaruhi perkembangannya. Sebenarnya saat ini JUL sudah ada, tapi belum ada yang menggunakannya. Dari “biasa saja”: di JUL level logging berbeda dengan yang ada di Logback, Log4j, Slf4j, dan ini memperburuk pemahaman di antara mereka. Membuat logger kurang lebih serupa. Untuk melakukan ini, Anda perlu mengimpor:
java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
Nama kelas diberikan secara khusus untuk mengetahui dari mana logging berasal. Sejak Java 8, dimungkinkan untuk melewati Supplier<String>. Ini membantu menghitung dan membuat string hanya pada saat benar-benar dibutuhkan, dan tidak setiap saat, seperti sebelumnya. Hanya dengan dirilisnya Java 8 pengembang memecahkan masalah penting, setelah itu JUL benar-benar dapat digunakan. Yaitu metode dengan argumen Supplier<String> msgSupplierseperti yang ditunjukkan di bawah ini:
public void info(Supplier<String> msgSupplier) {
   log(Level.INFO, msgSupplier);
}

JCL - jakarta commons penebangan

Karena kenyataan bahwa untuk waktu yang lama tidak ada standar industri dalam logging dan ada suatu masa ketika banyak orang membuat logger khusus mereka sendiri, mereka memutuskan untuk merilis JCL - pembungkus umum yang akan digunakan di atas yang lain. Mengapa? Ketika beberapa dependensi ditambahkan ke proyek, mereka dapat menggunakan logger yang berbeda dari logger pada proyek tersebut. Oleh karena itu, mereka ditambahkan secara transitif ke dalam proyek, yang menimbulkan masalah nyata ketika mencoba menggabungkan semuanya. Sayangnya, fungsi pembungkusnya sangat buruk dan tidak memberikan tambahan apa pun. Mungkin akan lebih mudah jika semua orang menggunakan JCL untuk melakukan pekerjaannya. Namun kenyataannya tidak berjalan seperti itu, jadi menggunakan JCL bukanlah ide yang baik saat ini.

Masuk kembali

Betapa sulitnya jalur sumber terbuka... Logback ditulis oleh pengembang yang sama dengan log4j untuk membuat penerusnya. Idenya sama dengan log4j. Perbedaannya adalah pada logback:
  • peningkatan kinerja;
  • menambahkan dukungan asli untuk slf4j;
  • Opsi pemfilteran telah diperluas.
Secara default, logback tidak memerlukan pengaturan apa pun dan mencatat semua log dari level DEBUG ke atas. Jika diperlukan konfigurasi, dapat dilakukan melalui konfigurasi xml:
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>app.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
        </encoder>
    </appender>
    <logger name="org.hibernate.SQL" level="DEBUG" />
    <logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
    <root level="info">
        <appender-ref ref="FILE" />
    </root>
</configuration>

SLF4J - fasad logging sederhana untuk java

Sekitar tahun 2006, salah satu pendiri log4j meninggalkan proyek dan membuat slf4j - Fasad Logging Sederhana untuk Java - pembungkus log4j, JUL, common-loggins, dan logback. Seperti yang Anda lihat, kemajuan telah mencapai titik di mana mereka membuat pembungkus di atas pembungkus... Selain itu, ini dibagi menjadi dua bagian: API, yang digunakan dalam aplikasi, dan implementasi, yang ditambahkan sebagai ketergantungan terpisah untuk setiap jenis logging. Misalnya, slf4j-log4j12.jar, slf4j-jdk14.jar. Cukup menghubungkan implementasi yang benar dan hanya itu: seluruh proyek akan bekerja dengannya. Slf4j mendukung semua fitur baru seperti pemformatan string untuk logging. Ada masalah seperti itu sebelumnya. Katakanlah ada entri log:
log.debug("User " + user + " connected from " + request.getRemoteAddr());
userAda konversi implisit pada objek user.toString()karena penggabungan string, dan ini membutuhkan waktu, yang memperlambat sistem. Dan semuanya baik-baik saja jika kita men-debug aplikasi. Masalah dimulai jika level logging untuk kelas ini adalah INFO dan lebih tinggi. Artinya, log ini tidak boleh ditulis, dan penggabungan string juga tidak boleh dilakukan. Secara teori, hal ini seharusnya diputuskan oleh perpustakaan logging itu sendiri. Terlebih lagi, ini ternyata menjadi masalah terbesar dari log4j versi pertama. Mereka tidak memberikan solusi yang normal, tetapi menyarankan untuk melakukannya seperti ini:
if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
Artinya, daripada satu baris logging, mereka menyarankan untuk menulis 3(!). Logging harus meminimalkan perubahan pada kode, dan tiga baris jelas bertentangan dengan pendekatan umum. slf4j tidak memiliki masalah kompatibilitas dengan JDK dan API, jadi solusi bagus segera muncul:
log.debug("User {} connected from {}", user, request.getRemoteAddr());
dimana {}menunjukkan penyisipan argumen yang diteruskan dalam metode. Artinya, yang pertama {}sesuai dengan user, yang kedua {}- request.getRemoteAddr(). Oleh karena itu, hanya jika tingkat logging mengizinkan logging, pesan ini dapat digabungkan menjadi satu pesan. Setelah itu, SJF4J dengan cepat semakin populer dan saat ini menjadi solusi terbaik. Oleh karena itu, kami akan mempertimbangkan logging menggunakan contoh bundel slf4j-log4j12.

Apa yang perlu dicatat

Tentu saja, Anda tidak boleh mencatat semuanya. Terkadang hal ini tidak perlu dan bahkan berbahaya. Misalnya, jika Anda menjanjikan data pribadi seseorang dan hal itu terungkap, akan ada masalah nyata, terutama pada proyek yang berorientasi ke Barat. Namun ada juga yang wajib untuk dicatat :
  1. Mulai/akhir aplikasi. Perlu kita ketahui bahwa aplikasi tersebut sebenarnya diluncurkan sesuai harapan kita dan berakhir sesuai harapan.
  2. Pertanyaan keamanan. Di sini sebaiknya mencatat upaya menebak kata sandi, mencatat login pengguna penting, dll.
  3. Beberapa status aplikasi . Misalnya saja peralihan dari satu keadaan ke keadaan lain dalam suatu proses bisnis.
  4. Beberapa informasi untuk debugging , dengan tingkat logging yang sesuai.
  5. Beberapa skrip SQL. Ada kasus nyata ketika hal ini diperlukan. Sekali lagi, dengan menyesuaikan level secara terampil, hasil luar biasa dapat dicapai.
  6. Thread yang dieksekusi (Thread) dapat dicatat jika pengoperasian yang benar dicentang.

Kesalahan pencatatan yang populer

Ada banyak perbedaan, tetapi berikut beberapa kesalahan umum:
  1. Pencatatan log yang berlebihan. Anda tidak boleh mencatat setiap langkah yang secara teoritis penting. Ada aturannya: log dapat memuat kinerja tidak lebih dari 10%. Jika tidak, akan ada masalah kinerja.
  2. Mencatat semua data ke dalam satu file. Hal ini akan membuat pembacaan/penulisan menjadi sangat sulit pada titik tertentu, belum lagi adanya batasan ukuran file pada sistem tertentu.
  3. Menggunakan level logging yang salah. Setiap tingkat penebangan mempunyai batasan yang jelas dan harus dihormati. Jika batasannya tidak jelas, Anda dapat menyetujui level mana yang akan digunakan.

Tingkat pencatatan

x: Terlihat
FATAL KESALAHAN MEMPERINGATKAN INFORMASI DEBUG JEJAK SEMUA
MATI
FATAL X
KESALAHAN X X
MEMPERINGATKAN X X X
INFORMASI X X X X
DEBUG X X X X X
JEJAK X X X X X X
SEMUA X X X X X X X
Apa yang dimaksud dengan level logging? Untuk menentukan peringkat kayu gelondongan, perlu diberikan sebutan dan perbedaan tertentu. Untuk tujuan ini, tingkat logging diperkenalkan. Levelnya diatur dalam aplikasi. Jika sebuah entri berada pada level di bawah yang ditentukan, entri tersebut tidak dimasukkan ke dalam log. Misalnya, kami memiliki log yang digunakan untuk men-debug aplikasi. Dalam pekerjaan produksi normal (ketika aplikasi digunakan untuk tujuan yang dimaksudkan), log tersebut tidak diperlukan. Oleh karena itu, tingkat logging akan lebih tinggi daripada tingkat debugging. Mari kita lihat level menggunakan log4j sebagai contoh. Solusi lain, kecuali JUL, menggunakan level yang sama. Ini dia urutannya menurun:
  • OFF: tidak ada log yang ditulis, semua akan diabaikan;
  • FATAL: kesalahan yang menyebabkan aplikasi tidak dapat lagi bekerja dan akan dihentikan, misalnya kesalahan JVM kehabisan memori;
  • ERROR: Tingkat kesalahan ketika ada masalah yang perlu diselesaikan. Kesalahan tidak menghentikan aplikasi secara keseluruhan. Kueri lain mungkin berfungsi dengan benar;
  • PERINGATAN: Menunjukkan log yang berisi peringatan. Tindakan tak terduga terjadi, meskipun demikian sistem menolak dan menyelesaikan permintaan;
  • INFO: log yang mencatat tindakan penting dalam aplikasi. Ini bukan kesalahan, ini bukan peringatan, ini adalah tindakan yang diharapkan dari sistem;
  • DEBUG: log diperlukan untuk men-debug aplikasi. Untuk memastikan bahwa sistem melakukan apa yang diharapkan, atau untuk menggambarkan tindakan sistem: “metode1 mulai bekerja”;
  • TRACE: log prioritas lebih rendah untuk debugging, dengan tingkat logging terendah;
  • ALL: level di mana semua log dari sistem akan dicatat.
Ternyata jika level logging INFO diaktifkan di suatu tempat dalam aplikasi, semua level akan login, mulai dari INFO hingga FATAL. Jika level logging FATAL, hanya log dengan level ini yang akan dicatat.

Merekam dan mengirim log: Appender

Kami akan mempertimbangkan proses ini menggunakan log4j sebagai contoh: ini memberikan banyak peluang untuk merekam/mengirim log:
  • untuk menulis ke file - solusi DailyRollingFileAppender ;
  • untuk menerima data ke konsol aplikasi - ConsoleAppender ;
  • untuk menulis log ke database - JDBCAppender ;
  • untuk mengontrol transmisi melalui TCP/IP - TelnetAppender ;
  • untuk memastikan bahwa logging tidak mempengaruhi kinerja - AsyncAppender .
Ada beberapa implementasi lainnya: daftar lengkapnya dapat ditemukan di sini . Omong-omong, jika penambahan yang diperlukan tidak tersedia, ini tidak menjadi masalah. Anda dapat menulis appender Anda sendiri dengan mengimplementasikan antarmuka Appender , yang hanya menerima log4j.

Node pencatatan

Untuk demonstrasinya kita akan menggunakan antarmuka slf4j, dan implementasi dari log4j. Membuat logger sangat sederhana: Anda perlu menulis yang berikut ini di kelas bernama MainDemo, di mana logging akan dilakukan:
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MainDemo.class);
Ini akan membuat logger untuk kita. Untuk membuat entri log, Anda dapat menggunakan banyak metode yang menunjukkan pada tingkat apa entri akan dibuat. Misalnya:
logger.trace("Method 1 started with argument={}", argument);
logger.debug("Database updated with script = {}", script);
logger.info("Application has started on port = {}", port);
logger.warn("Log4j didn't find log4j.properties. Please, provide them");
logger.error("Connection refused to host = {}", host);
Walaupun kita melewati kelas tersebut, pada akhirnya yang dituliskan adalah nama lengkap kelas tersebut beserta paket-paketnya. Hal ini dilakukan agar Anda kemudian dapat membagi proses masuk ke dalam node, dan mengonfigurasi tingkat logging dan penambahan untuk setiap node. Misalnya, nama kelas: com.github.romankh3.logginglecture.MainDemo- logger telah dibuat di dalamnya. Dan beginilah cara membaginya menjadi node logging. Node utama adalah null RootLogger . Ini adalah node yang menerima semua log dari keseluruhan aplikasi. Selebihnya dapat digambarkan seperti gambar di bawah ini: Penebangan: apa, bagaimana, dimana dan dengan apa?  - 4Appender mengonfigurasi pekerjaannya secara khusus pada node logging. Sekarang, dengan menggunakan log4j.properties sebagai contoh , kita akan melihat cara mengkonfigurasinya.

Konfigurasi langkah demi langkah dari Log4j.properties

Sekarang kita akan mengatur semuanya langkah demi langkah dan melihat apa yang bisa dilakukan:
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
Baris ini mengatakan bahwa kita mendaftarkan appender CONSOLE yang menggunakan implementasi org.apache.log4j.ConsoleAppender. Appender ini menulis data ke konsol. Selanjutnya, mari daftarkan appender lain yang akan menulis ke file:
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
Penting untuk dicatat bahwa appender masih perlu dikonfigurasi. Setelah kita memiliki appender yang terdaftar, kita dapat menentukan tingkat logging apa yang akan ada di node dan appender mana yang akan digunakan.

log4j.rootLogger=DEBUG, KONSOL, FILE

  • log4j.rootLogger berarti kita akan mengkonfigurasi node utama, yang berisi semua log;
  • setelah tanda sama dengan, kata pertama menunjukkan pada level berapa dan lebih tinggi log akan direkam (dalam kasus kami, ini adalah DEBUG);
  • kemudian setelah koma semua penambahan yang akan digunakan ditunjukkan.
Untuk mengonfigurasi node logging tertentu, Anda perlu menggunakan entri berikut:
log4j.logger.com.github.romankh3.logginglecture=TRACE, OWN, CONSOLE
di mana log4j.logger.ini digunakan untuk mengonfigurasi node tertentu, dalam kasus kami ini adalah com.github.romankh3.logginglecture. Dan sekarang mari kita bicara tentang menyiapkan appender CONSOLE:
# CONSOLE appender customisation
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.threshold=DEBUG
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] : %c:%L : %m%n
Di sini kita melihat bahwa kita dapat mengatur level dari mana appender akan memproses. Situasi sebenarnya: pesan dengan level info diterima oleh node logging dan diteruskan ke appender yang ditugaskan padanya, namun appender, dengan level peringatan dan lebih tinggi, menerima log ini, tetapi tidak melakukan apa pun dengannya. Selanjutnya, Anda perlu memutuskan template apa yang akan ada dalam pesan tersebut. Saya menggunakan PatternLayout sebagai contoh, tetapi ada banyak solusi di luar sana. Mereka tidak akan diungkapkan dalam artikel ini. Contoh pengaturan penambahan FILE:
# File appender customisation
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=./target/logging/logging.log
log4j.appender.FILE.MaxFileSize=1MB
log4j.appender.FILE.threshold=DEBUG
log4j.appender.FILE.MaxBackupIndex=2
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[ %-5p] - %c:%L - %m%n
Di sini Anda dapat mengonfigurasi ke file mana log akan ditulis, seperti yang dapat dilihat
log4j.appender.FILE.File=./target/logging/logging.log
Rekaman masuk ke file logging.log. Untuk menghindari masalah dengan ukuran file, Anda dapat mengatur maksimum: dalam hal ini, 1MB. MaxBackupIndex - memberitahukan berapa banyak file seperti itu yang akan ada. Jika lebih dari jumlah ini yang dibuat, file pertama akan dihapus. Untuk melihat contoh nyata di mana logging dikonfigurasi, Anda dapat membuka repositori terbuka di GitHub.

Mari kita konsolidasikan hasilnya

Coba lakukan semua yang dijelaskan sendiri:
  • Buat proyek Anda sendiri serupa dengan contoh di atas.
  • Jika Anda memiliki pengetahuan tentang penggunaan Maven, kami akan menggunakannya; jika tidak, berikut tautan ke artikel yang menjelaskan cara menghubungkan perpustakaan.

Mari kita simpulkan

  1. Kami berbicara tentang solusi apa yang ada di Java.
  2. Hampir semua perpustakaan logging yang dikenal ditulis di bawah kendali satu orang :D
  3. Kami mempelajari apa yang perlu dicatat dan apa yang tidak.
  4. Kami menemukan level logging.
  5. Kami berkenalan dengan node logging.
  6. Kami melihat apa itu appender dan kegunaannya.
  7. Kami mengonfigurasi file log4j.proterties langkah demi langkah.

Bahan tambahan

  1. JavaRush: Pencatatan. Lepaskan gulungan bola stectrace
  2. JavaRush: Kuliah logger
  3. Habr: Pencatatan log Java. Halo Dunia
  4. Habr: Java logging: kisah mimpi buruk
  5. Youtube: Kursus Golovach. Pencatatan. Bagian 1 , Bagian 2 , Bagian 3 , Bagian 4
  6. Log4j: tambahan
  7. Log4j: tata letak
Lihat juga artikel saya yang lain:
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION