10 tipp a megfelelő Alkalmazásnaplózáshoz

legújabb JCP partnerünk, Tomasz Nurkiewicz számos hozzászólást nyújtott be, amelyek leírják a megfelelő alkalmazásnaplózás alapelveit. Nagyon érdekesnek találtam őket, ezért úgy döntöttem, hogy tömörebb formátumban összesítem őket, és bemutatom neked. Tehát itt vannak a tiszta és hasznos naplókra vonatkozó javaslatai: (megjegyzés: Az eredeti hozzászólásokat kissé szerkesztették az olvashatóság javítása érdekében)

1) Használja a munkához megfelelő eszközöket

úgy tűnik, hogy sok programozó elfelejti, mennyire fontos az alkalmazás viselkedésének és aktuális tevékenységének naplózása. Amikor valaki tesz:

log.info("Happy and carefree logging");

szerencsére valahol a kódban valószínűleg nem veszi észre az alkalmazásnaplók fontosságát a karbantartás, a hangolás és a hiba azonosítása során. A jó naplók értékének alábecsülése szörnyű hiba.

véleményem szerint az SLF4J a legjobb elérhető naplózási API, főleg a nagyszerű mintahelyettesítési támogatás miatt:

log.debug("Found {} records matching filter: '{}'", records, filter); 

a Log4j akkor kell használni:

log.debug("Found " + records + " records matching filter: '" + filter + "'");

ez nem csak hosszabb és kevésbé olvasható, de nem is hatékony a karakterlánc-összefűzés széles körű használata miatt. Az SLF4J hozzáad egy szép {} helyettesítési funkciót. Továbbá, mivel a karakterlánc összefűzése elkerülhető, és a toString() nem hívható meg, ha a naplózási utasítás szűrve van, nincs szükség az isDebugEnabled () – re. BTW, észrevettél egyetlen idézőjelet a szűrő karakterlánc paramétere körül?

SLF4J csak egy fa ons. Implementációként a már meghirdetett Log4j keretrendszert javasolnám a jól bevált Log4J helyett.számos érdekes funkcióval rendelkezik, és a Log4J-vel ellentétben aktívan fejlesztik.

az utolsó ajánlott eszköz a Perf4J. mottójuk idézésére:

a Perf4J a rendszer.currentTimeMillis () mint log4j, hogy a rendszer.kifelé.println ()

hozzáadtam a Perf4J – t egy meglévő alkalmazáshoz nagy terhelés alatt, és néhány más alkalmazásban láttam. Mind az adminisztrátorokat, mind az üzleti felhasználókat lenyűgözte az egyszerű segédprogram által készített szép grafikonok. A teljesítményhibákat is pillanatok alatt felfedeztük. Maga a Perf4J megérdemli a saját cikkét, de egyelőre csak ellenőrizze a fejlesztői útmutatót.

továbbá, vegye figyelembe, hogy Ceki G Xhamlc (alapítója a Log4J, SLF4J és Logback projektek) javasolt egy egyszerű megközelítés, hogy megszabaduljon a commons-naplózás függőség (lásd a megjegyzést).

2) Ne felejtsd el, naplózási szintek vannak az Ön számára

minden alkalommal, amikor naplózási nyilatkozatot tesz, keményen gondolja, hogy melyik naplózási szint megfelelő az ilyen típusú eseményekhez, nem? Valahogy a programozók 90% – a soha nem figyel a naplózási szintekre, egyszerűen mindent ugyanazon a szinten naplóz, általában INFO vagy hibakeresés. Miért? A naplózási keretrendszereknek két fő előnye van a rendszerrel szemben.kifelé., azaz kategóriák és szintek. Mindkettő lehetővé teszi a naplózási utasítások szelektív szűrését véglegesen vagy csak diagnosztikai időre. Ha tényleg nem látja a különbséget, nyomtassa ki ezt a táblázatot, és nézze meg minden alkalommal, amikor elkezdi beírni a “napló.”az IDE – ben:

hiba-valami rettenetesen rossz történt, amit azonnal ki kell vizsgálni. Egyetlen rendszer sem képes elviselni az ezen a szinten bejelentkezett elemeket. Példa: NPE, az adatbázis nem érhető el, a kritikus fontosságú használati eset nem folytatható.

figyelmeztetés – a folyamat folytatódhat, de fokozott óvatossággal járjon el. Valójában mindig is két szintet akartam itt: egyet a nyilvánvaló problémákra, ahol a munka körül van (például: “Az aktuális adatok nem érhetők el, gyorsítótárazott értékeket használva”) és a második (nevezze meg: figyelem) a lehetséges problémákhoz és javaslatokhoz. Példa: “fejlesztési módban futó alkalmazás “vagy” az Adminisztrációs Konzol nincs jelszóval rögzítve”. Az alkalmazás képes tolerálni a figyelmeztető üzeneteket, de ezeket mindig meg kell indokolni és meg kell vizsgálni.

INFO – fontos üzleti folyamat befejeződött. Az ideális világban a rendszergazdának vagy a haladó felhasználónak képesnek kell lennie arra, hogy megértse az információs üzeneteket, és gyorsan megtudja, mit csinál az alkalmazás. Például, ha egy alkalmazás a repülőjegyek foglalásáról szól, minden jegyenként csak egy információs nyilatkozatot kell tartalmaznia, amely azt mondja: “lefoglalt jegy tól ig “. Az információs üzenet egyéb meghatározása: minden olyan művelet, amely jelentősen megváltoztatja az alkalmazás állapotát (adatbázis-frissítés, külső rendszerkérés).

DEBUG – Fejlesztők cucc. Később megbeszéljük, hogy milyen információkat érdemes naplózni.

TRACE – nagyon részletes információ, csak fejlesztésre szánt. Előfordulhat, hogy a nyomkövetési üzeneteket rövid ideig megőrzi az éles környezetben történő telepítés után, de ezeket a naplóbejegyzéseket ideiglenesnek tekinti, amelyeket végül ki kell vagy ki kell kapcsolni. A hibakeresés és a nyomkövetés közötti különbség a legnehezebb, de ha a naplózási utasítást a szolgáltatás fejlesztése és tesztelése után eltávolítja, akkor valószínűleg nyomkövetési szinten kell lennie.

a fenti lista csak egy javaslat, létrehozhat saját utasításkészletet, amelyet követni kell, de fontos, hogy legyen néhány. Az én tapasztalatom az, hogy mindig mindent naplózunk szűrés nélkül (legalábbis az alkalmazás kódjából), de az a képesség, hogy gyorsan szűrjük a naplókat, és megfelelő részletességgel kinyerjük az információkat, életmentő lehet.

az utolsó említésre méltó dolog az infamous is * Enabled() feltétel. Néhányan minden naplózási nyilatkozat előtt feltették:

if(log.isDebugEnabled()) log.debug("Place for your commercial");

személyesen, úgy találom, hogy ez az idióma csak rendetlenség, amelyet el kell kerülni. A teljesítmény javulása (különösen az SLF4J minta helyettesítése esetén) irrelevánsnak tűnik, és korai optimalizálásnak tűnik. Is, meg tudja észrevenni a duplikációt? Nagyon ritkán fordul elő, hogy az explicit feltétel megléte indokolt – amikor be tudjuk bizonyítani, hogy a naplózási üzenet elkészítése drága. Más helyzetekben csak végezze el a naplózást, és hagyja, hogy a naplózási keretrendszer elvégezze a munkáját (szűrés).

3) tudja, mit naplóz?

minden alkalommal, amikor naplózási nyilatkozatot ad ki, szánjon egy percet arra, hogy megnézze, mi lesz pontosan a naplófájlban. Utána olvassa el a naplókat, és szúrja ki a hibás mondatokat. Először is, kerülje az ilyen npe-ket:

log.debug("Processing request with id: {}", request.getId());

teljesen biztos benne, hogy ez a kérés itt nem nulla?

egy másik buktató a gyűjtemények naplózása. Ha az adatbázisból hibernált tartományobjektumok gyűjteményét töltötte le, és gondatlanul naplózta őket, mint itt:

log.debug("Returning users: {}", users);

SLF4J fogja hívni toString () csak akkor, ha a nyilatkozat ténylegesen nyomtatott, ami elég szép. De ha igen … ki a memória hiba, N+1 select probléma, szál éhezés (naplózás szinkron!), lusta inicializálás kivétel, naplók tároló teljesen kitöltött-ezek mindegyike előfordulhat.

sokkal jobb ötlet például csak a domain objektumok azonosítóit (vagy akár csak a gyűjtemény méretét) naplózni. De, hogy egy gyűjtemény ids, ha van egy gyűjtemény objektumok, amelyek getid () módszer hihetetlenül nehéz és nehézkes a Java. Groovy egy nagy spread operátor (users*. id), Java tudjuk emulálni a Commons beanutils könyvtár:

log.debug("Returning user ids: {}", collect(users, "id"));

ahol a collect () módszer a következőképpen valósítható meg:

public static Collection collect(Collection collection, String propertyName) { return CollectionUtils.collect(collection, new BeanToPropertyValueTransformer(propertyName));}

az utolsó dolog, amit meg kell említeni, a helytelen végrehajtása vagy használata toString (). Először hozzon létre toString () minden osztályhoz, amely bárhol megjelenik a naplózási utasításokban, lehetőleg a ToStringBuilder használatával (de nem annak fényvisszaverő megfelelőjével). Másodszor, vigyázzon a tömbökre és a nem tipikus gyűjteményekre. Lehet, hogy a tömböknek és néhány furcsa gyűjteménynek nincs toString() implementálva az egyes elemek toString () hívása. Használjon tömböket #deepToString JDK segédprogram módszer. Gyakran olvassa el a naplókat, hogy észrevegye a helytelenül formázott üzeneteket.

4) kerülje a mellékhatásokat

a naplózási utasításoknak nem vagy csak kis hatással kell lenniük az alkalmazás viselkedésére. Nemrégiben egy barátom példát adott egy olyan rendszerre, amely csak akkor dobta a Hibernates LazyInitializationException-jét, ha valamilyen adott környezetben fut. Amint azt valószínűleg a kontextusból kitalálta, néhány naplózási utasítás lusta inicializált gyűjtemény betöltését okozta a munkamenet csatolásakor. Ezen a környezetben a naplózási szinteket növelték, és a gyűjtést már nem inicializálták. Gondoljon bele, mennyi időbe telik megtalálni a hibát anélkül, hogy tudná ezt a kontextust?

egy másik mellékhatás az alkalmazás lelassulása. Gyors válasz: ha túl sokat naplózol, vagy nem megfelelően használod a toString() függvényt és/vagy a string összefűzést, a naplózásnak van egy mellékhatása. Milyen nagy? Jól, láttam szerver újraindítása minden 15 perc, mert egy szál éhezés okozta túlzott naplózás. Most ez egy mellékhatás! Tapasztalataim szerint néhány száz MiB valószínűleg a felső határa annak, hogy mennyit tud bejelentkezni a lemezre óránként.

természetesen, ha a naplózási nyilatkozat önmagában nem sikerül, és az üzleti folyamat leáll a kivétel miatt, ez is hatalmas mellékhatás. Láttam egy ilyen konstrukciót ennek elkerülésére:

try { log.trace("Id=" + request.getUser().getId() + " accesses " + manager.getPage().getUrl().toString())} catch(NullPointerException e) {}

ez egy igazi kód, de kérlek, hogy a világ egy kicsit jobb hely, és ne csináld, soha.

5) legyen tömör és leíró

minden naplózási utasításnak tartalmaznia kell mind az adatokat, mind a leírást. Tekintsük a következő példákat:

log.debug("Message processed");log.debug(message.getJMSMessageID());log.debug("Message with id '{}' processed", message.getJMSMessageID());

melyik naplót szeretné látni egy ismeretlen alkalmazás hibájának diagnosztizálása közben? Hidd el, a fenti példák szinte ugyanolyan gyakoriak. Egy másik anti-minta:

if(message instanceof TextMessage) //...else log.warn("Unknown message type");

olyan nehéz volt felvenni a tényleges üzenet típusát, az üzenet azonosítóját stb. a figyelmeztető karakterláncban? Tudom, hogy valami rosszul sült el, de mi? Mi volt a kontextus?

egy harmadik anti-minta a “magic-log”. Valós példa: a legtöbb programozó a csapat tudta, hogy 3 ampersands, majd felkiáltójel, majd hash, majd álvéletlenszerű alfanumerikus karakterlánc log azt jelenti,”üzenet XYZ id érkezett”. Senki sem zavarta, hogy módosítsa a napló, egyszerűen valaki nyomja meg a billentyűzetet, és úgy döntött, néhány egyedi “&&&!# “string, úgy, hogy könnyen megtalálható a maga által.

ennek következtében az egész naplófájl véletlenszerű karaktersorozatnak tűnik. Valaki még azt is figyelembe veheti, hogy a fájl érvényes Perl program. Ehelyett a naplófájlnak olvashatónak, tisztának és leírónak kell lennie. Ne használjon mágikus számokat, naplóértékeket, számokat, azonosítókat, és ne szerepeltesse azok kontextusát. Mutassa meg a feldolgozott adatokat és mutassa meg azok jelentését. Mutassa meg, mit csinál a program valójában. A jó naplók nagyszerű dokumentációként szolgálhatnak az alkalmazás kódjáról.

említettem már, hogy nem kell jelszavakat és személyes adatokat naplózni? Ne!

6) Tune a minta

naplózás minta egy csodálatos eszköz, amely átláthatóan hozzáad egy értelmes összefüggésben minden naplózási nyilatkozatot csinál. De nagyon alaposan meg kell fontolnia, hogy mely információkat vegye fel a mintájába. Például a naplózási dátum, amikor a naplók óránként gördülnek, értelmetlen, mivel a dátum már szerepel a naplófájl nevében. Éppen ellenkezőleg, a szálnév naplózása nélkül nem tudna nyomon követni egyetlen folyamatot sem naplók használatával, ha két szál egyidejűleg működik-a naplók átfedik egymást. Ez rendben lehet az egyszálú alkalmazásokban-amelyek manapság szinte halottak.

tapasztalataim szerint az ideális naplózási mintának tartalmaznia kell (természetesen magát a naplózott üzenetet kivéve): aktuális idő (dátum nélkül, ezredmásodperc pontossággal), naplózási szint, a szál neve, egyszerű naplózó neve (nem teljesen minősített) és az üzenet. A Logback-ben ez valami hasonló:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} %-5level %m%n</pattern> </encoder></appender>

soha ne adja meg a fájlnevet, az osztálynevet és a sorszámot, bár ez nagyon csábító. Még a kódból kiadott üres naplóbejegyzéseket is láttam:

log.info("");

mivel a programozó feltételezte, hogy a sorszám a naplózási minta része lesz, és tudta, hogy “ha üres naplózási üzenet jelenik meg a fájl 67.sorában (az authenticate() metódusban), ez azt jelenti, hogy a felhasználó hitelesített”. Ezenkívül az osztálynév, a metódusnév és/vagy a sorszám naplózása komoly hatással van a teljesítményre.

a naplózási keretek valamivel fejlettebb tulajdonsága a leképezett diagnosztikai kontextus fogalma. Az MDC egyszerűen egy szál-helyi alapon kezelt térkép. Bármelyik kulcs-érték párt elhelyezheti ebben a térképen, és azóta minden naplózási utasítás, amelyet ebből a szálból adtak ki, ezt az értéket csatolja a minta részeként.

7) Log metódus argumentumok és visszatérési értékek

amikor hibát talál a fejlesztés során, általában egy hibakeresőt futtat, amely megpróbálja felkutatni a lehetséges okot. Most képzelje el egy ideig, hogy nem használhat hibakeresőt. Például azért, mert a hiba néhány nappal ezelőtt egy ügyfélkörben jelent meg, és minden, ami van, naplók. Képes lennél bármit is találni bennük?

ha követed az egyes metódusok bemeneteinek és kimeneteinek (argumentumok és visszatérési értékek) naplózásának egyszerű szabályát, akkor már nincs szükséged hibakeresőre. Természetesen ésszerűnek kell lennie, de minden olyan módszer, amely: hozzáfér a külső rendszerhez (beleértve az adatbázist is), blokkokhoz, várakozásokhoz stb. figyelembe kell venni. Egyszerűen kövesse ezt a mintát:

public String printDocument(Document doc, Mode mode) { log.debug("Entering printDocument(doc={}, mode={})", doc, mode); String id = //Lengthy printing operation log.debug("Leaving printDocument(): {}", id); return id;}

mivel mind a metódushívás kezdetét, mind végét naplózod, manuálisan felfedezheted a nem hatékony kódot, sőt észlelheted a holtpontok és az éhezés lehetséges okait is – egyszerűen a “belépés” után, a megfelelő “kilépés”nélkül. Ha a módszereinek értelmes nevei vannak, a naplók olvasása öröm lenne. Ezenkívül sokkal egyszerűbb elemezni, hogy mi ment rosszul, mivel minden lépésnél pontosan tudja, mi lett feldolgozva. Akár egy egyszerű AOP szempontot is használhat a módszerek széles skálájának naplózásához a kódban. Ez csökkenti a kód duplikációját, de légy óvatos, mivel hatalmas mennyiségű hatalmas naplóhoz vezethet.

érdemes megfontolni a hibakeresési vagy nyomkövetési szinteket, amelyek a legalkalmasabbak az ilyen típusú naplókhoz. És ha felfedezi, hogy néhány metódust túl gyakran hívnak meg, és a naplózás károsíthatja a teljesítményt, egyszerűen csökkentse az adott osztály naplózási szintjét, vagy távolítsa el teljesen a naplót (talán csak egyet hagy az egész metódus meghívására?) De mindig jobb, ha túl sok van, nem pedig túl kevés naplózási utasítás. A naplózási utasításokat ugyanolyan tisztelettel kezelje, mint az egységteszteket – a kódot naplózási rutinokkal kell lefedni, mint az egységteszteket. A rendszer egyetlen része sem maradhat naplózás nélkül. Ne feledje, hogy néha a gördülő naplók megfigyelése az egyetlen módja annak megállapítására, hogy az alkalmazás megfelelően működik-e, vagy örökre lefagy.

8) vigyázzon a külső rendszerekre

