Socket
Socket
Sign inDemoInstall

pidusage

Package Overview
Dependencies
Maintainers
1
Versions
50
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

examples/README.md

14

CHANGELOG.MD

@@ -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 @@

43

index.js
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

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc