ca-apm-probe
Version:
CA APM Node.js Agent monitors real-time health and performance of Node.js applications
144 lines (113 loc) • 4.22 kB
JavaScript
/**
* Copyright (c) 2015 CA. All rights reserved.
*
* This software and all information contained therein is confidential and proprietary and
* shall not be duplicated, used, disclosed or disseminated in any way except as authorized
* by the applicable license agreement, without the express written permission of CA. All
* authorized reproductions must be marked with this language.
*
* EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE EXTENT
* PERMITTED BY APPLICABLE LAW, CA PROVIDES THIS SOFTWARE WITHOUT WARRANTY
* OF ANY KIND, INCLUDING WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL CA BE
* LIABLE TO THE END USER OR ANY THIRD PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR
* INDIRECT, FROM THE USE OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, LOST
* PROFITS, BUSINESS INTERRUPTION, GOODWILL, OR LOST DATA, EVEN IF CA IS
* EXPRESSLY ADVISED OF SUCH LOSS OR DAMAGE.
*/
/*!
* proc
* Copyright(c) 2012 Daniel D. Shaw <dshaw@dshaw.com>
* MIT Licensed
*/
// is there anything even left of the original version by dshaw?
var fs = require('fs');
//
// This gets all messed up on 64-bit Solaris because the initial version assumed
// 32 bits for all longs. If this module ever get used for anything *other*
// than Solaris, you'll want to verify that the sizes of these types are
// still valid.
//
// typedef struct timespec { /* definition per POSIX.4 */
// time_t tv_sec; /* seconds */
// long tv_nsec; /* and nanoseconds */
// } timespec_t;
// ...
// typedef long time_t; /* time of day in seconds */
var sizeof_long = 4; // 32-bit
var sizeof_timespec = 8;
if (process.arch == 'x64') {
sizeof_long = 8;
sizeof_timespec = 16;
}
function readTimespec(buf, offset) {
// this would be pretty janky for 64-bit, but because that 32-bit timestamp
// isn't going to hit the 64-bit space until 2037, it's Good Enough[tm]
return buf.readInt32LE(offset) +
(buf.readInt32LE(offset + sizeof_long) / 1000000000);
}
exports.usage = function usage(pid, callback) {
fs.readFile('/proc/' + pid + '/usage', function(err, buf) {
if (err) {
return callback(err, null);
};
var data = {};
var offset = 0;
// lwp id. 0: process or defunct
data.lwpid = buf.readUInt32LE(offset);
offset += 4;
// number of contributing lwps
data.count = buf.readUInt32LE(offset);
offset += 4;
// current time stamp
data.tstamp = readTimespec(buf, offset);
offset += sizeof_timespec;
// process/lwp creation time stamp
data.create = readTimespec(buf, offset);
offset += sizeof_timespec;
// process/lwp termination time stamp
data.term = readTimespec(buf, offset);
offset += sizeof_timespec;
// total lwp real (elapsed) time
data.rtime = readTimespec(buf, offset);
offset += sizeof_timespec;
// user level cpu time
data.utime = readTimespec(buf, offset);
offset += sizeof_timespec;
// system call cpu time
data.stime = readTimespec(buf, offset);
offset += sizeof_timespec;
// there's normally another big pile of values we could read, but
// don't need any of them
callback(null, data);
});
};
// we only check this on linux, need to make sure that the field numbers
// are valid on other platforms if we want to use it there as well
exports.stat =
function stat(pid, callback) {
fs.readFile('/proc/' + pid + '/stat', 'ascii', function(err, data) {
if (err) {
return callback(err, null);
}
var stats_pid = data.split(' ');
var ret = {};
ret.utime = parseInt(stats_pid[13]);
ret.stime = parseInt(stats_pid[14]);
ret.ptime = ret.utime + ret.stime;
fs.readFile('/proc/stat', 'ascii', function(err, data) {
if (err) return;
ret.all = data.match('cpu +(.*)\n')[1].split(' ');
ret.all = array_sum(ret.all);
callback(null, ret);
})
});
}
function array_sum(a) {
var k, s = 0;
if (typeof a !== 'object') return null;
for (k in a) {
s += (a[k] * 1);
}
return s;
}