Skip to content

Commit

Permalink
Added Data Sampling and fixed unix compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Brumwell committed Nov 16, 2012
1 parent 773dd7b commit 45791ec
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 17 deletions.
12 changes: 7 additions & 5 deletions lib/parsers/unix.js
Expand Up @@ -9,23 +9,25 @@ module.exports = function() {
lines.forEach(function(line) { lines.forEach(function(line) {
var trimmed = line.trim().replace(/\s+/g, ' '), var trimmed = line.trim().replace(/\s+/g, ' '),
data = trimmed && trimmed.split(' ') || [], data = trimmed && trimmed.split(' ') || [],
pid = data[0] && parseInt(data[0], 10), pid = data[0],
pi = pids.indexOf(pid); pi = pids.indexOf(pid);




if (pid && pi !== -1) { if (pid && pi !== -1) {
_this.emit('data', _this._pids[pid], { data = {
cputime: data[1].replace(':', '').replace(':', '.'), cputime: data[1].replace(':', '').replace(':', '.'),
memoryUsage: data[2] ? data[2].replace(/[^\d]/g, '') : '0', memoryUsage: data[2] ? data[2].replace(/[^\d]/g, '') : '0',
uptime: new Date().getTime() - _this._pids[pid].meta._started uptime: new Date().getTime() - _this._pids[pid].meta._started
}) };

_this.emit('data', _this._pids[pid], data)

_this._collect(_this._pids[pid], data);


delete pids[pi]; delete pids[pi];
} }
}) })


console.log(lines, pids);

return pids; return pids;
} }
} }
12 changes: 8 additions & 4 deletions lib/parsers/win.js
Expand Up @@ -12,13 +12,17 @@ module.exports = function() {
pi = pids.indexOf(pid); pi = pids.indexOf(pid);




if (pid && pi !== -1) { if (pid && pi !== -1) {
_this.emit('data', _this._pids[pid], { data = {
cputime: data[ data.length - 2 ].replace(':', '').replace(':', '.'), cputime: data[ data.length - 2 ].replace(':', '').replace(':', '.'),
memoryUsage: data[4] ? data[4].replace(/[^\d]/g, '') : '0', memoryUsage: data[4] ? data[4].replace(/[^\d]/g, '') : '0',
uptime: new Date().getTime() - _this._pids[pid].meta._started uptime: new Date().getTime() - _this._pids[pid].meta._started
}) };


_this.emit('data', _this._pids[pid], data);

_this._collect(_this._pids[pid], data);

delete pids[pi]; delete pids[pi];
} }
}); });
Expand Down
22 changes: 21 additions & 1 deletion lib/vitals.js
@@ -1,6 +1,6 @@
var util = require('util'), var util = require('util'),
os = require('os'), os = require('os'),
Parser = os.platform().indexOf('win') != -1 ? require('./parsers/win') : require('./parsers/linux'), Parser = os.platform().indexOf('win') != -1 ? require('./parsers/win') : require('./parsers/unix'),
EventEmitter = require('events').EventEmitter; EventEmitter = require('events').EventEmitter;




Expand All @@ -11,6 +11,10 @@ function Vitals(options) {


options.interval = options.interval || 3000; options.interval = options.interval || 3000;


options.sampleRate = 0.5;

options.maxSamples = options.maxSamples || 100;

this.options = options; this.options = options;


this.length = 0; this.length = 0;
Expand Down Expand Up @@ -173,6 +177,22 @@ Vitals.prototype._run = function() {
}); });
} }


Vitals.prototype._collect = function(proc, data) {
if (! Array.isArray(proc.meta._samples)) {
proc.meta._samples = [];
}

if (Math.random() <= this.options.sampleRate) {
data.collected = new Date().getTime();

proc.meta._samples.push(data);

if (proc.meta._samples.length > this.options.maxSamples) {
proc.meta._samples = proc.meta._samples.splice(this.options.maxSamples * -1);
}
}
}

Vitals.prototype.emit = function() { Vitals.prototype.emit = function() {
var _this = this, var _this = this,
args = arguments; args = arguments;
Expand Down
11 changes: 10 additions & 1 deletion readme.md
Expand Up @@ -9,12 +9,15 @@


## Features ## Features


- Windows & Unix support - Windows & Unix support
- Meta data support - Meta data support
- Data sampling


## Options ## Options


- `interval` the interval in which to poll the processes (Default 3000ms) - `interval` the interval in which to poll the processes (Default 3000ms)
- `maxSamples` the maximum number of samples to retain
- `sampleRate` the rate at which to sample data between 0 (disabled) and 1 for 100%, ie: 0.15 for 15% of the time


## Events ## Events


Expand Down Expand Up @@ -80,6 +83,12 @@ Count number of processes being monitored
vitals.length vitals.length
``` ```


Sampling Data
vitals.on('data', function(proc, data) {
//proc.meta._samples == Array[data, data, data]
//data.collected is the time the sample was collected
});

Events Events


```js ```js
Expand Down
69 changes: 63 additions & 6 deletions test/test.js
Expand Up @@ -301,19 +301,15 @@ describe('Health Monitor', function(){
assert.exists(data.uptime); assert.exists(data.uptime);
assert.exists(data.memoryUsage); assert.exists(data.memoryUsage);
done(); done();
}); });

health.start();
}) })


it('should emit#data that contains process meta data', function(done) { it('should emit#data that contains process meta data', function(done) {
health.on('data', function(proc, data) { health.on('data', function(proc, data) {
assert.exists(proc.meta.custom); assert.exists(proc.meta.custom);
assert.equal('meta', proc.meta.custom); assert.equal('meta', proc.meta.custom);
done(); done();
}); });

health.start();
}) })


afterEach(function() { afterEach(function() {
Expand All @@ -326,6 +322,67 @@ describe('Health Monitor', function(){
}) })
}) })


describe('Data Sampling', function() {
before(function() {
health.options.sampleRate = 1;
});

beforeEach(function() {
health.add(process.pid, {custom: 'meta'});
health.start();
})

it('should provide sample data', function(done) {
health.on('data', function(proc, data) {
assert.exists(proc.meta._samples);
assert.equal(1, proc.meta._samples.length);
done();
})
})

it('should emit#data that contains uptime, cputime, memory usage and timestamp when collected', function(done) {
health.on('data', function(proc, data) {
assert.exists(proc.meta._samples);
assert.exists(proc.meta._samples[0].cputime);
assert.exists(proc.meta._samples[0].uptime);
assert.exists(proc.meta._samples[0].memoryUsage);
assert.exists(proc.meta._samples[0].collected);
done();
})
})

it('should adhere to the max sampling rate', function(done) {
var count = 0,
until = 10;

health.options.maxSamples = 3;

this.timeout(10000);

health.on('data', function(proc, data) {
++count;

assert.exists(proc.meta._samples);
assert.equal(count > 3 ? 3 : count, proc.meta._samples.length);

if (count >= until) {
assert(count > proc.meta._samples.length);
done();
}
})
})

afterEach(function() {
health.removeAllListeners('data');
health.remove();
health.stop();
})

after(function() {
health.remove();
})
});

describe('Stopping', function() { describe('Stopping', function() {
before(function() { before(function() {
health.add(process.pid, {custom: 'meta'}); health.add(process.pid, {custom: 'meta'});
Expand Down

0 comments on commit 45791ec

Please sign in to comment.