JavaRush /Blog Java /Random-MS /Log masuk Java: apa, bagaimana, di mana dan dengan apa?

Log masuk Java: apa, bagaimana, di mana dan dengan apa?

Diterbitkan dalam kumpulan
Hello semua, komuniti JavaRush! Hari ini kita akan bercakap tentang pengelogan Java:
  1. Apa itu, mengapa ia. Dalam kes apakah lebih baik untuk digunakan, dalam kes apakah ia tidak?
  2. Apakah jenis pelaksanaan pembalakan yang terdapat di Jawa dan apakah yang perlu kita lakukan dengan kepelbagaian ini?
  3. Tahap pembalakan. Mari kita bincangkan apa itu appender dan cara mengkonfigurasinya dengan betul.
  4. Mengelog nod dan cara mengkonfigurasinya dengan betul supaya semuanya berfungsi seperti yang kita mahu.
Bahan ini ditujukan untuk khalayak yang luas. Ia akan menjadi jelas kepada mereka yang baru mengenali Java, dan mereka yang sudah bekerja, tetapi hanya mengetahuinya dengan logger.info(“log something”); Let's Go!

Mengapa pembalakan diperlukan?

Mari kita lihat kes sebenar di mana pembalakan akan menyelesaikan masalah. Berikut adalah contoh dari kerja saya. Terdapat titik aplikasi yang berintegrasi dengan perkhidmatan lain. Saya menggunakan pengelogan mata ini sebagai "alibi" : jika penyepaduan tidak berfungsi, mudah untuk mengetahui dari mana masalah itu berasal. Ia juga dinasihatkan untuk log maklumat penting yang disimpan ke pangkalan data. Contohnya, mencipta pengguna pentadbir. Ini adalah perkara yang baik untuk log.

Alat Pengelogan Java

Pembalakan: apa, bagaimana, di mana dan dengan apa?  - 2Penyelesaian terkenal untuk log masuk di Java termasuk:
  • log4j
  • JUL - java.util.logging
  • JCL - jakarta commons logging
  • Log balik
  • SLF4J - fasad pembalakan mudah untuk java
Mari kita lihat dengan cepat setiap daripada mereka, dan dalam bahagian praktikal bahan kita akan mengambil sambungan Slf4j - log4j sebagai asas . Ini mungkin kelihatan pelik sekarang, tetapi jangan risau: pada akhir artikel semuanya akan menjadi jelas.

System.err.println

Pada mulanya, sudah tentu, terdapat System.err.println (output rekod ke konsol). Ia masih digunakan untuk mendapatkan log dengan cepat semasa penyahpepijatan. Sudah tentu, tidak perlu bercakap tentang sebarang tetapan di sini, jadi mari kita ingat dan teruskan.

Log4j

Ini sudah menjadi penyelesaian penuh, yang dicipta daripada keperluan pembangun. Ia ternyata menjadi alat yang sangat menarik untuk digunakan. Disebabkan oleh pelbagai keadaan, penyelesaian ini tidak pernah masuk ke dalam JDK, yang sangat mengecewakan seluruh komuniti. log4j mempunyai pilihan konfigurasi supaya pengelogan boleh dihidupkan dalam pakej com.example.typedan dimatikan dalam subpakej com.example.type.generic. Ini memungkinkan untuk memisahkan dengan cepat apa yang perlu dilog daripada apa yang tidak diperlukan. Adalah penting untuk ambil perhatian di sini bahawa terdapat dua versi log4j: 1.2.x dan 2.x.x, yang tidak serasi antara satu sama lain . log4j menambah konsep seperti appender , iaitu alat yang log direkodkan dan susun atur - pemformatan log. Ini membolehkan anda merekodkan hanya perkara yang anda perlukan dan bagaimana anda memerlukannya. Kita akan bercakap lebih lanjut tentang appender sedikit kemudian.

JUL - java.util.logging

