added currentLoad per cpu/core, cpu cache (L1, L2, L3) and cpu flags

This commit is contained in:
Sebastian Hildebrandt 2017-01-14 16:59:25 +01:00
parent a4d5b79d43
commit 1178e9c081
5 changed files with 340 additions and 160 deletions

View File

@ -16,6 +16,9 @@
New Functions
- `cpuCache`: returns CPU cache (L1, L2, L3) sizes (new in version 3.14)
- `cpuFlags`: returns CPU flags (new in version 3.14)
- `currentLoad.cpus`: returns current load per cpu/core in an array (new in version 3.14)
- `shell`: returns standard shell e.g. /bin/bash (new in version 3.13)
- `blockDevices`: returns array of block devices like disks, partitions, raids, roms (new in version 3.10)
- `dockerContainerProcesses`: returns processes for a specific docker container (new in version 3.8)
@ -29,8 +32,9 @@ New Functions
- `dockerAll`: returns a list of all docker containers including their stats (new in version 3.1)
- `disksIO`: returns overall diskIO and IOPS values for all mounted volumes (new in version 3.0)
Bug Fixes
Bug Fixes / improvements
- improvement `cpuTemperature` - works now also on Raspberry Pi
- bugfix `disksIO` - on OSX read and write got mixed up
- several bug fixes (like assess errors in `cpuCurrentspeed`, potentially incorrect results in `users`, ...)
- testet on even more platforms and linux distributions
@ -90,6 +94,7 @@ Other changes
| Version | Date | Comment |
| -------------- | -------------- | -------- |
| 3.14.0 | 2017-01-14 | added currentLoad per cpu/core, cpu cache and cpu flags |
| 3.13.0 | 2016-11-23 | added shell (returns standard shell) |
| 3.12.0 | 2016-11-17 | refactoring and extended currentLoad |
| 3.11.2 | 2016-11-16 | blockDevices: improved for older lsblk versions |

View File

@ -42,6 +42,7 @@ si.cpu()
### Latest Activity
- Version 3.14.0: added currentLoad per cpu/core, cpu cache (L1, L2, L3) and cpu flags
- Version 3.13.0: added shell (returns standard shell)
- Version 3.12.0: refactoring and extended currentLoad (better OSX coverage and added irq load).
- Version 3.11.0: blockDevices now also for OSX and also extended (+ label, model, serial, protocol).
@ -124,6 +125,12 @@ This library is splitted in several sections:
| - brand | X | X | e.g. 'Core(TM)2 Duo' |
| - speed | X | X | in GHz e.g. '3.40' |
| - cores | X | X | # cores |
| si.cpuFlags(cb) | X | X | CPU flags|
| si.cpuCache(cb) | X | X | CPU cache sizes |
| - l1d | X | X | L1D size |
| - l1i | X | X | L1I size |
| - l2 | X | X | L2 size |
| - l3 | X | X | L3 size |
| si.cpuCurrentspeed(cb) | X | X | current CPU speed (in GHz)|
| - avg | X | X | avg CPU speed (all cores) |
| - min | X | X | min CPU speed (all cores) |
@ -227,6 +234,7 @@ This library is splitted in several sections:
| - currentload_nice | X | X | CPU-Load Nice in % |
| - currentload_system | X | X | CPU-Load System in % |
| - currentload_irq | X | X | CPU-Load System in % |
| - cpus[] | X | X | current loads per CPU in % |
| si.fullLoad(cb) | X | X | CPU-full load since bootup in % |
| si.services('mysql, apache2', cb) | X | X | pass comma separated string of services |
| - [0].name | X | X | name of service |

View File

@ -25,6 +25,23 @@ const _windows = (_platform == 'Windows_NT');
const NOT_SUPPORTED = 'not supported';
let _cpu_speed = '0.00';
let _current_cpu = {
user: 0,
nice: 0,
system: 0,
idle: 0,
irq: 0,
load: 0,
tick: 0,
ms: 0,
currentload: 0,
currentload_user: 0,
currentload_nice: 0,
currentload_system: 0,
currentload_irq: 0
};
let _cpus = [];
let _corecount = 0;
function cpuBrandManufacturer(res) {
res.brand = res.brand.replace(/\(R\)+/g, "®");
@ -203,16 +220,32 @@ function cpuTemperature(callback) {
if (callback) { callback(result) }
resolve(result);
} else {
exec("/opt/vc/bin/vcgencmd measure_temp", function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
if (lines.length > 0 && lines[0].indexOf('=')) {
result.main = parseFloat(lines[0].split("=")[1]);
result.max = result.main
}
fs.stat('/sys/class/thermal/thermal_zone0/temp', function(err, stat) {
if(err == null) {
exec("cat /sys/class/thermal/thermal_zone0/temp", function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
if (lines.length > 0) {
result.main = parseFloat(lines[0]) / 1000.0;
result.max = result.main
}
}
if (callback) { callback(result) }
resolve(result);
});
} else {
exec("/opt/vc/bin/vcgencmd measure_temp", function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
if (lines.length > 0 && lines[0].indexOf('=')) {
result.main = parseFloat(lines[0].split("=")[1]);
result.max = result.main
}
}
if (callback) { callback(result) }
resolve(result);
});
}
if (callback) { callback(result) }
resolve(result);
});
}
@ -227,3 +260,281 @@ function cpuTemperature(callback) {
}
exports.cpuTemperature = cpuTemperature;
// --------------------------
// CPU Flags
function cpuFlags(callback) {
return new Promise((resolve, reject) => {
process.nextTick(() => {
if (_windows) {
let error = new Error(NOT_SUPPORTED);
if (callback) { callback(NOT_SUPPORTED) }
reject(error);
}
let result = '';
if (_linux) {
exec("lscpu", function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
lines.forEach(function (line) {
if (line.split(':')[0].toUpperCase().indexOf('FLAGS') != -1) {
result = line.split(':')[1].trim().toLowerCase();
}
});
}
if (callback) { callback(result) }
resolve(result);
});
}
if (_darwin) {
exec("sysctl machdep.cpu.features", function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
if (lines.length > 0 && lines[0].indexOf('machdep.cpu.features:') != -1) {
result = lines[0].split(':')[1].trim().toLowerCase();
}
}
if (callback) { callback(result) }
resolve(result);
});
}
});
});
}
exports.cpuFlags = cpuFlags;
// --------------------------
// CPU Flags
function cpuCache(callback) {
return new Promise((resolve, reject) => {
process.nextTick(() => {
if (_windows) {
let error = new Error(NOT_SUPPORTED);
if (callback) { callback(NOT_SUPPORTED) }
reject(error);
}
let result = {};
if (_linux) {
exec("lscpu", function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
lines.forEach(function (line) {
let parts = line.split(':');
if (parts[0].toUpperCase().indexOf('L1D CACHE') != -1) {
result.l1d = parseInt(parts[1].trim()) * (parts[1].indexOf('K') != -1 ? 1024 : 1);
}
if (parts[0].toUpperCase().indexOf('L1I CACHE') != -1) {
result.l1i = parseInt(parts[1].trim()) * (parts[1].indexOf('K') != -1 ? 1024 : 1);
}
if (parts[0].toUpperCase().indexOf('L2 CACHE') != -1) {
result.l2 = parseInt(parts[1].trim()) * (parts[1].indexOf('K') != -1 ? 1024 : 1);
}
if (parts[0].toUpperCase().indexOf('L3 CACHE') != -1) {
result.l3 = parseInt(parts[1].trim()) * (parts[1].indexOf('K') != -1 ? 1024 : 1);
}
});
}
if (callback) { callback(result) }
resolve(result);
});
}
if (_darwin) {
exec("sysctl hw.l1icachesize hw.l1dcachesize hw.l2cachesize hw.l3cachesize", function (error, stdout) {
if (!error) {
let lines = stdout.toString().split('\n');
lines.forEach(function (line) {
let parts = line.split(':');
if (parts[0].toLowerCase().indexOf('hw.l1icachesize') != -1) {
result.l1d = parseInt(parts[1].trim()) * (parts[1].indexOf('K') != -1 ? 1024 : 1);
}
if (parts[0].toLowerCase().indexOf('hw.l1dcachesize') != -1) {
result.l1i = parseInt(parts[1].trim()) * (parts[1].indexOf('K') != -1 ? 1024 : 1);
}
if (parts[0].toLowerCase().indexOf('hw.l2cachesize') != -1) {
result.l2 = parseInt(parts[1].trim()) * (parts[1].indexOf('K') != -1 ? 1024 : 1);
}
if (parts[0].toLowerCase().indexOf('hw.l3cachesize') != -1) {
result.l3 = parseInt(parts[1].trim()) * (parts[1].indexOf('K') != -1 ? 1024 : 1);
}
});
}
if (callback) { callback(result) }
resolve(result);
});
}
});
});
}
exports.cpuCache = cpuCache;
// --------------------------
// CPU - current load - in %
function getLoad() {
return new Promise((resolve) => {
process.nextTick(() => {
let loads = os.loadavg().map(function (x) { return x / util.cores() });
let avgload = parseFloat((Math.max.apply(Math, loads)).toFixed(2));
let result = {};
let now = Date.now() - _current_cpu.ms;
if (now >= 200) {
_current_cpu.ms = Date.now();
const cpus = os.cpus();
let totalUser = 0;
let totalSystem = 0;
let totalNice = 0;
let totalIrq = 0;
let totalIdle = 0;
let cores = [];
_corecount = cpus.length;
for (let i = 0; i < _corecount; i++) {
const cpu = cpus[i].times;
totalUser += cpu.user;
totalSystem += cpu.sys;
totalNice += cpu.nice;
totalIrq += cpu.irq;
totalIdle += cpu.idle;
let tmp_tick = (_cpus && _cpus[i] && _cpus[i].totalTick ? _cpus[i].totalTick : 0);
let tmp_load = (_cpus && _cpus[i] && _cpus[i].totalLoad ? _cpus[i].totalLoad : 0);
let tmp_user = (_cpus && _cpus[i] && _cpus[i].user ? _cpus[i].user : 0);
let tmp_system = (_cpus && _cpus[i] && _cpus[i].sys ? _cpus[i].sys : 0);
let tmp_nice = (_cpus && _cpus[i] && _cpus[i].nice ? _cpus[i].nice : 0);
let tmp_irq = (_cpus && _cpus[i] && _cpus[i].irq ? _cpus[i].irq : 0);
_cpus[i] = cpu;
_cpus[i].totalTick = _cpus[i].user + _cpus[i].sys + _cpus[i].nice + _cpus[i].irq + _cpus[i].idle;
_cpus[i].totalLoad = _cpus[i].user + _cpus[i].sys + _cpus[i].nice + _cpus[i].irq;
_cpus[i].currentTick = _cpus[i].totalTick - tmp_tick;
_cpus[i].load = (_cpus[i].totalLoad - tmp_load) / _cpus[i].currentTick * 100;
_cpus[i].load_user = (_cpus[i].user - tmp_user) / _cpus[i].currentTick * 100;
_cpus[i].load_system = (_cpus[i].sys - tmp_system) / _cpus[i].currentTick * 100;
_cpus[i].load_nice = (_cpus[i].nice - tmp_nice) / _cpus[i].currentTick * 100;
_cpus[i].load_irq = (_cpus[i].irq - tmp_irq) / _cpus[i].currentTick * 100;
cores[i] = {};
cores[i].load = _cpus[i].load;
cores[i].load_user = _cpus[i].load_user;
cores[i].load_system = _cpus[i].load_system;
cores[i].load_nice = _cpus[i].load_nice;
cores[i].load_irq = _cpus[i].load_irq;
}
let totalTick = totalUser + totalSystem + totalNice + totalIrq + totalIdle;
let totalLoad = totalUser + totalSystem + totalNice + totalIrq;
let currentTick = totalTick - _current_cpu.tick;
result = {
avgload: avgload,
currentload: (totalLoad - _current_cpu.load) / currentTick * 100,
currentload_user: (totalUser - _current_cpu.user) / currentTick * 100,
currentload_system: (totalSystem - _current_cpu.system) / currentTick * 100,
currentload_nice: (totalNice - _current_cpu.nice) / currentTick * 100,
currentload_irq: (totalIrq - _current_cpu.irq) / currentTick * 100,
cpus: cores
};
_current_cpu = {
user: totalUser,
nice: totalNice,
system: totalSystem,
idle: totalIdle,
irq: totalIrq,
tick: totalTick,
load: totalLoad,
ms: _current_cpu.ms,
currentload: result.currentload,
currentload_user: result.currentload_user,
currentload_system: result.currentload_system,
currentload_nice: result.currentload_nice,
currentload_irq: result.currentload_irq,
};
} else {
let cores = [];
for (let i = 0; i < _corecount; i++) {
cores[i] = {};
cores[i].load = _cpus[i].load;
cores[i].load_user = _cpus[i].load_user;
cores[i].load_system = _cpus[i].load_system;
cores[i].load_nice = _cpus[i].load_nice;
cores[i].load_irq = _cpus[i].load_irq;
}
result = {
avgload: avgload,
currentload: _current_cpu.currentload,
currentload_user: _current_cpu.currentload_user,
currentload_system: _current_cpu.currentload_system,
currentload_nice: _current_cpu.currentload_nice,
currentload_irq: _current_cpu.currentload_irq,
cpus: cores
};
}
resolve(result);
});
});
}
function currentLoad(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
getLoad().then(result => {
if (callback) { callback(result) }
resolve(result);
})
});
});
}
exports.currentLoad = currentLoad;
// --------------------------
// PS - full load
// since bootup
function getFullLoad() {
return new Promise((resolve) => {
process.nextTick(() => {
const cpus = os.cpus();
let totalUser = 0;
let totalSystem = 0;
let totalNice = 0;
let totalIrq = 0;
let totalIdle = 0;
for (let i = 0, len = cpus.length; i < len; i++) {
const cpu = cpus[i].times;
totalUser += cpu.user;
totalSystem += cpu.sys;
totalNice += cpu.nice;
totalIrq += cpu.irq;
totalIdle += cpu.idle;
}
let totalTicks = totalIdle + totalIrq + totalNice + totalSystem + totalUser;
let result = (totalTicks - totalIdle) / totalTicks * 100.0;
resolve(result);
});
});
}
function fullLoad(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
getFullLoad().then(result => {
if (callback) { callback(result) }
resolve(result);
})
});
});
}
exports.fullLoad = fullLoad;

View File

@ -81,6 +81,7 @@
// --------------------------------
//
// version date comment
// 3.14.0 2017-01-14 added currentLoad per cpu/core, cpu cache (L1, L2, L3) and cpu flags
// 3.13.0 2016-11-23 added shell (determines standard shell)
// 3.12.0 2016-11-17 refactoring and extended currentLoad (better OSX coverage and added irq load)
// 3.11.2 2016-11-16 blockDevices: improved for older lsblk versions
@ -288,7 +289,7 @@ function getDynamicData(srv, iface, callback) {
functionProcessed();
});
processes.currentLoad().then(res => {
cpu.currentLoad().then(res => {
data.currentLoad = res;
functionProcessed();
});
@ -394,8 +395,12 @@ exports.versions = osInfo.versions;
exports.shell = osInfo.shell;
exports.cpu = cpu.cpu;
exports.cpuFlags = cpu.cpuFlags;
exports.cpuCache = cpu.cpuCache;
exports.cpuCurrentspeed = cpu.cpuCurrentspeed;
exports.cpuTemperature = cpu.cpuTemperature;
exports.currentLoad = cpu.currentLoad;
exports.fullLoad = cpu.fullLoad;
exports.mem = mem;
@ -413,8 +418,6 @@ exports.networkInterfaces = network.networkInterfaces;
exports.networkStats = network.networkStats;
exports.networkConnections = network.networkConnections;
exports.currentLoad = processes.currentLoad;
exports.fullLoad = processes.fullLoad;
exports.services = processes.services;
exports.processes = processes.processes;
exports.processLoad = processes.processLoad;

View File

@ -29,153 +29,6 @@ let _process_cpu = {
list: {},
ms: 0
};
let _current_cpu = {
user: 0,
nice: 0,
system: 0,
idle: 0,
irq: 0,
load: 0,
tick: 0,
ms: 0,
currentload: 0,
currentload_user: 0,
currentload_nice: 0,
currentload_system: 0,
currentload_irq: 0
};
// --------------------------
// PS - current load - in %
function getLoad() {
return new Promise((resolve) => {
process.nextTick(() => {
let loads = os.loadavg().map(function (x) { return x / util.cores() });
let avgload = parseFloat((Math.max.apply(Math, loads)).toFixed(2));
let result = {};
let now = Date.now() - _current_cpu.ms;
if (now >= 200) {
_current_cpu.ms = Date.now();
const cpus = os.cpus();
let totalUser = 0;
let totalSystem = 0;
let totalNice = 0;
let totalIrq = 0;
let totalIdle = 0;
for (let i = 0, len = cpus.length; i < len; i++) {
const cpu = cpus[i];
totalUser += cpu.times.user;
totalSystem += cpu.times.sys;
totalNice += cpu.times.nice;
totalIrq += cpu.times.irq;
totalIdle += cpu.times.idle;
}
let totalTick = totalUser + totalSystem + totalNice + totalIrq + totalIdle;
let totalLoad = totalUser + totalSystem + totalNice + totalIrq;
let currentTick = totalTick - _current_cpu.tick;
result = {
avgload: avgload,
currentload: (totalLoad - _current_cpu.load) / currentTick * 100,
currentload_user: (totalUser - _current_cpu.user) / currentTick * 100,
currentload_system: (totalSystem - _current_cpu.system) / currentTick * 100,
currentload_nice: (totalNice - _current_cpu.nice) / currentTick * 100,
currentload_irq: (totalIrq - _current_cpu.irq) / currentTick * 100
};
_current_cpu = {
user: totalUser,
nice: totalNice,
system: totalSystem,
idle: totalIdle,
irq: totalIrq,
tick: totalTick,
load: totalLoad,
ms: _current_cpu.ms,
currentload: result.currentload,
currentload_user: result.currentload_user,
currentload_nice: result.currentload_nice,
currentload_system: result.currentload_system,
currentload_irq: result.currentload_irq,
};
} else {
result = {
avgload: avgload,
currentload: _current_cpu.currentload,
currentload_user: _current_cpu.currentload_user,
currentload_nice: _current_cpu.currentload_nice,
currentload_system: _current_cpu.currentload_system,
currentload_irq: _current_cpu.currentload_irq,
};
}
resolve(result);
});
});
}
function currentLoad(callback) {
return new Promise((resolve) => {
process.nextTick(() => {
getLoad().then(result => {
if (callback) { callback(result) }
resolve(result);
})
});
});
}
exports.currentLoad = currentLoad;
// --------------------------
// PS - full load
// since bootup
function getFullLoad() {
return new Promise((resolve) => {
process.nextTick(() => {
let result = {};
if (_linux) {
if (fs.existsSync('/proc/uptime')) {
let output = fs.readFileSync('/proc/uptime').toString();
output = output.replace(/ +/g, " ").split(' ');
let uptime = parseFloat(output[0]);
let idletime = parseFloat(output[1]) / util.cores();
result.fullload = (uptime - idletime) / uptime * 100.0;
resolve(result);
}
}
if (_darwin) {
result.fullload = 0;
resolve(result);
}
});
});
}
function fullLoad(callback) {
return new Promise((resolve, reject) => {
process.nextTick(() => {
if (_windows) {
let error = new Error(NOT_SUPPORTED);
if (callback) { callback(NOT_SUPPORTED) }
reject(error);
}
getFullLoad().then(result => {
if (callback) { callback(result) }
resolve(result);
})
});
});
}
exports.fullLoad = fullLoad;
// --------------------------
// PS - services