Comparando el nodo Winston y Bunyan.js Logging

Hablemos de registro, ¿de acuerdo? Arnold, que lleva un tronco gigante, se siente como una introducción apropiada a este artículo en el que vamos a hablar del Nodo popular.marcos de registro de js.

Si está escribiendo cualquier tipo de aplicación de larga duración, el registro detallado es primordial para detectar problemas y depurar. Sin registros, tendría pocas formas de saber cómo se comporta su aplicación, si hay errores, cómo es el rendimiento, si hace algo o simplemente se cae sobre cualquier otra solicitud cuando no la está mirando.

Requisitos

Identifiquemos algunos requisitos que podemos usar para enfrentar los marcos entre sí. Algunos de estos requisitos son bastante triviales, otros no lo son tanto.

  1. Marca de tiempo en cada línea de registro. Este es bastante autoexplicativo: debería ser capaz de saber cuándo ocurrió cada entrada de registro.
  2. El formato de registro debe ser fácilmente digerible tanto por los humanos como por las máquinas.
  3. Permite múltiples flujos de destino configurables. Por ejemplo, es posible que esté escribiendo registros de seguimiento en un archivo, pero cuando se encuentre un error, escriba en el mismo archivo, luego en el archivo de errores y envíe un correo electrónico al mismo tiempo.

En función de estos requisitos (y popularidad), hay dos marcos de registro para Node.js que vale la pena revisar, en particular:

  • Bunyan de Trent Mick.
  • Winston es parte del framework Flatiron y está patrocinado por nodejitstu.

consola

Antes de llegar a Bunyan y Winston, veamos a nuestro viejo amigo console. El tipo de registro más rudimentario que podría hacer es usar los métodos console.log y console.error. Esto es mejor que nada, pero difícilmente la mejor solución. La consola escribe en STDOUT y STDERR respectivamente. Hay una advertencia muy interesante para saber cuando se trata de métodos console en el nodo.js.

Las funciones de la consola son síncronas cuando el destino es un terminal o un archivo (para evitar mensajes perdidos en caso de salida prematura) y asíncronas cuando se trata de una tubería (para evitar el bloqueo durante largos períodos de tiempo).

es decir, en el ejemplo siguiente, stdout es no-bloqueo mientras stderr es el bloqueo:

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

Este es básicamente un «rollo de su propio» registro de enfoque. Es totalmente manual, tienes que crear tu propio formato y básicamente administrar todo tú mismo. Esto consume mucho tiempo, es propenso a errores y probablemente desee centrarse en las características de su aplicación en su lugar. Teniendo en cuenta que hay bibliotecas de registro de código abierto que se mantienen activamente, esto no vale la pena si está tratando de centrarse en la entrega de características.

Winston

Uno de los más populares Nodo.marcos de registro de js es Winston. Está diseñado para ser una biblioteca de registro simple y universal con soporte para múltiples transportes (un transporte en el mundo de Winston es esencialmente un dispositivo de almacenamiento, por ejemplo, donde se almacenan sus registros). Cada instancia de un registrador Winston puede tener varios transportes configurados en diferentes niveles de registro.

Instalación

npm install winston

Uso

El más básico Winston uso consiste en llamar a la instancia predeterminada que se exporta desde el winston módulo.

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

El de arriba es el mismo como:

Ambos ejemplos, se producirá el siguiente resultado:

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

Formato

Personalmente estoy un poco perplejo por la falta de detalles en el valor predeterminado del formateador. No hay marca de tiempo, nombre de máquina o ID de proceso y el formato de salida es ligeramente adecuado para el análisis de la máquina. Dicho esto, puede obtener toda la información usted mismo con solo un poco de trabajo adicional.

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

Produce el siguiente resultado, que es más informativo, pero todavía no muy adecuada para analizar el equipo.

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

por último, el log método proporciona los mismos métodos de interpolación como util.format, por ejemplo:

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

Transportadores

Winston podría ser configurados mediante el constructor de opciones o método expuesto, que están muy bien documentados en la página de GitHub. La mayor parte de la configuración suele girar en torno a varios transportes. Fuera de la caja, Winston viene con transportes basados en consola y archivos y si echa un vistazo a npmjs.org verás que hay módulos de comunidad para casi todo lo imaginable, desde MongoDB hasta plataformas comerciales de terceros.

Uno de los transportadores más notables en mi opinión es winston-irc de Nathan Zadoks, que puedes usar para registrar errores en el canal IRC de tu equipo. Puedo ver esto muy útil.

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

Varios registradores

Una vez que su aplicación comience a crecer, es probable que desee tener varios registradores con configuraciones diferentes donde cada registrador es responsable de un área de características (o categoría) diferente. Winston lo soporta de dos maneras: a través de winston.loggerse instancias de winston.Container. De hecho, winston.loggers es sólo una instancia predefinida de winston.Container:

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

Ahora que su registradores están configurados, se puede requerir Winston en cualquier archivo en la aplicación y acceder a estas pre-configurado registradores:

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

Más

Este es el más básico de Winston uso, pero hay muy pocas otras características, la más notable:

  • Perfiles
  • interpolación de cadenas
  • Consultar y streaming
  • el Manejo de excepciones