Salah satu kelebihan utama ialah penyelesaiannya - JUL disertakan dalam JDK (Java development kit). Malangnya, semasa pembangunannya, bukan log4j popular yang diambil sebagai asas, tetapi penyelesaian daripada IBM, yang mempengaruhi perkembangannya. Malah, pada masa ini terdapat JUL, tetapi tiada siapa yang menggunakannya. Daripada "begitu-begitu": dalam JUL tahap pembalakan adalah berbeza daripada apa yang ada dalam Logback, Log4j, Slf4j, dan ini memburukkan persefahaman antara mereka. Mencipta pembalak adalah lebih kurang serupa. Untuk melakukan ini, anda perlu mengimport:
java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
Nama kelas diluluskan secara khusus untuk mengetahui dari mana pembalakan itu datang. Sejak Java 8, adalah mungkin untuk lulus Supplier<String>. Ini membantu mengira dan mencipta rentetan hanya pada masa ia benar-benar diperlukan, dan bukan setiap masa, seperti sebelum ini. Hanya dengan keluaran Java 8, pembangun menyelesaikan masalah penting, selepas itu JUL benar-benar boleh digunakan. Iaitu, kaedah dengan hujah Supplier<String> msgSupplierseperti yang ditunjukkan di bawah:
public void info(Supplier<String> msgSupplier) {
   log(Level.INFO, msgSupplier);
}

JCL - jakarta commons logging

Disebabkan fakta bahawa untuk masa yang lama tidak ada standard industri dalam pembalakan dan terdapat satu tempoh apabila ramai orang mencipta pembalak tersuai mereka sendiri, mereka memutuskan untuk mengeluarkan JCL - pembungkus biasa yang akan digunakan berbanding yang lain. kenapa? Apabila beberapa kebergantungan ditambahkan pada projek, mereka boleh menggunakan pembalak yang berbeza daripada pembalak pada projek. Disebabkan ini, mereka telah ditambah secara transitif kepada projek, yang menimbulkan masalah sebenar apabila cuba menyusun semuanya. Malangnya, pembungkus itu sangat lemah dalam fungsi dan tidak memperkenalkan sebarang tambahan. Ia mungkin lebih mudah jika semua orang menggunakan JCL untuk melakukan kerja mereka. Tetapi pada hakikatnya ia tidak berjaya seperti itu, jadi menggunakan JCL bukanlah idea yang baik pada masa ini.

Log balik

Betapa sukarnya laluan sumber terbuka... Logback telah ditulis oleh pembangun yang sama dengan log4j untuk mencipta pengganti kepadanya. Ideanya adalah sama seperti log4j. Perbezaannya ialah dalam log balik:
  • prestasi yang bertambah baik;
  • menambah sokongan asli untuk slf4j;
  • Pilihan penapisan telah dikembangkan.
Secara lalai, log balik tidak memerlukan sebarang tetapan dan merekodkan semua log dari peringkat DEBUG dan ke atas. Jika konfigurasi diperlukan, ia boleh 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 pembalakan mudah untuk java

Sekitar tahun 2006, salah seorang bapa pengasas log4j meninggalkan projek itu dan mencipta slf4j - Fasad Pembalakan Mudah untuk Java - pembalut di sekitar log4j, JUL, log-log masuk biasa dan log balik. Seperti yang anda lihat, kemajuan telah mencapai tahap bahawa mereka mencipta pembungkus di atas pembungkus... Selain itu, ia dibahagikan kepada dua bahagian: API, yang digunakan dalam aplikasi, dan pelaksanaan, yang ditambah sebagai kebergantungan berasingan untuk setiap jenis pembalakan. Sebagai contoh, slf4j-log4j12.jar, slf4j-jdk14.jar. Ia cukup untuk menyambung pelaksanaan yang betul dan itu sahaja: keseluruhan projek akan berfungsi dengannya. Slf4j menyokong semua ciri baharu seperti pemformatan rentetan untuk pengelogan. Ada masalah seperti itu sebelum ini. Katakan terdapat entri log:
log.debug("User " + user + " connected from " + request.getRemoteAddr());
userTerdapat penukaran tersirat dalam objek user.toString()kerana penggabungan rentetan, dan ini memerlukan masa, yang melambatkan sistem. Dan semuanya ok jika kita nyahpepijat aplikasi. Masalah bermula jika tahap pengelogan untuk kelas ini adalah INFO dan lebih tinggi. Iaitu, log ini tidak boleh ditulis, dan penggabungan rentetan juga tidak boleh dilakukan. Secara teorinya, ini sepatutnya diputuskan oleh perpustakaan pembalakan itu sendiri. Lebih-lebih lagi, ini ternyata menjadi masalah terbesar versi pertama log4j. Mereka tidak memberikan penyelesaian biasa, tetapi mencadangkan melakukannya seperti ini:
if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
Iaitu, daripada satu baris pembalakan, mereka mencadangkan menulis 3(!). Pembalakan harus meminimumkan perubahan pada kod, dan tiga baris jelas bercanggah dengan pendekatan umum. slf4j tidak mempunyai masalah keserasian dengan JDK dan API, jadi penyelesaian yang cantik segera muncul:
log.debug("User {} connected from {}", user, request.getRemoteAddr());
di mana {}menandakan sisipan hujah yang diluluskan dalam kaedah. Iaitu, yang pertama {}sepadan dengan user, yang kedua {}- request.getRemoteAddr(). Disebabkan ini, hanya jika tahap pembalakan membenarkan pembalakan, mesej ini boleh digabungkan menjadi satu. Selepas ini, SJF4J cepat berkembang popular dan kini merupakan penyelesaian terbaik. Oleh itu, kami akan mempertimbangkan pengelogan menggunakan contoh berkas slf4j-log4j12.

Apa yang perlu dilog

Sudah tentu, anda tidak sepatutnya log semua. Kadang-kadang ini tidak perlu dan bahkan berbahaya. Sebagai contoh, jika anda mencagarkan data peribadi seseorang dan entah bagaimana ia terbongkar, akan ada masalah sebenar, terutamanya pada projek yang berorientasikan ke arah Barat. Tetapi terdapat juga sesuatu yang wajib untuk log :
  1. Mula/akhir permohonan. Kita perlu tahu bahawa aplikasi itu sebenarnya dilancarkan seperti yang kita jangkakan dan berakhir seperti yang dijangkakan.
  2. Soalan keselamatan. Di sini adalah baik untuk log masuk percubaan meneka kata laluan, log masuk log pengguna penting, dsb.
  3. Sesetengah permohonan menyatakan . Contohnya, peralihan dari satu negeri ke negeri lain dalam proses perniagaan.
  4. Beberapa maklumat untuk penyahpepijatan , dengan tahap pengelogan yang sesuai.
  5. Beberapa skrip SQL. Terdapat kes sebenar apabila ini diperlukan. Sekali lagi, dengan mahir menyesuaikan tahap, keputusan yang cemerlang boleh dicapai.
  6. Benang yang dilaksanakan (Benang) boleh dilog dalam kes di mana operasi yang betul diperiksa.

Kesilapan pembalakan popular

Terdapat banyak nuansa, tetapi berikut adalah beberapa kesilapan biasa:
  1. Pembalakan berlebihan. Anda tidak seharusnya melog setiap langkah yang secara teorinya boleh menjadi penting. Terdapat peraturan: log boleh memuatkan prestasi tidak lebih daripada 10%. Jika tidak, masalah prestasi akan berlaku.
  2. Log semua data ke dalam satu fail. Ini akan menyukarkan membaca/menulisnya pada satu ketika, apatah lagi terdapat had saiz fail pada sistem tertentu.
  3. Menggunakan tahap pengelogan yang salah. Setiap peringkat pembalakan mempunyai sempadan yang jelas dan harus dihormati. Jika sempadan adalah samar-samar, anda boleh bersetuju pada tahap mana yang hendak digunakan.

Tahap pembalakan

x: Kelihatan
MAUT RALAT AMARAN INFO DEBUG JEJAK SEMUA
DIMATIKAN
MAUT x
RALAT x x
AMARAN x x x
INFO 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
Apakah tahap pembalakan? Untuk menentukan kedudukan log, adalah perlu untuk memberikan sebutan dan perbezaan tertentu. Untuk tujuan ini, tahap pembalakan telah diperkenalkan. Tahap ditetapkan dalam aplikasi. Jika entri tergolong dalam tahap di bawah yang ditetapkan, ia tidak dimasukkan ke dalam log. Sebagai contoh, kami mempunyai log yang digunakan untuk nyahpepijat aplikasi. Dalam kerja pengeluaran biasa (apabila aplikasi digunakan untuk tujuan yang dimaksudkan), log sedemikian tidak diperlukan. Oleh itu, tahap pembalakan akan lebih tinggi daripada penyahpepijatan. Mari kita lihat tahap menggunakan log4j sebagai contoh. Penyelesaian lain, kecuali JUL, menggunakan tahap yang sama. Di sini mereka berada dalam susunan yang semakin berkurangan:
  • MATI: tiada log ditulis, semua akan diabaikan;
  • FATAL: ralat selepas itu aplikasi tidak lagi dapat berfungsi dan akan dihentikan, sebagai contoh, ralat memori JVM;
  • RALAT: Kadar ralat apabila terdapat masalah yang perlu diselesaikan. Ralat tidak menghentikan aplikasi secara keseluruhan. Pertanyaan lain mungkin berfungsi dengan betul;
  • AMARAN: Menunjukkan log yang mengandungi amaran. Tindakan yang tidak dijangka berlaku, walaupun ini sistem menentang dan menyelesaikan permintaan;
  • INFO: log yang merekodkan tindakan penting dalam aplikasi. Ini bukan ralat, ini bukan amaran, ini adalah tindakan sistem yang dijangkakan;
  • DEBUG: log diperlukan untuk nyahpepijat aplikasi. Untuk memastikan sistem melakukan apa yang diharapkan daripadanya, atau untuk menerangkan tindakan sistem: "kaedah1 mula berfungsi";
  • TRACE: log keutamaan yang lebih rendah untuk penyahpepijatan, dengan tahap pengelogan terendah;
  • SEMUA: tahap di mana semua log daripada sistem akan direkodkan.
Ternyata jika tahap pengelogan INFO didayakan di beberapa tempat dalam aplikasi, semua peringkat akan dilog, bermula dari INFO dan sehingga FATAL. Jika tahap pembalakan adalah FATAL, hanya log dengan tahap ini akan direkodkan.

Merekod dan menghantar log: Lampiran

Kami akan mempertimbangkan proses ini menggunakan log4j sebagai contoh: ia menyediakan banyak peluang untuk merekod/menghantar log:
  • untuk menulis ke fail - penyelesaian DailyRollingFileAppender ;
  • untuk menerima data ke dalam konsol aplikasi - ConsoleAppender ;
  • untuk menulis log ke pangkalan data - JDBCAppender ;
  • untuk mengawal penghantaran melalui TCP/IP - TelnetAppender ;
  • untuk memastikan bahawa pengelogan tidak menjejaskan prestasi - AsyncAppender .
Terdapat beberapa pelaksanaan lain: senarai penuh boleh didapati di sini . Dengan cara ini, jika lampiran yang diperlukan tidak tersedia, ini tidak menjadi masalah. Anda boleh menulis appender anda sendiri dengan melaksanakan antara muka Appender , yang hanya menerima log4j.

Nod pembalakan

Untuk demonstrasi kami akan menggunakan antara muka slf4j, dan pelaksanaan dari log4j. Mencipta pembalak adalah sangat mudah: anda perlu menulis yang berikut dalam kelas bernama MainDemo, di mana pengelogan akan dilakukan:
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MainDemo.class);
Ini akan mencipta pembalak untuk kita. Untuk membuat entri log, anda boleh menggunakan banyak kaedah yang menunjukkan pada tahap mana entri akan dibuat. Sebagai contoh:
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 kami lulus kelas, akhirnya ia adalah nama penuh kelas dengan pakej yang ditulis. Ini dilakukan supaya anda boleh membahagikan pengelogan ke dalam nod, dan mengkonfigurasi tahap pengelogan dan pelengkap untuk setiap nod. Sebagai contoh, nama kelas: com.github.romankh3.logginglecture.MainDemo- pembalak telah dicipta di dalamnya. Dan ini adalah bagaimana ia boleh dibahagikan kepada nod pembalakan. Nod utama ialah RootLogger null . Ini adalah nod yang menerima semua log keseluruhan aplikasi. Selebihnya boleh digambarkan seperti yang ditunjukkan di bawah: Pembalakan: apa, bagaimana, di mana dan dengan apa?  - 4Penambah mengkonfigurasi kerja mereka secara khusus pada nod pembalakan. Sekarang, menggunakan log4j.properties sebagai contoh , kita akan melihat cara mengkonfigurasinya.

Konfigurasi langkah demi langkah Log4j.properties

