En guide for Java-utviklere

En av de mest avgjørende delene av programvareutviklingsprosessen er å ha riktig logging. Med mange forskjellige Java-logging-rammeverk tilgjengelig, er det viktig å velge en som er enkel å bruke. Samtidig bør det valgte rammeverket ha høy ytelse, utvidbare funksjoner og tillate tilpasning. Log4j2 er et gratis Java-loggingsbibliotek som krysser av for alle boksene.

Integrering av Log4j2 med hvilken som helst applikasjon låser opp alternativer som avansert filtrering, Java 8 lambda-støtte, egenskapsoppslag og tilpassede loggnivåer. La oss ta en titt på hvordan du kan legge til Log4j2 til prosjektene dine og hvilke funksjoner som kan hjelpe deg med å holde deg på toppen av spillet ditt.

Hva er Log4j2?

Logging er metoden for å fange opp nyttig informasjon, kjent som logger, som kan refereres til og analyseres senere. Du kan bruke loggene til å raskt feilsøke programkode. Applikasjonslogger hjelper deg med å forstå kodeflyten og takle produksjonsproblemer og feil.

Annet enn de diagnostiske brukstilfellene, brukes logger også til revisjonsformål – for eksempel sporing av om en varslingsmelding har blitt sendt til brukeren eller ikke.

Log4j2 er et av de mest populære Java-loggingsbibliotekene. Det er en etterfølger til det svært innflytelsesrike Log4j-biblioteket. Utviklet av Apache Software Foundation og en del av Apache Logging Services, er Log4j2 en gratis og åpen kildekode-programvare (FOSS) distribuert under Apache-lisensen, versjon 2.0.

Log4j2 er bygget på toppen av det solide fundamentet til den originale Log4j. Det er fordeler med å bruke en Logger fremfor enkle utskriftssetninger av System.out.println(). Dette inkluderer å ha kontroll over hvilke meldinger som skal vises samtidig som du unngår andre loggmeldinger. Å ha riktige logger er avgjørende i et produksjonsmiljø der feilsøkingsprogrammer ikke er tilgjengelige.

Hvordan legge til Log4j2 til prosjektet ditt?

Det er flere måter å legge til Log4j2 til Java-prosjektet ditt. Det anbefales å være på Java 8 eller nyere for å bruke alle funksjonene til Log4j2.

La oss diskutere de ulike metodene som du kan legge til Log4j2 avhengig av kravene du måtte ha.

Legger til Log4j2 til prosjekter ved hjelp av Apache Maven

Hvis prosjektet ditt bruker Apache Maven som byggesystem, må Log4j2-avhengighetene legges til pom.xml-filen.

<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>

For å gjøre det enklere å opprettholde den samme versjonen på tvers av forskjellige artefakter, har Log4j2 en BOM-fil (Bill of Material) pom.xml. Hvis du legger det til under avhengighetsadministrasjonen din, trenger du ikke å legge til versjonene individuelt.

<!-- 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>

Legger til Log4j2 til prosjekter ved hjelp av Apache Gradle

I tilfelle du bruker Apache Gradle som byggeverktøy, kan du legge til Log4j2-avhengighetene til build.gradle-filen.

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

Hvis du bruker Gradle versjon 5.0 eller nyere, har du muligheten til å importere Log4j2 Maven Bill Of Materials (BOM) for å opprettholde konsistente avhengighetsversjoner. Dette kan oppnås ved å legge til følgende i build.gradle-filen.

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'
}

For Gradle versjoner 2.8-4.10 er det ingen mulighet for direkte import av Maven BOM. Du må legge til en ekstra plugin for funksjonaliteten for avhengighetsadministrasjon.

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'
}

Legger til Log4j2 til frittstående applikasjoner uten byggeverktøy

Hvis prosjektet ditt ikke har et byggeverktøy, kan du laste ned den nødvendige artefaktversjonen av Log4j2 fra den offisielle Log4j2-nedlastingssiden.

  Roblox Super Evolution Codes: Løs inn nå

Når du har lastet ned dem, må du sørge for at applikasjonens klassebane inkluderer følgende krukker.

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

Hva er komponentene i Log4j2?

For å forstå funksjonene til Log4j2 og utnytte dens evner til det fulle, er det viktig å forstå hvordan Log4j2 fungerer. Under overflaten utgjør flere byggeklosser Log4j2. La oss snakke om dem en etter en.

#1. LoggerContext

LoggerContext er den sentrale enheten i loggingssystemet. Den inneholder alle loggerne som er forespurt i applikasjonen. Den inneholder også en referanse til konfigurasjonen.

#2. Konfigurasjon

Konfigurasjonen inneholder all informasjon som kreves av loggingssystemet. Dette inkluderer loggere, vedlegg, filtre og mer. I Log4j2 kan du definere konfigurasjonen ved å bruke forskjellige filformater som XML, JSON og YAML, og også programmatisk gjennom Log4j2 API.

En automatisk reload finner sted hver gang en egenskap endres i konfigurasjonen. Derfor er det ikke noe krav om omstart av applikasjonen.

#3. Logger

Hovedkomponenten i Log4j2-systemet er loggeren. Loggere hentes i applikasjonskoden ved å bruke LogManager.getLogger()-setningen og brukes til å generere logger. Loggmeldinger kan genereres på ulike alvorlighetsnivåer, for eksempel feilsøking, info, advarsel, feil og fatal.

#4. LoggerConfig

LoggerConfig er ansvarlig for oppførselen til en spesifikk logger. Den definerer virkemåten og innstillingene for loggingshendelser generert av den aktuelle loggeren. Den tillater konfigurasjon av forskjellige loggingsnivåer, oppsett av vedlegg og bruk av filtre.

#5. Filter

Du kan selektivt behandle logghendelser i Log4j2 ved hjelp av filtre. Filtre brukes basert på spesifikke kriterier. Du kan bruke disse filtrene på loggere eller vedlegg. Filtre kontrollerer hvilke logghendelser som tillates å passere gjennom loggingsrørledningen for videre behandling. Ved hjelp av filtre kan loggingsatferden finjusteres, slik at kun de relevante loggene blir behandlet.

#6. Vedlegg

Destinasjonen for enhver loggmelding bestemmes av vedleggeren. En enkelt logger kan ha flere vedlegg. En logghendelse vil bli sendt til alle vedleggerne for den gitte loggeren. Log4j2 har mange forhåndskonfigurerte vedlegg. For eksempel brukes ConsoleAppender til å logge meldinger til konsollen, og FileAppender brukes til å sende ut meldinger til en fil. Hver vedlegg trenger sin egen layout som bestemmer hvordan den endelige loggmeldingen vil se ut.

#7. Oppsett

I Log4j2 brukes layouten til å definere hvordan den endelige loggmeldingen skal se ut. En layout er knyttet til en vedlegg. Mens en vedlegg bestemmer utdatamålet, beskriver layouten hvordan meldingen skal sendes ut.

Topp 5 funksjoner i Log4j2

Log4j2 er funksjonsrikt, og det er det som skiller den fra andre tilgjengelige Java-logging-rammeverk. Fra å ha asynkrone loggere til å støtte Java 8 lambdaer, har Log4j2 et forsprang på andre. La oss diskutere noen av de bemerkelsesverdige egenskapene til dette rammeverket.

#1. Utvide funksjonaliteten ved hjelp av plugins

I Log4j 1.x, for å lage utvidelser, var det nødvendig med mange kodemodifikasjoner. Log4j2 løser problemet med utvidbarhet ved å introdusere Plugin-systemet.

Du kan erklære et nytt plugin ved å bruke @Plugin-kommentaren på klassen din. Ved å bruke kraften til plugins kan du lage dine egne komponenter som filtre og vedlegg. Tredjepartskomponenter kan også enkelt legges til biblioteket.

#2. Java 8 Lambda-støtte

Med utgivelsen av Log4j2 versjon 2.4 ble støtte for Java 8 lambda-uttrykk introdusert. Med lambda-uttrykk kan du definere loggingslogikken inline. Dette reduserer behovet for flerlinjekontroller eller anonyme indre klasser. Dette sikrer også at dyre metoder ikke blir utført unødvendig. Dermed er ikke bare koden renere og lettere å lese, men systemkostnadene reduseres også.

  8 beste AI-drevne dataprognoser og prediksjonsverktøy for bedrifter

La oss vurdere et eksempel der du logger resultatet av en kostbar operasjon, men bare hvis feilsøkingsnivået er aktivert. Før støtten for lambdaer, ville dette bli utført ved å bruke koden nedenfor:

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