ez az előző tipp speciális esete: ha külső rendszerrel kommunikál, fontolja meg az alkalmazásból származó összes adat naplózását. Pont. Az integráció nehéz feladat, és két alkalmazás (két különböző gyártó, környezet, technológiai stack és csapat) közötti problémák diagnosztizálása különösen nehéz. Nemrégiben például felfedeztük, hogy a teljes üzenetek tartalmának naplózása, beleértve a SOAP-ot és a HTTP-fejléceket az Apache CXF webszolgáltatásokban, rendkívül hasznos az integráció és a rendszer tesztelése során.

ez egy nagy overhead, és ha a teljesítmény egy probléma, akkor mindig tiltsa naplózás. De mi értelme van egy gyors, de törött alkalmazásnak, amelyet senki sem tud megjavítani? Legyen különösen óvatos a külső rendszerekkel való integráció során, és készüljön fel ennek a költségnek a megfizetésére. Ha szerencséd van, és az összes integrációt egy ESB kezeli, akkor valószínűleg a busz a legjobb hely minden bejövő kérés és válasz naplózására. Lásd például öszvérek log-komponens.

néha a külső rendszerekkel kicserélt információ mennyisége elfogadhatatlanná teszi mindent naplózni. Másrészt a tesztelés során és egy rövid ideig a gyártás során (például amikor valami baj történik) szeretnénk mindent naplókba menteni, és készen állunk a teljesítményköltségek megfizetésére. Ezt a naplózási szintek gondos használatával lehet elérni. Vessen egy pillantást a következő idiómára:

Collection<Integer> requestIds = //...if(log.isDebugEnabled()) log.debug("Processing ids: {}", requestIds);else log.info("Processing ids size: {}", requestIds.size());

ha ez az adott naplózó hibakeresési üzenetek naplózására van konfigurálva, akkor a requestIds gyűjtemény teljes tartalmát kinyomtatja. De ha információs üzenetek nyomtatására van konfigurálva, akkor csak a gyűjtemény mérete kerül kiadásra. Ha kíváncsi vagy, miért felejtettem el az isInfoEnabled () feltételt, menj vissza a 2.tipphez. Érdemes megemlíteni, hogy a requestIds gyűjtemény ebben az esetben nem lehet null. Bár helyesen lesz naplózva null-ként, ha a hibakeresés engedélyezve van, de a big fat NullPointerException dobásra kerül, ha a logger INFO-ra van konfigurálva. Ne feledje, a leckét a mellékhatások tip # 4?

9) A kivételek helyes naplózása

először is kerülje a kivételek naplózását, hagyja, hogy a keretrendszer vagy a tároló (bármi is legyen) tegye meg helyetted. Van egy, ekhem, kivétel ez alól a szabály alól: ha néhány távoli szolgáltatásból (rmi, EJB remote session bean stb.), amely képes sorosítani a kivételeket, győződjön meg arról, hogy mindegyik elérhető az ügyfél számára (az API része). Ellenkező esetben az ügyfél kap NoClassDefFoundError: SomeFancyException helyett a” true ” hiba.

a naplózási kivételek a naplózás egyik legfontosabb szerepe, de sok programozó hajlamos a naplózást a kivétel kezelésének egyik módjaként kezelni. Néha visszaadják az alapértelmezett értéket (jellemzően null, 0 vagy üres karakterlánc), és úgy tesznek, mintha semmi sem történt volna. Máskor először naplózzák a kivételt, majd becsomagolják, majd visszadobják:

log.error("IO exception", e);throw new MyCustomException(e);

ez a konstrukció Majdnem mindig ugyanazt a veremkövetést kétszer nyomtatja ki, mert valami végül elkapja a MyCustomException-t, és naplózza az okát. Jelentkezzen be, vagy tekerje be és dobja vissza (ami előnyösebb), soha ne mindkettőt, különben a naplók zavaróak lesznek.

