Log4j: pra-roditelj Java okvira za evidenciju dnevnika
Kada budem slobodan, često se krišom krećem kroz grupu i nadzirem svaki potez i svaku reć prijatelja. Osećaj trenutnog razrednog starešine me čini veoma srećnim, uz malu trku dosade.
Evo, u grupi čitaoca Warring States perioda pronašao sam takav istorijat ćaskanja:

Zapravo postoji prijatelj koji ne zna šta znači "pisanje dnevnika", ne zna kako da uči, a još jedan prijatelj odgovara da zna samo Log4j!
U jednom trenutku, dobio sam udar od 10.000 tačaka, srce mi je neobjašnjivo tužno, poput onog tugovanog psa. Jer na internetu uvek postoje neki ljubomci koji me neprestano napadaju, govoreći da moji članci nisu dublji, bez dubine - oni su moje predodređene crne crve, ne verujete, na Mai Mai potražite "Chenmo Wang Er", možete videti njihove napade bez novosti.
Želim samo da pitam, šta je, članci za početnike imaju potrebu za početničkom grupom, a ja sam upravo pomogao takvoj velikoj grupi početnika, trebao bih biti hvaljen, zar ne?
(Kao da nije bitno, kako se zapravo brinem? Ručno pas)

Zanemari to, idem svojim putem, održi početnu nepromenjivost! Ovaj članak će govoriti o Log4j, ovom pra-roditelju pisanja dnevnika. Pisanje dnevnika u Java-u je u stvari umetnost, garantujem, ova rečenica nikako nije prevara.
Dokazi pokazuju da pisanje dnevnika sigurno utiče na performanse programa, to je neosporno, jer se radi dodatni posao. Posebno u programima sa veoma čestim transakcijama, pojava velikog broja dnevnika zaista će biti neučinkovita.
S obzirom na performanse, prijatelji moraju ozbiljno da nauče kako elegantno da pišu Java dnevnike. Na kraju, performanse su važan pokazatelj odličnosti programera.
01, Zašto je potrebno pisati dnevnik u Java-u
System.out.println() je verovatno najčešći način pisanja dnevnika kada učimo Java, gotovo svaki Java početnik je tako radio, čak i neki stari poznavaoci.
Razlog zašto se na ovaj način piše dnevnik je što je veoma pogodno, lako za početak, posebno uz pomoć IDE-a, samo pritisnite so dva slova na tastaturi i možete pozvati System.out.println().

U lokalnom okruženju, nema problema korišćenje System.out.println() za pisanje dnevnika, možete videti informacije na konzoli. Ali ako je u produkcijskom okruženju, System.out.println() postaje potpuno beskoristan.
Informacije štampane na konzoli nisu sačuvane u datoteku dnevnika, mogu se samo trenutno videti, u slučaju jednog ekrana dnevnika je i prihvatljivo. Ako je količina dnevnika vrlo velika, konzola uopšte ne može da stane. Zato je potreban napredniji API za evidenciju dnevnika (kao što su Log4j i java.util.logging).
Oni mogu sačuvati velike količine informacija o dnevniku u datoteku i kontrolisati veličinu svake datoteke, ako se napuni, sačuvaju u sledeću, lako za pretragu.
02, Važnost biranja različitih nivoa dnevnika
Kada koristite Java dnevnik, morate obratiti pažnju na nivo dnevnika, na primer uobičajeni DEBUG, INFO, WARN i ERROR.
DEBUG nivo je najniži, kada treba da štampate informacije o otklanjanju grešaka, koristite ovaj nivo, ne preporučuje se u produkcijskom okruženju.
INFO nivo je viši, kada treba da štampate neke važne informacije, koristite ovaj.
WARN se koristi za beleženje nekih vrsta upozorenja, na primer prekid veze između klijenta i servera, gubitak veze sa bazom podataka.
ERROR je viši nivo od WARN-a, koristi se za beleženje informacija o greškama ili izuzecima.
FATAL se koristi kada program doživi kobnu grešku, što znači da se program možda nepravilno prekida.
OFF je najviši nivo, znači da se sve poruke neće ispisivati.
Ovaj nivo je zasnovan na Log4j-u, razlikuje se od java.util.logging, potonji nudi više nivoa dnevnika, na primer SEVERE, FINER, FINEST.

