Un ghid pentru dezvoltatorii Java

Una dintre cele mai importante părți ale procesului de dezvoltare a software-ului este înregistrarea corectă. Având la dispoziție o mulțime de cadre diferite de jurnalizare Java, este important să alegeți unul care să fie ușor de utilizat. În același timp, cadrul pe care îl alegeți ar trebui să aibă performanțe ridicate, caracteristici extensibile și să permită personalizarea. Log4j2 este o bibliotecă gratuită de jurnalizare Java care bifează toate căsuțele.

Integrarea Log4j2 cu orice aplicație deblochează opțiuni precum filtrarea avansată, suportul Java 8 lambda, căutările de proprietăți și nivelurile de jurnal personalizate. Să aruncăm o privire la modul în care puteți adăuga Log4j2 la proiectele dvs. și ce caracteristici vă pot ajuta să rămâneți în fruntea jocului.

Ce este Log4j2?

Înregistrarea este metoda de captare a informațiilor utile, cunoscute sub numele de jurnal, care pot fi referite și analizate ulterior. Puteți utiliza jurnalele pentru a depana rapid codul aplicației. Jurnalele de aplicații ajută la înțelegerea fluxului de cod și la rezolvarea problemelor și erorilor de producție.

În afară de cazurile de utilizare pentru diagnosticare, jurnalele sunt folosite și în scopuri de audit, de exemplu, pentru a urmări dacă un mesaj de notificare a fost sau nu trimis cu succes utilizatorului.

Log4j2 este una dintre cele mai populare biblioteci de jurnalizare Java. Este un succesor al bibliotecii foarte influente Log4j. Dezvoltat de Apache Software Foundation și o parte a Apache Logging Services, Log4j2 este un software gratuit și cu sursă deschisă (FOSS) distribuit sub Licența Apache, versiunea 2.0.

Log4j2 este construit pe fundația solidă a Log4j original. Există avantaje de a folosi un Logger față de instrucțiunile de tipărire simple ale System.out.println(). Aceasta include controlul asupra mesajelor care să apară, evitând în același timp alte mesaje de jurnal. A avea jurnalele adecvate este esențială într-un mediu de producție în care dispozitivele de depanare nu sunt disponibile.

Cum să adăugați Log4j2 la proiectul dvs.?

Există mai multe moduri de a adăuga Log4j2 la proiectul dvs. Java. Este recomandabil să fiți pe Java 8 sau o versiune superioară pentru a utiliza toate caracteristicile Log4j2.

Să discutăm despre diferitele metode prin care puteți adăuga Log4j2 în funcție de cerințele pe care le puteți avea.

Adăugarea Log4j2 la proiecte folosind Apache Maven

Dacă proiectul dvs. folosește Apache Maven ca sistem de compilare, dependențele Log4j2 trebuie adăugate la fișierul pom.xml.

<dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.20.0</version>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.20.0</version>
  </dependency>
</dependencies>

Pentru a facilita menținerea aceleiași versiuni în diferite artefacte, Log4j2 are un fișier pom.xml Bill of Material (BOM). Dacă îl adăugați în gestionarea dependenței, nu trebuie să adăugați versiunile individual.

<!-- Add the BOM to the dependencyManagement -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-bom</artifactId>
      <version>2.20.0</version>
      <scope>import</scope>
      <type>pom</type>
    </dependency>
  </dependencies>
</dependencyManagement>

<!-- Once the BOM is added, the versions are not required -->
<dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
  </dependency>
</dependencies>

Adăugarea Log4j2 la proiecte folosind Apache Gradle

În cazul în care utilizați Apache Gradle ca instrument de compilare, puteți adăuga dependențele Log4j2 la fișierul build.gradle.

dependencies {
  implementation 'org.apache.logging.log4j:log4j-api:2.20.0'
  implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
}

Dacă utilizați versiunea Gradle 5.0 sau o versiune superioară, aveți opțiunea de a importa lista de materiale (BOM) Log4j2 Maven pentru a menține versiuni de dependență consistente. Acest lucru poate fi realizat adăugând următoarele în fișierul dvs. build.gradle.

dependencies {
  implementation platform('org.apache.logging.log4j:log4j-bom:2.20.0')

  implementation 'org.apache.logging.log4j:log4j-api'
  runtimeOnly 'org.apache.logging.log4j:log4j-core'
}

