diff --git a/lib/God.js b/lib/God.js index dc0019972..3e4c1d541 100644 --- a/lib/God.js +++ b/lib/God.js @@ -291,9 +291,6 @@ God.handleExit = function handleExit(clu, exit_code, kill_signal) { return false; } - if (proc.process.pid) - pidusage.unmonitor(proc.process.pid); - var stopping = (proc.pm2_env.status == cst.STOPPING_STATUS || proc.pm2_env.status == cst.STOPPED_STATUS || proc.pm2_env.status == cst.ERRORED_STATUS) || (proc.pm2_env.autorestart === false || diff --git a/lib/God/ActionMethods.js b/lib/God/ActionMethods.js index 1556a1652..092b7df38 100644 --- a/lib/God/ActionMethods.js +++ b/lib/God/ActionMethods.js @@ -41,55 +41,63 @@ module.exports = function(God) { */ God.getMonitorData = function getMonitorData(env, cb) { var processes = God.getFormatedProcesses(); + var pids = processes.filter(filterBadProcess) + .map(function(pro, i) { + var pid = getProcessId(pro) + return pid; + }) + + // No pids, return empty statistics + if (pids.length === 0) { + return cb(null, processes.map(function(pro) { + pro['monit'] = { + memory : 0, + cpu : 0 + }; - async.eachSeries(processes, function computeMonitor(pro, next) { - if (pro.pm2_env.status == cst.ONLINE_STATUS) { - var pid = pro.pid; - - if (pro.pm2_env.axm_options && pro.pm2_env.axm_options.pid) { - if (isNaN(pro.pm2_env.axm_options.pid)) { - pro['monit'] = { - memory : 0, - cpu : 0 - }; - return process.nextTick(next); - } - pid = pro.pm2_env.axm_options.pid; + return pro + })) + } + + pidusage(pids, function retPidUsage(err, statistics) { + // Just log, we'll set empty statistics + if (err) { + console.error('Error caught while calling pidusage'); + console.error(err); + } + + processes = processes.map(function(pro) { + if (filterBadProcess(pro) === false) { + pro['monit'] = { + memory : 0, + cpu : 0 + }; + + return pro; } - pidusage.stat(pid, function retPidUsage(err, res) { - if (err) { - // Do not log, some time modules does not retrieve PID - // console.error('Error caught while calling pidusage'); - // console.error(err); - pro['monit'] = { - memory : 0, - cpu : 0 - }; - return next(); - } + var pid = getProcessId(pro); + var stat = statistics[pid]; + if (!stat) { pro['monit'] = { - memory : Math.floor(res.memory), - cpu : Math.floor(res.cpu) + memory : 0, + cpu : 0 }; - res = null; - pid = null; - return next(); - }); - } - else { + + return pro; + } + pro['monit'] = { - memory : 0, - cpu : 0 + memory: stat.memory, + cpu: stat.cpu }; - return next(); - } - }, function retMonitor(err, res) { - if (err) return cb(God.logAndGenerateError(err), null); - return cb(null, processes); - }); + return pro; + }); + + cb(null, processes); + }); }; /** @@ -304,7 +312,6 @@ module.exports = function(God) { God.killProcess(proc.process.pid, proc.pm2_env, function(err) { proc.pm2_env.status = cst.STOPPED_STATUS; - pidusage.unmonitor(proc.process.pid); God.notify('exit', proc); @@ -841,3 +848,27 @@ module.exports = function(God) { }); }; }; + +function filterBadProcess(pro) { + if (pro.pm2_env.status !== cst.ONLINE_STATUS) { + return false; + } + + if (pro.pm2_env.axm_options && pro.pm2_env.axm_options.pid) { + if (isNaN(pro.pm2_env.axm_options.pid)) { + return false; + } + } + + return true; +} + +function getProcessId(pro) { + var pid = pro.pid + + if (pro.pm2_env.axm_options && pro.pm2_env.axm_options.pid) { + pid = pro.pm2_env.axm_options.pid; + } + + return pid +} diff --git a/package.json b/package.json index 3702dbaec..8e9a96084 100644 --- a/package.json +++ b/package.json @@ -174,7 +174,7 @@ "moment": "^2.19", "needle": "^2.2.0", "nssocket": "0.6.0", - "pidusage": "^2.0.0", + "pidusage": "^2.0.5", "pm2-axon": "3.1.0", "pm2-axon-rpc": "0.5.0", "pm2-deploy": "^0.3.9", diff --git a/test/programmatic/god.mocha.js b/test/programmatic/god.mocha.js index 887a15f34..5c22cd533 100644 --- a/test/programmatic/god.mocha.js +++ b/test/programmatic/god.mocha.js @@ -256,4 +256,52 @@ describe('God', function() { }); }); + it('should get monitor data', function(done) { + var f = require('child_process').fork('../fixtures/echo.js') + + var processes = [ + // stopped status + { + pm2_env: {status: cst.STOPPED_STATUS} + }, + // axm pid + { + pm2_env: { + status: cst.ONLINE_STATUS, axm_options: {pid: process.pid} + } + }, + // axm pid is NaN + { + pm2_env: { + status: cst.ONLINE_STATUS, axm_options: {pid: 'notanumber'} + } + }, + { + pm2_env: { + status: cst.ONLINE_STATUS + }, + pid: f.pid + } + ] + + // mock + var g = { + getFormatedProcesses: function() { + return processes + } + } + + require('../../lib/God/ActionMethods.js')(g) + + g.getMonitorData({}, function(err, procs) { + should(err).be.null(); + procs.length.should.be.equal(processes.length); + procs[0].monit.should.be.deepEqual({memory: 0, cpu: 0}); + procs[1].monit.memory.should.be.greaterThan(0); + procs[2].monit.should.be.deepEqual({memory: 0, cpu: 0}); + procs[3].monit.memory.should.be.greaterThan(0); + f.kill() + done() + }) + }); });