Å ha flere slike brukstilfeller vil unødvendig innføre betingede kontroller. Men med Log42 kan den samme handlingen utføres som følger:

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

Metoden exprensiveOperation() blir bare evaluert hvis feilsøkingsnivået er aktivert. Det er ikke behov for noen eksplisitte kontroller.

#3. Asynkrone loggere

Hver logghendelse er en I/O-operasjon, som øker systemoverhead. For å dempe dette introduserer Log4j2 Asynkrone Loggere som kjører i en separat tråd fra applikasjonstråden. Når du bruker asynkrone loggere, får anropstråden umiddelbart tilbake kontrollen etter å ha påkalt logger.log()-metoden.

Dette lar den fortsette med applikasjonslogikken i stedet for å vente på at loggingshendelsen skal fullføres. Ved å utnytte denne asynkrone oppførselen oppnås en større logggjennomstrømning. Du kan enten velge å gjøre alle loggere asynkrone som standard eller ha en blanding av både synkron og asynkron oppførsel.

#4. Søppelfri logging

I Java er søppelinnsamling prosessen der ubrukte objekter i applikasjonen automatisk ryddes opp. Selv om du ikke trenger å ta hånd om denne operasjonen manuelt, har søppelhenting sine egne overhead.

Hvis applikasjonen din lager for mange objekter i løpet av kort tid, kan søppelinnsamlingsprosessen ta opp mer systemressurser enn nødvendig. Flere loggbiblioteker, inkludert tidligere versjoner av Log4j, lager mange midlertidige objekter under loggingsprosessen. Deretter påvirker det økte trykket på søppelsamleren systemets ytelse.

Siden versjon 2.6 kjører Log4j2 i «søppelfri» modus. Dette er standard oppførsel. Derfor gjenbrukes gjenstander, og opprettelsen av midlertidige blir kraftig redusert.

Følgende bilder viser hvordan Log4j2 versjon 2.6 reduserer problemet med unødvendige objekter, sammenlignet med Log4j2 versjon 2.5.

I Log4j2 versjon 2.5 blir det opprettet mange midlertidige objekter under loggingsprosessen; Kilde: apache.org

I Log4j2.6 er det ingen midlertidige objekter opprettet under loggingsprosessen; Kilde: apache.org

#5. Oppslag

I log4j2 kan du legge til kontekstuell informasjon til loggene dine ved å bruke oppslag. Ved å bruke dem kan du legge til data fra ulike kilder, for eksempel systemegenskaper, miljøvariabler eller egendefinerte verdier. Dermed kan du inkludere relevant informasjon som hentes dynamisk, noe som gjør loggene mer nyttige.

La oss vurdere et eksempel der du vil logge brukerens økt-ID med alle logglinjer. Dette vil tillate deg å søke etter alle logger som tilsvarer en økt-ID.

Den brute-force-måten å gjøre dette på ville være å eksplisitt legge til økt-ID-en individuelt, noe som blir vanskelig å vedlikeholde. Snart kan du glemme å legge den til, og dermed miste verdifull informasjon.

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);

En bedre måte å gjøre det på ville være å bruke Context Map Lookup. Sesjons-IDen kan legges til trådkonteksten i applikasjonskoden. Verdien kan deretter brukes i Log4j2-konfigurasjonen. Dermed er behovet for å eksplisitt omtale det i loggmeldinger eliminert.

ThreadContext.put("sessionId", sessionId);

Når verdien er lagt til, kan den samme brukes i Lookup ved å bruke nøkkelordet ctx.

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

Hvordan lage tilpassede loggnivåer i Log4j2?

Loggnivåer i Log4j2 brukes til å kategorisere logghendelser basert på deres alvorlighetsgrad eller viktighet. Du kan kontrollere loggnivået når du logger en melding i applikasjonskoden.

  HDMI vs. DisplayPort – Hvilken er bedre?

For eksempel, logger.debug() legger til DEBUG-nivået. Tilsvarende legger logger.error() til ERROR-nivået. Dette avgjør hvilke meldinger som til slutt vises i utdataene. Du kan konfigurere loggnivået i konfigurasjonsfilen.

De forhåndskonfigurerte loggnivåene i Log4j2 og deres tilsvarende verdier er nevnt nedenfor.

OFF0FATAL100ERROR200WARN300INFO400DEBUG500TRACE600ALLMAX VERD

