Confrontando il nodo Winston e Bunyan.js Logging

Parliamo di registrazione, dovremmo? Arnold qui portando un registro gigante si sente come un appropriato intro a questo articolo in cui ci accingiamo a parlare di nodo popolare.framework di registrazione js.

Se stai scrivendo qualsiasi tipo di applicazione long living, la registrazione dettagliata è fondamentale per individuare i problemi e il debug. Senza i registri avresti pochi modi per dire come si comporta la tua applicazione, ci sono errori, come sono le prestazioni, sta facendo qualcosa o sta semplicemente cadendo su ogni altra richiesta quando non la stai guardando.

Requisiti

Consente di identificare alcuni requisiti che possiamo utilizzare per mettere i framework l’uno contro l’altro. Alcuni di questi requisiti sono piuttosto banali, altri non sono così tanto.

  1. Timestamp ogni riga di registro. Questo è abbastanza autoesplicativo-dovresti essere in grado di dire quando si è verificata ogni voce di registro.
  2. Il formato di registrazione dovrebbe essere facilmente digeribile dagli esseri umani e dalle macchine.
  3. Consente più flussi di destinazione configurabili. Ad esempio, potresti scrivere registri di traccia in un file, ma quando si verifica un errore, scrivere nello stesso file, quindi nel file di errore e inviare un’e-mail allo stesso tempo.

Sulla base di questi requisiti (e popolarità) ci sono due framework di registrazione per Node.js vale la pena di verificare, in particolare:

  • Bunyan di Trent Mick.
  • Winston fa parte del framework Flatiron e sponsorizzato da nodejitstu.

console

Prima di arrivare a Bunyan e Winston, diamo un’occhiata al nostro vecchio amicoconsole. Il tipo di registrazione più rudimentale che potresti fare è usare i metodiconsole.log econsole.error. Questo è meglio di niente, ma difficilmente la soluzione migliore. La console scrive rispettivamente su STDOUT e STDERR. C’è un avvertimento molto interessante da sapere quando si tratta di console metodi nel nodo.js.

Le funzioni della console sono sincrone quando la destinazione è un terminale o un file (per evitare la perdita di messaggi in caso di uscita prematura) e asincrone quando si tratta di una pipe (per evitare il blocco per lunghi periodi di tempo).

Cioè, nel seguente esempio, stdout non blocca mentre stderr sta bloccando:

$ node script.js 2> error.log | tee info.log

Questo è fondamentalmente un approccio di registrazione “roll your own”. È completamente manuale, devi inventare il tuo formato e fondamentalmente gestire tutto da solo. Questo richiede tempo, è soggetto a errori e probabilmente si desidera concentrarsi sulle funzionalità dell’applicazione. Considerando che ci sono librerie di registrazione open source là fuori che vengono mantenute attivamente, questo non vale la pena se si sta cercando di concentrarsi sulla fornitura di funzionalità.

Winston

Uno dei Nodi più popolari.js logging frameworks è Winston. È progettato per essere una libreria di registrazione semplice e universale con supporto per più trasporti (un trasporto nel mondo di Winston è essenzialmente un dispositivo di archiviazione, ad esempio dove i log finiscono per essere archiviati). Ogni istanza di un logger Winston può avere più trasporti configurati a diversi livelli di registrazione.

Installazione

npm install winston

Utilizzo

L’utilizzo più semplice di Winston consiste nel chiamare l’istanza predefinita esportata dal modulo winston.

var winston = require('winston');winston.log('info', 'Hello distributed log files!');winston.info('Hello again distributed logs');

di cui sopra è la stessa:

Entrambi gli esempi produrrà il seguente output:

info: Hello distributed log files!info: Hello again distributed logs

Formattazione

Personalmente sono un po ‘ perplesso dalla mancanza di dettagli in il formatter. Non esiste un timestamp, un nome macchina o un ID processo e il formato di output è leggermente adatto per l’analisi della macchina. Detto questo, puoi ottenere tutte le informazioni da solo con un po ‘ di lavoro extra.

