Protokolovanie jazyka Java s vnoreným diagnostickým kontextom (NDC)

1. Prehľad

Vnorený diagnostický kontext (NDC) je mechanizmus, ktorý pomáha odlíšiť vložené správy protokolu z rôznych zdrojov. NDC to robí tak, že poskytuje možnosť pridať charakteristické kontextové informácie ku každému záznamu protokolu.

V tomto článku sa budeme venovať použitiu NDC a jeho použitiu / podpore v rôznych rámcoch protokolovania Java.

2. Diagnostické kontexty

V typickej viacvláknovej aplikácii, ako je webová aplikácia alebo REST API, je každá požiadavka klienta doručená iným vláknom. Protokoly vygenerované z takejto aplikácie budú kombináciou všetkých požiadaviek a zdrojov klientov. To sťažuje akýkoľvek obchodný zmysel protokolov alebo ladenie.

Vnorený diagnostický kontext (NDC) spravuje hromadu kontextových informácií na základe jednotlivých vlákien. Údaje v NDC sú k dispozícii pre každú požiadavku na protokol v kóde a je možné ich nakonfigurovať tak, aby sa prihlásili s každou správou o protokole, a to aj na miestach, kde rozsah údajov nie je. Tieto kontextové informácie v každej protokolovej správe pomáhajú rozlíšiť protokoly podľa ich zdroja a kontextu.

Mapovaný diagnostický kontext (MDC) tiež spravuje informácie na základe vlákna, ale ako mapa.

3. Zásobník NDC vo vzorovej aplikácii

Na ukážku použitia zásobníka NDC si vezmime príklad REST API, ktoré posiela peniaze na investičný účet.

Informácie požadované ako vstup sú vyjadrené v Investícia trieda:

