10 Tips for Proper Application Logging

our latest JCP partner, Tomasz Nurkiewicz, has submitted a number of posts describing the basic principles of right application logging. Löysin ne varsin mielenkiintoinen, joten päätin koota ne tiiviimmässä muodossa ja esittää ne teille. Joten, tässä ovat hänen ehdotuksia puhdas ja hyödyllinen lokit: (huomautus: Alkuperäisiä julkaisuja on hieman muokattu luettavuuden parantamiseksi)

1) Käytä työhön sopivia työkaluja

monet ohjelmoijat näyttävät unohtavan, kuinka tärkeää on sovelluksen käyttäytymisen kirjaaminen ja sen nykyinen toiminta. Kun joku laittaa:

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

onneksi jossain koodissa hän ei luultavasti ymmärrä sovelluslokien merkitystä huollon, virityksen ja vikojen tunnistamisen aikana. Hyvien tukkien arvon aliarvioiminen on kauhea virhe.

mielestäni SLF4J on paras käytettävissä oleva kirjausrajapinta, lähinnä suuren kuviokorviketuen ansiosta:

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

log4j: ssä sinun täytyisi käyttää:

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

tämä on paitsi pidempi ja vähemmän luettava, mutta myös tehoton, koska laaja käyttö merkkijono concatenation. SLF4J lisää mukavan {} – korvausominaisuuden. Koska myös merkkijonojen yhdistämistä vältetään ja tostringiä() ei kutsuta, jos kirjauslauseke suodatetaan, isdebugenabledia() ei enää tarvita. Btw, Oletko huomannut yhden lainausmerkit noin suodatin merkkijono parametri?

SLF4J on pelkkä julkisivu. Toteutuksena suosittelisin jo mainostettua Logback-kehystä vakiintuneen Log4J: n sijaan. siinä on monia mielenkiintoisia ominaisuuksia ja päinvastoin kuin Log4J: ssä, sitä kehitetään aktiivisesti.

viimeinen suositeltu työkalu on Perf4J. lainatakseni heidän mottoaan:

Perf4J on System.currentimemillis () kuten log4j on järjestelmään.ulos.println ()

olen lisännyt Perf4J: n yhteen olemassa olevaan sovellukseen raskaalla kuormituksella ja nähnyt sen toiminnassa muutamassa muussa. Sekä järjestelmänvalvojat että yrityskäyttäjät olivat vaikuttuneita tämän yksinkertaisen apuohjelman tuottamista mukavista kuvioista. Myös suorituskykyvirheet huomasimme alta aikayksikön. Perf4J itse ansaitsee oman artikkelin, mutta nyt vain tarkistaa niiden Kehittäjä opas.

huomaa lisäksi, että Ceki Gülcü (log4j -, SLF4J-ja Logback-projektien perustaja) ehdotti yksinkertaista tapaa päästä eroon commons-loging-riippuvuudesta (katso hänen kommenttinsa).

2) Älä unohda, kirjaustasot ovat olemassa sinua varten

joka kerta, kun teet kirjausilmoituksen, mietit tarkkaan, mikä kirjaustaso on sopiva tällaiseen tapahtumaan, eikö niin? Jotenkin 90% ohjelmoijista ei koskaan kiinnitä huomiota kirjaustasoihin, yksinkertaisesti kirjaamalla kaikki samalle tasolle, tyypillisesti INFO tai DEBUG. Miksi? Puunkorjuukehyksillä on kaksi merkittävää etua järjestelmään verrattuna.ulos., eli luokat ja tasot. Molemmat voit valikoivasti suodattaa kirjaus lausekkeet pysyvästi tai vain diagnostiikan aikaa. Jos et todellakaan näe eroa, tulosta tämä taulukko ja katso sitä joka kerta, kun alat kirjoittaa ” loki.”sinun IDEASSASI:

virhe – jotain hirveän väärää oli tapahtunut, joka on tutkittava välittömästi. Mikään järjestelmä ei voi sietää tällä tasolla kirjattuja kohteita. Esimerkki: NPE, tietokanta ei ole käytettävissä, tehtävän kriittistä käyttötapausta ei voida jatkaa.

varoita-prosessia voidaan jatkaa, mutta ole erityisen varovainen. Oikeastaan olen aina halunnut olla kaksi tasoa täällä: yksi ilmeinen ongelmia, joissa työ-around olemassa (esim.: ”Nykyinen tieto ei ole käytettävissä välimuistissa olevien arvojen avulla”) ja toiseksi (nimi: huomio) mahdollisten ongelmien ja ehdotusten varalta. Esimerkki:” sovellus käynnissä kehitystilassa ”tai”hallintakonsoli ei ole suojattu salasanalla”. Sovellus sietää varoitusviestejä, mutta ne on aina perusteltava ja tutkittava.

INFO-tärkeä liiketoimintaprosessi on päättynyt. Ideaalimaailmassa ylläpitäjän tai kehittyneen käyttäjän pitäisi pystyä ymmärtämään INFOVIESTEJÄ ja selvittää nopeasti, mitä sovellus tekee. Esimerkiksi Jos sovellus on kyse varauksen lentoliput, pitäisi olla vain yksi INFO lausuma jokaista lippua sanomalla ”varattu lippu alkaen”. INFOVIESTIN muu määritelmä: jokainen toiminto, joka muuttaa sovelluksen tilaa merkittävästi (tietokannan päivitys, ulkoinen järjestelmäpyyntö).

DEBUG-kehittäjien juttuja. Keskustelen myöhemmin siitä, millaisia tietoja kannattaa kirjata.

TRACE – erittäin yksityiskohtaista tietoa, joka on tarkoitettu ainoastaan kehittämiseen. Saatat pitää jäljitysviestejä lyhyen aikaa käyttöönoton jälkeen tuotantoympäristössä, mutta käsitellä näitä lokilausekkeita väliaikaisina, jotka pitäisi tai voitaisiin sammuttaa lopulta. VIANJÄLJITYKSEN ja jäljityksen välinen ero on kaikkein vaikein, mutta jos laitat kirjauslausekkeen ja poistat sen sen jälkeen, kun ominaisuus on kehitetty ja testattu, sen pitäisi luultavasti olla JÄLJITETASOLLA.

yllä oleva lista on vain ehdotus, voit luoda oman ohjesarjan, jota noudattaa, mutta on tärkeää, että on joitakin. Kokemukseni on, että aina kaikki on kirjautunut ilman suodatusta (ainakin sovelluskoodista), mutta kyky suodattaa lokit nopeasti ja poimia tiedot asianmukaisella yksityiskohtaisella tasolla saattaa olla hengenpelastaja.

viimeinen mainitsemisen arvoinen asia on pahamaineinen on*käytössä () – ehto. Jotkut laittavat sen ennen jokaista kirjausilmoitusta:

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

henkilökohtaisesti, mielestäni tämä idiomi on vain sotkua, että olisi vältettävä. Suorituskyvyn parantaminen (erityisesti käytettäessä SLF4J kuvio korvaaminen käsitelty aiemmin) tuntuu merkityksetön ja haisee ennenaikainen optimointi. Huomaatko myös päällekkäisyydet? On hyvin harvinaisia tapauksia, kun ottaa nimenomainen ehto on perusteltua – kun voimme todistaa, että rakentaminen kirjaus viesti on kallista. Muissa tilanteissa, vain tehdä työsi kirjautumalla ja anna loging framework tehdä työnsä (suodatus).

3)tiedätkö mitä kirjaat?

joka kerta, kun annat kirjausilmoituksen, ota hetki aikaa ja katso, mitä lokitiedostoon tarkalleen tulee. Lue lokit jälkeenpäin ja paikalla epämuodostuneita lauseita. Ensinnäkin, vältä NPEs näin:

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

oletko aivan varma, ettei pyyntö ole tyhjä?

toinen sudenkuoppa on hakkuukokoelmat. Jos hait kokoelman verkkotunnuksia tietokannasta käyttämällä Hibernate ja huolimattomasti kirjata ne kuten täällä:

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

SLF4J kutsuu tostringiä () vasta, kun lauseke on oikeasti painettu, mikä on varsin mukavaa. Mutta jos se tekee … pois muistin virhe, N + 1 Valitse ongelma, thread nälkään (kirjaaminen on synkroninen!), laiska alustus poikkeus, lokit varastointi täynnä täysin-jokainen näistä saattaa esiintyä.

on paljon parempi idea kirjata esimerkiksi vain verkkotunnusten tunnukset (tai jopa vain kokoelman koko). Mutta kokoelma tunnuksia kun ottaa kokoelma esineitä ottaa getId () menetelmä on uskomattoman vaikeaa ja hankalaa Java. Groovy on suuri leviäminen operaattori (käyttäjät*. id), Java voimme jäljitellä sitä Commons Beanutils kirjasto:

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

jossa collect () – menetelmä voidaan toteuttaa seuraavasti:

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

viimeinen mainittava asia on epäasianmukainen toteutus tai käyttö toString(). Luo ensin toString () jokaiselle luokalle, joka näkyy missä tahansa kirjausilmoituksissa, mieluiten käyttämällä Tostringbuilderia (mutta ei sen heijastavaa vastinetta). Toiseksi, varo taulukoita ja ei-tyypillisiä kokoelmia. Matriiseissa ja eräissä oudoissa kokoelmissa ei välttämättä ole toteutettu toString () – nimitystä, jossa jokaisen kohteen toString() kutsutaan. Käytä Arrays #deepToString JDK utility method. Ja lukea lokit usein paikalla väärin muotoillut viestit.

4) vältä haittavaikutuksia

Kirjauslauseilla ei pitäisi olla mitään tai vain vähän vaikutusta sovelluksen käyttäytymiseen. Äskettäin ystäväni antoi esimerkin järjestelmästä, joka heitti Horrorates’ LazyInitializationException vain ajettaessa jossain tietyssä ympäristössä. Kuten Olet luultavasti arvannut asiayhteydestä, jokin lokilauseke aiheutti laiskan alustetun kokoelman lataamisen, kun istunto liitettiin. Tässä ympäristössä hakkuutasoja nostettiin eikä keruuta enää alustettu. Kuinka kauan kestäisi löytää bugi tietämättä tätä asiayhteyttä?

toinen haittavaikutus on levityksen hidastuminen. Nopea vastaus: jos kirjaat liikaa tai käytät väärin toString() ja/tai merkkijono concatenation, kirjaaminen on suorituskyvyn sivuvaikutus. Kuinka iso? No, olen nähnyt palvelimen uudelleenkäynnistyksen 15 minuutin välein, koska Lanka nälkään aiheuttama liiallinen kirjaaminen. Nyt tämä on sivuvaikutus! Kokemukseni mukaan muutama sata MiB on luultavasti yläraja sille, kuinka paljon levylle voi kirjautua tunnissa.

totta kai jos loki-ilmoitus itsessään epäonnistuu ja aiheuttaa liiketoimintaprosessin päättymisen poikkeuksen vuoksi, on tämä myös valtava sivuvaikutus. Olen nähnyt tällaisen Konstruktion välttää tämän:

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

tämä on todellinen koodi, mutta tehkää maailmasta parempi paikka, älkääkä koskaan tehkö sitä.

5) suppea ja kuvaileva

jokaisen kirjauslausekkeen tulee sisältää sekä tietoja että kuvausta. Harkitsehan seuraavia esimerkkejä:

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

minkä lokin haluat nähdä, kun vianmääritys tuntemattomassa sovelluksessa tapahtuu? Uskokaa minua, kaikki edellä mainitut esimerkit ovat lähes yhtä yleisiä. Toinen anti-kuvio:

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

oliko se niin vaikeaa sisällyttää sinulle todellinen viestin tyyppi, viestin tunnus, jne. varoitusnarussa? Jokin meni pieleen, mutta mitä? Mikä oli asiayhteys?

kolmas Anti-kuvio on ”taika-loki”. Tosielämän esimerkki: useimmat ohjelmoijat joukkue tiesi, että 3 ampersands seuraa huutomerkki, jonka jälkeen hash, jonka jälkeen pseudorandom aakkosnumeerinen merkkijono loki tarkoittaa ”viesti XYZ id vastaanotettu”. Kukaan vaivautunut muuttamaan loki, yksinkertaisesti joku osui näppäimistö ja valitsi joitakin ainutlaatuisia ”&&&!# ”string, jotta se löytyy helposti itse.

tämän seurauksena koko lokitiedosto näyttää satunnaiselta merkkisarjalta. Joku saattaa jopa pitää kyseistä tiedostoa kelvollisena Perl-ohjelmana. Sen sijaan lokitiedoston tulisi olla luettava, puhdas ja kuvaileva. Älä käytä maagisia numeroita, lokiarvoja, numeroita, tunnuksia ja sisällytä niiden asiayhteyttä. Näytä käsiteltävät tiedot ja näytä niiden merkitys. Näytä, mitä ohjelma todella tekee. Hyvät lokit voivat toimia itse sovelluskoodin hyvänä dokumentaationa.

mainitsinko olla kirjaamatta salasanoja ja mitään henkilökohtaisia tietoja? Älä!

6) Viritä kuviosi

Kirjauskuvio on loistava työkalu, joka läpinäkyvästi lisää mielekkään kontekstin jokaiseen tekemääsi kirjauskuvioon. Mutta sinun täytyy harkita hyvin tarkkaan, mitä tietoja sisällyttää kaavaasi. Esimerkiksi kirjauspäivä, jolloin lokit rullaavat tunnin välein, on turha, koska päivämäärä sisältyy jo lokitiedoston nimeen. Päinvastoin, ilman kirjaamista säiettä nimi et voi seurata mitään prosessia käyttäen Lokit Kun kaksi kierteet toimivat samanaikaisesti-lokit limittyvät. Tämä voisi olla hieno yksisäikeisissä sovelluksissa-jotka ovat lähes kuolleita nykyään.

kokemukseni mukaan ihanteellisen kirjauskuvion tulisi sisältää (tietenkin paitsi itse Kirjautunut viesti): nykyinen aika (ilman päivämäärää, millisekunnin tarkkuus), kirjaustaso, langan nimi, yksinkertainen metsurin nimi (ei täysin pätevä) ja viesti. Logback se on jotain:

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

tiedostonimeä, luokkanimeä ja rivinumeroa ei pidä koskaan lisätä, vaikka se on hyvin houkuttelevaa. Olen jopa nähnyt tyhjiä loki lausuntoja annetaan koodi:

log.info("");

koska ohjelmoija oletti, että rivinumero tulee olemaan osa kirjauskuviota ja hän tiesi, että ”jos tyhjä kirjausviesti näkyy tiedoston 67.rivillä (authenticate () – menetelmällä), se tarkoittaa, että käyttäjä on todennettu”. Lisäksi kirjausluokan nimi, menetelmän nimi ja/tai rivinumero vaikuttaa vakavasti suorituskykyyn.

kirjauskehysten hieman kehittyneempi ominaisuus on kartoitetun diagnostisen Kontekstin käsite. MDC on yksinkertaisesti kartta, jota hallinnoidaan säiepohjaisesti. Tähän karttaan voi laittaa minkä tahansa avainarvoparin, ja sen jälkeen jokainen tästä langasta annettu kirjaus on liitetty tähän arvoon osana kaavaa.

7) Log metodin argumentit ja palautusarvot

kun löydät vian kehityksen aikana, suoritat tyypillisesti vianetsintätyökalun, joka yrittää jäljittää mahdollisen syyn. Nyt kuvitella jonkin aikaa, että et voi käyttää debuggeri. Esimerkiksi siksi, että vika ilmeni asiakasympäristössä muutama päivä sitten ja kaikki mitä sinulla on on lokit. Löytyisikö niistä mitään?

jos noudatat yksinkertaista sääntöä, jonka mukaan jokaisen menetelmän syöte ja tuotos (argumentit ja palautusarvot) kirjataan ylös, et tarvitse enää edes debuggeria. Tietenkin, sinun täytyy olla kohtuullinen, mutta jokainen menetelmä, että: käyttää ulkoista järjestelmää (mukaan lukien tietokanta), lohkot, odottaa, jne. tämä on otettava huomioon. Seuraa vain tätä mallia:

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;}

koska kirjaat sekä metodin alun että lopun, voit manuaalisesti löytää tehottoman koodin ja jopa havaita mahdolliset umpikujien ja nälkiintymisen syyt – yksinkertaisesti huolehtimalla ”syöttämisestä” ilman vastaavaa ”poistumista”. Jos metodeillasi on mielekkäät nimet, lokkien lukeminen olisi mukavaa. Myös sen analysointi, mikä meni pieleen, on paljon yksinkertaisempaa, koska jokaisessa vaiheessa tiedät tarkalleen, mitä on käsitelty. Voit jopa käyttää yksinkertaista AOP-aspektia kirjataksesi monenlaisia menetelmiä koodiisi. Tämä vähentää koodin päällekkäisyyttä, mutta ole varovainen, koska se voi johtaa valtavaan määrään valtavia lokeja.

kannattaa pitää DEBUG-tai TRACE-tasoja sopivimpina tämäntyyppisille lokeille. Ja jos huomaat jonkin menetelmän kutsutaan liian usein ja kirjaaminen voi vahingoittaa suorituskykyä, yksinkertaisesti vähentää kirjaamisen taso kyseisen luokan tai poistaa loki kokonaan (ehkä jättäen vain yksi koko menetelmän kutsuminen?) Mutta on aina parempi, että on liian paljon kuin liian vähän kirjausilmoituksia. Käsittele kirjausilmoituksia samalla kunnioituksella kuin yksikkötestejä – koodisi tulee peittää kirjausrutiineilla kuten yksikkötesteillä. Mikään osa järjestelmästä ei saa jäädä ilman lokia ollenkaan. Muista, joskus tarkkailu lokit liikkuvan ohi on ainoa tapa kertoa, onko sovellus toimii oikein tai roikkuu ikuisesti.

8) varo ulkoisia järjestelmiä

tämä on edellisen vinkin erikoistapaus: jos kommunikoit ulkoisen järjestelmän kanssa, harkitse jokaisen hakemuksestasi tulevan ja sisään pääsevän tiedon kirjaamista. Aika. Integrointi on kova työ ja ongelmien diagnosointi kahden sovelluksen välillä (ajattele kahta eri toimittajaa, ympäristöjä, teknologiapinoja ja tiimejä) on erityisen vaikeaa. Viime aikoina olemme esimerkiksi havainneet, että koko viestien sisällön, mukaan lukien SOAP-ja HTTP-otsikot Apache CXF-verkkopalveluissa, kirjaaminen on erittäin hyödyllistä integraation ja järjestelmätestauksen aikana.

tämä on iso yleiskustannus, ja jos suorituskyky on ongelma, voit aina poistaa kirjaamisen käytöstä. Mutta mitä hyötyä on nopeasta, mutta rikkinäisestä sovelluksesta, jota kukaan ei voi korjata? Ole erityisen varovainen integroidessasi ulkoisiin järjestelmiin ja valmistaudu maksamaan nämä kustannukset. Jos olet onnekas ja ESB hoitaa kaiken integraatiosi, bussi on luultavasti paras paikka kirjata jokainen saapuva pyyntö ja vastaus. Katso esimerkiksi muulien lokikomponentti.

joskus ulkoisten järjestelmien kanssa vaihdetun tiedon määrä tekee kaiken kirjaamisen mahdottomaksi. Toisaalta testauksen aikana ja lyhyen aikaa tuotannossa (esimerkiksi silloin, kun jotain tapahtuu väärin) haluaisimme, että kaikki on tallennettu tukkiin ja olemme valmiita maksamaan suorituskykykuluja. Tämä voidaan saavuttaa käyttämällä huolellisesti hakkuutasot. Vain katsomaan seuraavia idiomi:

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

jos tämä tietty loggeri on määritetty kirjaamaan DEBUG-viestit, se tulostaa koko requestids-kokoelman sisällön. Mutta jos se on määritetty tulostamaan INFO viestejä,vain koko kokoelma lähetetään. Jos mietit, miksi unohdin isInfoEnabled () kunnossa, mene takaisin kärki #2. Yksi asia mainitsemisen arvoinen on, että requestIds kokoelma ei pitäisi olla nolla tässä tapauksessa. Vaikka se kirjataan oikein null, jos DEBUG on käytössä, mutta big fat NullPointerException heitetään, jos logger on määritetty INFO. Muistatko läksyni sivuvaikutuksista tip #4: ssä?

9) Tukkipoikkeukset kunnolla

ensinnäkin, vältä hakkuupoikkeuksia, anna puitteesi tai konttisi (mikä se sitten onkin) tehdä se puolestasi. On yksi, ekhem, poikkeus tähän sääntöön: jos heität poikkeuksia jostain etäpalvelusta (RMI, EJB remote session bean jne.), joka pystyy serializing poikkeuksia, varmista, että ne kaikki ovat asiakkaan saatavilla (ovat osa API). Muuten asiakas saa NoClassDefFoundError: SomeFancyException sijaan ”totta” virhe.

