Miten Log4j:tä ja MDC:tä käytetään Java Spring Boot -sovelluksessa?

Moulin Raphaël

Follow

19.12, 2018 – 4 min read

Ensimmäisen projektimme yhteydessä jouduimme kohtaamaan monia virheenkorjaustapauksia. Yksinkertaiset viestit lokitiedostoissa eivät aina riitä. Saattaa esimerkiksi olla tarpeen saada lisätietoja toiminnon suorittaneesta käyttäjästä (hänen IP-osoitteensa, hänen oikeutensa, hänen tunnuksensa, …). Meidän tapauksessamme sovelluksemme oli rakennettu useista mikropalveluista, ja halusimme tunnistaa tarkasti virtauksen, jota mikropalvelusta toiseen siirtyvä pyyntö seuraa. Tätä varten luotiin yksilöllinen tunniste, joka näytettiin jokaisen verkkosovelluksen lokitiedoissa. Tämä auttoi meitä paljon ratkaisemaan ongelmia käyttämiemme kolmansien osapuolten sovellusten kanssa.

  • Miten viestejä lokitetaan?
  • Mitä kontekstitietoja lisätään viesteihimme?
  • Voidaanko nämä tiedot lisätä, kun ajetaan asynkronisia säikeitä?

Tämä artikkeli auttaa sinua rakentamaan Spring Boot Java -sovelluksen viestien kirjaamiseen Log4j:n avulla ja käyttämään tämän kirjaston MDC:tä (Mapping Diagnostic Context) lisäämään viestien lisäksi kontekstitietoa erityisesti asynkronisten tehtävien yhteydessä.

Aloitetaan luomalla klassinen Spring Boot -sovellus sisäänrakennetun Log4j-kirjaston avulla. Tämän kirjaston avulla voimme käyttää loggeria, joka tuottaa erityyppisiä lokiviestejä (info, virhe, varoitus, …)

  1. Valmistetaan Spring Initializrissä (https://start.spring.io/) Spring Bootin perusprojekti ilman riippuvuuksia.
  2. Muokataan pom.xml-tiedostoa lisäämällä siihen riippuvuudet, joita tarvitaan Log4j-kirjaston käyttämiseen
  3. Luotaan src/main/resources/log4j2.xml-tiedosto, jossa määritellään tulevien lokiviestien muoto

pom.xml

src/main/resources/log4j2.xml

Näytetään ensimmäinen lokiviestimme

Nykyisessä tilassa sovelluksen käynnistyessä (esimerkiksi IDE:llä tai Mavenin avulla) lokiviestejä ei näy. Luomme komponentin, joka käyttää Log4j-kirjastoa lokiviestin kirjaamiseen.

Luo src/main/java/com/sipios/example/mdc/Execute.java-tiedosto alla olevalla koodilla. Paketin nimi on tässä com.sipios.example.mdc, se on tietenkin korvattava omallasi 🙂

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

Jos suoritat sovelluksen, ensimmäinen määriteltyä muotoa noudattava lokiviesti näytetään nyt. Myös error– ja warning-metodien käyttö on mahdollista. Näitä tyyppejä vastaavat lokiviestit näytetään.

Käytä MDC:tä (Mapping Diagnostic Context) lokissa

Nyt kun tiedämme, miten Log4j-kirjastoa käytetään, voimme käyttää MDC:tä (Mapping Diagnostic Context), jonka avulla voimme liittää viestiin datakartan. Joitakin esimerkkejä tiedoista, joita suosittelemme laittamaan MDC:hen:

  • Tämänhetkisen istunnon tiedot (käyttäjä, kysely, pyyntö …)
  • Mittarit prosessin suorituksesta (alku- ja suoritusaika, …)
  • Tietoja sovelluksen versiosta

Tämä kartta näytetään lokitiedostoissa, jos Log4j-sanomamuodon määrittelyssä käytetään %X-maskia. Näin on tässä tapauksessa src/main/resources/log4j2.xml-tiedostossa. Edellisessä suorituksessa näemme {}, joka tarkoittaa tyhjää Mapia.

MDC:n käyttäminen on hyvin yksinkertaista ja sitä käytetään kuten klassista Mapia put, get, remove, clear-metodien kautta… Lisätään kaksi merkintää MDC:hen ja suoritetaan sovellus.

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

MDC:hen lisätään kaksi merkintää ja suoritetaan sovellus. Jos haluat tyhjentää sen esimerkiksi jättämällä komponentin, käytä vain clear-metodia. Tämä antaisi tällöin seuraavan tuloksen.

Miten se toimii asynkronisten komponenttien kanssa?

Kokeillaan MDC:tä asynkronisten komponenttien kanssa (komponentti, joka suoritetaan pääsäikeen rinnakkaisessa säikeessä)! Ensinnäkin meidän on konfiguroitava sovelluksemme suorittamaan tällaisia papuja. Luomme palvelun, jossa on kaksi metodia, joista toinen on synkroninen ja toinen asynkroninen.

  1. Add @EnableAsync-annotaatio Application-luokkaan
  2. Luo palvelu, jolla on normaali metodi ja @Async-metodi
  3. Modifioi komponentti injektoimaan ja käyttämään palvelun metodeja
  4. Käynnistä sovellus

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

Add taskExecutor in Application class

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

Re-execute :

Niin kuin näemme, MDC:n async-käytössä olevassa säikeessä MDC:n on tyhjä. Itse asiassa jokainen asynkroninen tehtävä aloitetaan uudessa säikeessä. Jokainen säie on linkitetty tehtävän suorittajan aloittamaan Map MDC:hen. Tällä suorittajalla on mahdollista pelata, jotta saadaan sama MDC kuin pääsäikeessä. Lisätään asyncExecutoriin decorator MDC:n monistamiseksi!

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

Määritä tämä decorator async configissa

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

Käynnistä sovellus

Kaikki! Voimme välittää lokitiedostoihin kaiken haluamamme kontekstin synkronisissa tai asynkronisissa tehtävissä.

Tämän ansiosta sovelluksen virheenkorjaus on yksinkertaisempaa ja ymmärrettävämpää. Osana projektiamme tämä on säästänyt paljon aikaa keskustelussa avustajiemme kanssa. Se on nyt sinusta kiinni 🙂

Bibliografia

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

Vastaa

Sähköpostiosoitettasi ei julkaista.