Java-logning med indlejret diagnostisk kontekst (NDC)

1. Oversigt

Nested Diagnostic Context (NDC) er en mekanisme, der hjælper med at skelne sammenflettede logmeddelelser fra forskellige kilder. NDC gør dette ved at give mulighed for at tilføje særprægede kontekstuelle oplysninger til hver logpost.

I denne artikel vil vi undersøge brugen af ​​NDC og dets anvendelse / support i forskellige Java-logningsrammer.

2. Diagnostiske sammenhænge

I en typisk applikation med flere tråde som en webapplikation eller REST API'er, serveres hver klientanmodning af en anden tråd. De logfiler, der genereres fra en sådan applikation, vil være en blanding af alle klientanmodninger og kilder. Dette gør det vanskeligt at skabe mening i logfilerne eller fejlfinding.

Nested Diagnostic Context (NDC) administrerer en stak af kontekstuelle oplysninger, pr. Tråd. Dataene i NDC er tilgængelige for enhver loganmodning i koden og kan konfigureres til at logge med hver logmeddelelse - selv på steder, hvor dataene ikke er inden for omfanget. Denne kontekstuelle information i hver logmeddelelse hjælper med at skelne logfilerne efter dens kilde og kontekst.

Mapped Diagnostic Context (MDC) håndterer også oplysninger pr. Tråd, men som et kort.

3. NDC-stakken i en prøveapplikation

For at demonstrere brugen af ​​en NDC-stak, lad os tage et eksempel på en REST API, der sender penge til en investeringskonto.

De krævede oplysninger som input er repræsenteret i et Investering klasse:

offentlig klasse investering {privat strengtransaktionId; privat String ejer; privat Langt beløb; offentlig investering (strengtransaktionId, streng ejer, langt beløb) {this.transactionId = transactionId; this.owner = ejer; dette.beløb = beløb; } // standard getters og setters}

Overførslen til investeringskontoen udføres ved hjælp af InvestmentService. Den fulde kildekode for disse klasser kan findes i dette github-projekt.

I prøveapplikationen dataene Transaktions ID og ejer placeres i NDC-stakken i den tråd, der behandler en given anmodning. Disse data er tilgængelige i hver logmeddelelse i den tråd. På denne måde kan hver unikke transaktion spores, og den relevante kontekst for hver logmeddelelse kan identificeres.

4. NDC i Log4j

Log4j giver en klasse kaldet NDC som giver statiske metoder til at administrere data i NDC-stakken. Grundlæggende brug:

  • Når du går ind i en kontekst, skal du bruge NDC.push () for at tilføje kontekstdata i den aktuelle tråd
  • Brug, når du forlader sammenhængen NDC.pop () at fjerne kontekstdataene
  • Når du forlader tråden, skal du ringe NDC. Fjern () for at fjerne diagnostisk kontekst for tråden og sikre, at hukommelsen frigøres (fra og med Log4j 1.3 er det ikke længere nødvendigt)

I prøveapplikationen skal vi bruge NDC til at tilføje / fjerne kontekstuelle data på relevante steder i koden:

import org.apache.log4j.NDC; @RestController offentlig klasse Log4JController {@Autowired @Qualifier ("Log4JInvestmentService") privat InvestmentService log4jBusinessService; @RequestMapping (værdi = "/ ndc / log4j", metode = RequestMethod.POST) offentlig ResponseEntity postPayment (@RequestBody Investment investering) {NDC.push ("tx.id =" + investering.getTransactionId ()); NDC.push ("tx.owner =" + investering.getOwner ()); log4jBusinessService.transfer (investering.getAmount ()); NDC.pop (); NDC.pop (); NDC. fjern (); returner ny ResponseEntity (investering, HttpStatus.OK); }}

Indholdet af NDC kan vises i logbeskeder ved hjælp af %x indstilling i ConversionPattern bruges af appender i log4j.egenskaber:

log4j.appender.consoleAppender.layout.ConversionPattern =% -4r [% t]% 5p% c {1} -% m - [% x]% n

Lad os implementere REST API til tomcat. Eksempel på anmodning:

POST / logging-service / ndc / log4j {"transactionId": "4", "ejer": "Marc", "beløb": 2000}

Vi kan se de diagnostiske kontekstoplysninger i logoutputtet:

48569 [http-nio-8080-exec-3] INFO Log4JInvestmentService - Forberedelse til overførsel af 2000 $. - [tx.id = 4 tx.owner = Marc] 49231 [http-nio-8080-exec-4] INFO Log4JInvestmentService - Forberedelse til overførsel af 1500 $. - [tx.id = 6 tx.owner = Samantha] 49334 [http-nio-8080-exec-3] INFO Log4JInvestmentService - Er overførslen på 2000 $ gennemført med succes? rigtigt. - [tx.id = 4 tx.owner = Marc] 50023 [http-nio-8080-exec-4] INFO Log4JInvestmentService - Er overførslen på 1500 $ gennemført med succes? rigtigt. - [tx.id = 6 tx.ejer = Samantha] ...

5. NDC i Log4j 2

NDC i Log4j 2 kaldes som trådkontekststak:

import org.apache.logging.log4j.ThreadContext; @RestController offentlig klasse Log4J2Controller {@Autowired @Qualifier ("Log4J2InvestmentService") privat InvestmentService log4j2BusinessService; @RequestMapping (værdi = "/ ndc / log4j2", metode = RequestMethod.POST) offentlig ResponseEntity postPayment (@RequestBody Investment investering) {ThreadContext.push ("tx.id =" + investering.getTransactionId ()); ThreadContext.push ("tx.owner =" + investering.getOwner ()); log4j2BusinessService.transfer (investering.getAmount ()); ThreadContext.pop (); ThreadContext.pop (); ThreadContext.clearAll (); returner ny ResponseEntity (investering, HttpStatus.OK); }}

Ligesom med Log4j, lad os bruge %x i Log4j 2-konfigurationsfilen log4j2.xml:

Log output:

204724 [http-nio-8080-exec-1] INFO Log4J2InvestmentService - Forbereder overførsel af 1500 $. - [tx.id = 6, tx.owner = Samantha] 205455 [http-nio-8080-exec-2] INFO Log4J2InvestmentService - Forberedelse til overførsel af 2000 $. - [tx.id = 4, tx.owner = Marc] 205525 [http-nio-8080-exec-1] INFO Log4J2InvestmentService - Er overførslen på 1500 $ gennemført med succes? falsk. - [tx.id = 6, tx.owner = Samantha] 206064 [http-nio-8080-exec-2] INFO Log4J2InvestmentService - Er overførslen på 2000 $ gennemført med succes? rigtigt. - [tx.id = 4, tx.eejer = Marc] ...

6. NDC i logningsfacader (JBoss Logging)

Loggningsfacader som SLF4J giver integration med forskellige logningsrammer. NDC understøttes ikke i SLF4J (men inkluderet i slf4j-ext-modul). JBoss Logging er en logningsbro, ligesom SLF4J. NDC understøttes i JBoss Logging.

Som standard søger JBoss Logging i ClassLoader for tilgængeligheden af ​​back-end / udbydere i følgende rækkefølge: JBoss LogManager, Log4j 2, Log4j, SLF4J og JDK Logging.

JBoss LogManager som loggeudbyder bruges typisk i WildFly-applikationsserveren. I vores tilfælde vælger JBoss logging bridge den næste rækkefølge (som er Log4j 2) som loggingudbyder.

Lad os begynde med at tilføje den krævede afhængighed i pom.xml:

 org.jboss.logging jboss-logging 3.3.0.Final 

Den seneste version af afhængigheden kan kontrolleres her.

Lad os tilføje kontekstuelle oplysninger til NDC-stakken:

import org.jboss.logging.NDC; @RestController offentlig klasse JBossLoggingController {@Autowired @Qualifier ("JBossLoggingInvestmentService") privat InvestmentService jbossLoggingBusinessService; @RequestMapping (værdi = "/ ndc / jboss-logning", metode = RequestMethod.POST) offentlig ResponseEntity postPayment (@RequestBody Investment investering) {NDC.push ("tx.id =" + investering.getTransactionId ()); NDC.push ("tx.owner =" + investering.getOwner ()); jbossLoggingBusinessService.transfer (investering.getAmount ()); NDC.pop (); NDC.pop (); NDC.klar (); returner ny ResponseEntity (investering, HttpStatus.OK); }}

Log output:

17045 [http-nio-8080-exec-1] INFO JBossLoggingInvestmentService - Forberedelse til overførsel af 1.500 $. - [tx.id = 6, tx.owner = Samantha] 17725 [http-nio-8080-exec-1] INFO JBossLoggingInvestmentService - Er overførslen på 1.500 $ gennemført med succes? rigtigt. - [tx.id = 6, tx.owner = Samantha] 18257 [http-nio-8080-exec-2] INFO JBossLoggingInvestmentService - Forbereder sig på at overføre 2.000 $. - [tx.id = 4, tx.owner = Marc] 18904 [http-nio-8080-exec-2] INFO JBossLoggingInvestmentService - Er overførslen på 2.000 $ gennemført med succes? rigtigt. - [tx.id = 4, tx.eejer = Marc] ...

7. Konklusion

Vi har set, hvordan diagnostisk sammenhæng hjælper med at korrelere logfiler på en meningsfuld måde - fra et forretningsmæssigt synspunkt såvel som til fejlfindingsformål. Det er en uvurderlig teknik til at berige logning, især i applikationer med flere tråde.

Eksemplet brugt i denne artikel kan findes i Github-projektet.


$config[zx-auto] not found$config[zx-overlay] not found