Sekarang kami akan menetapkan semuanya langkah demi langkah dan melihat apa yang boleh dilakukan:
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
Baris ini mengatakan bahawa kami sedang mendaftarkan appender CONSOLE yang menggunakan pelaksanaan org.apache.log4j.ConsoleAppender. Penambah ini menulis data ke konsol. Seterusnya, mari kita daftarkan pelengkap lain yang akan menulis pada fail:
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
Adalah penting untuk ambil perhatian bahawa pelengkap masih perlu dikonfigurasikan. Sebaik sahaja kami telah mempunyai penambah berdaftar, kami boleh menentukan tahap pembalakan yang akan berada dalam nod dan penambah yang akan digunakan.

log4j.rootLogger=DEBUG, CONSOLE, FAIL

  • log4j.rootLogger bermakna kami akan mengkonfigurasi nod utama, yang mengandungi semua log;
  • selepas tanda sama, perkataan pertama menunjukkan pada tahap dan lebih tinggi log akan direkodkan (dalam kes kami, ini adalah DEBUG);
  • maka selepas koma semua lampiran yang akan digunakan ditunjukkan.
Untuk mengkonfigurasi nod pengelogan tertentu, anda perlu menggunakan entri berikut:
log4j.logger.com.github.romankh3.logginglecture=TRACE, OWN, CONSOLE
di mana log4j.logger.ia digunakan untuk mengkonfigurasi nod tertentu, dalam kes kami ia adalah com.github.romankh3.logginglecture. Dan sekarang mari kita bercakap tentang menyediakan 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 bahawa kita boleh menetapkan tahap dari mana penambah akan memproses. Situasi sebenar: mesej dengan tahap maklumat telah diterima oleh nod pengelogan dan diteruskan kepada penambah yang ditugaskan kepadanya, tetapi penambah, dengan tahap amaran dan lebih tinggi, menerima log ini, tetapi tidak melakukan apa-apa dengannya. Seterusnya, anda perlu memutuskan templat yang akan ada dalam mesej. Saya menggunakan PatternLayout dalam contoh, tetapi terdapat banyak penyelesaian di luar sana. Mereka tidak akan didedahkan dalam artikel ini. Contoh menyediakan penambah 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 boleh mengkonfigurasi fail mana log akan ditulis, seperti yang dapat dilihat dari
log4j.appender.FILE.File=./target/logging/logging.log
Rakaman pergi ke fail logging.log. Untuk mengelakkan masalah dengan saiz fail, anda boleh menetapkan maksimum: dalam kes ini, 1MB. MaxBackupIndex - memberitahu berapa banyak fail sedemikian akan ada. Jika lebih daripada nombor ini dicipta, fail pertama akan dipadamkan. Untuk melihat contoh sebenar di mana pengelogan dikonfigurasikan, anda boleh pergi ke repositori terbuka di GitHub.

Mari kita satukan hasilnya

Cuba lakukan semua yang diterangkan sendiri:
  • Buat projek anda sendiri seperti yang terdapat dalam contoh di atas.
  • Jika anda mempunyai pengetahuan tentang menggunakan Maven, kami akan menggunakannya; jika tidak, berikut adalah pautan ke artikel yang menerangkan cara menyambungkan perpustakaan.

Mari kita ringkaskan

  1. Kami bercakap tentang penyelesaian yang ada di Jawa.
  2. Hampir semua perpustakaan pembalakan yang diketahui ditulis di bawah kawalan seorang :D
  3. Kami belajar apa yang perlu dilog dan apa yang tidak.
  4. Kami mengetahui tahap pembalakan.
  5. Kami berkenalan dengan nod pembalakan.
  6. Kami melihat apa itu appender dan untuk apa ia.
  7. Kami mengkonfigurasi fail log4j.proteties langkah demi langkah.

Bahan tambahan

  1. JavaRush: Pembalakan. Lepaskan bebola stektras
  2. JavaRush: Kuliah Logger
  3. Habr: Pembalakan Java. Hai dunia
  4. Habr: Java logging: kisah mimpi ngeri
  5. Youtube: kursus Golovach. Pembalakan. Bahagian 1 , Bahagian 2 , Bahagian 3 , Bahagian 4
  6. Log4j: lampiran
  7. Log4j: susun atur
Lihat juga artikel saya yang lain:
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION