La oss snakke om logging, skal vi? Arnold over her bærer en gigantisk logg føles som en passende intro til denne artikkelen der vi skal snakke om populære Node.js logging rammeverk.
hvis du skriver noen form for lang levende søknad, er detaljert logging viktig for å oppdage problemer og feilsøking. Uten logger vil du ha få måter å fortelle hvordan søknaden din oppfører seg, er det feil, hva er ytelsen som, gjør det noe i det hele tatt, eller er det bare å falle over hver annen forespørsel når du ikke ser på den.
Krav
lar identifisere noen krav som vi kan bruke til å sette rammene mot hverandre. Noen av disse kravene er ganske trivielle, andre er ikke så mye.
- Tidsstempel hver logglinje. Denne er ganske selvforklarende-du bør kunne fortelle når hver loggoppføring oppstod.
- Logging format bør være lett fordøyelig av mennesker så vel som maskiner.
- Tillater flere konfigurerbare destinasjonsstrømmer. For eksempel kan du skrive sporingslogger til en fil, men når det oppstår en feil, skriv til samme fil, deretter til feilfil og send en e-post samtidig.
Basert på disse kravene (og popularitet) er det to logging rammeverk For Node.js verdt å sjekke ut, spesielt:
- Bunyan Av Trent Mick.Winston Er en del Av Flatiron-rammeverket og sponset av nodejitstu.
konsoll
før Vi kommer Til Bunyan og Winston, la oss se på vår gamle venn console
. Den mest rudimentære typen logging du kan gjøre er å bruke console.log
og console.error
metoder. Dette er bedre enn ingenting, men neppe den beste løsningen. Konsoll skriver til HENHOLDSVIS stdout og STDERR. Det er en veldig interessant advarsel å vite når det gjelder console
metoder I Node.js.
konsollfunksjonene er synkrone når målet er en terminal eller en fil (for å unngå tapte meldinger ved tidlig utgang) og asynkron når det er et rør (for å unngå blokkering i lange perioder).
Det vil si i følgende eksempel at stdout ikke blokkerer mens stderr blokkerer:
$ node script.js 2> error.log | tee info.log
dette er i utgangspunktet en» rull din egen » logging tilnærming. Det er fullt manuell, du må komme opp med ditt eget format og i utgangspunktet administrere alt selv. Dette er tidkrevende, utsatt for feil, og du vil sannsynligvis fokusere på applikasjonsfunksjonene dine i stedet. Tatt i betraktning at det er open source logging biblioteker der ute som er aktivt vedlikeholdt, er dette ikke verdt innsatsen hvis du prøver å fokusere på å levere funksjoner.
Winston
En av De mest populære Nodene.js logging rammer Er Winston. Den er designet for å være et enkelt og universelt loggbibliotek med støtte for flere transporter (en transport i Winstons verden er egentlig en lagringsenhet, for eksempel hvor loggene dine blir lagret). Hver forekomst Av En Winston logger kan ha flere transporter konfigurert på ulike logging nivåer.
Installasjon
npm install winston
Bruk
Den mest grunnleggende Winston-bruken består av å kalle standardforekomsten som eksporteres frawinston
modulen.
var winston = require('winston');winston.log('info', 'Hello distributed log files!');winston.info('Hello again distributed logs');
Formatering
personlig er jeg litt forvirret av mangelen på detaljer i standardformateren. Det er ingen tidsstempel, maskinnavn ELLER prosess-ID, og utdataformatet er mildt egnet for maskinparsing. Når det er sagt at du kan få all informasjon ut selv med bare litt ekstra arbeid.
winston.info('Hello world!', {timestamp: Date.now(), pid: process.pid});
Produserer følgende utgang, som er mer informativ, men likevel ikke veldig egnet for maskinparsing.
info: Hello world! timestamp=1402286804314, pid=80481
til Slutt girlog
metoden samme strenginterpoleringsmetoder somutil.format
, for eksempel:
winston.log('info', 'test message %d', 123);
transportører
winston kan konfigureres Via konstruktøralternativer eller eksponert metode som er veldig grundig dokumentert på github-siden. Det meste av konfigurasjonen dreier seg vanligvis om ulike transporter. Ut Av boksen Winston kommer med konsoll og fil basert transporter og hvis du har en titt på npmjs.org du vil se at det er fellesskapsmoduler for stort sett alt tenkelig, alt Fra MongoDB til kommersielle tredjepartsplattformer.En av de mer bemerkelsesverdige transportørene etter Min mening er winston-irc av Nathan Zadoks som du kan bruke til å logge feil PÅ lagets IRC-kanal. Jeg kan se dette kommer i veldig hendig.
winston.add(require('winston-irc'), { host: 'irc.somewhere.net', nick: 'logger', pass: 'hunter2', channels: { '#logs': true, 'sysadmin': }});
Flere Loggere
når søknaden din begynner å vokse, er det stor sjanse for at du vil ha flere loggere med forskjellige konfigurasjoner der hver logger er ansvarlig for et annet funksjonsområde (eller kategori). Winston støtter det på to måter: gjennom winston.loggers
og forekomster av winston.Container
. Faktisk er winston.loggers
bare en forhåndsdefinert forekomst av winston.Container
:
winston.loggers.add('category1', {console: { ... }, file: { ... }});winston.loggers.add('category2', {irc: { ... }, file: { ... }});
Mer h3 dette er mest grunnleggende winston-bruk, men det er ganske mange andre funksjoner, spesielt:
- Profilering
- String interpolering
- Spørring og streaming
- Håndtering exeptions
Bunyan
Illustrasjon Av Brendan Corris
Bunyan av Trent Mick er en annen logging rammeverk som jeg tror bør vurderes. Bunyan tar en litt annen tilnærming til logging enn Winston gjør sitt oppdrag å gi strukturerte, maskinlesbare logger som førsteklasses borgere. Som et resultat er en loggpost fra Bunyan en linje med JSON.stringify
utdata med noen vanlige navn for de nødvendige og vanlige feltene for en loggpost.
Installasjon
npm install bunyan
Bruk
var bunyan = require('bunyan');var log = bunyan.createLogger({name: 'myapp'});log.info('hi');log.warn({lang: 'fr'}, 'au revoir');
Som vil produsere følgende utgang:
Som du kan se, ut av boksen bunyan er Ikke veldig menneskelig vennlig, men de fleste moderne loggsystemer forstår json-format innfødt, noe som betyr at det er lite å gjøre her for å mate loggene andre steder for lagring og behandling. Som standard er det ganske mye metadata som følger med hver melding, for eksempel tidsstempel, PROSESS-ID, vertsnavn og programnavn.selvfølgelig finner ikke oss mennesker dette veldig fordøyelig og for å adressere at det er et bunyan
cli-verktøy som tar INN JSON via STDIN. Her er det samme eksemplet som sendes gjennom bunyan
:
node example.js | bunyan
Produserer følgende utdata:
INFO: myapp/13372 on pwony-2: hi WARN: myapp/13372 on pwony-2: au revoir (lang=fr)
hovedfordelen her er at du ikke trenger å konfigurere noe for utviklingsmiljø, alt du trenger å gjøre er å pipe tilbunyan
. Sjekk Ut GitHub-siden for mer dokumentasjon på cli-verktøyet.
JSON
En av de viktigste forskjellene Mellom Bunyan og Winston er At Bunyan fungerer veldig bra når du vil logge komplekse sammenhenger og objekter. La oss se på denne linjen og dens utgang fra eksemplet ovenfor:
Du kan se at {lang: 'fr'}
ble slått sammen med hovedloggen og au revoir
ble msg
. Nå bilde noe sånt som dette:
log.info(user, 'registered');log.info({user: user}, 'registered');
Som produserer:
Eller når piped gjennombunyan
:
skjønnheten i denne tilnærmingen vil bli klart når du ser på barn loggere.
Barneloggere
Bunyan har et konsept av barneloggere, som gjør det mulig å spesialisere en logger for en underkomponent av søknaden din, dvs. for å opprette en ny logger med flere bundne felt som skal inkluderes i loggpostene. En barnelogger opprettes med log.child(...)
. Dette kommer i utrolig hendig hvis du vil ha scoped loggere for ulike komponenter i systemet, forespørsler, eller bare ren funksjon samtaler. La oss se på noen kode.
Tenk deg at du vil bære request ID gjennom alle logglinjer for en gitt forespørsel, slik at du kan knytte dem alle sammen.
req.log
loggeren vil alltid beholde sin kontekst overført tillog.child()
funksjonen og slå den sammen med alle påfølgende samtaler, slik at utgangen vil se slik ut:
{"name":"myapp","hostname":"pwony-2","pid":14837,"level":30,"reqId":"XXXX-XX-XXXX","user":"[email protected]","time":"2014-05-26T18:27:43.530Z","v":0}
serializers
to problemer oppstår når bunyan prøver å stringify hele objekter:
- sirkelreferanser. Winston er litt smartere her og oppdager sirkulære referanser når de oppstår (men resultatutgangen
$ref=$
er ikke veldig nyttig). - Uønsket støy. Det føles for meg at fordi objekter er første klasse i det er mye lettere å komme inn i en vane med å bare dumpe alt inn i loggen.
For å hjelpe til med å håndtere begge deler, Har Bunyan et konsept av serializer som i utgangspunktet er transformasjonsfunksjoner som lar deg omfang ned ofte passerte objekter til bare de feltene du er interessert i:
prøver nå å logge req
objektet vil bare inkludere de tre feltene vi er interessert i.
Strømmer
Strømmer I Bunyan er det samme som transportører i Winston – det er en måte å sende loggene dine andre steder for visning og lagring. Bunyan bruker En Skrivbar Stream grensesnitt med noen ekstra attributter. En Bunyan logger forekomst har en eller flere strømmer og er spesifisert med streams
alternativ:
var log = bunyan.createLogger({ name: "foo", streams: });
Mer
Her er noen flere bemerkelsesverdige ting å utforske I Bunyan:
- Runtime log snooping via dtrace støtte
- logg posten felt
som å velge?
Winston og Bunyan er begge veldig modne og etablerte loggrammer og er veldig mye på nivå med funksjoner. Winston har mye fellesskapsstøtte med ulike loggingsmoduler. Bunyan gjør det enkelt ut av boksen for å analysere logger, men etterlater forbruk opp brukeren (vanligvis syslog drain fungerer ganske bra her). Jeg føler alt kommer ned til preferanse og hvor lett det er å integrere med stabelen din.
- Hva kommer til neste Node utgivelse? Les om åtte spennende Nye Node v0.12-funksjoner og hvordan du får mest mulig ut av dem, fra forfatterne selv.
- Klar til å utvikle Apier I Node.js og få dem koblet til dataene dine? Sjekk Ut Noden.js LoopBack API rammeverk. Vi har gjort det enkelt å komme i gang enten lokalt eller på din favoritt sky, med en enkel npm installere.
- Trenger du opplæring og sertifisering For Node? Lær mer om Både de private og åpne Alternativene StrongLoop tilbyr.