Log4j 2: Apache-ovo visoko-performantno alat za evidenciju dnevnika
Log4j 2, kao što ime sugeriše, to je nadogradnja Log4j-a, poput Pro verzije kod mobilnih telefona. Ja kao alatni čovjek za pisanje članaka, ili zaposleni, kako ne mogu da ne završim ovaj poslednji članak.
Log4j, SLF4J, Logback imaju istog oca — Ceki Gulcu, ali Log4j 2 je izuzetak, to je proizvod Apache fondacije.
SLF4J i Logback kao zamene za Log4j, u mnogim aspektima učinili su neophodna poboljšanja, zašto je onda potreban Log4j 2? Mogu samo reći da su programeri Apache fondacije mnogo slobodni, ne, vrlo borbeni, da ne bi bilo njihovog duha perfekcionizma, ovaj svet programiranja bi bio mnogo dosadan, jer manje "spremno za korišćenje" točkova.
U prethodnom članku sam rekao, šef mi je strogo naredio da prebacim sistem evidencije dnevnika na Logback, uspešno sam završio posao, šef je bio srećan, pohvalio me da sam ovaj zaposleni vrlo predan. Da izrazim zahvalnost šefu, odlučio sam tajno da probam Log4j 2, mada još uvek nije gotov proizvod, možda će doneti određene rizike projektu. Ali ko me je takav zaposleni koji voli svoj posao.

01, Gde je Log4j 2 moćniji
- U okruženju sa više niti, protok Log4j 2 je 10 puta viši od Logback-a, kašnjenje je smanjeno za nekolike redova veličine. Ova izjava zvuči kao naduvanje, u svakom slučaju Log4j 2 zvaničnici sami se hvale.
Asinhroni Logger Log4j 2 koristi bezblokirske strukture podataka, dok asinhroni Logger Logback-a i Log4j-a koriste ArrayBlockingQueue. Za blokirajuće redove, aplikacije sa više niti obično se susreću sa nadmetanjem blokiranja pri pokušaju da stavke dnevnika u red.
Sledeći dijagram ilustruje uticaj bezblokirskih struktura podataka na protok u rešenjima sa više niti. Log4j 2 se bolje proširuje s povećanjem broja niti: aplikacije sa više niti mogu evidentirati više dnevnika. Druge biblioteke za evidenciju dnevnika zbog postojanja nadmetanja blokiranja, pri evidentiranju više niti, ukupni protok ostaje konstantan ili opada. To znači da će se pri korišćenju drugih biblioteka za evidenciju dnevnika svaka pojedinačna nit moći manje da evidentira dnevnik.

Performanse su najveća prednost Log4j 2, u pogledu drugih prednosti, na primer sledećih, mogu se zanemariti, koliko je tekst kratak, toliko je bitno.
Log4j 2 može smanjiti pritisak na garbage collector.
Podržava Lambda izraze.
Podržava automatsko ponovno učitavanje konfiguracije.
02, Primer korišćenja Log4j 2
Neću više pričati suviše, krenimo direktno u praksu. Teorijsko znanje je korisno, ali nije bolje od ruku-on prakse, to je takođe "ne tako dobra" programska navika koju sam razvio tokom godina: u praksi pronalazim probleme, rešavam probleme, tražim teorijsku osnovu.
Prvi korak, dodajte zavisnost Log4j 2 u datoteku pom.xml:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
</dependency>(ovaj artifactId je i dalje log4j, ne odražava 2, u verziji se odražava, malo natera ljude da misle da je log4j)
Drugi korak, napravimo najjednostavniji testni slučaj:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Demo {
private static final Logger logger = LogManager.getLogger(Demo.class);
public static void main(String[] args) {
logger.debug("log4j2");
}
}Pokrenite Demo klasu, možete videti sledeće informacije na konzoli:
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.Log4j 2 čak nije odštampao "log4j2" na konzoli, i žalio se da nismo odredili konfiguracionu datoteku. U ovom pogledu, mislim da nije dobro kao Logback, jer će on ispisati.
Za početnike ovo nije prijateljski, jer kada se suoče sa ovom situacijom, često ne znaju šta da rade. Iako u dnevnik piše ERROR, kod nije kompajlirao niti se pokrenuo s greškom, zašto ne ispisuješ?
Kao iskusni programer, moram ti reći, u ovom trenutku najbolje je istražiti zašto. Kako to uraditi?
Možemo kopirati ključne reči iz informacija dnevnika, na primer: "No log4j2 configuration file found", i zatim pretražiti u Intellij IDEA, ako ste preuzeli izvorni kod i dokumentaciju, bez iznenađenja, možete pronaći ovaj tekst u ConfigurationFactory klasi.
Možete staviti prekidnu tačku u metodu, i onda debugovati, videće sledeći sadržaj.

