%PDF- %PDF-
Direktori : /lib/node_modules/pm2/node_modules/pm2-sysmonit/src/ |
Current File : //lib/node_modules/pm2/node_modules/pm2-sysmonit/src/SystemInfos.js |
const sysinfo = require('systeminformation') const psList = require('./psList.js') const async = require('async') const MeanCalc = require('./MeanCalc.js') 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, load: null, loads: null }, graphics: { model: null, driverVersion: null, memTotal: null, memUsed: null, temperature: null }, mem: { total: null, free: null, active: null, usage: 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'], default_interface: null, network: {}, // Procs containers: [], processes: { cpu_sorted: null, mem_sorted: null }, services: { running: null, stopped: 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)) Object.keys(report.network).forEach(iname => { report.network[iname] = { ip4: this.infos.network[iname].ip4, ip6: this.infos.network[iname].ip6, tx_5: this.infos.network[iname].tx_5.val(), rx_5: this.infos.network[iname].rx_5.val(), rx_errors_60: this.infos.network[iname].rx_errors_60.val(), tx_errors_60: this.infos.network[iname].tx_errors_60.val(), rx_dropped_60: this.infos.network[iname].rx_dropped_60.val(), tx_dropped_60: this.infos.network[iname].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 } 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) } 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() // 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 getDefaultNetInterface = () => { return sysinfo.networkInterfaceDefault() .then(iface => { this.infos.default_interface = iface }) } 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) .then(getDefaultNetInterface) .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 => { if (!data) return cb() 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, cpuLoad (cpuTempCollection = () => { sysinfo.cpuTemperature() .then(data => { this.infos.cpu.temperature = (data.main).toFixed(1) setTimeout(cpuTempCollection.bind(this), 5000) }) .catch(e => { setTimeout(cpuTempCollection.bind(this), 5000) }) })(); (cpuLoad = () => { sysinfo.currentLoad() .then(data => { this.infos.cpu.load = data.currentLoad.toFixed(1) this.infos.cpu.loads = data.cpus.map(cpu => Math.floor(cpu.load)).join('|') setTimeout(cpuLoad.bind(this), 1000) }) .catch(e => { setTimeout(cpuLoad.bind(this), 1000) }) })(); } memStats(cb) { sysinfo.mem() .then(data => { this.infos.mem.total = (data.total / DEFAULT_CONVERSION / 1024).toFixed(2) this.infos.mem.free = (data.free / DEFAULT_CONVERSION / 1024).toFixed(2) this.infos.mem.active = (data.active / DEFAULT_CONVERSION / 1024).toFixed(2) this.infos.mem.available = (data.available / DEFAULT_CONVERSION / 1024).toFixed(2) this.infos.mem.usage = ((data.active / data.total) * 100).toFixed(1) 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 => { // Get only partition of > 800 and not /boot var fse = fss.filter(fs => ((fs.size / (1024 * 1024)) > 800) && fs.mount != '/boot' && !fs.mount.includes('efi')) 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 = () => { sysinfo.fsOpenFiles() .then(open_files => { this.infos.fd.opened = open_files.allocated this.infos.fd.max = open_files.max }) .catch(e => { console.error(`Could not retrieve fds`) console.error(e) }) } setInterval(() => { getFDOpened() }, 5000) getFDOpened() } networkStatsWorker() { var latencyCollection, networkStatsCollection var self = this function grabStats(inter) { let started = false let rx = 0 let tx = 0 let rx_e = 0 let tx_e = 0 let rx_d = 0 let tx_d = 0 let net_interface = inter.iface; function networkStatsCollection(net_interface) { self.infos.network[net_interface] = { ip4: inter.ip4, ip6: inter.ip6, 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) } sysinfo.networkStats(net_interface) .then((net) => { let new_rx = (net[0].rx_bytes - rx) / DEFAULT_CONVERSION let new_tx = (net[0].tx_bytes - tx) / DEFAULT_CONVERSION rx = net[0].rx_bytes tx = net[0].tx_bytes let new_rx_e = (net[0].rx_errors - rx_e) / DEFAULT_CONVERSION let new_tx_e = (net[0].tx_errors - tx_e) / DEFAULT_CONVERSION rx_e = net[0].rx_errors tx_e = net[0].tx_errors let new_rx_d = (net[0].rx_dropped - rx_d) / DEFAULT_CONVERSION let 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) { self.infos.network[net_interface].rx_5.add(new_rx) self.infos.network[net_interface].tx_5.add(new_tx) self.infos.network[net_interface].rx_errors_60.add(new_rx_e) self.infos.network[net_interface].tx_errors_60.add(new_tx_e) self.infos.network[net_interface].rx_dropped_60.add(new_rx_d) self.infos.network[net_interface].tx_dropped_60.add(new_tx_d) } started = true setTimeout(() => { networkStatsCollection(net_interface) }, 1000) }) .catch(e => { console.error(`Error on retrieving network stats`, e) setTimeout(() => { networkStatsCollection(net_interface) }, 1000) }) } networkStatsCollection(net_interface) } sysinfo.networkInterfaces() .then(interfaces => { interfaces.forEach(inter => { if (inter.ip4 == '127.0.0.1') return grabStats(inter) }) }) .catch(e => { console.error(`Cannot retrieve interfaces`) console.error(e) }) // (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) // }) // })() } } module.exports = SystemInfo if (require.main === module) { var sys = new SystemInfo() sys.startCollection() setInterval(() => { console.log(JSON.stringify(sys.report(), null, 2)) }, 5000) }