03, Kako način greške u evidenciji dnevnika utiče na performanse
Zašto kažem da način greške u evidenciji dnevnika utiče na performanse programa? Jer što je više puta evidentiran dnevnik, to znači više puta izvršenje IO operacija nad datotekom, što znači da će uticati na performanse programa, možete li razumeti?
Iako je obični hard disk nadograđen na SSD, brzina čitanja i pisanja je mnogo poboljšana, ali je disk u poređenju sa memorijom i CPU-om ipak prespor! Kao razlika u brzini između zapruge i Mercedes-Benza.
Zato je tako važno birati nivo dnevnika. Za program, evidentiranje dnevnika je obavezna opcija, stoga se može kontrolisati samo nivo dnevnika i dnevnik štampan na ovom nivou.
Za dnevnik DEBUG nivoa, morate koristiti sledeći način:
if(logger.isDebugEnabled()){
logger.debug("DEBUG je uključen");
}Kada je DEBUG nivo uključen, štampajte dnevnik, ovaj način možete videti kada gledate mnogo izvornog koda, vrlo je čest.
Ne zaboravite, u produkcijskom okruženju, nemojte uključiti dnevnik DEBUG nivoa, inače će program postati vrlo spor pri velikom evidentiranju dnevnika, možda čak i tiho će eksplodirati prostor na disku.

04, Zašto birati Log4j umesto java.util.logging
java.util.logging pripada izvornom API-ju za evidenciju dnevnika, Log4j pripada biblioteci treće strane, ali predlažem korišćenje Log4j, jer je Log4j lakši za korišćenje. Dnevnik nivoa java.util.logging je više od Log4j, ali nije potrebno, postaje suvišan.
Druga prednost Log4j je što ne treba ponovo pokretati Java program kako bi se podesio nivo evidencije dnevnika, vrlo je fleksibilan. Možete koristiti datoteku log4j.properties da podesite nivo evidencije dnevnika Log4j, izlazno okruženje i način evidencije datoteke dnevnika.
Log4j je takođe bezbedan za nitove, može se sigurno koristiti u okruženju sa više niti.
Prvo pogledajmo način korišćenja java.util.logging:
package com.itwanger;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
/**
* @author WeChat pretraži "Chenmo Wang Er", odgovori sa ključnom rečju PDF
*/
public class JavaUtilLoggingDemo {
public static void main(String[] args) throws IOException {
Logger logger = Logger.getLogger("test");
FileHandler fileHandler = new FileHandler("javautillog.txt");
fileHandler.setFormatter(new SimpleFormatter());
logger.addHandler(fileHandler);
logger.info("Sitna informacija");
}
}Nakon pokretanja programa, u direktorijumu target će se generisati datoteka pod nazivom javautillog.txt, sadržaj je sledeći:

Zatim pogledajmo način korišćenja Log4j.
Prvi korak, uvedite Log4j paket u datoteku pom.xml:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>Drugi korak, kreirajte datoteku log4j.properties u direktorijumu resources, sadržaj je sledeći:
### Podešavanje###
log4j.rootLogger = debug,stdout,D,E
### Izlazne informacije na konzolu ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### Izlaz dnevnika DEBUG nivoa i više u =debug.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.D.File = debug.log
log4j.D.Append = true
log4j.D.Threshold = DEBUG
log4j.D.layout = org.apache.log4j.PatternLayout
log4j.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### Izlaz dnevnika ERROR nivoa i više u =error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.E.File =error.log
log4j.E.Append = true
log4j.E.Threshold = ERROR
log4j.E.layout = org.apache.log4j.PatternLayout
log4j.E.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n1) Podesite koreni Logger, sintaksa je sledeća:
log4j.rootLogger = [ level ] , appenderName, appenderName, …level je prioriteta dnevnika, od visokog do niskog su redom ERROR, WARN, INFO, DEBUG. Ako se ovde definiše INFO, tada se neće štampati informacije o dnevniku nižeg nivoa DEBUG.
appenderName se odnosi na mesto gde se šalju informacije o dnevniku, može se odrediti više mesta, trenutna konfiguraciona datoteka ima 3 mesta, redom stdout, D, E.
2) Podesite odredište izlaza dnevnika, sintaksa je sledeća:
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.option = valueNLog4j nudi sledećih 5 odredišta:
- org.apache.log4j.ConsoleAppender: konzola
- org.apache.log4j.FileAppender: datoteka
- org.apache.log4j.DailyRollingFileAppender: svaki dan generiše novu datoteku
- org.apache.log4j.RollingFileAppender: kada veličina datoteke premaši prag, generiše se nova datoteka
- org.apache.log4j.WriterAppender: šalje informacije o dnevniku u bilo koje određeno mesto u formatu toka
3) Podesite format informacija o dnevniku, sintaksa je sledeća:
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
…
log4j.appender.appenderName.option = valueNLog4j nudi sledeća 4 formata:
- org.apache.log4j.HTMLLayout: HTML tabela
- org.apache.log4j.PatternLayout: prilagođeno
- org.apache.log4j.SimpleLayout: uključuje nivo i informacionu strunu dnevnika
- org.apache.log4j.TTCCLayout: uključuje vreme generisanja dnevnika, nit, kategoriju i druge informacije
Parametri prilagođenog formata su sledeći:
- %m: štampa poruku određenu u kodu
- %p: štampa prioritet
- %r: štampa milisekunde protekle od pokretanja aplikacije do izlaska ove informacije o dnevniku
- %c: štampa pun naziv klase gde se nalazi
- %t: štampa naziv nita gde se nalazi dnevnik
- %n: štampa znak za povratak i novi red
- %d: štampa vreme tačke dnevnika
- %l: štampa lokacije pojave dnevnika, uključujući naziv klase, naziv nita, naziv metode, broj linija koda, na primer:
method:com.itwanger.Log4jDemo.main(Log4jDemo.java:14)
Treći korak, napišite Demo za korišćenje:
package com.itwanger;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
/**
* @author WeChat pretraži "Chenmo Wang Er", odgovori sa ključnom rečju PDF
*/
public class Log4jDemo {
private static final Logger logger = LogManager.getLogger(Log4jDemo.class);
public static void main(String[] args) {
// zabilježi informaciju debug nivoa
logger.debug("debug.");
// zabilježi informaciju info nivoa
logger.info("info.");
// zabilježi informaciju error nivoa
logger.error("error.");
}
}1) Dobijte Logger objekat
Da biste koristili Log4j, prvo morate dobiti Logger objekat, on je odgovoran za štampanje informacija o dnevniku. Obični format je sledeći:
private static final Logger logger = LogManager.getLogger(Log4jDemo.class);2) Štampajte dnevnik
Nakon što dobijete Logger objekat, možete štampati dnevnik prema različitim prioritetima. Uobičajeno ima sledeća 4 vrste:
Logger.debug() ;
Logger.info() ;
Logger.warn() ;
Logger.error() ;Nakon pokretanja programa, u direktorijumu target će se generisati dve datoteke, jedna pod nazivom debug.log, sadržaj je sledeći:
2020-10-20 20:53:27 [ main:0 ] - [ DEBUG ] debug.
2020-10-20 20:53:27 [ main:3 ] - [ INFO ] info.
2020-10-20 20:53:27 [ main:3 ] - [ ERROR ] error.Druga se zove error.log, sadržaj je sledeći:
2020-10-20 20:53:27 [ main:3 ] - [ ERROR ] error.05, 8 malih trikova za pisanje dnevnika
- Kod štampanja dnevnika DEBUG nivoa, ne zaboravite koristiti
isDebugEnabled()! Prijatelji su sigurno veoma znatiželjni, zašto to uraditi?
Prvo pogledajmo izvorni kod metode isDebugEnabled():
public
boolean isDebugEnabled() {
if(repository.isDisabled( Level.DEBUG_INT))
return false;
return Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel());
}Interno koristi metod isDisabled() da bi proverio nivo dnevnika, ako je DEBUG onemogućen, vratiće false.
Zatim pogledajmo izvorni koda metode debug():
public
void debug(Object message) {
if(repository.isDisabled(Level.DEBUG_INT))
return;
if(Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel())) {
forcedLog(FQCN, Level.DEBUG, message, null);
}
}E, zar takođe koristi metod isDisabled() za proveru? Zar korišćenje isDebugEnabled() nije dodatak zmije? Da li je direktno korišćenje logger.debug() dobro? Dozvolite mi da objasnim prijateljima.
Ako prilikom štampanja informacija o dnevniku treba da pozovete metod da biste dobili vrednost parametra, kao što je ovde:
logger.debug("Korisničko ime je:" + getName());Ako metod getName() treba 6 sekundi, gotovo je! Iako je nivo dnevnika definisan u konfiguracionoj datoteci kao INFO, metod getName() i dalje će uporno izvršiti 6 sekundi, pa pozvati debug(), to je veoma loše!
Iako se debug() ne izvršava kada je INFO, to znači da getName() ne treba da se izvršava, ali je upravo izvršen 6 sekundi, zar nije vrlo glupo?
if(logger.isDebugEnabled()) {
logger.debug("Korisničko ime je:" + getName());
}Zamenjeno gore navedenim načinom, tada se getName() sigurno ne izvršava, zar ne?
S obzirom na performanse programa, isDebugEnabled() postaje neophodnim! Ako se pri debug() ne prenose parametri, zaista nije potrebno proveravati da li je DEBUG omogućen.
- Ozbiljno birajte nivo štampanja informacija o dnevniku, jer je ovo previše važno! Ako se može samo kroz dnevnik videti šta se desilo sa programom, onda su neophodne informacije moraju biti štampane, ali ako se štampa previše, to će uticati na performanse programa.
Stoga, štampajte info() ako treba INFO, štampajte debug() ako treba DEBUG, nemojte ga slobodno koristiti.
Koristite Log4j umesto
System.out,System.errilie.printStackTrace()za pisanje dnevnika, razloge sam već objasnio, neću ponavljati.Koristite datoteku log4j.properties da podesite dnevnik, iako nije obavezno, korišćenje ove datoteke će učiniti program fleksibilnijim, ima osećaj "moja teritorija, ja odlučujem".
Ne zaboravite da prilikom štampanja dnevnika dodate pun naziv klase i naziv nita, u okruženju sa više niti je ovo posebno važno, inače će biti previše teško locirati problem.
Prilikom štampanja informacija o dnevniku pokušajte da bude što je moguće više kompletno, ne previše skraćeno, posebno pri susretu sa izuzecima ili greškama (informacije moraju zadržati dve vrste: informacije o mestu događaja i informacije o stogu izuzetaka, ako se ne obrađuju, baciti ih kroz ključnu reč throws), kako bi se izbeglo da su sve informacije o dnevnom bezdane pri pretrazi problema.
Razlikujte informacije o dnevniku, dodajte prefiks kada šaljete određenu vrstu informacija o dnevniku, na primer dodajte
DB_LOGu sve dnevike baze podataka, kada je ovakav dnevnik vrlo veliki, možete ga brzo locirati krozgrepLinux naredbu.Ne štampajte lozinke, brojeve bankovnih računa i druge osetljive informacije u datoteku dnevnika.

06, Zaključak
Pisanje dnevnika je zaista umetnost, ako ne radi dobro, može ozbiljno da utiče na performanse servera. Najgore je što je evidentirao dnevnik, ali na kraju se ispostavi da je korisnost nula, to je zaista nezamislivo! Posebno u produkcijskom okruženju, problem nije evidentiran, ali reprodukcija ima određenu slučajnost, u to vreme, zaista je "pozivanje neba ne odgovara, pozivanje zemlje ne odgovara"!