verejná trieda Investment {private String transactionId; súkromný vlastník reťazca; súkromná Dlhá suma; verejné investície (StringactionId, vlastník reťazca, dlhá suma) {this.transactionId = transactionId; this.owner = owner; this.amount = suma; } // štandardní zakladatelia a zakladatelia}

Prevod na investičný účet sa vykonáva pomocou InvestmentService. Celý zdrojový kód pre tieto triedy nájdete v tomto projekte github.

Vo vzorovej aplikácii údaje transactionId a vlastník sú umiestnené v zásobníku NDC, vo vlákne, ktoré spracováva danú požiadavku. Tieto údaje sú k dispozícii v každej denníkovej správe v danom vlákne. Týmto spôsobom je možné vysledovať každú jedinečnú transakciu a identifikovať relevantný kontext každej správy denníka.

4. NDC v Log4j

Log4j poskytuje triedu s názvom NDC ktorá poskytuje statické metódy na správu údajov v zásobníku NDC. Základné použitie:

  • Pri zadávaní kontextu použite NDC.push () pridať kontextové údaje do aktuálneho vlákna
  • Pri odchode z kontextu použite NDC.pop () vylúčiť kontextové údaje
  • Pri vystupovaní z vlákna volajte NDC.remove () odstrániť diagnostický kontext vlákna a zabezpečiť uvoľnenie pamäte (od verzie Log4j 1.3, už nie je potrebné)

V ukážkovej aplikácii použijeme NDC na pridanie / odstránenie kontextových údajov na relevantných miestach v kóde:

import org.apache.log4j.NDC; @RestController verejná trieda Log4JController {@Autowired @Qualifier ("Log4JInvestmentService") súkromná InvestmentService log4jBusinessService; @RequestMapping (value = "/ ndc / log4j", method = RequestMethod.POST) public ResponseEntity postPayment (@RequestBody Investment investment) {NDC.push ("tx.id =" + investment.getTransactionId ()); NDC.push ("tx.owner =" + investment.getOwner ()); log4jBusinessService.transfer (investment.getAmount ()); NDC.pop (); NDC.pop (); NDC.remove (); návrat new ResponseEntity (investment, HttpStatus.OK); }}

Obsah NDC je možné zobraziť v protokolových správach pomocou %X možnosť v ConversionPattern použitý prihlasovateľom v log4j.properties:

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

Nasadime REST API do kocoura. Ukážka žiadosti:

POST / logging-service / ndc / log4j {"transactionId": "4", "vlastník": "Marc", "suma": 2000}

Vo výstupe protokolu môžeme vidieť diagnostické kontextové informácie:

48569 [http-nio-8080-exec-3] INFO Log4JInvestmentService - príprava na prevod 2 000 $. - [tx.id = 4 tx.owner = Marc] 49231 [http-nio-8080-exec-4] INFO Log4JInvestmentService - Príprava na prevod 1500 $. - [tx.id = 6 tx.owner = Samantha] 49334 [http-nio-8080-exec-3] INFO Log4JInvestmentService - Bol prevod 2 000 $ úspešne dokončený? pravda. - [tx.id = 4 tx.owner = Marc] 50023 [http-nio-8080-exec-4] INFO Log4JInvestmentService - Bol prevod 1500 $ úspešne dokončený? pravda. - [tx.id = 6 tx.owner = Samantha] ...

5. NDC v Log4j 2

NDC v Log4j 2 sa nazýva Thread Context Stack:

import org.apache.logging.log4j.ThreadContext; @RestController verejná trieda Log4J2Controller {@Autowired @Qualifier ("Log4J2InvestmentService") súkromná InvestmentService log4j2BusinessService; @RequestMapping (value = "/ ndc / log4j2", method = RequestMethod.POST) public ResponseEntity postPayment (@RequestBody Investment investment) {ThreadContext.push ("tx.id =" + investment.getTransactionId ()); ThreadContext.push ("tx.owner =" + investment.getOwner ()); log4j2BusinessService.transfer (investment.getAmount ()); ThreadContext.pop (); ThreadContext.pop (); ThreadContext.clearAll (); návrat new ResponseEntity (investment, HttpStatus.OK); }}

Rovnako ako v prípade Log4j používajme %X v konfiguračnom súbore Log4j 2 log4j2.xml:

Výstup protokolu:

204724 [http-nio-8080-exec-1] INFO Log4J2InvestmentService - príprava na prevod 1500 $. - [tx.id = 6, tx.owner = Samantha] 205455 [http-nio-8080-exec-2] INFO Log4J2InvestmentService - Príprava prevodu 2 000 $. - [tx.id = 4, tx.owner = Marc] 205525 [http-nio-8080-exec-1] INFO Log4J2InvestmentService - Bol prevod 1500 $ úspešne dokončený? nepravdivé. - [tx.id = 6, tx.owner = Samantha] 206064 [http-nio-8080-exec-2] INFO Log4J2InvestmentService - Bol prevod 2 000 $ úspešne dokončený? pravda. - [tx.id = 4, tx.owner = Marc] ...

6. NDC v protokolovacích fasádach (protokolovanie JBoss)

Ťažobné fasády ako SLF4J poskytujú integráciu s rôznymi rámcami ťažby dreva. NDC nie je podporované v SLF4J (ale sú súčasťou modulu slf4j-ext). JBoss Logging je protokolovací mostík, rovnako ako SLF4J. Protokol NDC je podporovaný v protokole JBoss.

V predvolenom nastavení bude prehľadávanie JBoss prehľadávať ClassLoader dostupnosť back-endov / poskytovateľov v nasledujúcom poradí priorít: JBoss LogManager, Log4j 2, Log4j, SLF4J a JDK Logging.

JBoss LogManager ako poskytovateľ protokolovania sa zvyčajne používa na aplikačnom serveri WildFly. V našom prípade si protokolový mostík JBoss vyberie nasledujúci v poradí podľa priority (čo je Log4j 2) ako poskytovateľ protokolovania.

Začnime pridaním požadovanej závislosti do pom.xml:

 org.jboss.logovanie protokolovania jboss 3.3.0. Konečné 

Najnovšiu verziu závislosti si môžete skontrolovať tu.

Pridajme kontextové informácie do zásobníka NDC:

import org.jboss.logging.NDC; @RestController verejná trieda JBossLoggingController {@Autowired @Qualifier ("JBossLoggingInvestmentService") súkromná InvestmentService jbossLoggingBusinessService; @RequestMapping (value = "/ ndc / jboss-loging", method = RequestMethod.POST) public ResponseEntity postPayment (@RequestBody Investment investment) {NDC.push ("tx.id =" + investment.getTransactionId ()); NDC.push ("tx.owner =" + investment.getOwner ()); jbossLoggingBusinessService.transfer (investment.getAmount ()); NDC.pop (); NDC.pop (); NDC.clear (); návrat new ResponseEntity (investment, HttpStatus.OK); }}

Výstup protokolu:

17045 [http-nio-8080-exec-1] INFO JBossLoggingInvestmentService - príprava na prevod 1 500 $. - [tx.id = 6, tx.owner = Samantha] 17725 [http-nio-8080-exec-1] INFO JBossLoggingInvestmentService - Bol prevod 1 500 $ úspešne dokončený? pravda. - [tx.id = 6, tx.owner = Samantha] 18257 [http-nio-8080-exec-2] INFO JBossLoggingInvestmentService - Príprava prevodu 2 000 $. - [tx.id = 4, tx.owner = Marc] 18904 [http-nio-8080-exec-2] INFO JBossLoggingInvestmentService - Bol prevod 2 000 $ úspešne dokončený? pravda. - [tx.id = 4, tx.owner = Marc] ...

7. Záver

Videli sme, ako diagnostický kontext pomáha pri korelácii protokolov zmysluplným spôsobom - z obchodného hľadiska aj na účely ladenia. Je to neoceniteľná technika na obohatenie protokolovania, najmä v aplikáciách s viacerými vláknami.

Príklad použitý v tomto článku nájdete v projekte Github.