Por solicitud de registro en Node.js

Soy un desarrollador de Java con experiencia que toma Node.js y hace el cambio al modelo asíncrono. La mayoría de las cosas van bien, excepto para el registro. No puedo encontrar nada similar a log4j y NDCs en Java mientras se desarrolla en Node.js con Express.

Mi objective es hacer que cada statement de registro anteponga automáticamente la siguiente información:

[2013-11-07 11: 17: 04.615 serverScript INFO 7036 192.168.7.209]

Esto incluye la marca de tiempo, el nombre del archivo js que escribe esta statement (para aplicaciones de nodos modularizados), el nivel de depuración, la ID del proceso (clústeres en ejecución) y la dirección IP del cliente.

Puedo hacer que escriba esto cuando ingresa inicialmente en mi controlador de solicitudes, pero sin propagar un conjunto de parámetros a cada función llamada, las declaraciones del registrador dentro de las subrutinas no tienen la información. Sé que puedo crear una instancia de mi registrador dentro de cada archivo js que inicializa su nombre, pero todavía tengo que encontrar una solución para la dirección IP del cliente. Para solicitudes de mayor duración, la dirección que establezco en mi registrador se sobrescribe cuando llega la siguiente solicitud, por lo que las direcciones IP registradas se cruzan.

He analizado Winston pero no he podido resolver este problema ni siquiera con él. ¿Alguien ha logrado esto? Es muy útil realizar un seguimiento de los problemas de campo cuando puede filtrar por IP para ver solo la actividad de un usuario.

[edit: prueba de la solución de paso de parámetros hasta que aprenda la forma de syslog]

