Launch Week Day 3: Introducing Organization Notifications in Socket.Learn More
Socket
Book a DemoSign in
Socket

pidusage

Package Overview
Dependencies
Maintainers
1
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pidusage - npm Package Compare versions

Comparing version
1.2.0
to
2.0.0
+11
examples/README.md
# Example section
## server.js
Used to be tested with an HTTP benchmark tool like this one: https://github.com/wg/wrk.
Start the server, run the tests on `localhost:8020`
## stresstest.js
Just start node stresstest.js (but be carefull though...)
var http = require('http')
var pusage = require('../')
http.createServer(function (req, res) {
res.writeHead(200)
res.end('hello world\n')
}).listen(8020)
var interval = setInterval(function () {
pusage.stat(process.pid, function (err, stat) {
if (err) {
throw err
}
console.log(stat)
})
}, 100)
process.on('exit', function () {
clearInterval(interval)
})
var pusage = require('../')
// stress test to compare with top or another tool
console.log('This is my PID: %s', process.pid)
// classic "drop somewhere"... yeah I'm a lazy guy
var formatBytes = function (bytes, precision) {
var kilobyte = 1024
var megabyte = kilobyte * 1024
var gigabyte = megabyte * 1024
var terabyte = gigabyte * 1024
if ((bytes >= 0) && (bytes < kilobyte)) {
return bytes + ' B '
} else if ((bytes >= kilobyte) && (bytes < megabyte)) {
return (bytes / kilobyte).toFixed(precision) + ' KB '
} else if ((bytes >= megabyte) && (bytes < gigabyte)) {
return (bytes / megabyte).toFixed(precision) + ' MB '
} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
return (bytes / gigabyte).toFixed(precision) + ' GB '
} else if (bytes >= terabyte) {
return (bytes / terabyte).toFixed(precision) + ' TB '
} else {
return bytes + ' B '
}
}
var i = 0
var bigMemoryLeak = []
var stress = function (cb) {
var j = 500
var arr = []
while (j--) {
arr[j] = []
for (var k = 0; k < 1000; k++) {
arr[j][k] = {lorem: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum non odio venenatis, pretium ligula nec, fringilla ipsum. Sed a erat et sem blandit dignissim. Pellentesque sollicitudin felis eu mattis porta. Nullam nec nibh nisl. Phasellus convallis vulputate massa vitae fringilla. Etiam facilisis lectus in odio lacinia rutrum. Praesent facilisis vitae urna a suscipit. Aenean lacinia blandit lorem, et ullamcorper metus sagittis faucibus. Nam porta eros nisi, at adipiscing quam varius eu. Vivamus sed sem quis lorem varius posuere ut quis elit.'}
}
}
bigMemoryLeak.push(arr)
pusage.stat(process.pid, function (err, stat) {
if (err) {
throw err
}
console.log('Pcpu: %s', stat.cpu)
console.log('Mem: %s', formatBytes(stat.memory))
if (i === 100) {
return cb(null, true)
} else if (stat.memory > 3e8) {
console.log("That's enough right?")
cb(null, true)
}
i++
return cb(null, false)
})
}
var interval = function () {
return setTimeout(function () {
stress(function (err, stop) {
if (err) {
throw err
}
if (stop) {
process.exit()
} else {
return interval()
}
})
}, 400)
}
setTimeout(function () {
interval()
}, 2000)
var os = require('os')
var fs = require('fs')
var exec = require('child_process').exec
var parallel = require('./parallel')
/**
* Gathers Clock, PageSize and system uptime through /proc/uptime
* This method is mocked in procfile tests
*/
function updateCpu (cpu, next) {
if (cpu !== null) {
getRealUptime(function (err, uptime) {
if (err) return next(err)
cpu.uptime = uptime
next(null, cpu)
})
return
}
parallel([
getClockAndPageSize,
getRealUptime
], function (err, data) {
if (err) return next(err)
cpu = {
clockTick: data[0].clockTick,
pageSize: data[0].pageSize,
uptime: data[1]
}
next(null, cpu)
})
}
module.exports = updateCpu
/**
* Fallback on os.uptime(), though /proc/uptime is more precise
*/
function getRealUptime (next) {
fs.readFile('/proc/uptime', 'utf8', function (err, uptime) {
if (err || uptime === undefined) {
console.warn("[pidusage] We couldn't find uptime from /proc/uptime, using os.uptime() value")
return next(null, os.uptime())
}
return next(null, parseFloat(uptime.split(' ')[0]))
})
}
function getClockAndPageSize (next) {
parallel([
function getClockTick (cb) {
getconf('CLK_TCK', {default: 100}, cb)
},
function getPageSize (cb) {
getconf('PAGESIZE', {default: 4096}, cb)
}
], function (err, data) {
if (err) return next(err)
next(null, {clockTick: data[0], pageSize: data[1]})
})
}
function getconf (keyword, options, next) {
if (typeof options === 'function') {
next = options
options = { default: '' }
}
exec('getconf ' + keyword, function (error, stdout, stderr) {
if (error !== null) {
console.error('Error while getting ' + keyword, error)
return next(null, options.default)
}
stdout = parseInt(stdout)
if (!isNaN(stdout)) {
return next(null, stdout)
}
return next(null, options.default)
})
}
// execute an array of asynchronous functions in parallel
// @param {Array} fns - an array of functions
// @param {Function} done - callback(err, results)
function parallel (fns, done) {
var pending = fns.length
var results = []
function each (i, err, result) {
results[i] = result
if (--pending === 0 || err) {
done && done(err, results)
done = null
}
}
fns.forEach(function (fn, i) {
fn(function (err, res) {
each(i, err, res)
})
})
}
module.exports = parallel
var os = require('os')
var UNSUPPORTED = 'unsupported'
// Also available "procfile" removed in 2.0.0 because of crappy benchmarks compared to ps
var platformToMethod = {
darwin: 'ps',
sunos: 'ps',
freebsd: 'ps',
netbsd: 'ps',
win: 'wmic',
linux: 'ps',
aix: 'ps',
procfile: 'procfile',
unsupported: UNSUPPORTED
}
var platform = os.platform()
if (platform.match(/^win/)) platform = 'win' // nor is windows a winner...
if (!platformToMethod[platform]) platform = UNSUPPORTED
module.exports = platformToMethod[platform]
module.exports.UNSUPPORTED = UNSUPPORTED
var fs = require('fs')
var path = require('path')
var updateCpu = require('./cpu')
var parallel = require('./parallel')
var cpu = null
function readProcFile (pid, options, done) {
var hst = options.history[pid] ? options.history[pid] : {}
// Arguments to path.join must be strings
fs.readFile(path.join('/proc', '' + pid, 'stat'), 'utf8', function (err, infos) {
if (err) {
return done(err, null)
}
var date = Date.now()
// https://github.com/arunoda/node-usage/commit/a6ca74ecb8dd452c3c00ed2bde93294d7bb75aa8
// preventing process space in name by removing values before last ) (pid (name) ...)
var index = infos.lastIndexOf(')')
infos = infos.substr(index + 2).split(' ')
// according to http://man7.org/linux/man-pages/man5/proc.5.html (index 0 based - 2)
// In kernels before Linux 2.6, start was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks
var stat = {
utime: parseFloat(infos[11]),
stime: parseFloat(infos[12]),
cutime: parseFloat(infos[13]),
cstime: parseFloat(infos[14]),
start: parseFloat(infos[19]) / cpu.clockTick,
rss: parseFloat(infos[21])
}
// http://stackoverflow.com/questions/16726779/total-cpu-usage-of-an-application-from-proc-pid-stat/16736599#16736599
var childrens = options.childrens ? stat.cutime + stat.cstime : 0
var total = (stat.stime - (hst.stime || 0) + stat.utime - (hst.utime || 0) + childrens) / cpu.clockTick
// time elapsed between calls in seconds
var seconds = Math.abs(hst.uptime !== undefined ? cpu.uptime - hst.uptime : stat.start - cpu.uptime)
if (seconds === 0) seconds = 1 // we sure can't divide through 0
options.history[pid] = stat
options.history[pid].uptime = cpu.uptime
var cpuPercent = (total / seconds) * 100
var memory = stat.rss * cpu.pageSize
return done(null, {
cpu: cpuPercent,
memory: memory,
time: ((stat.utime + stat.stime) / cpu.clockTick) * 1000, // elapsed time in ms
start: new Date(date - seconds * 1000), // start date
pid: pid
})
})
}
function procfile (pid, options, done) {
updateCpu(cpu, function (err, result) {
if (err) return done(err)
cpu = result
var fns = []
if (!Array.isArray(pid)) {
pid = [pid]
}
pid.forEach(function (id, i) {
fns[i] = function (cb) {
readProcFile(id, options, cb)
}
})
parallel(fns, done)
})
}
module.exports = procfile
var spawn = require('child_process').spawn
var os = require('os')
var PLATFORM = os.platform()
/**
* Get pid informations through ps command
* @param {Number|Number[]} pid
* @param {Object} options
* @return {Function} callback(err, stat)
* on os x skip headers with pcpu=,rss=
* on linux it could be --no-header
* on solaris 11 can't figure out a way to do this properly so...
*/
function ps (pid, options, done) {
if (Array.isArray(pid)) {
pid = pid.join(',')
}
var args = ['-o', 'pcpu,rss,pid,time', '-p', pid]
if (PLATFORM === 'aix') {
args = ['-o', 'pcpu,rsssize,pid,time', '-p', pid]
}
var ps = spawn('ps', args)
var error
var stdout
ps.on('error', function (err) {
error = err
})
ps.stdout.on('data', function (d) {
stdout += d.toString()
})
ps.on('close', function () {
var date = Date.now()
if (error) return done(error, null)
stdout = stdout.split(os.EOL)
var statistics = []
for (var i = 1; i < stdout.length; i++) {
stdout[i] = stdout[i].trim()
if (!stdout[i]) {
continue
}
var line = stdout[i].replace(/^\s+/, '').replace(/\s\s+/g, ' ').split(' ')
var time = 0
// Example output 7-22:43:36
var tmp = line[3].split(':')
var days = 0
if (~tmp[0].indexOf('-')) {
var daysAndHours = tmp[0].split('-')
tmp[0] = daysAndHours[1]
days = daysAndHours[0]
}
time = (days * 86400 + tmp[0] * 3600 + tmp[1] * 60 + tmp[2]) * 1000
statistics[i - 1] = {
cpu: parseFloat(line[0].replace(',', '.')),
memory: parseFloat(line[1]) * 1024,
pid: parseInt(line[2], 0),
time: time, // time in ms
start: new Date(date - time)
}
}
done(null, statistics)
})
}
module.exports = ps
var format = require('util').format
var os = require('os')
var spawn = require('child_process').spawn
function wmic (pid, options, done) {
var prefix = 'ProcessId='
var whereClause = ''
if (!Array.isArray(pid)) pid = [pid]
var curr = pid[0]
if (!options.history[curr]) options.history[curr] = {}
whereClause = prefix + curr
for (var i = 1; i < pid.length; i++) {
curr = pid[i]
if (!options.history[curr]) options.history[curr] = {}
whereClause += ' or ' + prefix + curr
}
// http://social.msdn.microsoft.com/Forums/en-US/469ec6b7-4727-4773-9dc7-6e3de40e87b8/cpu-usage-in-for-each-active-process-how-is-this-best-determined-and-implemented-in-an?forum=csharplanguage
var args = ['PROCESS', 'where', '"' + whereClause + '"', 'get', 'ProcessId,workingsetsize,usermodetime,kernelmodetime']
var wmic = spawn('wmic', args, {detached: true, windowsHide: true, windowsVerbatimArguments: true})
var stdout = ''
var stderr = ''
var error = ''
// Note: On Windows the returned value includes fractions of a second. Use Math.floor() to get whole seconds.
var uptime = Math.floor(os.uptime())
wmic.stdout.on('data', function (d) {
stdout += d.toString()
})
wmic.stderr.on('data', function (d) {
stderr += d.toString()
})
wmic.on('error', function (err) {
error = '[pidusage] Command "wmic ' + args.join(' ') + '" failed with error ' + err.message
})
wmic.on('close', function (code) {
var date = Date.now()
stdout = stdout.trim()
stderr = stderr.trim()
if (!stdout || code !== 0) {
error += format('%s %s Wmic errored, please open an issue on https://github.com/soyuka/pidusage with this message.%s', os.EOL, new Date().toString(), os.EOL)
error += format('Command was "wmic %s" %s System informations: %s - release: %s %s - type %s %s', args.join(' '), os.EOL, os.EOL, os.release(), os.EOL, os.type(), os.EOL)
stderr = error + (stderr ? format('Wmic reported the following error: %s.', stderr) : 'Wmic reported no errors (stderr empty).')
stderr = format('%s%s%sWmic exited with code %d.', os.EOL, stderr, os.EOL, code)
stderr = format('%s%sStdout was %s', stderr, os.EOL, stdout || 'empty')
return done(new Error(stderr), null)
}
stdout = stdout.split(os.EOL)
var statistics = []
for (var i = 1; i < stdout.length; i++) {
var line = stdout[i].replace(/\s\s+/g, ' ').split(' ')
// results are in alphabetical order
var id = parseInt(line[1], 10)
var hst = options.history[id]
var workingsetsize = parseFloat(line[3])
var stats = {
kernelmodetime: parseFloat(line[0]),
usermodetime: parseFloat(line[2])
}
// process usage since last call (obscure sheeeeet don't ask)
var total = (stats.kernelmodetime - (hst.kernelmodetime || 0) + stats.usermodetime - (hst.usermodetime || 0)) / 10000000
// time elapsed between calls
var seconds = hst.uptime !== undefined ? uptime - hst.uptime : 0
var cpu = seconds > 0 ? (total / seconds) * 100 : 0
options.history[id] = stats
options.history[id].uptime = uptime
statistics[i - 1] = {
cpu: cpu,
memory: workingsetsize,
time: stats.usermodetime + stats.kernelmodetime, // should be ms according to https://msdn.microsoft.com/en-us/library/aa394372(v=vs.85).aspx
start: new Date(date - (stats.usermodetime + stats.kernelmodetime)),
pid: id
}
}
done(null, statistics)
})
wmic.stdin.end()
}
module.exports = wmic
var bench = require('nanobench')
var fs = require('fs')
var history = {}
function clear () {
for (var i in history) {
delete history[i]
}
}
function getProcessList (cb) {
fs.readdir('/proc', function (err, list) {
if (err) throw err
cb(list.filter(function (v) {
return !isNaN(parseInt(v))
}))
})
}
getProcessList(function (list) {
console.log('Benching %d process', list.length)
bench('procfile', function (b) {
var procfile = require('../lib/procfile')
b.start()
procfile(list, {history: history}, function (err, data) {
if (err) throw err
b.end()
clear()
})
})
bench('ps', function (b) {
var ps = require('../lib/ps')
b.start()
ps(list, {history: history}, function (err, data) {
if (err) throw err
b.end()
clear()
})
})
})
var http = require('http')
http.createServer(function (req, res) {
res.writeHead(200)
res.end('hello world\n')
}).listen(8020)
var mockery = require('mockery')
function before () {
mockery.enable({
warnOnReplace: false,
warnOnUnregistered: false,
useCleanCache: true
})
}
function after () {
mockery.deregisterAll()
mockery.disable()
}
function test (tape) {
tape.test('procfile stat', function (t) {
if (require('os').platform() === 'win32') {
return t.end()
}
t.plan(2)
before()
var fs = require('fs')
fs.readFile = function (path, encoding, callback) {
if (path === '/proc/uptime') {
callback(null, '100 0')
return
}
// proc/<pid>/stat
var infos = '0 (test)'
for (var i = 0; i < 22; i++) {
if (i === 12) {
infos += ' ' + currentStime
} else {
infos += ' 0'
}
}
callback(null, infos)
}
var clockTick = 100
var os = require('os')
os.platform = function () { return 'procfile' }
mockery.registerMock('os', os)
mockery.registerMock('fs', fs)
mockery.registerMock('./cpu.js', function (cpu, next) {
next({
clockTick: clockTick,
uptime: clockTick,
pagesize: 4096
})
})
// set the previous history as if kernel module usage had been called before
var kernelModulePid = 0
var currentStime = 10000 * clockTick
var previousStime = 2000 * clockTick
var pidusage = require('..')
pidusage._history[kernelModulePid] = {}
pidusage._history[kernelModulePid].uptime = 0
pidusage._history[kernelModulePid].utime = 0
pidusage._history[kernelModulePid].stime = previousStime
pidusage.stat(kernelModulePid, function (err, stat) {
t.error(err)
t.equal(stat.cpu, (currentStime - previousStime) / clockTick)
after()
})
})
}
module.exports = test
var mockery = require('mockery')
var EventEmitter = require('events')
var streamify = require('string-to-stream')
var through = require('through')
function before () {
mockery.enable({
warnOnReplace: false,
warnOnUnregistered: false,
useCleanCache: true
})
}
function after () {
mockery.deregisterAll()
mockery.disable()
}
function test (tape) {
tape.test('ps stat (darwin)', function (t) {
t.plan(4)
before()
var os = require('os')
os.platform = function () { return 'darwin' }
mockery.registerMock('os', os)
var childprocess = require('child_process')
childprocess.spawn = function (command, args) {
t.equal(command, 'ps')
t.deepEqual(args, ['-o', 'pcpu,rss,pid,time', '-p', process.pid])
var ee = new EventEmitter()
var writable = through(function (data) {
this.queue(data)
})
var data = [
'%CPU RSS PID TIME',
'0.0 1234 ' + process.pid + ' 7-22:43:36'
]
ee.stdout = writable
streamify(data.join(os.EOL)).pipe(writable)
writable.on('end', function () {
ee.emit('close')
})
return ee
}
mockery.registerMock('child_process', childprocess)
// require after mock
var pidusage = require('..')
pidusage.stat(process.pid, {advanced: true}, function (err, stat) {
t.error(err)
t.equal(stat.time, 68658036000)
// @TODO test that the date given is 7 days, 22 hours, 43 minutes and 36 seconds in the past
after()
})
})
}
module.exports = test
var mockery = require('mockery')
var EventEmitter = require('events')
var streamify = require('string-to-stream')
var through = require('through')
function before () {
mockery.enable({
warnOnReplace: false,
warnOnUnregistered: false,
useCleanCache: true
})
}
function after () {
mockery.deregisterAll()
mockery.disable()
}
function test (tape) {
tape.test('wmic stat (win32)', function (t) {
t.plan(6)
before()
var os = require('os')
os.platform = function () { return 'win32' }
mockery.registerMock('os', os)
var childprocess = require('child_process')
childprocess.spawn = function (command, args) {
t.equal(command, 'wmic')
t.deepEqual(args, ['PROCESS', 'where', '"ProcessId=' + process.pid + '"', 'get', 'ProcessId,workingsetsize,usermodetime,kernelmodetime'])
var ee = new EventEmitter()
var writable = through(function (data) {
this.queue(data)
})
var data = [
'KernelModeTime ProcessId UserModeTime WorkingSetSize',
'153750000 ' + process.pid + ' 8556250000 110821376'
]
ee.stdout = writable
ee.stderr = through(function () {})
ee.stdin = {end: function () {}}
streamify(data.join(os.EOL)).pipe(writable)
writable.on('end', function () {
ee.emit('close', 0)
})
return ee
}
mockery.registerMock('child_process', childprocess)
// require after mock
var pidusage = require('..')
pidusage.stat(process.pid, function (err, stat) {
t.error(err)
t.equal(stat.memory, 110821376)
t.equal(stat.time, 8710000000)
t.equal(stat.pid, process.pid)
// @TODO test that the date
after()
})
})
}
module.exports = test
+11
-9

@@ -0,11 +1,13 @@

sudo: false
language: node_js
branches:
only:
- master
node_js:
- '9'
- '8'
- '6'
- '4'
os:
- linux
- osx
node_js:
- "8"
- "6"
- "4"
- linux
- osx
cache:
directories:
- node_modules
init:
- git config --global core.autocrlf input
- git config --global core.autocrlf input
build: off
environment:
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.12"
- nodejs_version: "4"
- nodejs_version: "5"
- nodejs_version: '9'
- nodejs_version: '8'
- nodejs_version: '6'
- nodejs_version: '4'
platform:
- x86
- x64
cache:
- node_modules
install:
- ps: Install-Product node $env:nodejs_version
- node --version
- npm --version
- npm install
test_script:
- node --version
- npm --version
- cmd: npm test
matrix:
allow_failures:
- nodejs_version: "0.10"
build: off
- npm test

@@ -0,1 +1,15 @@

### 2.0
There is no BC break but because the code got refactored a lot and that the default retrieval method has changed we're bumping a major version.
- allow multiple pids
- remove `advanced` option
- `start` result is now a `Date` instance
- don't use `/proc` files anymore but use `ps` instead
- more tests
### 1.2.0
Introduce `advanced` option to get time, and start
### 1.1.0

@@ -2,0 +16,0 @@

+18
-25
var os = require('os')
var stats = require('./lib/stats')
var platform = require('./lib/platform')
var history = {}
var wrapper = function (statType) {
var wrapper = function (method) {
return function (pid, options, cb) {

@@ -11,33 +13,24 @@ if (typeof options === 'function') {

return stats[statType](pid, options, cb)
if (method === platform.UNSUPPORTED) {
return cb(new Error(os.platform() + ' is not supported yet, please open an issue (https://github.com/soyuka/pidusage)'), null)
}
options.history = history
return stats[method](pid, options, cb)
}
}
var pusage = {
darwin: wrapper('ps'),
sunos: wrapper('ps'),
freebsd: wrapper('ps'),
netbsd: wrapper('proc'),
win: wrapper('win'),
linux: wrapper('proc'),
aix: wrapper('ps'),
unsupported: function (pid, options, cb) {
cb = typeof options === 'function' ? options : cb
exports.stat = wrapper(platform)
cb(new Error(os.platform() + ' is not supported yet, please fire an issue (https://github.com/soyuka/pidusage)'))
exports.unmonitor = function (pid) {
if (!pid) {
for (var i in history) {
delete history[i]
}
return
}
}
var platform = os.platform()
platform = platform.match(/^win/) ? 'win' : platform // nor is windows a winner...
platform = pusage[platform] ? platform : 'unsupported'
exports.stat = function () {
pusage[platform].apply(stats, [].slice.call(arguments))
delete history[pid]
}
exports.unmonitor = function (pid) {
delete stats.history[pid]
}
exports._history = stats.history
exports._history = history

@@ -1,232 +0,36 @@

var os = require('os')
var fs = require('fs')
var p = require('path')
var exec = require('child_process').exec
var spawn = require('child_process').spawn
var helpers = require('./helpers')
var format = require('util').format
var PLATFORM = os.platform()
// Statistics processor files
var wmic = require('./wmic')
var ps = require('./ps')
var procfile = require('./procfile')
var stats = {
history: {},
cpu: null, // used to store cpu informations
proc: function (pid, options, done) {
var self = this
/**
* Just a callback wrapper to keep backward compatibility
*/
function callback (err, statistics, options, done) {
if (err) return done(err, null)
if (this.cpu !== null) {
fs.readFile('/proc/uptime', 'utf8', function (err, uptime) {
if (err) {
return done(err, null)
}
// BC
if (statistics.length === 1) {
return done(null, statistics[0])
}
if (uptime === undefined) {
console.error("[pidusage] We couldn't find uptime from /proc/uptime")
self.cpu.uptime = os.uptime()
} else {
self.cpu.uptime = uptime.split(' ')[0]
}
return done(null, statistics)
}
return self.proc_calc(pid, options, done)
})
} else {
helpers.cpu(function (err, cpu) {
if (err) {
return done(err, null)
}
self.cpu = cpu
return self.proc_calc(pid, options, done)
})
}
},
proc_calc: function (pid, options, done) {
pid = parseInt(pid, 10)
var history = this.history[pid] ? this.history[pid] : {}
var cpu = this.cpu
var self = this
// Arguments to path.join must be strings
fs.readFile(p.join('/proc', '' + pid, 'stat'), 'utf8', function (err, infos) {
if (err) {
return done(err, null)
}
// https://github.com/arunoda/node-usage/commit/a6ca74ecb8dd452c3c00ed2bde93294d7bb75aa8
// preventing process space in name by removing values before last ) (pid (name) ...)
var index = infos.lastIndexOf(')')
infos = infos.substr(index + 2).split(' ')
// according to http://man7.org/linux/man-pages/man5/proc.5.html (index 0 based - 2)
// In kernels before Linux 2.6, start was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks
var stat = {
utime: parseFloat(infos[11]),
stime: parseFloat(infos[12]),
cutime: parseFloat(infos[13]),
cstime: parseFloat(infos[14]),
start: parseFloat(infos[19]) / cpu.clockTick,
rss: parseFloat(infos[21])
}
// http://stackoverflow.com/questions/16726779/total-cpu-usage-of-an-application-from-proc-pid-stat/16736599#16736599
var childrens = options.childrens ? stat.cutime + stat.cstime : 0
var total = stat.stime - (history.stime || 0) + stat.utime - (history.utime || 0) + childrens
total = total / cpu.clockTick
// time elapsed between calls
var seconds = history.uptime !== undefined ? cpu.uptime - history.uptime : stat.start - cpu.uptime
seconds = Math.abs(seconds)
seconds = seconds === 0 ? 1 : seconds // we sure can't divide through 0
self.history[pid] = stat
self.history[pid].uptime = cpu.uptime
var cpuPercent = (total / seconds) * 100
var memory = stat.rss * cpu.pagesize
if (!options.advanced) {
return done(null, {
cpu: cpuPercent,
memory: memory
})
}
return done(null, {
cpu: cpuPercent,
memory: memory,
time: stat.utime + stat.stime,
start: stat.start
})
module.exports = {
procfile: function (pid, options, done) {
procfile(pid, options, function (err, statistics) {
callback(err, statistics, options, done)
})
},
/**
* Get pid informations through ps command
* @param {int} pid
* @return {Function} done (err, stat)
* on os x skip headers with pcpu=,rss=
* on linux it could be --no-header
* on solaris 11 can't figure out a way to do this properly so...
*/
ps: function (pid, options, done) {
pid = parseInt(pid, 10)
var cmd = 'ps -o pcpu,rss -p '
if (options.advanced) {
cmd = 'ps -o pcpu,rss,time,start -p '
if (PLATFORM === 'aix') {
cmd = 'ps -o pcpu,rssize,time,start -p '
}
} else if (PLATFORM === 'aix') {
cmd = 'ps -o pcpu,rssize -p ' // this one could work on other platforms see AIX section in man ps
}
exec(cmd + pid, function (err, stdout, stderr) {
if (err) {
return done(err, null)
}
stdout = stdout.split(os.EOL)[1]
stdout = stdout.replace(/^\s+/, '').replace(/\s\s+/g, ' ').split(' ')
var cpuPercent = parseFloat(stdout[0].replace(',', '.'))
var memory = parseFloat(stdout[1]) * 1024
if (!options.advanced) {
return done(null, {
cpu: cpuPercent,
memory: memory
})
}
return done(null, {
cpu: cpuPercent,
memory: memory,
time: parseFloat(stdout[2]),
start: parseFloat(stdout[3])
})
ps(pid, options, function (err, statistics) {
callback(err, statistics, options, done)
})
},
/**
* This is really in a beta stage
*/
win: function (pid, options, done) {
pid = parseInt(pid, 10)
var history = this.history[pid] ? this.history[pid] : {}
// http://social.msdn.microsoft.com/Forums/en-US/469ec6b7-4727-4773-9dc7-6e3de40e87b8/cpu-usage-in-for-each-active-process-how-is-this-best-determined-and-implemented-in-an?forum=csharplanguage
var args = 'PROCESS ' + pid + ' get workingsetsize,usermodetime,kernelmodetime'
var wmic = spawn('wmic', args.split(' '), {detached: true})
var stdout = ''
var stderr = ''
var self = this
// Note: On Windows the returned value includes fractions of a second. Use Math.floor() to get whole seconds.
var uptime = Math.floor(os.uptime())
wmic.stdout.on('data', function (d) {
stdout += d.toString()
wmic: function (pid, options, done) {
wmic(pid, options, function (err, statistics) {
callback(err, statistics, options, done)
})
wmic.stderr.on('data', function (d) {
stderr += d.toString()
})
wmic.on('error', function (err) {
console.error('[pidusage] Command "wmic ' + args + '" failed with error %s', err)
})
wmic.on('close', function (code) {
stdout = stdout.trim()
stderr = stderr.trim()
if (!stdout || code !== 0) {
var error = format('%s Wmic errored, please open an issue on https://github.com/soyuka/pidusage with this message.%s', new Date().toString(), os.EOL)
error += format('Command was "wmic %s" %s System informations: %s - release: %s %s - type %s %s', args, os.EOL, os.EOL, os.release(), os.EOL, os.type(), os.EOL)
stderr = error + (stderr ? format('Wmic reported the following error: %s.', stderr) : 'Wmic reported no errors (stderr empty).')
stderr = format('%s%s%sWmic exited with code %d.', os.EOL, stderr, os.EOL, code)
stderr = format('%s%sStdout was %s', stderr, os.EOL, stdout || 'empty')
return done(new Error(stderr, null))
}
stdout = stdout.split(os.EOL)[1].replace(/\s\s+/g, ' ').split(' ')
var stats = {
kernelmodetime: parseFloat(stdout[0]),
usermodetime: parseFloat(stdout[1])
}
var workingsetsize = parseFloat(stdout[2])
// process usage since last call
var total = stats.kernelmodetime - (history.kernelmodetime || 0) + stats.usermodetime - (history.usermodetime || 0)
total = total / 10000000
// time elapsed between calls
var seconds = history.uptime !== undefined ? uptime - history.uptime : 0
var cpu = 0
if (seconds > 0) {
cpu = (total / seconds) * 100
}
self.history[pid] = stats
self.history[pid].uptime = uptime
if (!options.advanced) {
return done(null, {cpu: cpu, memory: workingsetsize})
}
return done(null, {
cpu: cpu,
memory: workingsetsize,
time: stats.usermodetime + stats.kernelmodetime,
start: seconds
})
})
wmic.stdin.end()
}
}
module.exports = stats
{
"name": "pidusage",
"version": "1.2.0",
"version": "2.0.0",
"description": "Cross-platform process cpu % and memory usage of a PID — Edit",

@@ -8,6 +8,9 @@ "main": "index.js",

"devDependencies": {
"chai": "~3.4.1",
"mocha": "~2.3.4",
"faucet": "0.0.1",
"mockery": "1.4.0",
"standard": "^10.0.3"
"nanobench": "^2.1.1",
"standard": "^10.0.3",
"string-to-stream": "^1.1.0",
"tape": "^4.9.0",
"through": "^2.3.8"
},

@@ -18,3 +21,3 @@ "engines": {

"scripts": {
"test": "standard index.js lib/*.js test/*.js && mocha test/test.js --reporter min && node test/stresstest.js"
"test": "standard index.js lib/*.js test/*.js && node test/test.js | faucet"
},

@@ -21,0 +24,0 @@ "repository": {

@@ -47,3 +47,3 @@ pidusage

```javascript
pusage(process.pid, {advanced: true}, function (err, stat) {
pusage.stat(process.pid, {advanced: true}, function (err, stat) {
console.log(stat.time, stat.start)

@@ -58,4 +58,4 @@ })

- `memory` memory bytes
- `time` user + system time
- `start` time process was started
- `time` total cpu time in miliseconds
- `start` Date when process was started
```

@@ -106,4 +106,8 @@

#### pidusage-promise
Need promise? Use [`pidusage-promise`](https://github.com/soyuka/pidusage-promise)!
## Licence
MIT

@@ -1,163 +0,70 @@

/* global beforeEach, afterEach, it, describe */
var mockery = require('mockery')
var expect = require('chai').expect
var os = require('os')
var path = require('path')
var test = require('tape')
var fork = require('child_process').fork
var platform = require('../lib/platform')
var pidusage = require('../')
// classic "drop somewhere"... yeah I'm a lazy guy
var formatBytes = function (bytes, precision) {
var kilobyte = 1024
var megabyte = kilobyte * 1024
var gigabyte = megabyte * 1024
var terabyte = gigabyte * 1024
test('integration', function (t) {
t.plan(5)
if ((bytes >= 0) && (bytes < kilobyte)) {
return bytes + ' B '
} else if ((bytes >= kilobyte) && (bytes < megabyte)) {
return (bytes / kilobyte).toFixed(precision) + ' KB '
} else if ((bytes >= megabyte) && (bytes < gigabyte)) {
return (bytes / megabyte).toFixed(precision) + ' MB '
} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
return (bytes / gigabyte).toFixed(precision) + ' GB '
} else if (bytes >= terabyte) {
return (bytes / terabyte).toFixed(precision) + ' TB '
} else {
return bytes + ' B '
}
}
t.equal(typeof pidusage.stat, 'function')
t.equal(typeof pidusage.unmonitor, 'function')
describe('pid usage', function () {
this.timeout(10000)
beforeEach(function () {
mockery.enable({
warnOnReplace: false,
warnOnUnregistered: false,
useCleanCache: true
})
pidusage.stat(process.pid, function (err, stats) {
t.comment('Pid: ' + process.pid + '. Platform: ' + os.platform())
console.log(stats)
t.error(err)
t.deepEqual(Object.keys(stats).sort(), ['cpu', 'memory', 'pid', 'start', 'time'])
t.ok(typeof stats.start, 'Date')
})
})
afterEach(function () {
mockery.deregisterAll()
mockery.disable()
})
test('unmonitor with pid (only wmic and procfile)', function (t) {
if (platform === 'ps' || platform === platform.UNSUPPORTED) {
t.end()
return
}
it('should get pid usage', function (cb) {
var pusage = require('../').stat
pusage(process.pid, function (err, stat) {
expect(err).to.equal(null)
expect(stat).to.be.an('object')
expect(stat).to.have.property('cpu')
expect(stat).to.have.property('memory')
t.plan(3)
console.log('Pcpu: %s', stat.cpu)
console.log('Mem: %s', formatBytes(stat.memory))
cb()
})
pidusage.stat(process.pid, {advanced: true}, function (err, stats) {
t.error(err)
t.ok(pidusage._history[process.pid])
pidusage.unmonitor(process.pid)
t.notOk(pidusage._history[process.pid])
})
})
it('should get advanced pid usage', function (cb) {
var pusage = require('../').stat
pusage(process.pid, {advanced: true}, function (err, stat) {
expect(err).to.equal(null)
expect(stat).to.be.an('object')
expect(stat).to.have.property('cpu')
expect(stat).to.have.property('memory')
expect(stat).to.have.property('time')
expect(stat).to.have.property('start')
test('unmonitor without pid (only wmic and procfile)', function (t) {
if (platform === 'ps' || platform === platform.UNSUPPORTED) {
t.end()
return
}
console.log('Pcpu: %s', stat.cpu)
console.log('Mem: %s', formatBytes(stat.memory))
t.plan(3)
cb()
})
pidusage.stat(process.pid, {advanced: true}, function (err, stats) {
t.error(err)
t.ok(pidusage._history[process.pid])
pidusage.unmonitor()
t.notOk(pidusage._history[process.pid])
})
})
it('should get pid usage multiple time', function (cb) {
var pusage = require('../').stat
var num = 0
var interval
test('integration mutliple pids', function (t) {
t.plan(3)
var p = fork(path.join(__dirname, './fixtures/http.js'))
var pids = [process.pid, p.pid]
function launch () {
pusage(process.pid, function (err, stat) {
expect(err).to.equal(null)
expect(stat).to.be.an('object')
expect(stat).to.have.property('cpu')
expect(stat).to.have.property('memory')
console.log('Pcpu: %s', stat.cpu)
console.log('Mem: %s', formatBytes(stat.memory))
if (++num === 5) {
clearInterval(interval)
cb()
} else {
setTimeout(launch, 100)
}
})
}
interval = setTimeout(launch, 1000)
pidusage.stat(pids, function (err, stats) {
t.error(err)
t.equal(stats.length, 2)
t.deepEqual(Object.keys(stats[1]).sort(), ['cpu', 'memory', 'pid', 'start', 'time'])
p.kill()
})
})
it('should calculate correct cpu when user space time is zero (kernel module)', function (cb) {
// force platform to linux to test this case
var os = require('os')
os.platform = function () {
return 'linux'
}
// override readFile to simulate the system time only (kernel module) case
var fs = require('fs')
var clockTick = 100
fs.readFile = function (path, encoding, callback) {
if (path === '/proc/uptime') {
callback(null, '0 0')
} else { // proc/<pid>/stat
var infos = '0 (test)'
for (var i = 0; i < 22; i++) {
if (i === 12) {
infos += ' ' + currentStime
} else {
infos += ' 0'
}
}
callback(null, infos)
}
}
var helpers = require('../lib/helpers')
helpers.cpu = function (next) {
next(null, {
clockTick: clockTick,
uptime: clockTick,
pagesize: 4096
})
}
// mock out to simulate kernel module and linux platform
mockery.registerMock('fs', fs)
mockery.registerMock('os', os)
mockery.registerMock('./helpers.js', helpers)
var pusage = require('..')
// set the previous history as if kernel module usage had been called before
var kernelModulePid = 0
var currentStime = 10000 * clockTick
var previousStime = 2000 * clockTick
pusage._history[kernelModulePid] = {}
pusage._history[kernelModulePid].uptime = 0
pusage._history[kernelModulePid].utime = 0
pusage._history[kernelModulePid].stime = previousStime
pusage.stat(kernelModulePid, function (err, stat) {
if (err) {
return cb(err)
}
expect(stat.cpu).to.be.equal((currentStime - previousStime) / clockTick)
cb()
})
})
})
require('./procfile')(test)
require('./ps')(test)
require('./wmic')(test)

Sorry, the diff of this file is not supported yet

var os = require('os')
var exec = require('child_process').exec
module.exports = {
getconf: function (keyword, options, next) {
if (typeof options === 'function') {
next = options
options = { default: '' }
}
exec('getconf ' + keyword, function (error, stdout, stderr) {
if (error !== null) {
console.error('Error while getting ' + keyword, error)
return next(null, options.default)
}
stdout = parseInt(stdout)
if (!isNaN(stdout)) {
return next(null, stdout)
}
return next(null, options.default)
})
},
cpu: function (next) {
var self = this
self.getconf('CLK_TCK', {default: 100}, function (err, clockTick) {
if (err) {
return next(err)
}
self.getconf('PAGESIZE', {default: 4096}, function (err, pagesize) {
if (err) {
return next(err)
}
next(null, {
clockTick: clockTick,
uptime: os.uptime(),
pagesize: pagesize
})
})
})
}
}
#Test section
## test.js
Run this one first. `mocha test`
## server.js
Used to be tested with an HTTP benchmark tool like this one: https://github.com/wg/wrk.
Start the server, run the tests on `localhost:8020`
## stresstest.js
Just start node stresstest.js (but be carefull though...)
var http = require('http')
var pusage = require('../')
http.createServer(function (req, res) {
res.writeHead(200)
res.end('hello world\n')
}).listen(8020)
var interval = setInterval(function () {
pusage.stat(process.pid, function (err, stat) {
if (err) {
throw err
}
console.log(stat)
})
}, 100)
process.on('exit', function () {
clearInterval(interval)
})
var pusage = require('../')
// stress test to compare with top or another tool
console.log('This is my PID: %s', process.pid)
// classic "drop somewhere"... yeah I'm a lazy guy
var formatBytes = function (bytes, precision) {
var kilobyte = 1024
var megabyte = kilobyte * 1024
var gigabyte = megabyte * 1024
var terabyte = gigabyte * 1024
if ((bytes >= 0) && (bytes < kilobyte)) {
return bytes + ' B '
} else if ((bytes >= kilobyte) && (bytes < megabyte)) {
return (bytes / kilobyte).toFixed(precision) + ' KB '
} else if ((bytes >= megabyte) && (bytes < gigabyte)) {
return (bytes / megabyte).toFixed(precision) + ' MB '
} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
return (bytes / gigabyte).toFixed(precision) + ' GB '
} else if (bytes >= terabyte) {
return (bytes / terabyte).toFixed(precision) + ' TB '
} else {
return bytes + ' B '
}
}
var i = 0
var bigMemoryLeak = []
var stress = function (cb) {
var j = 500
var arr = []
while (j--) {
arr[j] = []
for (var k = 0; k < 1000; k++) {
arr[j][k] = {lorem: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum non odio venenatis, pretium ligula nec, fringilla ipsum. Sed a erat et sem blandit dignissim. Pellentesque sollicitudin felis eu mattis porta. Nullam nec nibh nisl. Phasellus convallis vulputate massa vitae fringilla. Etiam facilisis lectus in odio lacinia rutrum. Praesent facilisis vitae urna a suscipit. Aenean lacinia blandit lorem, et ullamcorper metus sagittis faucibus. Nam porta eros nisi, at adipiscing quam varius eu. Vivamus sed sem quis lorem varius posuere ut quis elit.'}
}
}
bigMemoryLeak.push(arr)
pusage.stat(process.pid, function (err, stat) {
if (err) {
throw err
}
console.log('Pcpu: %s', stat.cpu)
console.log('Mem: %s', formatBytes(stat.memory))
if (i === 100) {
return cb(null, true)
} else if (stat.memory > 3e8) {
console.log("That's enough right?")
cb(null, true)
}
i++
return cb(null, false)
})
}
var interval = function () {
return setTimeout(function () {
stress(function (err, stop) {
if (err) {
throw err
}
if (stop) {
process.exit()
} else {
return interval()
}
})
}, 400)
}
setTimeout(function () {
interval()
}, 2000)
app.post("/downloadCertsZip", function (req, res) {
var hostPath = __dirname +'/certificate/'+req.body.dp_hostname;
var interPath = __dirname +'/certificate/'+req.body.dp_hostname+'/intermediate/';
if (fs.existsSync(hostPath) && fs.existsSync(interPath)){
fs.readdir(interPath,function(err, interfiles){
if (err) {
//this is not how you should handle errors, you need to give a response to the user.....
return console.error(err);
}
var fl = interfiles.length;
console.log("length",fl);
if(fl >0){
var certPath = __dirname +'/certificate/'+req.body.dp_hostname+'/certificate/';
res.type('application/zip');
res.attachment('file.zip');
var archive = archiver('zip');
archive.pipe(res);
fs.readdir(certPath,function(err, files){
if (err) {
//this is not how you should handle errors...
return console.error(err);
}
archive.append(fs.createReadStream(certPath+files[0]),{name:files[0]})
interfiles.forEach(function(interfile){
if(interfile){
archive.append(fs.createReadStream(interPath+interfile),{name:interfile})
}
});
archive.finalize();
});
}
// nothing here again?
});
}
//nothing happens when files does not exist? You need to close the request...
});