move sysmonitoring logic to pm2-sysmonit + fix pm2 ls

This commit is contained in:
Unitech 2021-01-13 13:57:18 +01:00
parent d520de93a4
commit 042a32afce
12 changed files with 53 additions and 948 deletions

View File

@ -1725,13 +1725,11 @@ class API {
if ((conf.PM2_PROGRAMMATIC && process.env.PM2_USAGE != 'CLI'))
return false;
return that.Client.executeRemote('getSystemData', {}, (err, sys_infos) => {
that.Client.executeRemote('getMonitorData', {}, (err, proc_list) => {
doList(err, proc_list, sys_infos)
})
return that.Client.executeRemote('getMonitorData', {}, (err, proc_list) => {
doList(err, proc_list)
})
function doList(err, list, sys_infos) {
function doList(err, list) {
if (err) {
if (that.gl_retry == 0) {
that.gl_retry += 1;
@ -1758,7 +1756,7 @@ class API {
chalk.bold(that.gl_interact_infos.machine_name),
chalk.bold(dashboard_url))
}
UX.list(list, sys_infos, commander);
UX.list(list, commander);
//Common.printOut(chalk.white.italic(' Use `pm2 show <id|name>` to get more details about an app'));
}

View File

@ -32,21 +32,13 @@ module.exports = function(CLI) {
};
/**
* Get version of the daemonized PM2
* @method getVersion
* @callback cb
* Install pm2-sysmonit
*/
CLI.prototype.launchSysMonitoring = function(cb) {
var that = this;
this.set('pm2:sysmonit', 'true', () => {
that.Client.executeRemote('launchSysMonitoring', {}, function(err) {
if (err)
Common.err(err)
else
Common.log('System Monitoring launched')
return cb ? cb.apply(null, arguments) : that.exitCli(cst.SUCCESS_EXIT);
})
that.install('pm2-sysmonit', (err, apps) => {
return cb ? cb.apply(null, arguments) : that.exitCli(cst.SUCCESS_EXIT);
})
};

View File

@ -24,10 +24,10 @@ function checkIfProcessAreDumped(list) {
.map(proc => proc.name)
var diff = apps_dumped.filter(a => !apps_running.includes(a))
if (diff.length > 0) {
Common.printOut(`Current process list running is not in sync with saved list. App ${chalk.bold(diff.join(' '))} differs. Type 'pm2 save' to synchronize.`)
Common.warn(`Current process list is not synchronized with saved list. App ${chalk.bold(diff.join(' '))} differs. Type 'pm2 save' to synchronize.`)
}
else if (apps_dumped.length != apps_running.length) {
Common.printOut(`Current process list running is not in sync with saved list. Type 'pm2 save' to synchronize'`)
Common.warn(`Current process list is not synchronized with saved list. Type 'pm2 save' to synchronize.`)
}
} catch(e) {
}
@ -402,39 +402,51 @@ function listHighResourcesProcesses(sys_infos) {
* Sys info line
*/
function miniMonitBar(sys_infos) {
let sys_metrics = sys_infos.pm2_env.axm_monitor
let cpu = sys_metrics['cpu']
if (typeof(cpu) == 'undefined') return
var sys_summary_line = `${chalk.bold.cyan('host metrics')} `
sys_summary_line += `| ${chalk.bold('cpu')}: ${UxHelpers.colorizedMetric(sys_infos.cpu.usage, 40, 70, '%')}`
if (sys_infos.cpu.temperature && sys_infos.cpu.temperature != '-1') {
sys_summary_line += ` ${UxHelpers.colorizedMetric(sys_infos.cpu.temperature, 50, 70, 'º')}`
sys_summary_line += `| ${chalk.bold('cpu')}: ${UxHelpers.colorizedMetric(cpu.value, 40, 70, '%')}`
let temp = sys_metrics['cpu:temp'].value
if (temp && temp != '-1') {
sys_summary_line += ` ${UxHelpers.colorizedMetric(temp, 50, 70, 'º')}`
}
if (sys_infos.mem) {
var perc_mem_usage = (((sys_infos.mem.available) / sys_infos.mem.total) * 100).toFixed(1)
let mem_total = sys_metrics['mem:total'].value
let mem_available = sys_metrics['mem:available'].value
if (mem_total) {
var perc_mem_usage = (((mem_available) / mem_total) * 100).toFixed(1)
sys_summary_line += ` | ${chalk.bold('mem free')}: ${UxHelpers.colorizedMetric(perc_mem_usage, 30, 10, '%')} `
}
if (sys_infos.network) {
var latency = (sys_infos.network.latency).toFixed(1)
if (latency == -1) {
sys_summary_line += `| ${chalk.bold('net')}: ${chalk.red('offline')} `
}
else {
sys_summary_line += `| ${chalk.bold('net')}: `
//sys_summary_line += `${colorizedMetric(latency, 100, 150, 'ms')} `
sys_summary_line += `${UxHelpers.colorizedMetric(sys_infos.network.rx_5, 10, 20, 'mb/s')} `
sys_summary_line += `${UxHelpers.colorizedMetric(sys_infos.network.tx_5, 10, 20, 'mb/s')} `
}
}
let interfaces = Object.keys(sys_metrics).filter(m => m.includes('net') && m != 'net:default').map(i => i.split(':')[1]).filter((iface, i, self) => self.indexOf(iface) === i)
interfaces.forEach(iface => {
sys_summary_line += `| ${chalk.bold(iface)}: `
sys_summary_line += `${UxHelpers.colorizedMetric(sys_metrics[`net:${iface}:rx_5`].value, 10, 20, 'mb/s')} `
sys_summary_line += `${UxHelpers.colorizedMetric(sys_metrics[`net:${iface}:tx_5`].value, 10, 20, 'mb/s')} `
})
if (CONDENSED_MODE == false) {
if (sys_infos.storage) {
sys_summary_line += `| ${chalk.bold('disk')}: ⇓ ${UxHelpers.colorizedMetric(sys_infos.storage.io.read, 10, 20, 'mb/s')}`
sys_summary_line += `${UxHelpers.colorizedMetric(sys_infos.storage.io.write, 10, 20, 'mb/s')} `
}
let read = sys_metrics['io:r'].value
let write = sys_metrics['io:w'].value
sys_summary_line += `| ${chalk.bold('disk')}: ⇓ ${UxHelpers.colorizedMetric(read, 10, 20, 'mb/s')}`
sys_summary_line += `${UxHelpers.colorizedMetric(write, 10, 20, 'mb/s')} `
let disks = Object.keys(sys_metrics).filter(m => m.includes('fs:')).map(i => i.split(':')[1]).filter((iface, i, self) => self.indexOf(iface) === i)
var disk_nb = 0
sys_infos.storage.filesystems.forEach(fs => {
disk_nb++
var perc_used = ((fs.used / fs.size) * 100).toFixed()
if (perc_used > 60)
sys_summary_line += `${chalk.grey(fs.fs)} ${UxHelpers.colorizedMetric(perc_used, 80, 90, '%')} `
disks.forEach(fs => {
let use = sys_metrics[`fs:${fs}:use`].value
if (use > 60)
sys_summary_line += `${chalk.grey(fs)} ${UxHelpers.colorizedMetric(use, 80, 90, '%')} `
})
}
@ -448,7 +460,7 @@ function miniMonitBar(sys_infos) {
* @param {Object} list
* @param {Object} system informations (via pm2 sysmonit/pm2 sysinfos)
*/
module.exports = function(list, sys_infos, commander) {
module.exports = function(list, commander) {
var pm2_conf = Configuration.getSync('pm2')
if (!list)
@ -456,17 +468,9 @@ module.exports = function(list, sys_infos, commander) {
listModulesAndAppsManaged(list, commander)
if (sys_infos) {
if (sys_infos.containers && sys_infos.containers.length > 0 &&
(pm2_conf && pm2_conf.show_docker == "true"))
containersListing(sys_infos)
if (sys_infos.processes && (sys_infos.processes.cpu_sorted || sys_infos.processes.mem_sorted))
listHighResourcesProcesses(sys_infos)
if (sys_infos.cpu && sys_infos.cpu.usage)
miniMonitBar(sys_infos)
}
let sysmonit = list.filter(proc => proc.name == 'pm2-sysmonit')
if (sysmonit && sysmonit[0])
miniMonitBar(sysmonit[0])
checkIfProcessAreDumped(list)
}

View File

@ -217,9 +217,7 @@ Daemon.prototype.innerStart = function(cb) {
profileCPU : profile.bind(this, 'cpu'),
profileMEM : profile.bind(this, 'mem'),
prepare : God.prepare,
launchSysMonitoring : God.launchSysMonitoring,
getMonitorData : God.getMonitorData,
getSystemData : God.getSystemData,
startProcessId : God.startProcessId,
stopProcessId : God.stopProcessId,

View File

@ -79,10 +79,6 @@ God.init = function() {
this.configuration = Configuration.getSync('pm2')
if (this.configuration && this.configuration.sysmonit == 'true') {
God.launchSysMonitoring({}, () => { console.log('System monitoring launched') })
}
setTimeout(function() {
God.Worker.start()
}, 500)
@ -586,27 +582,4 @@ God.injectVariables = function injectVariables (env, cb) {
return cb(null, env);
};
God.launchSysMonitoring = function(env, cb) {
if (God.system_infos_proc !== null)
return cb(new Error('Sys Monitoring already launched'))
try {
var sysinfo = require('./Sysinfo/SystemInfo.js')
God.system_infos_proc = new sysinfo()
setInterval(() => {
God.system_infos_proc.query((err, data) => {
if (err) return
God.system_infos = data
})
}, 1000)
God.system_infos_proc.fork()
} catch(e) {
console.log(e)
God.system_infos_proc = null
}
return cb()
}
God.init()

View File

@ -118,23 +118,6 @@ module.exports = function(God) {
});
};
/**
* Description
* @method getSystemData
* @param {} env
* @param {} cb
* @return
*/
God.getSystemData = function getSystemData(env, cb) {
if (God.system_infos_proc !== null)
God.system_infos_proc.query((err, data) => {
cb(null, data)
})
else {
cb(new Error('Sysinfos not launched, type: pm2 sysmonit'))
}
};
/**
* Description
* @method dumpProcessList

View File

@ -1,26 +0,0 @@
class MeanCalc {
constructor(count) {
this.metrics = []
this.count = count
}
inspect() {
return this.val()
}
add(value) {
if (this.metrics.length >= this.count) {
this.metrics.shift()
}
this.metrics.push(value)
}
val() {
if (this.metrics.length == 0) return 0
let sum = this.metrics.reduce((prev, curr) => curr += prev)
return Math.floor((sum / this.metrics.length) * 1000) / 1000
}
}
module.exports = MeanCalc

View File

@ -1,118 +0,0 @@
const PM2 = require('./../../API.js')
const psList = require('../psList.js')
const SERVICES_ASSOCIATION = {
'mongodb,mongo': {
module: 'pm2-mongodb'
},
'redis,redis-server': {
module: 'pm2-redis'
},
'elasticsearch': {
module: 'pm2-elasticsearch'
},
'docker': {
module: 'pm2-monit-docker'
},
'consul': {
module:'pm2-monit-consul'
},
'pm2': {
module: 'pm2-probe'
},
'fpm': {
module: 'pm2-php-fpm'
}
}
// 'python,python3': {
// module: 'pm2-python'
// },
// 'nginx': {
// module: 'pm2-monit-nginx'
// },
// 'haproxy': {
// module: 'pm2-monit-haproxy'
// },
// 'traeffik': {
// module: 'pm2-monit-traeffik'
// }
class ServicesDetection {
constructor() {
this.pm2 = new PM2()
}
startDetection(cb = () => {}) {
// Check running probes
this.monitoredServices((err, pm2_services) => {
// Check running services
this.discover((err, required_modules) => {
var required_monitoring_probes = Object.keys(required_modules)
// Make the diff between
// console.log(`Need to start following modules:`)
// console.log(_.difference(required_monitoring_probes, pm2_services))
this.pm2.install('pm2-server-monit', (err, apps) => {
cb()
})
})
})
}
monitoredServices(cb) {
var f_proc_list = []
this.pm2.list((err, proc_list) => {
f_proc_list = proc_list.map(p => {
return p.name
})
this.pm2.close()
cb(err, f_proc_list)
})
}
discover(cb) {
psList()
.then(processes => {
var supported_systems = Object.keys(SERVICES_ASSOCIATION)
var required_modules = {}
processes.forEach((proc) => {
supported_systems.forEach(sup_sys => {
var proc_names = sup_sys.split(',')
proc_names.forEach(proc_name => {
if (proc.name.includes(proc_name) === true ||
proc.cmd.includes(proc_name) === true) {
var key = SERVICES_ASSOCIATION[sup_sys].module
required_modules[key] = SERVICES_ASSOCIATION[sup_sys]
required_modules[key].monit = proc
}
})
})
})
return cb(null, required_modules)
})
.catch(e => {
console.error(`Error while listing processes`, e)
})
}
}
if (require.main === module) {
var serviceDetection = new ServicesDetection()
var process = (done) => {
serviceDetection.startDetection((err, procs) => {
done()
})
}
var iterate = () => {
process(() => {
setTimeout(iterate, 3000)
})
}
iterate()
}

View File

@ -1,633 +0,0 @@
const sysinfo = require('systeminformation')
const psList = require('./psList.js')
const async = require('async')
const MeanCalc = require('./MeanCalc.js')
const fork = require('child_process').fork
const DEFAULT_CONVERSION = 1024 * 1024
const os = require('os')
const fs = require('fs')
const debug = require('debug')('pm2:sysinfos')
class SystemInfo {
constructor() {
this.infos = {
baseboard: {
model: null,
version: null
},
cpu: {
manufacturer: null,
brand: null,
speedmax: null,
cores: null,
physicalCores: null,
processors: null,
temperature: null,
usage: null
},
graphics: {
model: null,
driverVersion: null,
memTotal: null,
memUsed: null,
temperature: null
},
mem: {
total: null,
free: null,
active: null
},
os: {
platform: null,
distro: null,
release: null,
codename: null,
kernel: null,
arch: null,
},
fd: {
opened: null,
max: null
},
storage: {
io: {
read: new MeanCalc(15),
write: new MeanCalc(15)
},
physical_disks: [{
device: null,
type: null,
name: null,
interfaceType: null,
vendor: null
}],
filesystems: [{
}]
},
connections: ['source_ip:source_port-dest_ip:dest_port-proc_name'],
network: {
latency: new MeanCalc(5),
tx_5: new MeanCalc(5),
rx_5: new MeanCalc(5),
rx_errors_60: new MeanCalc(60),
tx_errors_60: new MeanCalc(60),
tx_dropped_60: new MeanCalc(60),
rx_dropped_60: new MeanCalc(60)
},
// Procs
containers: [],
processes: {
cpu_sorted: null,
mem_sorted: null
},
services: {
running: null,
stopped: null
}
}
this.restart = true
this.ping_timeout = null
}
// Cast MeanCalc and other object to real value
// This method retrieve the machine snapshot well formated
report() {
var report = JSON.parse(JSON.stringify(this.infos))
report.network.latency = this.infos.network.latency.val()
report.network.tx_5 = this.infos.network.tx_5.val()
report.network.rx_5 = this.infos.network.rx_5.val()
report.network.rx_errors_60 = this.infos.network.rx_errors_60.val()
report.network.tx_errors_60 = this.infos.network.tx_errors_60.val()
report.network.rx_dropped_60 = this.infos.network.rx_dropped_60.val()
report.network.tx_dropped_60 = this.infos.network.tx_dropped_60.val()
report.storage.io.read = this.infos.storage.io.read.val()
report.storage.io.write = this.infos.storage.io.write.val()
return report
}
fork() {
this.process = fork(__filename, {
detached: false,
windowsHide: true,
stdio: ['inherit', 'inherit', 'inherit', 'ipc']
})
this.process.on('exit', (code) => {
console.log(`systeminfos collection process offline with code ${code}`)
// if (this.restart == true)
// this.fork()
})
this.process.on('error', (e) => {
console.log(`Sysinfo errored`, e)
})
this.process.on('message', (msg) => {
try {
msg = JSON.parse(msg)
}
catch (e) {
}
if (msg.cmd == 'ping') {
if (this.process.connected == true) {
try {
this.process.send('pong')
} catch(e) {
console.error('Cannot send message to Sysinfos')
}
}
}
})
}
query(cb) {
if (this.process.connected == true) {
try {
this.process.send('query')
} catch(e) {
return cb(new Error('not ready yet'), null)
}
}
else
return cb(new Error('not ready yet'), null)
var res = (msg) => {
try {
msg = JSON.parse(msg)
}
catch (e) {
}
if (msg.cmd == 'query:res') {
listener.removeListener('message', res)
return cb(null, msg.data)
}
}
var listener = this.process.on('message', res)
}
kill() {
this.restart = false
this.process.kill()
}
startCollection() {
this.staticInformations()
var dockerCollection, processCollection, memCollection,
servicesCollection, graphicsCollection
(dockerCollection = () => {
this.dockerSummary(() => {
setTimeout(dockerCollection.bind(this), 5000)
})
})();
(processCollection = () => {
this.processesSummary(() => {
setTimeout(processCollection.bind(this), 5000)
})
})();
(graphicsCollection = () => {
this.graphicsInformations(() => {
setTimeout(graphicsCollection.bind(this), 20000)
})
})();
// (servicesCollection = () => {
// this.servicesSummary(() => {
// setTimeout(servicesCollection.bind(this), 60000)
// })
// })();
(memCollection = () => {
this.memStats(() => {
setTimeout(memCollection.bind(this), 1000)
})
})();
//this.networkConnectionsWorker()
this.disksStatsWorker()
this.networkStatsWorker()
this.cpuStatsWorker()
this.fdStatsWorker()
setInterval(() => {
if (process.connected == false) {
console.error('Sysinfos not connected, exiting')
process.exit()
}
try {
process.send(JSON.stringify({cmd: 'ping'}))
} catch(e) {
console.error('PM2 is dead while doing process.send')
process.exit()
}
this.ping_timeout = setTimeout(() => {
console.error('PM2 is dead while waiting for a pong')
process.exit()
}, 2000)
}, 3000)
// Systeminfo receive command
process.on('message', (cmd) => {
if (cmd == 'query') {
try {
var res = JSON.stringify({
cmd: 'query:res',
data: this.report()
})
process.send(res)
} catch (e) {
console.error('Could not retrieve system informations', e)
}
}
else if (cmd == 'pong') {
clearTimeout(this.ping_timeout)
}
})
}
staticInformations() {
var getCPU = () => {
return sysinfo.cpu()
.then(data => {
this.infos.cpu = {
brand: data.manufacturer,
model: data.brand,
speed: data.speedmax,
cores: data.cores,
physicalCores: data.physicalCores
}
})
}
var getBaseboard = () => {
return sysinfo.system()
.then(data => {
this.infos.baseboard = {
manufacturer: data.manufacturer,
model: data.model,
version: data.version
}
})
}
var getOsInfo = () => {
return sysinfo.osInfo()
.then(data => {
this.infos.os = {
platform: data.platform,
distro: data.distro,
release: data.release,
codename: data.codename,
kernel: data.kernel,
arch: data.arch
}
})
}
var diskLayout = () => {
this.infos.storage.physical_disks = []
return sysinfo.diskLayout()
.then(disks => {
disks.forEach((disk) => {
this.infos.storage.physical_disks.push({
device: disk.device,
type: disk.type,
name: disk.name,
interfaceType: disk.interfaceType,
vendor: disk.vendor
})
})
})
}
getBaseboard()
.then(getCPU)
.then(getOsInfo)
.then(diskLayout)
.catch(e => {
debug(`Error when trying to retrieve static informations`, e)
})
}
dockerSummary(cb = () => {}) {
sysinfo.dockerContainers('all')
.then(containers => {
var non_exited_containers = containers.filter(container => container.state != 'exited')
var new_containers = []
async.forEach(non_exited_containers, (container, next) => {
sysinfo.dockerContainerStats(container.id)
.then(stats => {
var meta = container
stats[0].cpu_percent = (stats[0].cpu_percent).toFixed(1)
stats[0].mem_percent = (stats[0].mem_percent).toFixed(1)
stats[0].netIO.tx = (stats[0].netIO.tx / DEFAULT_CONVERSION).toFixed(1)
stats[0].netIO.rx = (stats[0].netIO.rx / DEFAULT_CONVERSION).toFixed(1)
stats[0].blockIO.w = (stats[0].blockIO.w / DEFAULT_CONVERSION).toFixed(1)
stats[0].blockIO.r = (stats[0].blockIO.r / DEFAULT_CONVERSION).toFixed(1)
meta.stats = Array.isArray(stats) == true ? stats[0] : null
new_containers.push(meta)
next()
})
.catch(e => {
debug(e)
next()
})
}, (err) => {
if (err)
debug(err)
this.infos.containers = new_containers.sort((a, b) => {
var textA = a.name.toUpperCase();
var textB = b.name.toUpperCase();
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
})
return cb()
})
})
.catch(e => {
debug(e)
return cb()
})
}
servicesSummary() {
sysinfo.services('*')
.then(services => {
this.infos.services.running = services.filter(service => service.running === true)
this.infos.services.stopped = services.filter(service => service.running === false)
})
.catch(e => {
debug(e)
})
}
processesSummary(cb) {
psList()
.then(processes => {
this.infos.processes.cpu_sorted = processes
.filter(a => !(a.cmd.includes('SystemInfo') && a.cmd.includes('PM2')))
.sort((a, b) => b.cpu - a.cpu).slice(0, 5)
this.infos.processes.mem_sorted = processes
.filter(a => !(a.cmd.includes('SystemInfo') && a.cmd.includes('PM2')))
.sort((a, b) => b.memory - a.memory).slice(0, 5)
return cb()
})
.catch(e => {
console.error(`Error when retrieving process list`, e)
return cb()
})
}
graphicsInformations(cb) {
sysinfo.graphics()
.then(data => {
let cg1 = data.controllers[0]
if (!cg1) return cb()
this.infos.graphics = {
model: cg1.model,
driverVersion: cg1.driverVersion,
memTotal: cg1.memoryTotal,
memUsed: cg1.memoryUsed,
temperature: cg1.temperatureGpu
}
return cb()
})
.catch(e => {
console.error(`Error while retrieving graphics informations`)
console.error(e)
return cb()
})
}
cpuStatsWorker() {
var cpuTempCollection
(cpuTempCollection = () => {
sysinfo.cpuTemperature()
.then(data => {
this.infos.cpu.temperature = data.main
setTimeout(cpuTempCollection.bind(this), 2000)
})
.catch(e => {
setTimeout(cpuTempCollection.bind(this), 2000)
})
})()
function fetch () {
const startMeasure = computeUsage()
setTimeout(_ => {
var endMeasure = computeUsage()
var idleDifference = endMeasure.idle - startMeasure.idle
var totalDifference = endMeasure.total - startMeasure.total
var percentageCPU = (10000 - Math.round(10000 * idleDifference / totalDifference)) / 100
this.infos.cpu.usage = (percentageCPU).toFixed(1)
}, 100)
}
function computeUsage () {
let totalIdle = 0
let totalTick = 0
const cpus = os.cpus()
for (var i = 0, len = cpus.length; i < len; i++) {
var cpu = cpus[i]
for (let type in cpu.times) {
totalTick += cpu.times[type]
}
totalIdle += cpu.times.idle
}
return {
idle: parseInt(totalIdle / cpus.length),
total: parseInt(totalTick / cpus.length)
}
}
setInterval(fetch.bind(this), 1000)
fetch.bind(this)()
}
memStats(cb) {
sysinfo.mem()
.then(data => {
this.infos.mem.total = (data.total / DEFAULT_CONVERSION).toFixed()
this.infos.mem.free = (data.free / DEFAULT_CONVERSION).toFixed()
this.infos.mem.active = (data.active / DEFAULT_CONVERSION).toFixed()
this.infos.mem.available = (data.available / DEFAULT_CONVERSION).toFixed()
return cb()
})
.catch(e => {
console.error(`Error while retrieving memory info`)
console.error(e)
return cb()
})
}
networkConnectionsWorker() {
var retrieveConn
(retrieveConn = () => {
sysinfo.networkConnections()
.then(conns => {
this.infos.connections = conns
.filter(conn => conn.localport != '443' && conn.peerport != '443')
.map(conn => `${conn.localaddress}:${conn.localport}-${conn.peeraddress}:${conn.peerport}-${conn.proc ? conn.proc : 'unknown'}`)
setTimeout(retrieveConn.bind(this), 10 * 1000)
})
.catch(e => {
console.error(`Error while retrieving filesystems info`)
console.error(e)
setTimeout(retrieveConn.bind(this), 10 * 1000)
})
})();
}
disksStatsWorker() {
var rx = 0
var wx = 0
var started = false
var fsSizeCollection, ioCollection
(fsSizeCollection = () => {
sysinfo.fsSize()
.then(fss => {
var fse = fss.filter(fs => (fs.size / (1024 * 1024)) > 200)
this.infos.storage.filesystems = fse
setTimeout(fsSizeCollection.bind(this), 30 * 1000)
})
.catch(e => {
console.error(`Error while retrieving filesystem infos (FSSIZE)`, e)
setTimeout(fsSizeCollection.bind(this), 10 * 1000)
})
})();
(ioCollection = () => {
sysinfo.fsStats()
.then(fs_stats => {
var new_rx = fs_stats.rx
var new_wx = fs_stats.wx
var read = ((new_rx - rx) / DEFAULT_CONVERSION).toFixed(3)
var write = ((new_wx - wx) / DEFAULT_CONVERSION).toFixed(3)
if (started == true) {
this.infos.storage.io.read.add(parseFloat(read))
this.infos.storage.io.write.add(parseFloat(write))
}
rx = new_rx
wx = new_wx
started = true
setTimeout(ioCollection.bind(this), 1000)
})
.catch(e => {
console.error(`Error while getting network statistics`, e)
setTimeout(ioCollection.bind(this), 1000)
})
})();
}
fdStatsWorker() {
var getFDOpened = () => {
fs.readFile('/proc/sys/fs/file-nr', (err, out) => {
if (err) return
const output = out.toString().trim()
const parsed = output.split('\t')
if (parsed.length !== 3) return
this.infos.fd.opened = parseInt(parsed[0])
this.infos.fd.max = parseInt(parsed[2])
})
}
setInterval(() => {
getFDOpened()
}, 20 * 1000)
getFDOpened()
}
networkStatsWorker() {
var latencyCollection, networkStatsCollection
// (latencyCollection = () => {
// sysinfo.inetLatency()
// .then(latency => {
// this.infos.network.latency.add(latency)
// setTimeout(latencyCollection.bind(this), 2000)
// })
// .catch(e => {
// debug(e)
// setTimeout(latencyCollection.bind(this), 2000)
// })
// })()
sysinfo.networkInterfaceDefault((net_interface) => {
var started = false
var rx = 0
var tx = 0
var rx_e = 0
var tx_e = 0
var rx_d = 0
var tx_d = 0;
(networkStatsCollection = () => {
sysinfo.networkStats(net_interface)
.then((net) => {
var new_rx = (net[0].rx_bytes - rx) / DEFAULT_CONVERSION
var new_tx = (net[0].tx_bytes - tx) / DEFAULT_CONVERSION
rx = net[0].rx_bytes
tx = net[0].tx_bytes
var new_rx_e = (net[0].rx_errors - rx_e) / DEFAULT_CONVERSION
var new_tx_e = (net[0].tx_errors - tx_e) / DEFAULT_CONVERSION
rx_e = net[0].rx_errors
tx_e = net[0].tx_errors
var new_rx_d = (net[0].rx_dropped - rx_d) / DEFAULT_CONVERSION
var new_tx_d = (net[0].tx_dropped - tx_d) / DEFAULT_CONVERSION
rx_d = net[0].rx_dropped
tx_d = net[0].tx_dropped
if (started == true) {
this.infos.network.rx_5.add(new_rx)
this.infos.network.tx_5.add(new_tx)
this.infos.network.rx_errors_60.add(new_rx_e)
this.infos.network.tx_errors_60.add(new_tx_e)
this.infos.network.rx_dropped_60.add(new_rx_d)
this.infos.network.tx_dropped_60.add(new_tx_d)
}
started = true
setTimeout(networkStatsCollection.bind(this), 1000)
})
.catch(e => {
console.error(`Error on retrieving network stats`, e)
setTimeout(networkStatsCollection.bind(this), 900)
})
})()
})
}
}
module.exports = SystemInfo
if (require.main === module) {
var sys = new SystemInfo()
sys.startCollection()
}

Binary file not shown.

View File

@ -1,63 +0,0 @@
'use strict';
const util = require('util');
const path = require('path');
const childProcess = require('child_process');
const TEN_MEGABYTES = 1000 * 1000 * 10;
const execFile = util.promisify(childProcess.execFile);
const windows = async () => {
// Source: https://github.com/MarkTiedemann/fastlist
const bin = path.join(__dirname, 'fastlist.exe');
const {stdout} = await execFile(bin, {maxBuffer: TEN_MEGABYTES});
return stdout
.trim()
.split('\r\n')
.map(line => line.split('\t'))
.map(([name, pid, ppid]) => ({
name,
pid: Number.parseInt(pid, 10),
ppid: Number.parseInt(ppid, 10)
}));
};
const main = async (options = {}) => {
const flags = (options.all === false ? '' : 'a') + 'wwxo';
const ret = {};
await Promise.all(['comm', 'args', 'ppid', 'uid', '%cpu', '%mem'].map(async cmd => {
const {stdout} = await execFile('ps', [flags, `pid,${cmd}`], {maxBuffer: TEN_MEGABYTES});
for (let line of stdout.trim().split('\n').slice(1)) {
line = line.trim();
const [pid] = line.split(' ', 1);
const val = line.slice(pid.length + 1).trim();
if (ret[pid] === undefined) {
ret[pid] = {};
}
ret[pid][cmd] = val;
}
}));
// Filter out inconsistencies as there might be race
// issues due to differences in `ps` between the spawns
return Object.entries(ret)
.filter(([, value]) => value.comm && value.args && value.ppid && value.uid && value['%cpu'] && value['%mem'])
.map(([key, value]) => ({
pid: Number.parseInt(key, 10),
name: path.basename(value.comm),
cmd: value.args,
ppid: Number.parseInt(value.ppid, 10),
uid: Number.parseInt(value.uid, 10),
cpu: Number.parseFloat(value['%cpu']),
memory: Number.parseFloat(value['%mem'])
}));
};
module.exports = process.platform === 'win32' ? windows : main;
// TODO: remove this in the next major version
module.exports.default = module.exports;

View File

@ -1,9 +1,9 @@
{
"name": "pm2",
"preferGlobal": true,
"version": "4.5.1",
"version": "5.0.0",
"engines": {
"node": ">=8.10.0"
"node": ">=10.0.0"
},
"directories": {
"bin": "./bin",
@ -201,9 +201,6 @@
"mocha": "^7.1.0",
"should": "^13"
},
"optionalDependencies": {
"systeminformation": "^4.32"
},
"bugs": {
"url": "https://github.com/Unitech/pm2/issues"
},