[2013-11-07 14:29:28.641 server INFO 7527 192.168.7.209] Got request from 192.168.7.209 for /ionmed/executeQuery? [2013-11-07 14:29:28.641 router INFO 7527 192.168.7.209] About to route a request for /ionmed/executeQuery, method=POST [2013-11-07 14:29:28.642 router INFO 7527 192.168.7.209] getting POSTed data [2013-11-07 14:29:28.642 router INFO 7527 192.168.7.209] POST params: {"sqlQuery":"select sleep(10)","sessionStart":"1383852558799","rand":"0.5510970998368581","jsessionid":"117DBAA89F599D923AF80D4AB171BDDF"} [2013-11-07 14:29:28.642 requestHandlers INFO 7527 192.168.7.209] 'query' was called. [2013-11-07 14:29:28.642 requestHandlers INFO 7527 192.168.7.209] select sleep(10) [2013-11-07 14:29:30.673 server INFO 7527 192.168.7.217] Got request from 192.168.7.217 for / [2013-11-07 14:29:30.673 router INFO 7527 192.168.7.217] About to route a request for /, method=GET [2013-11-07 14:29:30.673 router INFO 7527 192.168.7.217] No request handler found for /; serving as file [2013-11-07 14:29:30.673 router INFO 7527 192.168.7.217] Request handler 'serveFile' was called to get: /index.html [192.168.7.217 Thu, 07 Nov 2013 19:29:30 GMT] HTTP/1.1 GET "/node/" 200 "Mozilla/5.0 (iPod; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3" [2013-11-07 14:29:33.578 server INFO 7527 192.168.7.217] Got request from 192.168.7.217 for / [2013-11-07 14:29:33.578 router INFO 7527 192.168.7.217] About to route a request for /, method=GET [2013-11-07 14:29:33.578 router INFO 7527 192.168.7.217] No request handler found for /; serving as file [2013-11-07 14:29:33.579 router INFO 7527 192.168.7.217] Request handler 'serveFile' was called to get: /index.html [192.168.7.217 Thu, 07 Nov 2013 19:29:33 GMT] HTTP/1.1 GET "/node/" 200 "Mozilla/5.0 (iPod; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3" [2013-11-07 14:29:38.644 requestHandlers INFO 7527 192.168.7.209] sending response [192.168.7.209 Thu, 07 Nov 2013 19:29:38 GMT] HTTP/1.1 POST "/node/ionmed/executeQuery?" 200 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0" [2013-11-07 14:29:41.540 server INFO 7527 192.168.7.217] Got request from 192.168.7.217 for / [2013-11-07 14:29:41.541 router INFO 7527 192.168.7.217] About to route a request for /, method=GET [2013-11-07 14:29:41.541 router INFO 7527 192.168.7.217] No request handler found for /; serving as file [2013-11-07 14:29:41.541 router INFO 7527 192.168.7.217] Request handler 'serveFile' was called to get: /index.html [192.168.7.217 Thu, 07 Nov 2013 19:29:41 GMT] HTTP/1.1 GET "/node/" 200 "Mozilla/5.0 (iPod; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3" [2013-11-07 14:29:45.146 server INFO 7527 192.168.7.209] RLz6tmJ7KTH2R16VCVTX: bye {"user":"1"} [2013-11-07 14:29:45.176 server INFO 7527 192.168.7.209] RLz6tmJ7KTH2R16VCVTX: disconnected 

Ahora solo necesito descubrir cómo conseguir que el registrador de solicitudes rápidas esté en el mismo formato de entrada de línea que mi registrador interno hasta que todo se mueva a rsyslog.

Me metí en este mismo problema hace algún tiempo y, finalmente, podría pasar un tiempo investigándolo. El enfoque de @ibash y su publicación me pusieron a la cabeza para resolver el problema que tenía (gracias por su ayuda). Solo caminé algunos pasos más para imprimir en los registros automáticamente una identificación única por solicitud. En su caso, puede agregar la IP de origen y destino y toda la información necesaria para cada solicitud, utilizando el mismo enfoque e imprimirla automáticamente en todos los registros.

Mi enfoque: – Como explicó @ibash, usé el almacenamiento local de continuación para compartir información entre todos los módulos por solicitud. Así que genero una ID única por solicitud y la almaceno en un espacio de nombres creado con esta biblioteca: envolví la biblioteca de Winston (de una manera muy simple) para recuperar la información del espacio de nombres compartido y anular todos los métodos de Winston que uso agregando a la cadena de la identificación única. Obviamente, en su caso, debe agregar toda la información que necesita y ha almacenado previamente en el espacio de nombres de la biblioteca.

Como el problema era un poco complejo para explicar a las personas que no están familiarizadas con todas estas cosas, lo escribí en un post con un claro ejemplo que puede reutilizar si lo desea. El ajuste de Winston podría ser realmente útil: Express.js: registro de información con ID de solicitud única global – Node.js

Espero que pueda reutilizar mi código y quizás en el futuro Express implemente una solución para esto.

Estas instrucciones eran de una distribución de Ubuntu 12.04 que configuré, pero deberían aplicarse bastante cerca de RHEL, Fedora, CentOS, etc.

Rsyslog es una utilidad de registro del sistema que puede usar para registrar mensajes de cualquier progtwig en una máquina Linux. Primero necesitas encontrar la información de configuración de tu rsylog. Puedes hacerlo con el siguiente comando:

 sudo find / -name rsyslog.conf 

Si no puede encontrar el archivo de configuración, puede enumerar el servicio en ejecución para ver si rsyslog está incluso en su máquina con el siguiente comando:

 service --status-all 

Ahora abre el archivo que encuentra y haz lo siguiente:

  • Comente la línea $ ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
  • Descomentar $ ModLoad imtcp
  • Descomente $ InputTCPServerRun y ​​especifique el número de puerto 1514, va a usar 1514 b / c Ubuntu 12.04 rsyslog tiene un problema al dejar los permisos si uso el puerto 514, otras distribuciones no tienen problemas similares y puede mantener el número de puerto predeterminado. Resuelvo esto utilizando iptables para redireccionar el tráfico del puerto 514 a 1514
  • Cambie $ FileCreateMode 0640 a 0644

Ahora creé un archivo llamado /etc/rsyslog.d/10.conf (este es un archivo de configuración secundario para rsyslog donde podemos filtrar mensajes, nombrar archivos de registro, etc.) y le agregué lo siguiente:

 $template DailyPerHostLogs,"/var/log/MyLogFile_%$YEAR%_%$MONTH%_%$DAY%.log" #:msg,contains,"MsgName" -?DailyPerHostLogs *.* -?DailyPerHostLogs &~ 

Este archivo crea un nuevo archivo para cada día y encuentra cualquier mensaje enviado con MsgName en el texto, lo coloca en el archivo diario y luego lo elimina de la cola para que lo registren otras solicitudes de registro, por lo que no lo registramos dos veces.

Ahora puede reiniciar la máquina en la que está trabajando y todo debería estar funcionando. Puede verificar esto buscando archivos en / var / log como se define en 10.conf arriba. Golpee el registrador desde la línea de comandos emitiendo los siguientes comandos:

 logger this is from the command line echo "this is from the tcp port" > /dev/tcp/127.0.0.1/1514 

Debería ver ambas líneas aparecer en el archivo de registro. Si lo consigue, entonces continuemos con el módulo de nodo que podrá acceder al registro.

 var net = require('net'); var client = net.connect({port: this.1514}, function(){ console.log("Open"); }); client.write(' ' + "sMsgName: What"+ ' ' + "hath" + ' ' + "God wrought?" + '\n'); //Do everything else your program needs. . . 

El ‘\ n’ en la escritura le dice a rsyslog que hemos terminado con esta línea. Además, deberá anteponer un espacio para que funcione el filtrado: http://www.rsyslog.com/log-normalization-and-the-leading-space/

El diablo siempre está en los detalles con una configuración como esta, pero creo que esto te llevará a la mayor parte del camino y la búsqueda en Google te dará el rest del camino.

Respondiendo esto mientras escribía una publicación sobre cómo usar el almacenamiento local de continuación para guardar un “ID de transacción” con cada registro (sin propagarlo manualmente). Puedes hacer lo mismo para la ip del cliente, id de proceso, etc.

Siga este post: https://datahero.com/blog/2014/05/22/node-js-preserving-data-across-async-callbacks/

Pero en lugar de simplemente guardar un ID de transacción, también querrá estos: request.connection.remoteAddress and process.pid

Hazme saber si tienes alguna pregunta aquí o allá, y te responderé.

    Intereting Posts