winston.info('Hello world!', {timestamp: Date.now(), pid: process.pid});

Produce il seguente output, che è più informativo, ma ancora non molto adatto per l’analisi della macchina.

info: Hello world! timestamp=1402286804314, pid=80481

Infine, log metodo fornisce la stessa stringa metodi di interpolazione come util.format, per esempio:

winston.log('info', 'test message %d', 123);

Trasportatori

Winston potrebbero essere configurato tramite il costruttore di opzioni o metodo esposto molto accuratamente documentato sulla pagina di GitHub. La maggior parte della configurazione ruota tipicamente attorno a vari trasporti. Out of the box Winston viene fornito con console e trasporti basati su file e se si dispone di uno sguardo su npmjs.org vedrete che ci sono moduli di comunità per praticamente tutto ciò che si possa immaginare che vanno da MongoDB a piattaforme commerciali di terze parti.

Uno dei trasportatori più importanti a mio parere è winston-irc di Nathan Zadoks che puoi usare per registrare gli errori sul canale IRC del tuo team. Lo vedo molto utile.

winston.add(require('winston-irc'), { host: 'irc.somewhere.net', nick: 'logger', pass: 'hunter2', channels: { '#logs': true, 'sysadmin': }});

Più logger

Una volta che l’applicazione inizia a crescere, è probabile che si desidera avere più logger con configurazioni diverse in cui ogni logger è responsabile di una diversa area di funzionalità (o categoria). Winston lo supporta in due modi: attraversowinston.loggers e le istanze diwinston.Container. Infatti, winston.loggers è solo un’istanza predefinita di winston.Container:

winston.loggers.add('category1', {console: { ... }, file: { ... }});winston.loggers.add('category2', {irc: { ... }, file: { ... }});

Ora che i logger sono configurati, è possibile richiedere Winston in qualsiasi file di applicazione e accedere a questi pre-configurato logger:

var category1 = winston.loggers.get('category1');category1.info('logging from your IoC container-based logger');

Più

Questo è il più fondamentale di Winston utilizzo, ma ci sono un paio di altre caratteristiche, più in particolare:

  • Profilazione
  • String interpolazione
  • l’esecuzione di Query e streaming
  • Gestione exeptions

Bunyan

Illustrazione di Brendan Corris

Bunyan da Trento Mick è un altro di registrazione quadro che credo debba essere considerato. Bunyan ha un approccio leggermente diverso alla registrazione rispetto a Winston che ha la sua missione di fornire registri strutturati e leggibili dalla macchina come cittadini di prima classe. Di conseguenza, un record di registro da Bunyan è una riga diJSON.stringify output con alcuni nomi comuni per i campi necessari e comuni per un record di registro.

Installazione

npm install bunyan

Utilizzo

var bunyan = require('bunyan');var log = bunyan.createLogger({name: 'myapp'});log.info('hi');log.warn({lang: 'fr'}, 'au revoir');

Che produrrà il seguente output:

Come si può vedere, out of the box Bunyan non è molto amichevole umano, tuttavia la maggior parte dei moderni sistemi di registrazione capire il formato JSON in modo nativo, il che significa che c’è poco da fare qui per alimentare i registri altrove per l’archiviazione e l’elaborazione. Per impostazione predefinita, c’è un bel po ‘ di metadati inclusi in ogni messaggio, come timestamp, ID processo, nome host e nome dell’applicazione.

Naturalmente, noi umani, non lo troviamo molto digeribile e per affrontare che c’è uno strumento CLIbunyan a cui prende in JSON via STDIN. Ecco lo stesso esempio trasmesso tramite bunyan:

node example.js | bunyan

Produce il seguente output:

 INFO: myapp/13372 on pwony-2: hi WARN: myapp/13372 on pwony-2: au revoir (lang=fr)

