Flogger Folyékony naplózás

1. Áttekintés

Ebben az oktatóanyagban a Flogger keretrendszerről fogunk beszélni, amely egy folyékony naplózási API Java számára, amelyet a Google tervezett.

2. Miért kell használni a Flogger-t?

Az összes naplózási keretrendszerrel, mint például a Log4j és a Logback, miért van szükségünk egy újabb naplózási keretrendszerre?

Kiderült, hogy a Flogger számos előnnyel rendelkezik a többi keretrendszerrel szemben - vessünk egy pillantást.

2.1. Olvashatóság

A Flogger API folyékony jellege nagyban hozzájárul az olvashatóság javításához.

Nézzünk meg egy példát, ahol tíz ismétlésenként szeretnénk naplózni egy üzenetet.

A hagyományos naplózási keretrendszerrel valami ilyesmit látnánk:

int i = 0; // ... if (i% 10 == 0) {logger.info ("Ez a napló minden 10 iterációt megjelenít"); i ++; }

De most a Floggerrel a fentiek leegyszerűsíthetők:

logger.atInfo (). every (10) .log ("Ez a napló minden 10 iterációt mutat");

Bár azt állíthatnánk, hogy a naplózó utasítás Flogger verziója kissé verbósabbnak tűnik, mint a hagyományos változatok, nagyobb funkcionalitást tesz lehetővé, és végül olvashatóbb és kifejezhetőbb napló utasításokhoz vezet.

2.2. Teljesítmény

A naplózási objektumok optimalizálva vannak, amíg elkerüljük a hívást Sztring a naplózott objektumokon:

Felhasználó felhasználó = új Felhasználó (); logger.atInfo (). log ("A felhasználó:% s", felhasználó);

Ha naplózunk, a fentiek szerint, a háttérprogramnak lehetősége van optimalizálni a naplózást. Másrészt, ha hívunk Sztring közvetlenül, vagy összefűzze a húrokat, akkor ez a lehetőség elvész:

logger.atInfo (). log ("Ths felhasználó:% s", user.toString ()); logger.atInfo (). log ("Ths felhasználó:% s" + felhasználó);

2.3. Nyújthatóság

A Flogger keretrendszer már lefedi az alapfunkciók nagy részét, amelyet elvárhatunk egy naplózási kerettől.

Vannak azonban olyan esetek, amikor ki kellene egészítenünk a funkciókat. Ezekben az esetekben lehetséges az API kiterjesztése.

Jelenleg ehhez külön támogató osztályra van szükség. Kiterjeszthetjük például a Flogger API-t a UserLogger osztály:

logger.at (INFO) .forUserId (id) .withUsername (felhasználónév) .log ("Üzenet:% s", param);

Ez hasznos lehet olyan esetekben, amikor következetesen szeretnénk formázni az üzenetet. A UserLogger ezután biztosítaná az egyedi módszerek megvalósítását forUserId (karakterlánc azonosító) és withUsername (karakterlánc felhasználónév).

Ezt csináld meg, a UserLogger osztálynak meg kell hosszabbítania a AbstractLogger osztályt, és biztosítson egy megvalósítást az API számára. Ha megnézzük FluentLogger, ez csak egy naplózó, további módszerek nélkül, ezért kezdje az osztály jelenlegi állapotának másolásával, majd építsen fel ebből az alapból módszerek hozzáadásával.

2.4. Hatékonyság

A hagyományos keretrendszerek széles körben használják a varargokat. Ezek a módszerek újat igényelnek Tárgy[] kiosztandó és kitöltött, mielőtt a módszer meghívható lenne. Ezenkívül minden beírt alapvető típust automatikusan be kell jelölni.

Mindez további bytecode és késleltetéssel jár a hívás helyén. Különösen sajnálatos ha a napló utasítás valóban nincs engedélyezve. A költség nyilvánvalóbbá válik a hibakeresési szintű naplókban, amelyek gyakran ciklusokban jelennek meg. A Flogger ezeket a költségeket elárasztja azáltal, hogy teljesen elkerüli a varargokat.

A Flogger úgy oldja meg ezt a problémát, hogy folyékony hívásláncot használ, amelyből naplózási utasításokat lehet építeni. Ez lehetővé teszi, hogy a keretrendszer csak kis számú felülírást végezzen a napló módszerrel, és így képes legyen elkerülni az olyan dolgokat, mint a varargs és az auto-box. Ez azt jelenti, hogy az API számos új funkciót képes beilleszteni kombinatorikus robbanás nélkül.

Egy tipikus naplózási keretrendszer a következő módszerekkel rendelkezik:

szint (karakterlánc, objektum) szint (karakterlánc, objektum ...)