Pentru versiunile Gradle 2.8-4.10, nu există nicio opțiune pentru importarea directă a BOM-ului Maven. Trebuie să adăugați un plugin suplimentar pentru funcționalitatea de gestionare a dependențelor.

plugins {
  id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

dependencyManagement {
  imports {
    mavenBom 'org.apache.logging.log4j:log4j-bom:2.20.0'
  }
}

dependencies {
  implementation 'org.apache.logging.log4j:log4j-api'
  runtimeOnly 'org.apache.logging.log4j:log4j-core'
}

Adăugarea Log4j2 la aplicațiile independente fără un instrument de compilare

Dacă proiectul dvs. nu are un instrument de compilare, atunci puteți descărca versiunea de artefact necesară a Log4j2 de pe pagina oficială de descărcare a Log4j2.

  10 echipamente de gimnastică la domiciliu pentru a te transforma de la Couch Potato la pasionat de fitness

Odată ce le descărcați, trebuie să vă asigurați că calea de clasă a aplicației dvs. include următoarele borcane.

  • log4j-api-2.20.0.jar
  • log4j-core-2.20.0.jar

Care sunt componentele din Log4j2?

Pentru a înțelege caracteristicile Log4j2 și pentru a utiliza capacitățile sale la maximum, este important să înțelegeți cum funcționează Log4j2. Sub suprafață, mai multe blocuri alcătuiesc Log4j2. Să vorbim despre ele unul câte unul.

#1. LoggerContext

LoggerContext este unitatea centrală a sistemului de înregistrare. Deține toți Logger-urile solicitate în aplicație. De asemenea, conține o referință la Configurație.

#2. Configurare

Configurația conține toate informațiile cerute de sistemul de logare. Aceasta include Logger-urile, Appenders, Filtrele și multe altele. În Log4j2, puteți defini configurația utilizând diverse formate de fișiere, cum ar fi XML, JSON și YAML, și, de asemenea, în mod programatic prin API-ul Log4j2.

O reîncărcare automată are loc ori de câte ori se modifică orice proprietate în Configurație. Prin urmare, nu există nicio cerință pentru repornirea aplicației.

#3. Logger

Componenta principală a sistemului Log4j2 este Logger-ul. Loggerele sunt obținute în codul aplicației folosind instrucțiunea LogManager.getLogger() și sunt utilizate pentru a genera jurnalele. Mesajele de jurnal pot fi generate la diferite niveluri de severitate, cum ar fi depanare, informații, avertizare, eroare și fatale.

#4. LoggerConfig

LoggerConfig este responsabil pentru comportamentul unui anumit Logger. Acesta definește comportamentul și setările pentru înregistrarea evenimentelor generate de respectivul logger. Permite configurarea diferitelor niveluri de înregistrare, configurarea anexelor și aplicarea filtrelor.

#5. Filtru

Puteți procesa selectiv evenimentele de jurnal în Log4j2 folosind filtre. Filtrele sunt aplicate pe baza unor criterii specifice. Puteți aplica aceste filtre la loggers sau appenders. Filtrele controlează ce evenimente de jurnal au voie să treacă prin conducta de înregistrare pentru procesare ulterioară. Cu ajutorul filtrelor, comportamentul de înregistrare poate fi reglat fin, asigurându-se că numai jurnalele relevante sunt procesate.

#6. Apendicele

Destinația oricărui mesaj de jurnal este determinată de Appender. Un singur Logger poate avea mai mulți Appenders. Un eveniment de jurnal va fi trimis tuturor aplicanților pentru Loggerul dat. Log4j2 are o mulțime de apendice preconfigurate. De exemplu, ConsoleAppender este folosit pentru a înregistra mesajele în consolă, iar FileAppender este folosit pentru a trimite mesaje într-un fișier. Fiecare Appender are nevoie de propriul aspect care determină cum va arăta mesajul de jurnal final.

#7. Aspect

În Log4j2, Aspectul este folosit pentru a defini cum va arăta mesajul de jurnal final. Un Layout este asociat cu un Appender. În timp ce un Appender determină destinația de ieșire, Aspectul descrie modul în care va fi transmis mesajul.

Top 5 caracteristici ale Log4j2

Log4j2 este bogat în funcții și asta îl diferențiază de alte cadre de jurnalizare Java disponibile. De la a avea Loggere asincrone la suportul lambda Java 8, Log4j2 are un avantaj față de ceilalți. Să discutăm câteva dintre caracteristicile notabile ale acestui cadru.

#1. Extinderea funcționalităților folosind pluginuri

În Log4j 1.x, pentru a crea extensii, au fost necesare multe modificări de cod. Log4j2 rezolvă problema extensibilității prin introducerea sistemului Plugin.

Puteți declara un plugin nou utilizând adnotarea @Plugin din clasa dvs. Folosind puterea pluginurilor, vă puteți crea propriile componente, cum ar fi filtre și aplicații. Componentele de la terți pot fi, de asemenea, adăugate cu ușurință în bibliotecă.

#2. Suport Java 8 Lambda

Odată cu lansarea Log4j2 versiunea 2.4, a fost introdus suportul pentru expresiile lambda Java 8. Cu expresii lambda, vă puteți defini logica de înregistrare în linie. Acest lucru reduce nevoia de verificări pe mai multe linii sau clase interne anonime. Acest lucru asigură, de asemenea, că metodele costisitoare nu sunt executate inutil. Astfel, nu numai că codul este mai curat și mai ușor de citit, dar și suprasolicitarea sistemului este redusă.

  9 cele mai bune cursuri de învățare automată pentru a vă accelera cariera [2023]

Să luăm în considerare un exemplu în care înregistrați rezultatul unei operațiuni costisitoare, dar numai dacă nivelul de depanare este activat. Înainte de suportul pentru lambda, aceasta ar fi efectuată folosind codul menționat mai jos:

if (logger.isDebugEnabled()) {
    logger.debug("The output of the given operation is: {}", expensiveOperation());
}

Având mai multe astfel de cazuri de utilizare, ar introduce în mod inutil verificări condiționate. Cu toate acestea, cu Log42, aceeași acțiune poate fi efectuată după cum urmează:

logger.debug("The output of the given operation is: {}", () -> expensiveOperation()

Metoda exprensiveOperation() este evaluată numai dacă nivelul de depanare este activat. Nu este nevoie de verificări explicite.

#3. Loggere asincrone

Fiecare eveniment de jurnal este o operațiune I/O, care crește supraîncărcarea sistemului. Pentru a atenua acest lucru, Log4j2 introduce Loggere asincrone care rulează într-un fir separat de firul de execuție al aplicației. Când se utilizează Loggere asincrone, firul apelantului primește imediat controlul înapoi după invocarea metodei logger.log().

Acest lucru îi permite să continue cu logica aplicației, mai degrabă decât să aștepte finalizarea evenimentului de înregistrare. Folosirea acestui comportament asincron realizează o capacitate de înregistrare mai mare. Puteți alege fie să faceți toate loggerele asincrone în mod implicit, fie să aveți un amestec de comportament sincron și asincron.

#4. Înregistrare fără gunoi

În Java, colectarea gunoiului este procesul prin care obiectele neutilizate din aplicație sunt curățate automat. Deși nu trebuie să vă ocupați manual de această operațiune, colectarea gunoiului are propria sa suprasarcină.

Dacă aplicația dvs. creează prea multe obiecte într-o perioadă scurtă de timp, procesul de colectare a gunoiului poate ocupa mai multe resurse de sistem decât este necesar. Mai multe biblioteci de înregistrare, inclusiv versiunile anterioare ale Log4j, creează o mulțime de obiecte temporare în timpul procesului de înregistrare. Ulterior, presiunea crescută asupra colectorului de gunoi afectează performanța sistemului.

Începând cu versiunea 2.6, Log4j2 rulează în modul „fără gunoi”. Acesta este comportamentul implicit. Prin urmare, obiectele sunt reutilizate, iar crearea celor temporare este mult redusă.

Următoarele imagini arată cum Log4j2 versiunea 2.6 atenuează problema obiectelor inutile, în comparație cu Log4j2 versiunea 2.5.

În Log4j2 versiunea 2.5, o mulțime de obiecte temporare sunt create în timpul procesului de înregistrare; Sursa: apache.org

În Log4j2.6, nu există obiecte temporare create în timpul procesului de înregistrare; Sursa: apache.org

#5. Căutări

În log4j2, puteți adăuga informații contextuale la jurnalele dvs. folosind Căutări. Utilizându-le, puteți adăuga date din diverse surse, cum ar fi proprietățile sistemului, variabilele de mediu sau valorile personalizate. Astfel, puteți include informații relevante care sunt preluate dinamic, făcând jurnalele mai utile.

Să luăm în considerare un exemplu în care doriți să înregistrați ID-ul de sesiune al utilizatorului cu toate liniile de jurnal. Acest lucru vă va permite să căutați toate jurnalele corespunzătoare unui ID de sesiune.

Modul brut de a face acest lucru ar fi să adăugați în mod explicit ID-ul sesiunii individual, care devine dificil de întreținut. În curând s-ar putea să uitați să îl adăugați, pierzând astfel informații valoroase.

logger.info("The user data has been fetched for session id {}", sessionId);
...
logger.info("The transaction has been processed for session id {}", sessionId);
...
logger.info("Request has been successfully processed for session id {}", sessionId);

O modalitate mai bună de a face acest lucru ar fi să utilizați Căutarea hărții contextuale. ID-ul sesiunii poate fi adăugat la Contextul Thread-ului din codul aplicației. Valoarea poate fi apoi utilizată în configurația Log4j2. Astfel, este eliminată necesitatea menționării explicite a acestuia în mesajele de jurnal.

ThreadContext.put("sessionId", sessionId);

Odată ce valoarea este adăugată, aceeași poate fi folosită în Căutare folosind cuvântul cheie ctx.

<File name="Application" fileName="application.log">
  <PatternLayout>
    <pattern>%d %p %c{1.} [%t] $${ctx:sessionId} %m%n</pattern>
  </PatternLayout>
</File>

Cum se creează niveluri de jurnal personalizate în Log4j2?

Nivelurile de jurnal din Log4j2 sunt folosite pentru a clasifica evenimentele de jurnal în funcție de gravitatea sau importanța lor. Puteți controla nivelul de jurnal atunci când înregistrați un mesaj în codul aplicației.

De exemplu, logger.debug() adaugă nivelul DEBUG. În mod corespunzător, logger.error() adaugă nivelul EROARE. Aceasta determină ce mesaje apar în cele din urmă în rezultat. Puteți configura nivelul de jurnal în fișierul de configurare.

  Cum să creați un document principal și să adăugați subdocumente în MS Word 2016

Nivelurile de jurnal preconfigurate în Log4j2 și valorile lor corespunzătoare sunt menționate mai jos.

OFF0FATAL100ERROR200WARN300INFO400DEBUG500TRACE600ALLMAX VALUE

Dacă Nivelul de jurnal este setat la un anumit nivel, atunci sunt afișate toate liniile de jurnal pentru acea valoare corespunzătoare și cele de deasupra acesteia (cu o valoare mai mică). Ceilalți sunt ignorați.

De exemplu, dacă setați nivelul de jurnal la WARN, atunci vor fi afișate mesajele WARN, EROARE și FATAL. Orice linie de jurnal cu un nivel diferit va fi ignorată. Acest lucru este util în special atunci când rulați același cod în medii diferite.

Poate doriți să setați nivelul jurnalului la INFO sau DEBUG atunci când rulați codul în mediul dvs. de dezvoltare. Acest lucru vă va permite să vedeți mai multe jurnale și să vă ajutați în procesul de dezvoltare. Cu toate acestea, atunci când rulați într-un mediu de producție, ați dori să îl setați la EROARE. Astfel, vă veți putea concentra pe găsirea problemei în cazul în care apare vreo anomalie și nu trebuie să treceți prin linii de jurnal inutile.

S-ar putea întâmpla să doriți să adăugați propriul nivel de jurnal personalizat pe lângă cele preconfigurate. Log4j2 vă permite să faceți acest lucru cu ușurință. Să vedem cum vă puteți adăuga propriile niveluri de jurnal și să le utilizați în aplicația dvs.

#1. Adăugarea unui nivel personalizat de jurnal utilizând fișierul de configurare

Puteți adăuga niveluri de jurnal personalizate declarându-le în fișierul de configurare.

În exemplul de mai jos, un nivel de jurnal personalizat numit NOTICE a fost definit cu o valoare de 450. Aceasta îl plasează între INFO (cu o valoare de 400) și DEBUG (cu o valoare de 500). Aceasta înseamnă că dacă nivelul este setat la NOTICE, atunci mesajele INFO vor fi înregistrate, dar mesajele DEBUG vor fi omise.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <CustomLevels>
    <CustomLevel name="NOTICE" intLevel="450" />
  </CustomLevels>
 
  <Appenders>
    <File name="MyFile" fileName="logs/app.log">
      <PatternLayout pattern="%d %-7level %logger{36} - %msg%n"/>
    </File>
  </Appenders>
  <Loggers>
    <Root level="trace">
      <AppenderRef ref="MyFile" level="NOTICE" />
    </Root>
  </Loggers>
</Configuration>

#2. Adăugarea unui nivel de jurnal personalizat în cod

În afară de declararea lor în fișierul de configurare, puteți defini propriile niveluri de jurnal personalizate în cod.

final Level VERBOSE = Level.forName("VERBOSE", 550);

Aceasta va crea un nou nivel de jurnal numit VERBOSE. Acest nivel de jurnal se va afla între DEBUG (cu o valoare de 500) și TRACE (cu o valoare de 600). Dacă loggerul este setat la nivelul VERBOSE, atunci toate mesajele de jurnal ale VERBOSE și mai sus vor fi înregistrate, inclusiv DEBUG. Cu toate acestea, mesajele TRACE vor fi omise.

#3. Utilizarea nivelului jurnal personalizat din cod

Nivelurile de jurnal personalizate trebuie mai întâi declarate înainte de a fi utilizate. Le poți declara fie în fișierul de configurare, fie în codul tău. Odată declarat, sunteți liber să le utilizați.

Acest exemplu de cod arată cum puteți declara un nivel personalizat numit NOTICE și apoi îl puteți utiliza.

final Level NOTICE = Level.forName("NOTICE", 550);

final Logger logger = LogManager.getLogger();
logger.log(NOTICE, "a notice level message");

Deși acest lucru va genera mesajul necesar cu nivelul nou creat, ar putea deveni greoi să treceți întotdeauna în mod explicit nivelul. Din fericire, puteți genera cod sursă, astfel încât să obțineți metode de ajutor pentru înregistrarea nivelurilor personalizate. Folosind același lucru, veți putea să utilizați propria metodă de logger.notice() similară modului în care ați folosi logger.debug() sau logger.error().

Log4j2 vine cu un utilitar care vă ajută să vă creați propriile înregistrări extinse. Următoarea comandă creează un fișier Java numit CustomLogger.java. Acest fișier conține metodele de jurnal existente, împreună cu metodele nou generate pentru nivelul NOTICE.

java -cp log4j-core-2.20.0.jar org.apache.logging.log4j.core.tools.ExtendedLoggerGenerator 
        com.example.CustomLogger NOTICE=450 > com/example/CustomLogger.java

Odată ce fișierul este generat, puteți utiliza clasa din codul dvs. pentru a crea noi loggeri. Aceste înregistratoare vor conține metode suplimentare pentru nivelul dvs. de jurnal personalizat. Puteți extinde astfel funcționalitatea loggerelor dvs.

final Logger logger = CustomLogger.create(ValueFirstSmsSender.class);

//this new method is similar to using logger.debug()
logger.notice("a notice level message");

Concluzie

Log4j2 este un cadru de logare Java foarte puternic, care oferă o gamă largă de caracteristici, configurații, îmbunătățiri de performanță și multe altele. Având în vedere că jurnalele sunt o parte foarte importantă a procesului de dezvoltare a software-ului, un cadru robust precum Log4j2 îmbunătățește abilitățile aplicației.

Flexibilitatea și extensibilitatea Log4j2 permit capturarea adecvată a evenimentelor care au loc în aplicația dvs. Ulterior, vă dă putere să vă gândiți la jurnalele ca la un instrument puternic pentru depanare și auditare. Cu toate caracteristicile și îmbunătățirile sale, Log4j2 se deosebește și se face alegerea preferată într-o gamă variată de proiecte software.

Ați putea fi, de asemenea, interesat de aceste IDE-uri Java și complianti online.