Kroz izvorni kod možete videti, Log4j 2 će tražiti 4 vrste konfiguracionih datoteka, ekstenzije su redom properties, yaml, json i xml. Prefiksi su log4j2-test ili log4j2.
Nakon dobijanja ovog upozorenja, možete preći na treći korak.
Treći korak, dodajte datoteku log4j2-test.xml u direktorijum resursa (pogodno za poređenje sa Logback), sadržaj je sledeći:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="DEBUG">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>Format konfiguracione datoteke Log4j 2 je malo sličan Logback-u, osnovna struktura je element <Configuration>, sadrži 0 ili više elemenata <Appenders>, zatim 0 ili više elemenata <Loggers>, unutar kojih može biti najviše jedan element <Root>.
1) Podesite appender, to jest podesite odredište izlaza dnevnika.
Postoje Console, tipična konfiguracija konzole videli ste iznad, dozvolite mi da jednostavno objasnim format pattern-a:
%d{HH:mm:ss.SSS}označava vreme štampanja do milisekunde%tštampa naziv trenutne niti%-5levelštampa nivo dnevnika, -5 označava levo poravnanje i fiksno štampanje 5 znakova, ako nije dovoljno dopunjava se razmakom desno%loggerštampa naziv logger-a, najviše 36 znakova%msgtekst dnevnika%nnovi red
Dodatno nadopuni neke često korišćene zamenljive:
%Fštampa naziv datoteke klase gde se nalazi, na primer Demo.java%Lštampa broj linije%Mštampa naziv metoda gde se nalazi%lštampa broj linije izjave, uključujući naziv klase, naziv metoda, naziv datoteke, broj linija%pštampa nivo dnevnika%cštampa naziv paketa, ako sledi parametar{length.}, na primer%c{1.}, će ispisati prvi karakter naziva paketa, na primer stvarni naziv paketacom.itwangerće ispisati samoc.i
Ponovo pokrenite Demo klasu, možete videti informacije dnevne ispisane na konzoli:
10:14:04.657 [main] DEBUG com.itwanger.Demo - log4j22) Podesite Loggers, odredite nivo Root dnevnika i odredite koji Appender se aktivira.
3) Automatsko ponovno učitavanje konfiguracije.
Logback podržava automatsko ponovno učitavanje konfiguracije, Log4j 2 takođe podržava, ako želite da omogućite ovu funkcionalnost vrlo je jednostavno, samo dodajte atribut monitorInterval na element Configuration.
<Configuration monitorInterval="30">
...
</Configuration>Obratite pažnju da vrednost treba biti različita od nule, u gornjem primeru znači da će se proveravati promene u konfiguracionoj datoteci najmanje 30 sekundi. Najmanji interval je 5 sekundi.
03, Async primer
Pored Console, postoji i Async, može se koristiti uz način rada sa datotekom za asinhrono pisanje, tipična konfiguracija je sledeća:
<Configuration>
<Appenders>
<File name="DebugFile" fileName="debug.log">
<PatternLayout>
<Pattern>%d %p %c [%t] %m%n</Pattern>
</PatternLayout>
</File>
<Async name="Async">
<AppenderRef ref="DebugFile"/>
</Async>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Async"/>
</Root>
</Loggers>
</Configuration>U poređenju sa konfiguracionom datotekom Logback-a, Log4j 2 je zaista složeniji, nije tako lako za korišćenje, samo direktno kažem! Ali sam ga zamolio, moram da završim s plačem. Dodajmo ovaj Async u Appenders:
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="DebugFile" fileName="debug.log">
<PatternLayout>
<Pattern>%d %p %c [%t] %m%n</Pattern>
</PatternLayout>
</File>
<Async name="Async">
<AppenderRef ref="DebugFile"/>
</Async>
</Appenders>
<Loggers>
<Root level="DEBUG">
<AppenderRef ref="Console"/>
<AppenderRef ref="Async"/>
</Root>
</Loggers>
</Configuration>Ponovo pokrenite Demo klasu, možete videti datoteku debug.log u korenskom direktorijumu projekta, sadržaj je sledeći:
2020-10-30 09:35:49,705 DEBUG com.itwanger.Demo [main] log4j204, RollingFile primer
Naravno, i Log4j i Logback smo konfigurisali RollingFile, Log4j 2 takođe ne manjka. RollingFile će vršiti rotiranje datoteka dnevnika na osnovu strategije okidanja (Triggering) i strategije prelaza (Rollover). Ako se ne konfiguriše Rollover, koristiće se DefaultRolloverStrategy kao podrazumevana konfiguracija RollingFile-a.
Strategija okidanja uključuje, baziranu na cron izraz (izveden iz grčkog, znači vreme, korišćen za podešavanje vremenskog formata za redovno izvršavanje zadataka) CronTriggeringPolicy; baziranu na veličini datoteke SizeBasedTriggeringPolicy; baziranu na vremenu TimeBasedTriggeringPolicy.
Strategija prelaza uključuje, podrazumevanu strategiju prelaza DefaultRolloverStrategy, Direktan upis DirectWriteRolloverStrategy. U opštem slučaju, dovoljno je koristiti podrazumevanu strategiju prelaza, veoma je snažna.
Pogledajmo prvi primer konfiguracije bazirane na SizeBasedTriggeringPolicy i TimeBasedTriggeringPolicy, kao i podrazumevane DefaultRolloverStrategy strategije:
<Configuration>
<Appenders>
<RollingFile name="RollingFile" fileName="rolling.log"
filePattern="rolling-%d{yyyy-MM-dd}-%i.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="1 KB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>Da bismo verifikovali strategiju rotiranja datoteka, prilagodimo malo Demo klasu da štampa više dnevnika:
for (int i = 1;i < 20; i++) {
logger.debug("WeChat pretraži"{}", odgovori sa ključnom rečju"{}",ima iznenađenja","Chenmo Wang Er", "java");
}Ponovo pokrenite Demo klasu, možete videti 3 datoteke dnevnika dodate u korenskom direktorijumu:

Kombinujući naziv datoteke dnevnika, i zatim pogledajte konfiguraciju RollingFile-a, lako je razumeti.
fileName koristi za određivanje naziva datoteke.
filePattern koristi za određivanje šablona naziva datoteke, zavisi od strategije prelaska.
Budući da u konfiguracionoj datoteci nije eksplicitno navedena strategija prelaska, RollingFile će koristiti podrazumevanu DefaultRolloverStrategy.
Prvo pogledajmo atribute DefaultRolloverStrategy:

Zatim pogledajte vrednost filePattern rolling-%d{yyyy-MM-dd}-%i.log, gde je %d{yyyy-MM-dd} vrlo lako razumljivo, to je godina-mesec-dan; gde %i šta znači?
Prva datoteka dnevnika se zove rolling.log (najnoviji dnevnik se stavlja u ovu), druga datoteka bez datuma se zove rolling-1.log, druga datoteka bez datuma se zove rolling-2.log, na osnovu ovih informacija, možete li pogodati pravilo?
U stvari, to je u vezi sa atributom max u DefaultRolloverStrategy, trenutno se koristi podrazumevana vrednost, to jest 7, tada kada se rolling-8.log treba generisati, briše se rolling-1.log. Možete prilagoditi količinu izlaznog dnevnika u Demo-u da biste verifikovali.
- SizeBasedTriggeringPolicy, strategija okidanja bazirana na veličini datoteke dnevnika, veličina se izražava u bajtovima, sufiks može biti KB, MB ili GB, na primer 20 MB.
Pogledajmo još jedan primer kompresije datoteke dnevnika, pogledajmo konfiguraciju:
<RollingFile name="RollingFileGZ" fileName="gz/rolling.log"
filePattern="gz/%d{yyyy-MM-dd-HH}-%i.rolling.gz">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="1 KB"/>
</Policies>
</RollingFile>U atributnoj vrednosti fileName je sadržan direktorijum gz, to jest sve datoteke dnevnika će se staviti u ovaj direktorijum.
U atributnoj vrednosti filePattern je dodat sufiks gz, to označava da će datoteka dnevnika biti kompresovana, takođe može biti zip format.
Nakon pokretanja Demo-a, u direktorijumu gz možete videti sledeće datoteke:

Do sada, osnovni primer korišćenja Log4j 2 je završen. Testno okruženje je rešeno, idem da pitam šefa da li da koristim Log4j 2 u produkcijskom okruženju.