Il vantaggio principale qui è che non è necessario riconfigurare nulla per l’ambiente di sviluppo, tutto ciò che devi fare è pipe to bunyan. Controlla la pagina GitHub per ulteriori documentazione sullo strumento CLI.

JSON

Una delle differenze chiave tra Bunyan e Winston è che Bunyan funziona molto bene quando si desidera registrare contesti e oggetti complessi. Diamo un’occhiata a questa linea e al suo output dall’esempio sopra:

Puoi vedere che {lang: 'fr'} è stato fuso con l’oggetto di registro principale e au revoir è diventato msg. Ora immagina qualcosa del genere:

log.info(user, 'registered');log.info({user: user}, 'registered');

Che produce:

O quando viene trasmesso attraverso bunyan:

La bellezza di questo approccio diventerà chiara quando guardiamo i logger figli.

Child Logger

Bunyan ha un concetto di child logger, che consente di specializzare un logger per un sottocomponente dell’applicazione, ad es. per creare un nuovo logger con campi associati aggiuntivi che verranno inclusi nei suoi record di registro. Viene creato un logger figlio con log.child(...). Questo è incredibilmente utile se si desidera avere logger con ambito per diversi componenti nel sistema, richieste o semplici chiamate di funzione. Diamo un’occhiata a qualche codice.

Immagina di voler portare l’ID della richiesta attraverso tutte le righe di registro per una determinata richiesta in modo da poterle legare tutte insieme.

req.log logger, manterrà sempre il suo contesto passati al log.child() funzione e fondersi con tutte le chiamate successive, in modo che l’output dovrebbe essere simile a questo:

{"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}

Serializzatori

Due i problemi sorgono quando Bunyan cerca di stringify intero oggetti:

  1. riferimenti Circolari. Winston è un po ‘ più intelligente qui e rileva i riferimenti circolari quando si verificano (tuttavia l’output del risultato $ref=$ non è molto utile).
  2. Rumore indesiderato. Mi sembra che, poiché gli oggetti sono di prima classe, sia molto più facile prendere l’abitudine di scaricare tutto nel registro.

Per aiutare a gestire entrambi, Bunyan ha un concetto di serializzatore che sono fondamentalmente funzioni di trasformazione che consentono di ridurre gli oggetti comunemente passati solo ai campi che ti interessano:

Ora cercando di registrarereq l’oggetto includerebbe solo i tre campi a cui siamo interessati.

Stream

I flussi di Bunyan sono la stessa cosa dei trasportatori di Winston: è un modo per inviare i log altrove per scopi di visualizzazione e archiviazione. Bunyan utilizza un’interfaccia di flusso scrivibile con alcuni attributi aggiuntivi. Un Bunyan logger istanza ha uno o più flussi e specificati con il streams opzioni:

var log = bunyan.createLogger({ name: "foo", streams: });

Più

Qui ci sono alcuni più cose notevoli per esplorare in Bunyan:

  • Runtime registro snooping via Dtrace supporto
  • Log campi di record

Quale scegliere?

Winston e Bunyan sono entrambi framework di registrazione molto maturi e consolidati e sono molto alla pari in termini di funzionalità. Winston ha un sacco di supporto della comunità con vari moduli di registrazione. Bunyan rende facile l’analisi dei registri, ma lascia il consumo all’utente (generalmente syslog drain funziona abbastanza bene qui). Sento che tutto si riduce alle preferenze e quanto sia facile integrarsi con il tuo stack.

  • Cosa sta arrivando alla prossima release del nodo? Leggi otto interessanti nuove funzionalità di Node v0.12 e come sfruttarle al massimo, dagli stessi autori.
  • Pronto a sviluppare API nel nodo.js e collegarli ai tuoi dati? Controlla il Nodo.struttura API di LoopBack js. Abbiamo reso facile iniziare localmente o sul tuo cloud preferito, con una semplice installazione npm.
  • Hai bisogno di formazione e certificazione per Node? Scopri di più su entrambe le opzioni private e aperte StrongLoop offre.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.