Hur använder jag Log4j och MDC i en Java Spring Boot-applikation?

Moulin Raphaël

Follow

Dec 19, 2018 – 4 min read

I samband med ett av våra projekt stod vi inför många fall av felsökning. Det räcker inte alltid med enkla meddelanden i loggarna. Det kan till exempel vara nödvändigt att ha mer information om den användare som utförde åtgärden (hans IP, hans behörigheter, hans identifierare, …). I vårt fall byggdes vår applikation av flera mikrotjänster och vi ville exakt identifiera det flöde som följs av en begäran som passerar från en mikrotjänst till en annan. För detta ändamål genererades en unik identifierare som visades i loggarna för varje webbapplikation. Detta hjälpte oss mycket att lösa problem med tredjepartsapplikationer som vi använde.

  • Hur loggar man meddelanden?
  • Vilken kontextinformation ska läggas till i våra meddelanden?
  • Kan den här informationen läggas till när man kör asynkrona trådar?

Denna artikel hjälper dig att bygga en Spring Boot Java-applikation för att logga meddelanden med Log4j och använda det här bibliotekets MDC (Mapping Diagnostic Context) för att lägga till kontextualiseringsdata utöver meddelanden, särskilt för asynkrona uppgifter.

Låt oss börja med att generera en klassisk Spring Boot-applikation med det inbyggda Log4j-biblioteket. Med det här biblioteket kan vi använda en logger som genererar loggmeddelanden av olika typer (info, error, warning, …)

  1. På Spring Initializr (https://start.spring.io/) bygger du ett grundläggande Spring Boot-projekt utan några beroenden.
  2. Redigera filen pom.xml för att lägga till de beroenden som behövs för att använda Log4j-biblioteket
  3. Skapa src/main/resources/log4j2.xml-filen som definierar formatet för framtida loggmeddelanden

pom.xml

src/main/resources/log4j2.xml

Visa vårt första loggmeddelande

I det nuvarande läget, om vi startar applikationen (via ett IDE till exempel eller genom att använda Maven) visas inget loggmeddelande. Vi kommer att skapa en komponent som använder Log4j-biblioteket för att logga ett informationsmeddelande.

Skapa en fil src/main/java/com/sipios/example/mdc/Execute.java med koden nedan. Paketnamnet är här com.sipios.example.mdc, det ska naturligtvis ersättas med ditt 🙂

src/main/java/com/sipios/example/mdc/Execute.java

Om du kör programmet visas nu ett första loggmeddelande som respekterar det definierade formatet. Det är också möjligt att använda metoderna error och warning. Loggmeddelanden som motsvarar dessa typer kommer att visas.

Använd MDC (Mapping Diagnostic Context) i din logg

När vi nu vet hur vi ska använda Log4j-biblioteket kommer vi att kunna använda Mapping Diagnostic Context (MDC), som gör det möjligt för oss att associera en datamappning med vårt meddelande. Några exempel på data som vi rekommenderar att du lägger in i MDC:

  • Data om den aktuella sessionen (användare, fråga, begäran …)
  • Metri om processens utförande (starttid och utförandetid, …).)
  • Information om programversionen

Denna karta visas i loggarna om masken %X används i definitionen av Log4j-meddelandeformatet. Detta är fallet här i vår fil src/main/resources/log4j2.xml. I föregående exekvering ser vi {}, vilket indikerar en tom Map.

Att använda MDC är mycket enkelt och används som en klassisk Map via metoderna put, get, remove, clear… Låt oss lägga till två poster i MDC och köra programmet.

src/main/java/com/sipios/example/mdc/Execute.java

MDC är global och den bevaras så länge den inte ändras. Om du vill tömma den genom att till exempel lämna en komponent är det bara att använda metoden clear. Detta skulle då ge följande resultat.

Hur fungerar det med asynkrona komponenter?

Låt oss prova MDC med asynkrona komponenter (en komponent som exekveras på en parallell tråd till huvudtråden)! Först och främst måste vi konfigurera vårt program för att exekvera sådana bönor. Vi skapar en tjänst med två metoder, den ena är synkron och den andra asynkron.

  1. Lägg till @EnableAsync-annotationen till Application-klassen
  2. Skapa en tjänst med en normal metod och en @Async-metod
  3. Modifiera komponenten så att den injicerar och använder tjänstens metoder
  4. Starta applikationen

src/main/java/com/sipios/example/mdc/Application.java

src/main/java/com/sipios/example/mdc/service/Example.java

src/main/java/com/sipios/example/mdc/Execute.java

Lägg till taskExecutor i Application class

src/main/java/com/sipios/example/mdc/Application.java

Re-execute :

Som vi kan se är MDC i asynkron tråd tom. Varje asynkron uppgift startas faktiskt i en ny tråd. Varje tråd är kopplad till en Map MDC som initieras av uppgiftsutföraren. Det är möjligt att spela på denna exekutor för att få samma MDC som på huvudtråden. Låt oss lägga till en dekorator i asyncExecutor för att duplicera MDC!

src/main/java/com/sipios/example/mdc/ExampleTaskDecorator.java

Sätt den här dekoratorn i async config

src/main/java/com/sipios/example/mdc/Application.java

Relansera applikationen

Där är du! Vi kan i loggarna förmedla allt sammanhang som vi vill ha i synkrona eller asynkrona uppgifter.

Detta gör det enklare och mer begripligt att felsöka ett program. Som en del av vårt projekt har detta sparat oss mycket tid i utbytet med våra bidragsgivare. Det är upp till dig nu 🙂

Bibliografi

  • http://www.baeldung.com/mdc-in-log4j-2-logback
  • https://spring.io/guides/gs/async-method/
  • https://moelholm.com/2017/07/24/spring-4-3-using-a-taskdecorator-to-copy-mdc-data-to-async-threads/

.

Lämna ett svar

Din e-postadress kommer inte publiceras.