winston + PM2logginguncaughtException两次

我为我的NodeJS应用程序使用winston ,以具有结构化日志logging格式(JSON),稍后我将通过Filebeat处理并发送到Logstash。

正如PM2和12factor.net所build议的,我使用winston.transports.Console传输进行日志logging,并让PM2处理我的winston.transports.Consolestdoutstderr

在我的logger.js模块中,我有以下几点:

 "use strict"; const winston = require("winston"); // Remove logging on console winston.remove(winston.transports.Console); // env const env = process.env.NODE_ENV || 'development'; const isDev = env === "development"; // The default Console transport const defaultLogLevel = isDev ? "debug" : "info"; const consoleTransport = new winston.transports.Console({ level: defaultLogLevel, colorize: true, json: true, timestamp: true, exceptionsLevel: "error", prettyPrint: false, handleExceptions: true, humanReadableUnhandledException: false, exitOnError: true }); const defaultOptions = { transports: [ consoleTransport ] }; module.exports = function(options) { let initOpts = defaultOptions; if(options) { Object.assign(initOpts, options); } const logger = new winston.Logger(initOpts); // suppress any logger errors logger.emitErrs = false; winston.handleExceptions(consoleTransport); return logger; }; 

在我的主要应用程序文件server.js我运行这段代码来模拟一个未处理的exception被抛出,一个假的依赖关系是需要和没有find:

 "use strict"; var log = require('./logger')({name: "api-messages"}); log.info("some info message"); log.error("some error message"); var notFound = require("someInexistentPackage"); 

最后,在我的PM2 ecosystem.json我有以下几点:

 { "apps": [ { "name" : "my-app", "script" : "server.js", "max_restarts" : 1, "error_file" : "~/.pm2/logs/my-app.log", "out_file" : "~/.pm2/logs/my-app.log", "merge_logs" : true } ] } 

当我运行pm2 start ecosystem.json日志文件的内容如下:

 { "level": "info", "message": "some info message", "timestamp": "2017-06-08T16:10:05.967Z" } { "level": "error", "message": "some error message", "timestamp": "2017-06-08T16:10:05.968Z" } Error: Cannot find module 'someInexistentPackage' at Function.Module._resolveFilename (module.js:470:15) at Function.Module._load (module.js:418:25) at Module.require (module.js:498:17) at require (internal/module.js:20:19) at Object.<anonymous> (/Users/mps/Sites/my-app/server.js:10:20) at Module._compile (module.js:571:32) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:488:32) at tryModuleLoad (module.js:447:12) at Function.Module._load (module.js:439:3) { "date": "Thu Jun 08 2017 13:10:05 GMT-0300 (-03)", "process": { "pid": 50862, "uid": 501, "gid": 20, "cwd": "/Users/mps/Sites/my-app", "execPath": "/Users/mps/.nvm/versions/node/v7.10.0/bin/node", "version": "v7.10.0", "argv": [ "/Users/mps/.nvm/versions/node/v7.10.0/bin/node", "/Users/mps/.nvm/versions/node/v7.10.0/lib/node_modules/pm2/lib/ProcessContainerFork.js" ], "memoryUsage": { "rss": 36724736, "heapTotal": 9879552, "heapUsed": 6309680, "external": 63983 } }, "os": { "loadavg": [ 2.49560546875, 2.228515625, 2.0205078125 ], "uptime": 329559 }, "trace": [ { "column": 15, "file": "module.js", "function": "Module._resolveFilename", "line": 470, "method": "_resolveFilename", "native": false }, { "column": 25, "file": "module.js", "function": "Module._load", "line": 418, "method": "_load", "native": false }, { "column": 17, "file": "module.js", "function": "Module.require", "line": 498, "method": "require", "native": false }, { "column": 19, "file": "internal/module.js", "function": "require", "line": 20, "method": null, "native": false }, { "column": 20, "file": "/Users/mps/Sites/my-app/server.js", "function": null, "line": 10, "method": null, "native": false }, { "column": 32, "file": "module.js", "function": "Module._compile", "line": 571, "method": "_compile", "native": false }, { "column": 10, "file": "module.js", "function": "Module._extensions..js", "line": 580, "method": ".js", "native": false }, { "column": 32, "file": "module.js", "function": "Module.load", "line": 488, "method": "load", "native": false }, { "column": 12, "file": "module.js", "function": "tryModuleLoad", "line": 447, "method": null, "native": false }, { "column": 3, "file": "module.js", "function": "Module._load", "line": 439, "method": "_load", "native": false } ], "stack": [ "Error: Cannot find module 'someInexistentPackage'", " at Function.Module._resolveFilename (module.js:470:15)", " at Function.Module._load (module.js:418:25)", " at Module.require (module.js:498:17)", " at require (internal/module.js:20:19)", " at Object.<anonymous> (/Users/mps/Sites/my-app/server.js:10:20)", " at Module._compile (module.js:571:32)", " at Object.Module._extensions..js (module.js:580:10)", " at Module.load (module.js:488:32)", " at tryModuleLoad (module.js:447:12)", " at Function.Module._load (module.js:439:3)" ], "level": "error", "message": "uncaughtException: Cannot find module 'someInexistentPackage'", "timestamp": "2017-06-08T16:10:05.972Z" } 

正如你所看到的,PM2正在将未捕获的Exception添加到日志文件中,也就是这个代码:

 Error: Cannot find module 'someInexistentPackage' at Function.Module._resolveFilename (module.js:470:15) at Function.Module._load (module.js:418:25) at Module.require (module.js:498:17) at require (internal/module.js:20:19) at Object.<anonymous> (/Users/mps/Sites/my-app/server.js:10:20) at Module._compile (module.js:571:32) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:488:32) at tryModuleLoad (module.js:447:12) at Function.Module._load (module.js:439:3) 

这打破了我的日志的格式/结构,因为它是纯文本,而不是从winston收到格式化的JSON。

我相信这是一个PM2问题/ misconfiguration,因为如果我运行node server.js控制台输出只是JSON对象。

我必须在PM2的ecos.json文件中设置一个特定的属性吗?

我如何告诉PM2忽略Node的uncaughtException

唯一的select我已经提出了(我还没有尝试过),是改变我winston传输到winston.transports.File ,redirect所有日志到stdout并告诉PM2保存stderr在不同的文件,但我' d宁可坚持与控制台aproach。

防止PM2logginguncaughtException一种方法是将--no-pmx作为标志,即pm2 start --no-pmx myapp.js或将pmx: false添加到pmx: false文件。

这将禁用PMX注入PM2,PM2负责logging这个uncaughtException