Bunyan

Ilustración por Brendan Corris

Bunyan por Trent Mick es otro marco de registros que creo que deberían ser considerados. Bunyan adopta un enfoque ligeramente diferente al de Winston, haciendo su misión de proporcionar registros estructurados y legibles por máquina como ciudadanos de primera clase. Como resultado, un registro de registro de Bunyan es una línea de salida JSON.stringify con algunos nombres comunes para los campos necesarios y comunes para un registro de registro.

Instalación

npm install bunyan

Uso

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

Que producirá la siguiente salida:

Como puede ver, fuera de la caja, Bunyan no es muy amigable con los humanos, sin embargo, la mayoría de los sistemas de registro modernos entienden el formato JSON de forma nativa, lo que significa que hay poco que hacer aquí para alimentar los registros en otros lugares para su almacenamiento y procesamiento. De forma predeterminada, hay bastantes metadatos incluidos con cada mensaje, como marca de tiempo, ID de proceso, nombre de host y nombre de aplicación.

Por supuesto, nosotros, los humanos, no encontramos esto muy digerible y para abordar que hay una herramienta de CLI bunyan que toma JSON a través de STDIN. Aquí está el mismo ejemplo se canaliza a través de bunyan:

node example.js | bunyan

Produce el siguiente resultado:

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

La principal ventaja aquí es que usted no necesita volver a configurar nada para el entorno de desarrollo, todo lo que tienes que hacer es tubo a bunyan. Consulta la página de GitHub para obtener más documentación sobre la herramienta CLI.

JSON

Una de las diferencias clave entre Bunyan y Winston es que Bunyan funciona muy bien cuando se desea registrar contextos y objetos complejos. Veamos esta línea y su salida del ejemplo anterior:

Puede ver que {lang: 'fr'} se fusionó con el objeto de registro principal y au revoir se convirtió en msg. Ahora, imagine algo como esto:

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

Que produce:

O cuando se canaliza a través de bunyan:

La belleza de este enfoque se hará evidente cuando nos fijamos en el niño madereros.

Registradores de niños

Bunyan tiene un concepto de registradores de niños, que permite especializar un registrador para un subcomponente de su aplicación, p. ej. para crear un nuevo registrador con campos enlazados adicionales que se incluirán en sus registros de registro. Se crea un registrador hijo con log.child(...). Esto es increíblemente útil si desea tener registradores de alcance para diferentes componentes en su sistema, solicitudes o simplemente llamadas a funciones simples. Veamos un poco de código.

Imagine que desea llevar el ID de solicitud a todas las líneas de registro de una solicitud determinada para que pueda unirlas todas.

El registrador req.log siempre mantendrá su contexto pasado a la función log.child() y lo fusionará con todas las llamadas posteriores, de modo que la salida se verá algo así:

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

Serializadores

Dos problemas surgen cuando Bunyan intenta encadenar objetos enteros:

  1. Referencias circulares. Winston es un poco más inteligente aquí y detecta referencias circulares cuando ocurren (sin embargo, la salida de resultados $ref=$ no es muy útil).
  2. Ruido no deseado. Me parece que debido a que los objetos son de primera clase, es mucho más fácil adquirir el hábito de tirar todo en el tronco.

Para ayudar a lidiar con ambos, Bunyan tiene un concepto de serializador que son básicamente funciones de transformación que le permiten escalar objetos comúnmente pasados solo a los campos que le interesan:

Ahora tratando de registrar req el objeto solo incluiría los tres campos que nos interesan.

Los flujos

Los flujos en Bunyan son lo mismo que los transportadores en Winston: es una forma de enviar sus registros a otro lugar para fines de visualización y almacenamiento. Bunyan utiliza una interfaz de flujo de escritura con algunos atributos adicionales. Una instancia de Bunyan logger tiene una o más transmisiones y se especifican con la opción streams:

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

More

Aquí hay algunas cosas más notables para explorar en Bunyan:

  • Registro de tiempo de ejecución snooping a través de soporte de Dtrace
  • Campos de registro de registro

¿Qué elegir?

Winston y Bunyan son marcos de registro muy maduros y establecidos y están muy a la par en términos de características. Winston tiene mucho soporte de la comunidad con varios módulos de registro. Bunyan hace que sea fácil de usar analizar los registros, pero deja el consumo en manos del usuario (generalmente, el drenaje de registros del sistema funciona bastante bien aquí). Siento que todo se reduce a la preferencia y a lo fácil que es integrarse con su pila.

  • ¿Qué llegará a la próxima versión de nodo? Lea acerca de ocho nuevas y emocionantes funciones de Node v0. 12 y cómo aprovecharlas al máximo, de los propios autores.
  • Listo para desarrollar API en el nodo.js y conectarlos a sus datos? Mira el Nodo.marco de API de bucle invertido de js. Hemos hecho que sea fácil comenzar localmente o en su nube favorita, con una instalación simple de npm.
  • ¿Necesita capacitación y certificación para Node? Obtenga más información sobre las opciones privadas y abiertas que ofrece StrongLoop.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.