Hvis loggnivået er satt til et bestemt nivå, sendes alle logglinjene for den tilsvarende verdien og de over den (med mindre verdi) ut. De andre blir ignorert.

For eksempel, hvis du setter loggnivået til WARN, vil WARN, ERROR og FATAL-meldinger vises. Enhver logglinje med et annet nivå vil bli ignorert. Dette er spesielt nyttig når du kjører den samme koden i forskjellige miljøer.

Du vil kanskje sette loggnivået til INFO eller DEBUG når du kjører koden i utviklingsmiljøet ditt. Dette vil tillate deg å se flere logger og hjelpe i utviklingsprosessen. Men når du kjører i et produksjonsmiljø, vil du sette den til ERROR. Dermed vil du kunne fokusere på å finne problemet i tilfelle avvik oppstår og ikke trenger å gå gjennom unødvendige logglinjer.

Det kan hende du vil legge til ditt eget tilpassede loggnivå i tillegg til de forhåndskonfigurerte. Log4j2 lar deg gjøre det enkelt. La oss se hvordan du kan legge til dine egne loggnivåer og bruke dem i applikasjonen din.

#1. Legger til tilpasset loggnivå ved hjelp av konfigurasjonsfilen

Du kan legge til egendefinerte loggnivåer ved å deklarere dem i konfigurasjonsfilen.

I eksemplet nedenfor er et tilpasset loggnivå kalt NOTICE blitt definert med en verdi på 450. Dette plasserer det mellom INFO (med en verdi på 400) og DEBUG (med en verdi på 500). Dette betyr at hvis nivået er satt til NOTICE, vil INFO-meldinger bli logget, men DEBUG-meldinger vil bli hoppet over.

<?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. Legger til tilpasset loggnivå i kode

Bortsett fra å deklarere dem i konfigurasjonsfilen, kan du definere dine egne tilpassede loggnivåer i koden.

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

Dette vil opprette et nytt loggnivå kalt VERBOSE. Dette loggnivået vil ligge mellom DEBUG (med en verdi på 500) og TRACE (med en verdi på 600). Hvis loggeren er satt til nivået VERBOSE, vil alle loggmeldinger fra VERBOSE og over bli logget, inkludert DEBUG. TRACE-meldinger vil imidlertid bli hoppet over.

#3. Bruke det tilpassede loggnivået i koden

Egendefinerte loggnivåer må først deklareres før de brukes. Du kan deklarere dem enten i konfigurasjonsfilen eller i koden din. Når de er deklarert, står du fritt til å bruke dem.

Dette kodeeksemplet viser hvordan du kan deklarere et tilpasset nivå kalt NOTICE, og deretter bruke det samme.

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

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

Selv om dette vil generere den nødvendige meldingen med det nyopprettede nivået, kan det bli tungvint å alltid passere nivået eksplisitt. Heldigvis kan du generere kildekode slik at du får hjelpemetoder for å logge dine egendefinerte nivåer. Ved å bruke det samme vil du kunne bruke din egen metode for logger.notice() som ligner på hvordan du ville brukt logger.debug() eller logger.error().

Log4j2 kommer med et verktøy som hjelper deg med å lage dine egne utvidede loggere. Følgende kommando oppretter en Java-fil kalt CustomLogger.java. Denne filen inneholder de eksisterende loggmetodene, sammen med de nylig genererte metodene for NOTICE-nivået.

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

Når filen er generert, kan du bruke klassen i koden for å lage nye loggere. Disse loggerne vil inneholde flere metoder for ditt tilpassede loggnivå. Du kan dermed utvide funksjonaliteten til loggerne dine.

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

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

Konklusjon

Log4j2 er et veldig kraftig Java-loggingsrammeverk, som tilbyr et bredt spekter av funksjoner, konfigurasjoner, ytelsesforbedringer og mer. Med logger som en svært viktig del av programvareutviklingsprosessen, forbedrer det å ha et robust rammeverk som Log4j2 applikasjonens evner.

Log4j2s fleksibilitet og utvidbarhet tillater riktig fangst av hendelser som skjer i applikasjonen din. Deretter gir det deg mulighet til å tenke på logger som et kraftig verktøy for feilsøking og revisjon. Med alle sine funksjoner og forbedringer skiller Log4j2 seg ut og gjør seg selv til det foretrukne valget i en rekke ulike programvareprosjekter.

Du kan også være interessert i disse Java IDE-ene og online-kompliantene.