Kirjaamispoikkeukset on yksi tärkeimmistä tehtävistä kirjaamisessa ylipäätään, mutta monilla ohjelmoijilla on tapana käsitellä kirjaamista poikkeuksen käsittelytapana. He joskus palata oletusarvo (tyypillisesti null, 0 tai tyhjä merkkijono) ja teeskennellä, että mitään ei ole tapahtunut. Muina aikoina he ensin kirjaavat poikkeuksen ja sitten käärivät sen ja heittävät sen takaisin.:

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

tämä konstruktio tulostaa lähes aina saman pinon jäljen kaksi kertaa, koska jokin lopulta nappaa MyCustomException ja kirjaa sen syyn. Loki, tai kääri ja heittää takaisin (mikä on parempi), ei koskaan molemmat, muuten lokit on sekava.

mutta jos todella haluamme kirjata poikkeuksen? Jostain syystä (koska emme lue sovellusliittymiä ja dokumentteja?), noin puolet näkemistäni hakkuuilmoituksista on vääriä. Quick quiz, Mikä seuraavista lokilauseista kirjaa NPE: n oikein?

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}

yllättäen vain G ja mieluiten L ovat oikein! A ja B eivät edes käännä slf4j: ssä, toiset hylkäävät pinon jälkiä ja / tai tulostavat virheellisiä viestejä. Esimerkiksi E ei tulosta mitään, koska NPE ei yleensä tarjoa poikkeussanomaa eikä pinon jäljitystä myöskään tulosteta. Muista, että ensimmäinen argumentti on aina tekstiviesti, kirjoita jotain ongelman luonteesta. Älä sisällytä poikkeussanomaa, koska se tulostetaan automaattisesti lokitiedotteen jälkeen ennen pinon jäljitystä. Mutta jotta voit tehdä niin, sinun on läpäistävä poikkeus itse toisena argumenttina.

10) lokit helppolukuisia, helposti jäsenneltäviä

on olemassa kaksi vastaanottajaryhmää, jotka ovat erityisen kiinnostuneita sovelluslokeistasi: ihmiset (saatat olla eri mieltä, mutta ohjelmoijat kuuluvat myös tähän ryhmään) ja tietokoneet (tyypillisesti järjestelmän ylläpitäjien kirjoittamat komentotulkkikomennot). Lokit pitäisi soveltua molemmat näistä ryhmistä. Jos joku etsii selän takaa hakemuslokeja näkee (lähde Wikipedia):

sitten et varmaankaan ole noudattanut neuvojani. Lokien pitäisi olla luettavia ja helposti ymmärrettäviä aivan kuten koodin pitäisi.

toisaalta, jos sovelluksesi tuottaa puoli gigatavua lokeja tunnissa, yksikään ihminen tai yksikään graafinen tekstieditori ei koskaan onnistu lukemaan niitä kokonaan. Tässä vanhan koulukunnan grep, sed ja awk tulevat tarpeeseen. Jos se on mahdollista, yritä kirjoittaa lokiviestejä siten, että sekä ihmiset että tietokoneet voisivat ymmärtää niitä, esim. vältä numeroiden muotoilua, käytä kuvioita, jotka voidaan helposti tunnistaa säännöllisistä lausekkeista jne. Jos se ei ole mahdollista, tulosta tiedot kahdessa muodossa:

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)

Tietokoneet arvostavat ”ms jälkeen 1970 epoch” aikamuoto, kun taas ihmiset olisivat iloisia nähdessään” 1 päivä 10 tuntia 17 minuuttia 36 sekuntia ” tekstiä. Btw katsomaan Kestoformatils, mukava työkalu.

that ’s all guys, a” logging tips extravaganza ” from our JCP partner, Tomasz Nurkiewicz. Älä unohda jakaa!

Aiheeseen Liittyviä Artikkeleita :
  • Logging Antipatterns
  • Things Every Programmer Should Know
  • laws of Software Design
  • Java Best Practices – Vector vs ArrayList vs HashSet
  • Java Best Practices – DateFormat in a Multhreading Environment
  • Java Best Practices – High performance sarjanumerointi
  • Java best practices – string performance and exact string matching
related Snippets :
  • Create custom Formatter for Logger handler
  • Log method call
  • Set filter on Logger handler
  • Set Formatter for Logger handler
  • Logging aspect example
  • Log4j Maven example
  • hibernate – kirjauskokoonpano-slf4j + log4j ja logback