hol szint körülbelül hét naplószintű név egyike lehet (szigorú például kanonikus napló módszerrel, amely további naplószintet fogad el:

napló (szint, objektum ...)

Emellett általában vannak a módszerek olyan változatai, amelyek okot okoznak (a Dobható példány), amely a napló utasításhoz van társítva:

szint (dobható, karakterlánc, objektum) szint (dobható, karakterlánc, objektum ...)

Nyilvánvaló, hogy az API három problémát kapcsol össze egy metódushívásba:

  1. Megpróbálja meghatározni a naplószintet (módszerválasztás)
  2. Megpróbál metaadatokat csatolni a napló utasításhoz (Dobható ok)
  3. És a naplóüzenet és az argumentumok megadásával is.

Ez a megközelítés gyorsan megsokszorozza a különféle naplózási módszerek számát, amelyek szükségesek e független aggályok kielégítéséhez.

Most már láthatjuk, miért fontos, hogy két módszer legyen a láncban:

logger.atInfo (). withCause (e) .log ("Üzenet:% s", arg);

Most nézzük meg, hogyan használhatjuk a kódbázisunkban.

3. Függőségek

A Flogger beállítása nagyon egyszerű. Csak hozzá kell tennünk korbács és flogger-system-backend a miénknek pom:

  com.google.flogger flogger 0.4 com.google.flogger flogger-system-backend 0.4 futásidejű 

Ezeknek a függőségeknek a beállításával most folytathatjuk a rendelkezésünkre álló API felfedezését.

4. A Fluent API felfedezése

Először is nyilvánítsuk ki a statikus naplózónk példánya:

privát statikus végső FluentLogger naplózó = FluentLogger.forEnclosingClass ();

És most elkezdhetjük a fakitermelést. Kezdjük valami egyszerűvel:

int eredmény = 45/3; logger.atInfo (). log ("Az eredmény% d", eredmény);

A naplóüzenetek a Java bármelyikét használhatják printf formátum-specifikátorok, például %SD vagy % 016x.

4.1. A naplóhelyeken végzett munka elkerülése

A Flogger készítői javasolják, hogy kerüljük a munkákat a naplóban.

Tegyük fel, hogy a következő, hosszú ideje működő módszerrel tudjuk összefoglalni az összetevők jelenlegi állapotát:

public static String collectSummaries () {longRunningProcess (); int tételek = 110; int s = 30; return String.format ("% d másodperc telt el.% d elem feldolgozásra vár", s, elemek); }

Csábító felhívni gyűjtSummaries közvetlenül a napló nyilatkozatunkban:

logger.atFine (). log ("stats =% s", collectSummaries ());

A konfigurált naplószintektől vagy a sebességkorlátozástól függetlenül a gyűjtSummaries módszert minden alkalommal meghívják.

A naplózási keretrendszer középpontjában a letiltott naplózási nyilatkozatok költségeinek gyakorlatilag ingyenesvé tétele áll. Ez viszont azt jelenti, hogy közülük többen sérülés nélkül érintetlenül maradhatnak a kódban. A napló kimutatás megírása úgy, ahogy mi tettük, elveszíti ezt az előnyt.

Ehelyett a LazyArgs.lusta módszer:

logger.atFine (). log ("stats =% s", LazyArgs.lazy (() -> collectSummaries ()));

Most szinte semmilyen munkát nem végeznek a naplóban - csak példány létrehozása a lambda kifejezéshez. A Flogger csak akkor fogja értékelni ezt a lambdát, ha ténylegesen naplózni kívánja az üzenetet.

Bár megengedett a napló kimutatások használata engedélyezve:

if (logger.atFine (). isEnabled ()) {logger.atFine (). log ("összesítések =% s", collectSummaries ()); }

Ez nem szükséges, és kerülnünk kell, mert Flogger elvégzi ezeket az ellenőrzéseket helyettünk. Ez a megközelítés szintén csak a napló utasításokat őrzi szintenként, és nem segít a sebességkorlátozott napló utasításokban.

4.2. Kivételek kezelése

Mit szólnál a kivételekhez, hogyan kezeljük őket?

Nos, Flogger jön egy aStackTrace segítségével módszer, amellyel naplózhatunk a Dobható példa:

próbáld ki {int eredmény = 45/0; } catch (RuntimeException re) {logger.atInfo (). withStackTrace (StackSize.FULL) .withCause (re) .log ("Üzenet"); }

Hol aStackTrace segítségével érvként veszi a StackSize enum állandó értékekkel KICSI KÖZEPES NAGY vagy TELJES. A verem nyomát generálta withStackTrace () a-ként fog megjelenni LogSiteStackTrace kivétel az alapértelmezett java.util.logging háttér. Más háttérprogramok mégis dönthetnek úgy, hogy ezt másként kezelik.

4.3. Naplózási konfiguráció és szintek

Eddig használtuk logger.atInfo a legtöbb példánkban, de Flogger sok más szintet támogat. Megnézzük ezeket, de először ismertetjük a naplózási beállítások konfigurálását.

A naplózás konfigurálásához a LoggerConfig osztály.

Például amikor a naplózási szintet szeretnénk beállítani BÍRSÁG:

LoggerConfig.of (logger) .setLevel (Level.FINE);

A Flogger pedig különféle naplózási szinteket támogat:

logger.atInfo (). log ("Információs üzenet"); logger.atWarning (). log ("Figyelmeztető üzenet"); logger.atSevere (). log ("Súlyos üzenet"); logger.atFine (). log ("Finom üzenet"); logger.atFiner (). log ("Finomabb üzenet"); logger.atFinest (). log ("Finest Message"); logger.atConfig (). log ("Config Message");

4.4. Díjkorlátozás

Mi a helyzet a kamatkorlátozás kérdésével? Hogyan kezeljük azt az esetet, amikor nem akarunk minden iterációt naplózni?

Flogger a mi segítségünkre van minden (int n) módszer:

IntStream.range (0, 100) .forEach (érték -> {logger.atInfo (). Every (40) .log ("Ez a napló 40 iterációnként =>% d", érték);});

A fenti kimenet futtatásakor a következő kimenetet kapjuk:

2019. szeptember 18. 17:04:02 com.baeldung.flogger.FloggerUnitTest lambda $ givenAnInterval_shouldLogAfterEveryTInterval $ 0 INFO: Ez a napló minden 40 ismétlés = = 0 [CONTEXT ratelimit_count = 40] 2019. szeptember 18., 5:04:02 PM com. baeldung.flogger.FloggerUnitTest lambda $ givenAnInterval_shouldLogAfterEveryTInterval $ 0 INFO: Ez a napló minden 40 iterációt => 40 mutat. a napló minden 40 iterációt mutat => 80 [CONTEXT ratelimit_count = 40]

Mi van, ha naplózni akarunk 10 másodpercenként? Azután, tudjuk használni atMostEvery (int n, TimeUnit egység):

IntStream.range (0, 1_000_0000) .forEach (érték -> {logger.atInfo (). AtMostEvery (10, TimeUnit.SECONDS) .log ("Ez a napló [10 másodpercenként] =>% d", érték); });

Ezzel az eredmény most:

2019. szeptember 18. 17:08:06 com.baeldung.flogger.FloggerUnitTest lambda $ givenATimeInterval_shouldLogAfterEveryTimeInterval $ 1 INFO: Ez a napló [10 másodpercenként] => 0 [CONTEXT ratelimit_period = "10 SECONDS"] 2019. szeptember 18., 5:08 : 16 PM com.baeldung.flogger.FloggerUnitTest lambda $ givenATimeInterval_shouldLogAfterEveryTimeInterval $ 1 INFO: Ez a napló [10 másodpercenként] => 3545373 [CONTEXT ratelimit_period = "10 MÁSODIK [kihagyva: 3545372] 5:08:26, 2019:18:26:26] PM com.baeldung.flogger.FloggerUnitTest lambda $ givenATimeInterval_shouldLogAfterEveryTimeInterval $ 1 INFO: Ez a napló [10 másodpercenként] => 7236301 [CONTEXT ratelimit_period = "10 MÁSODIK [kihagyva: 3690927]"]

5. A Flogger használata más háttérprogramokkal

Szóval, mi van, ha szeretnénk vegye fel a Flogger alkalmazást a meglévő alkalmazásunkba, amely már használja a Slf4j vagy a Log4j alkalmazást például? Ez hasznos lehet olyan esetekben, amikor ki szeretnénk használni a meglévő konfigurációink előnyeit. A Flogger több háttérprogramot is támogat, amint látni fogjuk.

5.1 Flogger Slf4j-vel

Egy Slf4j háttér konfigurálása egyszerű. Először hozzá kell adnunk a flogger-slf4j-backend függőség a mi pom:

 com.google.flogger flogger-slf4j-backend 0.4 

Ezután el kell mondanunk Flogger-nek, hogy az alapértelmezettől eltérő háttérképet szeretnénk használni. Ezt úgy végezzük, hogy regisztrálunk egy Flogger gyárat a rendszer tulajdonságain keresztül:

System.setProperty ("flogger.backend_factory", "com.google.common.flogger.backend.slf4j.Slf4jBackendFactory # getInstance");

És most alkalmazásunk a meglévő konfigurációt fogja használni.

5.1 Flogger Log4j-vel

Hasonló lépéseket követünk a Log4j háttér konfigurálásához. Tegyük hozzá a flogger-log4j-backend függőség a mi pom:

 com.google.flogger flogger-log4j-backend 0.4 com.sun.jmx jmxri com.sun.jdmk jmxtools javax.jms jms log4j log4j 1.2.17 log4j apache-log4j-extrák 1.2.17 

Regisztrálnunk kell egy Flogger háttérgyárat is a Log4j-hez:

System.setProperty ("flogger.backend_factory", "com.google.common.flogger.backend.log4j.Log4jBackendFactory # getInstance");

És ennyi, alkalmazásunk most már fel van állítva a meglévő Log4j konfigurációk használatára!

6. Következtetés

Ebben az oktatóanyagban láthattuk, hogyan lehet a Flogger keretrendszert alternatívaként használni a hagyományos naplózási keretekhez. Láttunk néhány erőteljes funkciót, amelyekből profitálhatunk a keretrendszer használatakor.

Láttuk azt is, hogy miként tudjuk kihasználni a meglévő konfigurációinkat különböző háttérprogramok, például Slf4j és Log4j regisztrálásával.

Szokás szerint az oktatóanyag forráskódja elérhető a GitHubon.