de ha valóban szeretnénk naplózni a kivételt? Valamilyen okból (mert nem olvasunk API-kat és dokumentációt?), az általam látott naplózási nyilatkozatok körülbelül fele téves. Gyors kvíz, az alábbiak közül melyik naplózási utasítás fogja megfelelően naplózni az NPE-t?

try { Integer x = null; ++x;} catch (Exception e) { log.error(e); //A log.error(e, e); //B log.error("" + e); //C log.error(e.toString()); //D log.error(e.getMessage()); //E log.error(null, e); //F log.error("", e); //G log.error("{}", e); //H log.error("{}", e.getMessage()); //I log.error("Error reading configuration file: " + e); //J log.error("Error reading configuration file: " + e.getMessage()); //K log.error("Error reading configuration file", e); //L}

meglepő módon csak G és lehetőleg L helyes! A és B nem is fordít SLF4J-ben, mások eldobják a verem nyomait és/vagy helytelen üzeneteket nyomtatnak. Például az E nem fog kinyomtatni semmit, mivel az NPE általában nem ad kivételüzenetet, és a verem nyomkövetése sem lesz kinyomtatva. Ne feledje, hogy az első érv mindig a szöveges üzenet, írjon valamit a probléma természetéről. Ne tartalmazzon kivétel üzenetet, mivel az automatikusan kinyomtatásra kerül a naplóbejegyzés után, a verem nyomkövetése előtt. De ahhoz, hogy ezt megtehesse, magát a kivételt kell átadnia második érvként.

10) naplók könnyen olvasható, könnyen elemezhető

a vevők két csoportja különösen érdekli az alkalmazás naplóit: az emberek (lehet, hogy nem értenek egyet, de a programozók is ebbe a csoportba tartoznak) és a számítógépek (általában a rendszergazdák által írt shell szkriptek). A naplóknak mindkét csoport számára alkalmasnak kell lenniük. Ha valaki a hátad mögül nézi az alkalmazás naplóit, látja (forrás Wikipedia):

akkor valószínűleg nem követte a tippjeimet. A naplóknak olvashatónak és könnyen érthetőnek kell lenniük, csakúgy, mint a kódnak.

másrészt, ha az alkalmazás fél GB naplót készít óránként, sem ember, sem grafikus szövegszerkesztő nem fogja tudni teljesen elolvasni őket. Ez az, ahol a régi iskola grep, sed és awk jól jönnek. Ha lehetséges, próbálja meg úgy írni a naplózási üzeneteket, hogy azok mind az emberek, mind a számítógépek számára érthetőek legyenek, pl. kerülje a számok formázását, használjon olyan mintákat, amelyek reguláris kifejezésekkel könnyen felismerhetők stb. Ha ez nem lehetséges, nyomtassa ki az adatokat két formátumban:

log.debug("Request TTL set to: {} ({})", new Date(ttl), ttl);// Request TTL set to: Wed Apr 28 20:14:12 CEST 2010 (1272478452437)final String duration = DurationFormatUtils.formatDurationWords(durationMillis, true, true);log.info("Importing took: {}ms ({})", durationMillis, duration);//Importing took: 123456789ms (1 day 10 hours 17 minutes 36 seconds)

a számítógépek értékelni fogják az” ms after 1970 epoch “időformátumot, míg az emberek örömmel látják az” 1 nap 10 óra 17 perc 36 másodperc ” szöveget. Btw vessen egy pillantást DurationFormatUtils, szép eszköz.

ez mind srácok, egy “naplózási tippek extravagáns” JCP partnerünktől, Tomasz Nurkiewicz-től. Ne felejtsd el megosztani!

Kapcsolódó Cikkek :
  • naplózás Antipatterns
  • a dolgok minden programozó tudnia kell
  • törvények szoftver tervezés
  • Java legjobb gyakorlatok – Vektor vs ArrayList vs HashSet
  • Java legjobb gyakorlatok – DateFormat egy többszálú környezetben
  • Java legjobb gyakorlatok – nagy teljesítményű Sorosítás
  • Java legjobb gyakorlatok – string performance and exact string matching
kapcsolódó kivonatok :
  • hozzon létre egyéni Formázót A Logger handler számára
  • napló módszerhívás
  • szűrő beállítása A Logger handleren
  • állítsa be a Formázót A Logger handlerhez
  • naplózási szempont példa
  • Log4j Maven példa
  • hibernált naplózás konfiguráció – slf4j + log4j és logback