laten we praten over loggen, zullen we? Arnold hier draagt een gigantische log voelt als een passende intro van dit artikel waarin we gaan praten over populaire Node.js logging frameworks.
Als u enige vorm van lang leven applicatie aan het schrijven bent, is gedetailleerde logging van het grootste belang om problemen te spotten en debuggen. Zonder logs zou je weinig manieren hebben om te vertellen hoe je applicatie zich gedraagt, zijn er fouten, hoe de prestaties eruit zien, doet het iets of valt het gewoon over elk ander verzoek als je er niet naar kijkt.
vereisten
laten we een paar vereisten identificeren die we kunnen gebruiken om de frameworks tegen elkaar te plaatsen. Sommige van deze eisen zijn vrij triviaal, anderen zijn niet zo veel.
- tijdstempel op elke logregel. Deze is vrij zelfverklarend – je zou in staat moeten zijn om te zien wanneer elke log vermelding zich heeft voorgedaan.
- het Logboekformaat moet zowel door mensen als door machines goed verteerbaar zijn.
- staat meerdere configureerbare doelstreams toe. U kunt bijvoorbeeld trace logs naar één bestand schrijven, maar wanneer een fout wordt aangetroffen, schrijft u naar hetzelfde bestand, vervolgens naar het foutbestand en verzendt u tegelijkertijd een e-mail.
op basis van deze vereisten (en populariteit) zijn er twee logging frameworks voor Node.js de moeite waard, in het bijzonder:
- Bunyan door Trent Mick.Winston maakt deel uit van het Flatiron framework en wordt gesponsord door nodejitstu.
console
voordat we bij Bunyan en Winston komen, laten we eens kijken naar onze oude vriend console
. Het meest rudimentaire type logging dat je zou kunnen doen is het gebruik vanconsole.log
enconsole.error
methoden. Dit is beter dan niets, maar nauwelijks de beste oplossing. Console schrijft naar respectievelijk STDOUT en STDERR. Er is een zeer interessant voorbehoud om te weten als het gaat om console
methoden in Node.js.
De consolefuncties zijn synchroon wanneer de bestemming een terminal of een bestand is (om verloren berichten te voorkomen in geval van voortijdig afsluiten) en asynchroon wanneer het een pipe is (om blokkering voor lange tijd te voorkomen).
dat wil zeggen dat in het volgende voorbeeld stdout niet blokkeert terwijl stderr blokkeert:
$ node script.js 2> error.log | tee info.log
Dit is in principe een “roll your own” logging aanpak. Het is volledig handmatig, je moet komen met uw eigen formaat en in principe alles zelf beheren. Dit is tijdrovend, vatbaar voor fouten en u wilt zich waarschijnlijk richten op uw applicatie-functies in plaats daarvan. Gezien het feit dat er open source logging bibliotheken die er zijn die actief worden onderhouden, Dit is niet de moeite waard als je probeert te concentreren op het leveren van functies.
Winston
een van de meest populaire knooppunten.js logging frameworks is Winston. Het is ontworpen om een eenvoudige en universele logging bibliotheek met ondersteuning voor meerdere transporten (een transport in Winston ‘ s wereld is in wezen een opslagapparaat, bijvoorbeeld waar uw logs uiteindelijk worden opgeslagen). Elke instantie van een Winston logger kan meerdere transporten geconfigureerd op verschillende logging niveaus.
installatie
npm install winston
gebruik
het meest basale gebruik van Winston bestaat uit het aanroepen van de standaard instantie die wordt geëxporteerd vanuit de
winston
module.var winston = require('winston');winston.log('info', 'Hello distributed log files!');winston.info('Hello again distributed logs');
het bovenstaande is hetzelfde als:
beide voorbeelden produceren de volgende uitvoer:
info: Hello distributed log files!info: Hello again distributed logs
opmaak
persoonlijk ik ben een beetje verbaasd door het gebrek aan details in de standaard Formatter. Er is geen tijdstempel, machine naam of proces-ID en de output formaat is mild geschikt voor machine parsing. Dat gezegd hebbende, kunt u alle informatie uit jezelf met slechts een beetje extra werk.
winston.info('Hello world!', {timestamp: Date.now(), pid: process.pid});
produceert de volgende uitvoer, die informeler is, maar nog steeds niet erg geschikt voor het ontleden van machines.
info: Hello world! timestamp=1402286804314, pid=80481
de
log
methode biedt dezelfde string interpolatie-methoden zoalsutil.format
, bijvoorbeeld:winston.log('info', 'test message %d', 123);
Vervoerders
Winston kan worden geconfigureerd via de constructor opties of blootgesteld methode die zeer grondig gedocumenteerd op de GitHub pagina. Het grootste deel van de configuratie draait meestal om verschillende transporten. Out of the box Winston wordt geleverd met console en bestand gebaseerde transporten en als je een kijkje op npmjs.org u zult zien dat er community modules voor vrijwel alles denkbaar, variërend van MongoDB tot commerciële platforms van derden.
een van de meest opvallende transporters naar mijn mening is winston-irc van Nathan Zadoks die je kunt gebruiken om fouten in te loggen op het IRC-kanaal van je team. Ik zie dit van pas komen.
winston.add(require('winston-irc'), { host: 'irc.somewhere.net', nick: 'logger', pass: 'hunter2', channels: { '#logs': true, 'sysadmin': }});
meerdere Loggers
zodra uw toepassing begint te groeien, is de kans groot dat u meerdere loggers met verschillende configuraties wilt hebben waarbij elke logger verantwoordelijk is voor een ander functiegebied (of categorie). Winston ondersteunt dat op twee manieren: door
winston.loggers
en instanties vanwinston.Container
. In feite iswinston.loggers
slechts een vooraf gedefinieerde instantie vanwinston.Container
:winston.loggers.add('category1', {console: { ... }, file: { ... }});winston.loggers.add('category2', {irc: { ... }, file: { ... }});
nu uw loggers zijn geconfigureerd, kunt u Winston in elk bestand in uw toepassing nodig hebben en toegang krijgen tot deze vooraf geconfigureerde loggers:
var category1 = winston.loggers.get('category1');category1.info('logging from your IoC container-based logger');
meer
Dit is het meest basale gebruik van Winston, maar er zijn nogal wat andere functies, met name:
- profilering
- String interpolatie
- opvragen en streamen
- Handling exeptions
Bunyan
Illustratie door Brendan Corris
Bunyan door Trent Mick is een ander logboekraamwerk dat naar mijn mening moet worden overwogen. Bunyan neemt een iets andere benadering van logging dan Winston het maken van haar missie om gestructureerde, machine leesbare logs als eerste klas burgers. Als gevolg hiervan is een log record van Bunyan één regel van
JSON.stringify
uitvoer met enkele algemene namen voor de vereiste en gemeenschappelijke velden voor een log record.installatie
npm install bunyan
gebruik
var bunyan = require('bunyan');var log = bunyan.createLogger({name: 'myapp'});log.info('hi');log.warn({lang: 'fr'}, 'au revoir');
die de volgende uitvoer zal produceren:
box Bunyan is niet erg mensvriendelijk, maar de meeste moderne logging systemen begrijpen JSON-formaat native, wat betekent dat er weinig te doen is hier om de logs elders te voeden voor opslag en verwerking. Standaard is er nogal wat metagegevens opgenomen bij elk bericht, zoals tijdstempel, proces-ID, hostnaam en naam van de toepassing.
natuurlijk vinden wij mensen dit niet erg verteerbaar en om aan te pakken is er een
bunyan
CLI tool die JSON via STDIN opneemt. Hier is hetzelfde voorbeeld dat doorbunyan
:node example.js | bunyan
produceert de volgende uitvoer:
INFO: myapp/13372 on pwony-2: hi WARN: myapp/13372 on pwony-2: au revoir (lang=fr)
het belangrijkste voordeel hier is dat u niets opnieuw hoeft te configureren voor de ontwikkelomgeving, het enige wat u hoeft te doen is pipe naar
bunyan
. Bekijk de GitHub pagina voor meer documentatie over de CLI tool.JSON
een van de belangrijkste verschillen tussen Bunyan en Winston is dat Bunyan echt goed werkt wanneer je complexe contexten en objecten wilt loggen. Laten we eens kijken naar deze lijn en de uitvoer van het bovenstaande voorbeeld:
u kunt zien dat
{lang: 'fr'}
werd samengevoegd met het hoofdlogobject enau revoir
werdmsg
. Stel je nu iets als dit voor:log.info(user, 'registered');log.info({user: user}, 'registered');
welke produceert:
of wanneer doorgesluisd
bunyan
:De schoonheid van deze aanpak zal duidelijk worden als je naar child loggers kijkt.
Child Loggers
Bunyan heeft een concept van child loggers, wat het mogelijk maakt om een logger te specialiseren voor een subcomponent van uw toepassing, d.w.z. een nieuwe logger maken met extra gebonden velden die worden opgenomen in de logrecords. Een dochterlogger wordt aangemaakt met
log.child(...)
. Dit komt in ongelooflijk handig als u wilt hebben scoped loggers voor verschillende componenten in uw systeem, Verzoeken, of gewoon functie oproepen. Laten we eens wat code bekijken.stel je voor dat je verzoek-ID door alle logregels voor een bepaald verzoek wilt laten lopen, zodat je ze allemaal aan elkaar kunt koppelen.
de
req.log
logger zal altijd zijn context doorgeven aan delog.child()
functie en samenvoegen met alle volgende aanroepen, zodat de uitvoer er ongeveer zo uit zou zien:{"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
twee problemen doen zich voor wanneer Bunyan gehele objecten probeert te stringifyen:
- cirkelreferenties. Winston is hier een beetje slimmer en detecteert cirkelreferenties wanneer ze voorkomen (echter de resultaatuitvoer
$ref=$
is niet erg nuttig).- ongewenste ruis. Het voelt voor mij dat omdat objecten eersteklas zijn, het veel gemakkelijker is om de gewoonte te krijgen om alles gewoon in het logboek te dumpen.
om met beide zaken om te gaan, heeft Bunyan een concept van serializer dat in principe transformatiefuncties zijn die je toelaten om objecten te benaderen die gewoonlijk worden doorgegeven aan alleen de velden waarin je geïnteresseerd bent:
Probeer nu
req
object zou alleen de drie velden bevatten waarin we geïnteresseerd zijn.Streams
Streams in Bunyan zijn hetzelfde als transporters in Winston – het is een manier om uw logs elders te sturen voor weergave-en opslagdoeleinden. Bunyan gebruikt een beschrijfbare Stream interface met een aantal extra attributen. Een Bunyan logger instantie heeft een of meer streams en zijn opgegeven met de
streams
optie:var log = bunyan.createLogger({ name: "foo", streams: });
meer
Hier zijn nog een paar opmerkelijke dingen om te verkennen in Bunyan:
- runtime log snooping via Dtrace ondersteuning
- Log Record velden
welke te kiezen?
Winston en Bunyan zijn beide zeer volwassen en gevestigde logging frameworks en zijn zeer vergelijkbaar in termen van functies. Winston heeft veel steun van de Gemeenschap met verschillende logging modules. Bunyan maakt het gemakkelijk uit de doos om logs te ontleden, maar laat de consumptie van de gebruiker (over het algemeen syslog drain werkt vrij goed hier). Ik voel dat het allemaal komt neer op de voorkeur en hoe gemakkelijk het is om te integreren met uw stack.
- Wat komt er naar de volgende Node release? Lees over acht spannende nieuwe Node v0. 12 Functies en hoe u het meeste van hen te maken, van de auteurs zelf.
- klaar om API ‘ s te ontwikkelen in Node.js en krijgen ze verbonden met uw gegevens? Kijk eens naar het knooppunt.js LoopBack API framework. We hebben het gemakkelijk gemaakt om lokaal of op uw favoriete cloud aan de slag te gaan, met een eenvoudige NPM-installatie.
- opleiding en certificering nodig voor knooppunt? Meer informatie over zowel de private als open opties StrongLoop biedt.