appmetrics
Advanced tools
Comparing version 2.0.1 to 3.0.0
@@ -41,4 +41,4 @@ /******************************************************************************* | ||
'win32-x64']; | ||
var AGENTCORE_VERSION = "3.1.0"; | ||
var APPMETRICS_VERSION = "2.0.1"; | ||
var AGENTCORE_VERSION = "3.2.1"; | ||
var APPMETRICS_VERSION = "3.0.0"; | ||
@@ -90,3 +90,3 @@ var LOG_FILE = path.join(INSTALL_DIR, 'install.log'); | ||
console.log(platform + ' is not a currently supported platform. Exiting'); | ||
process.exit(1); | ||
fail(); | ||
} | ||
@@ -117,4 +117,4 @@ }; | ||
} | ||
console.log('Unsupported version ' + process.version + '. Exiting.'); | ||
process.exit(1); | ||
console.log('Unsupported version ' + process.version + '. Trying rebuild.'); | ||
fail(); | ||
}; | ||
@@ -136,25 +136,35 @@ | ||
if (agentCoreFlag) { | ||
fs.createReadStream('binaries/agentcore/tgz/'+filepath).pipe(zlib.createGunzip()).on('error', function(err) { | ||
console.log('ERROR: Failed to gunzip ' + filepath + ': ' + err.message); | ||
process.exit(1); | ||
}) | ||
.pipe(tar.Extract({path: destDir})).on('error', function(err) { | ||
console.log('ERROR: Failed to untar ' + filepath + ': ' + err.message); | ||
process.exit(1); | ||
}) | ||
.on('close', function() { | ||
console.log('Download and extract of ' + filepath + ' finished.'); | ||
}); | ||
if(fs.existsSync('binaries/agentcore/tgz/'+filepath)) { | ||
fs.createReadStream('binaries/agentcore/tgz/'+filepath).pipe(zlib.createGunzip()).on('error', function(err) { | ||
console.log('ERROR: Failed to gunzip ' + filepath + ': ' + err.message); | ||
fail(); | ||
}) | ||
.pipe(tar.Extract({path: destDir})).on('error', function(err) { | ||
console.log('ERROR: Failed to untar ' + filepath + ': ' + err.message); | ||
fail(); | ||
}) | ||
.on('close', function() { | ||
console.log('Download and extract of ' + filepath + ' finished.'); | ||
}); | ||
} else { | ||
console.log(filepath + " does not exist.") | ||
fail(); | ||
} | ||
} else { | ||
fs.createReadStream('binaries/appmetrics/tgz/'+filepath).pipe(zlib.createGunzip()).on('error', function(err) { | ||
console.log('ERROR: Failed to gunzip ' + filepath + ': ' + err.message); | ||
process.exit(1); | ||
}) | ||
.pipe(tar.Extract({path: destDir})).on('error', function(err) { | ||
console.log('ERROR: Failed to untar ' + filepath + ': ' + err.message); | ||
process.exit(1); | ||
}) | ||
.on('close', function() { | ||
console.log('Download and extract of ' + filepath + ' finished.'); | ||
}); | ||
if(fs.existsSync('binaries/appmetrics/tgz/'+filepath)) { | ||
fs.createReadStream('binaries/appmetrics/tgz/'+filepath).pipe(zlib.createGunzip()).on('error', function(err) { | ||
console.log('ERROR: Failed to gunzip ' + filepath + ': ' + err.message); | ||
fail(); | ||
}) | ||
.pipe(tar.Extract({path: destDir})).on('error', function(err) { | ||
console.log('ERROR: Failed to untar ' + filepath + ': ' + err.message); | ||
fail(); | ||
}) | ||
.on('close', function() { | ||
console.log('Download and extract of ' + filepath + ' finished.'); | ||
}); | ||
} else { | ||
console.log(filepath + " does not exist.") | ||
fail(); | ||
} | ||
} | ||
@@ -164,10 +174,15 @@ | ||
function fail() { | ||
console.log('Falling back to node-gyp rebuild'); | ||
process.exit(1); | ||
} | ||
var installWinRedis = function(filepath, destDir) { | ||
fs.createReadStream('binaries/winredis/'+filepath).pipe(zlib.createGunzip()).on('error', function(err) { | ||
console.log('ERROR: Failed to gunzip ' + filepath + ': ' + err.message); | ||
process.exit(1); | ||
fail(); | ||
}) | ||
.pipe(tar.Extract({path: destDir})).on('error', function(err) { | ||
console.log('ERROR: Failed to untar ' + filepath + ': ' + err.message); | ||
process.exit(1); | ||
fail(); | ||
}) | ||
@@ -174,0 +189,0 @@ .on('close', function() { |
20
index.js
@@ -30,2 +30,4 @@ /******************************************************************************* | ||
var heapdump = require('./heapdump.js'); | ||
var VERSION = require('./package.json').version | ||
var assert = require('assert') | ||
@@ -121,2 +123,15 @@ | ||
if(global.Appmetrics) { | ||
assert( | ||
global.Appmetrics.VERSION === VERSION, | ||
'Multiple versions of Node Application Metrics are being initialized.\n' + | ||
'This version ' + VERSION + ' is incompatible with already initialized\n' + | ||
'version ' + global.Appmetrics.VERSION+ '.\n' | ||
); | ||
module.exports = global.Appmetrics; | ||
} else { | ||
global.Appmetrics = module.exports; | ||
module.exports.VERSION = VERSION; | ||
} | ||
/* | ||
@@ -331,2 +346,7 @@ * Patch the module require function to run the probe attach function | ||
process.on('exit', function () { | ||
// take the event loop latency methods off the loop | ||
if (latencyRunning === true) { | ||
clearInterval(latencyCheckLoop); | ||
clearInterval(latencyReportLoop); | ||
} | ||
var headlessMode = agent.getOption('com.ibm.diagnostics.healthcenter.headless'); | ||
@@ -333,0 +353,0 @@ am.stop(); |
@@ -24,6 +24,2 @@ module.exports = Reader | ||
if (!props.path) { | ||
self.error('Must provide a path', null, true) | ||
} | ||
// polymorphism. | ||
@@ -89,2 +85,6 @@ // call fstream.Reader(dir) to get a DirReader object, etc. | ||
if (!props.path) { | ||
self.error('Must provide a path', null, true) | ||
} | ||
self.readable = true | ||
@@ -91,0 +91,0 @@ self.writable = false |
@@ -33,4 +33,2 @@ module.exports = Writer | ||
if (!props.path) self.error('Must provide a path', null, true) | ||
// polymorphism. | ||
@@ -65,2 +63,4 @@ // call fstream.Writer(dir) to get a DirWriter object, etc. | ||
if (!props.path) self.error('Must provide a path', null, true) | ||
// props is what we want to set. | ||
@@ -67,0 +67,0 @@ // set some convenience properties as well. |
@@ -7,2 +7,3 @@ #!/usr/bin/env node | ||
var dashdash = false | ||
var noglob = false | ||
var args = process.argv.slice(2).filter(function(arg) { | ||
@@ -13,2 +14,6 @@ if (dashdash) | ||
dashdash = true | ||
else if (arg === '--no-glob' || arg === '-G') | ||
noglob = true | ||
else if (arg === '--glob' || arg === '-g') | ||
noglob = false | ||
else if (arg.match(/^(-+|\/)(h(elp)?|\?)$/)) | ||
@@ -18,3 +23,3 @@ help = true | ||
return !!arg | ||
}); | ||
}) | ||
@@ -30,3 +35,5 @@ if (help || args.length === 0) { | ||
log('') | ||
log(' -h, --help Display this usage info') | ||
log(' -h, --help Display this usage info') | ||
log(' -G, --no-glob Do not expand glob patterns in arguments') | ||
log(' -g, --glob Expand glob patterns in arguments (default)') | ||
process.exit(help ? 0 : 1) | ||
@@ -39,3 +46,6 @@ } else | ||
return | ||
rimraf(args[n], function (er) { | ||
var options = {} | ||
if (noglob) | ||
options = { glob: false } | ||
rimraf(args[n], options, function (er) { | ||
if (er) | ||
@@ -42,0 +52,0 @@ throw er |
@@ -109,3 +109,3 @@ var concatMap = require('concat-map'); | ||
var isSequence = isNumericSequence || isAlphaSequence; | ||
var isOptions = /^(.*,)+(.+)?$/.test(m.body); | ||
var isOptions = m.body.indexOf(',') >= 0; | ||
if (!isSequence && !isOptions) { | ||
@@ -112,0 +112,0 @@ // {a},b} |
{ | ||
"name": "brace-expansion", | ||
"description": "Brace expansion as known from sh/bash", | ||
"version": "1.1.6", | ||
"version": "1.1.7", | ||
"repository": { | ||
@@ -13,3 +13,4 @@ "type": "git", | ||
"test": "tape test/*.js", | ||
"gentest": "bash test/generate.sh" | ||
"gentest": "bash test/generate.sh", | ||
"bench": "matcha test/perf/bench.js" | ||
}, | ||
@@ -21,2 +22,3 @@ "dependencies": { | ||
"devDependencies": { | ||
"matcha": "^0.7.0", | ||
"tape": "^4.6.0" | ||
@@ -47,11 +49,11 @@ }, | ||
}, | ||
"gitHead": "791262fa06625e9c5594cde529a21d82086af5f2", | ||
"gitHead": "892512024872ca7680554be90f6e8ce065053372", | ||
"bugs": { | ||
"url": "https://github.com/juliangruber/brace-expansion/issues" | ||
}, | ||
"_id": "brace-expansion@1.1.6", | ||
"_shasum": "7197d7eaa9b87e648390ea61fc66c84427420df9", | ||
"_id": "brace-expansion@1.1.7", | ||
"_shasum": "3effc3c50e000531fb720eaff80f0ae8ef23cf59", | ||
"_from": "brace-expansion@>=1.0.0 <2.0.0", | ||
"_npmVersion": "2.15.8", | ||
"_nodeVersion": "4.4.7", | ||
"_npmVersion": "4.2.0", | ||
"_nodeVersion": "7.8.0", | ||
"_npmUser": { | ||
@@ -62,4 +64,4 @@ "name": "juliangruber", | ||
"dist": { | ||
"shasum": "7197d7eaa9b87e648390ea61fc66c84427420df9", | ||
"tarball": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" | ||
"shasum": "3effc3c50e000531fb720eaff80f0ae8ef23cf59", | ||
"tarball": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz" | ||
}, | ||
@@ -77,8 +79,8 @@ "maintainers": [ | ||
"_npmOperationalInternal": { | ||
"host": "packages-16-east.internal.npmjs.com", | ||
"tmp": "tmp/brace-expansion-1.1.6.tgz_1469047715600_0.9362958471756428" | ||
"host": "packages-12-west.internal.npmjs.com", | ||
"tmp": "tmp/brace-expansion-1.1.7.tgz_1491552830231_0.7213963181711733" | ||
}, | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", | ||
"_resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", | ||
"readme": "ERROR: No README data found!" | ||
} |
@@ -8,2 +8,3 @@ # brace-expansion | ||
[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion) | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/) | ||
@@ -10,0 +11,0 @@ [![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion) |
{ | ||
"name": "rimraf", | ||
"version": "2.5.4", | ||
"version": "2.6.1", | ||
"main": "rimraf.js", | ||
@@ -33,5 +33,5 @@ "description": "A deep deletion module for node (like `rm -rf`)", | ||
"mkdirp": "^0.5.1", | ||
"tap": "^6.1.1" | ||
"tap": "^10.1.2" | ||
}, | ||
"gitHead": "2af08bbbd0a03549b278414309dc5d8097699443", | ||
"gitHead": "d84fe2cc6646d30a401baadcee22ae105a2d4909", | ||
"bugs": { | ||
@@ -41,7 +41,7 @@ "url": "https://github.com/isaacs/rimraf/issues" | ||
"homepage": "https://github.com/isaacs/rimraf#readme", | ||
"_id": "rimraf@2.5.4", | ||
"_shasum": "96800093cbf1a0c86bd95b4625467535c29dfa04", | ||
"_id": "rimraf@2.6.1", | ||
"_shasum": "c2338ec643df7a1b7fe5c54fa86f57428a55f33d", | ||
"_from": "rimraf@>=2.0.0 <3.0.0", | ||
"_npmVersion": "3.10.6", | ||
"_nodeVersion": "4.4.4", | ||
"_npmVersion": "4.3.0", | ||
"_nodeVersion": "8.0.0-pre", | ||
"_npmUser": { | ||
@@ -52,4 +52,4 @@ "name": "isaacs", | ||
"dist": { | ||
"shasum": "96800093cbf1a0c86bd95b4625467535c29dfa04", | ||
"tarball": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz" | ||
"shasum": "c2338ec643df7a1b7fe5c54fa86f57428a55f33d", | ||
"tarball": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz" | ||
}, | ||
@@ -63,8 +63,8 @@ "maintainers": [ | ||
"_npmOperationalInternal": { | ||
"host": "packages-16-east.internal.npmjs.com", | ||
"tmp": "tmp/rimraf-2.5.4.tgz_1469206941888_0.8645927573088557" | ||
"host": "packages-18-east.internal.npmjs.com", | ||
"tmp": "tmp/rimraf-2.6.1.tgz_1487908074285_0.8205490333493799" | ||
}, | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", | ||
"_resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", | ||
"readme": "ERROR: No README data found!" | ||
} |
@@ -88,3 +88,3 @@ module.exports = rimraf | ||
if (er) { | ||
if (isWindows && (er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && | ||
if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && | ||
busyTries < options.maxBusyTries) { | ||
@@ -314,2 +314,3 @@ busyTries ++ | ||
throw er | ||
rmdirSync(p, options, er) | ||
@@ -344,3 +345,22 @@ } | ||
}) | ||
options.rmdirSync(p, options) | ||
// We only end up here once we got ENOTEMPTY at least once, and | ||
// at this point, we are guaranteed to have removed all the kids. | ||
// So, we know that it won't be ENOENT or ENOTDIR or anything else. | ||
// try really hard to delete stuff on windows, because it has a | ||
// PROFOUNDLY annoying habit of not closing handles promptly when | ||
// files are deleted, resulting in spurious ENOTEMPTY errors. | ||
var retries = isWindows ? 100 : 1 | ||
var i = 0 | ||
do { | ||
var threw = true | ||
try { | ||
var ret = options.rmdirSync(p, options) | ||
threw = false | ||
return ret | ||
} finally { | ||
if (++i < retries && threw) | ||
continue | ||
} | ||
} while (true) | ||
} |
@@ -9,3 +9,3 @@ { | ||
"description": "Advanced file system stream things", | ||
"version": "1.0.10", | ||
"version": "1.0.11", | ||
"repository": { | ||
@@ -33,3 +33,3 @@ "type": "git", | ||
"license": "ISC", | ||
"gitHead": "24fabdec32e334dd3b130d77b38c010e3119b102", | ||
"gitHead": "1e4527ffe8688d4f5325283d7cf2cf2d61f14c6b", | ||
"bugs": { | ||
@@ -39,14 +39,14 @@ "url": "https://github.com/npm/fstream/issues" | ||
"homepage": "https://github.com/npm/fstream#readme", | ||
"_id": "fstream@1.0.10", | ||
"_shasum": "604e8a92fe26ffd9f6fae30399d4984e1ab22822", | ||
"_id": "fstream@1.0.11", | ||
"_shasum": "5c1fb1f117477114f0632a0eb4b71b3cb0fd3171", | ||
"_from": "fstream@>=1.0.2 <2.0.0", | ||
"_npmVersion": "3.10.0", | ||
"_nodeVersion": "4.4.5", | ||
"_npmVersion": "4.1.2", | ||
"_nodeVersion": "7.7.1", | ||
"_npmUser": { | ||
"name": "othiym23", | ||
"email": "ogd@aoaioxxysz.net" | ||
"name": "zkat", | ||
"email": "kat@sykosomatic.org" | ||
}, | ||
"dist": { | ||
"shasum": "604e8a92fe26ffd9f6fae30399d4984e1ab22822", | ||
"tarball": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz" | ||
"shasum": "5c1fb1f117477114f0632a0eb4b71b3cb0fd3171", | ||
"tarball": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz" | ||
}, | ||
@@ -72,8 +72,8 @@ "maintainers": [ | ||
"_npmOperationalInternal": { | ||
"host": "packages-16-east.internal.npmjs.com", | ||
"tmp": "tmp/fstream-1.0.10.tgz_1466189553883_0.3062701092567295" | ||
"host": "packages-18-east.internal.npmjs.com", | ||
"tmp": "tmp/fstream-1.0.11.tgz_1488923219641_0.18055859790183604" | ||
}, | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz", | ||
"_resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", | ||
"readme": "ERROR: No README data found!" | ||
} |
{ | ||
"name": "appmetrics", | ||
"version": "2.0.1", | ||
"version": "3.0.0", | ||
"engines": { "node": ">=4" }, | ||
"description": "Node Application Metrics", | ||
@@ -18,7 +19,8 @@ "bin": { | ||
"node-gyp": "3.x", | ||
"semver": "^5.3.0", | ||
"tap": "7.x" | ||
}, | ||
"scripts": { | ||
"test": "tap --reporter tap --timeout=120 tests/*tests.js tests/probes/http-outbound-probe-test.js tests/headless_test.js", | ||
"install": "node extract_all_binaries.js" | ||
"test": "tap --reporter tap --timeout=120 tests/*tests.js tests/probes/http-outbound-probe-test.js tests/probes/http-probe-test.js tests/headless_test.js", | ||
"install": "node extract_all_binaries.js || node extract_all_binaries.js" | ||
}, | ||
@@ -25,0 +27,0 @@ "directories": { |
@@ -123,9 +123,11 @@ /******************************************************************************* | ||
AxonProbe.prototype.metricsEnd = function(context, methodName, methodArgs, socketType) { | ||
context.timer.stop(); | ||
// default to quality of service (qos) 0, as that's what the axon module does | ||
if( isSendMethod(socketType) ) { | ||
am.emit('axon', {time: context.timer.startTimeMillis, method: methodName, duration: context.timer.timeDelta, type: socketType}) | ||
} else { | ||
am.emit('axon', {time: context.timer.startTimeMillis, event: methodName, duration: context.timer.timeDelta, type: socketType}) | ||
}; | ||
if(context && context.timer) { | ||
context.timer.stop(); | ||
// default to quality of service (qos) 0, as that's what the axon module does | ||
if( isSendMethod(socketType) ) { | ||
am.emit('axon', {time: context.timer.startTimeMillis, method: methodName, duration: context.timer.timeDelta, type: socketType}) | ||
} else { | ||
am.emit('axon', {time: context.timer.startTimeMillis, event: methodName, duration: context.timer.timeDelta, type: socketType}) | ||
}; | ||
} | ||
}; | ||
@@ -138,5 +140,5 @@ | ||
if (methodName === 'message') { | ||
context.req = request.startRequest('AXON', methodName, true, context.timer); | ||
context.req = request.startRequest('axon', methodName, true, context.timer); | ||
} else { | ||
context.req = request.startRequest('AXON', methodName, false, context.timer); | ||
context.req = request.startRequest('axon', methodName, false, context.timer); | ||
} | ||
@@ -146,5 +148,6 @@ }; | ||
AxonProbe.prototype.requestEnd = function (context, methodName, methodArgs) { | ||
context.req.stop({topic: methodArgs[0]}); | ||
if(context && context.req) | ||
context.req.stop({topic: methodArgs[0]}); | ||
}; | ||
module.exports = AxonProbe; | ||
module.exports = AxonProbe; |
@@ -107,21 +107,23 @@ /******************************************************************************* | ||
RiakProbe.prototype.metricsEnd = function(probeData, method, methodArgs) { | ||
probeData.timer.stop(); | ||
eventTimer = probeData.timer; | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
eventTimer = probeData.timer; | ||
//Work out if options, command or query are needed. Defaults to just method | ||
var jsonToEmit = {time: eventTimer.startTimeMillis, method: method, duration: eventTimer.timeDelta}; | ||
var key = ''; | ||
//Work out if options, command or query are needed. Defaults to just method | ||
var jsonToEmit = {time: eventTimer.startTimeMillis, method: method, duration: eventTimer.timeDelta}; | ||
var key = ''; | ||
if (optionsAndCallbackMethods.indexOf(method) > -1) { | ||
key = 'options'; | ||
} else if (commandMethods.indexOf(method) > -1) { | ||
key = 'command'; | ||
} else if (queryMethods.indexOf(method) > -1) { | ||
key = 'query'; | ||
} | ||
if (optionsAndCallbackMethods.indexOf(method) > -1) { | ||
key = 'options'; | ||
} else if (commandMethods.indexOf(method) > -1) { | ||
key = 'command'; | ||
} else if (queryMethods.indexOf(method) > -1) { | ||
key = 'query'; | ||
} | ||
if (key != '') { | ||
jsonToEmit[key] = methodArgs[0]; | ||
if (key != '') { | ||
jsonToEmit[key] = methodArgs[0]; | ||
} | ||
am.emit('riak', jsonToEmit); | ||
} | ||
am.emit('riak', jsonToEmit); | ||
}; | ||
@@ -133,9 +135,10 @@ | ||
RiakProbe.prototype.requestStart = function (probeData, method, methodArgs) { | ||
probeData.req = request.startRequest( 'DB', 'query', false, probeData.timer ); | ||
probeData.req = request.startRequest( 'basho-riak-client', 'query', false, probeData.timer ); | ||
}; | ||
RiakProbe.prototype.requestEnd = function (probeData, method, methodArgs) { | ||
probeData.req.stop({method: method}); | ||
if(probeData && probeData.req) | ||
probeData.req.stop({method: method}); | ||
}; | ||
module.exports = RiakProbe; | ||
module.exports = RiakProbe; |
@@ -45,2 +45,3 @@ /******************************************************************************* | ||
var urlRequested= ""; | ||
var headers = ""; | ||
if(typeof options === 'object') { | ||
@@ -51,2 +52,5 @@ urlRequested = formatURL(options) | ||
} | ||
if(options.headers) { | ||
headers = options.headers; | ||
} | ||
} else if (typeof options === 'string') { | ||
@@ -58,2 +62,5 @@ urlRequested = options; | ||
} | ||
if(parsedOptions.headers) { | ||
headers = parsedOptions.headers; | ||
} | ||
} | ||
@@ -68,4 +75,4 @@ | ||
methodArgs.statusCode = args[0].statusCode | ||
that.metricsProbeEnd(probeData, requestMethod, urlRequested, args[0]); | ||
that.requestProbeEnd(probeData, requestMethod, urlRequested, args[0]); | ||
that.metricsProbeEnd(probeData, requestMethod, urlRequested, args[0], headers); | ||
that.requestProbeEnd(probeData, requestMethod, urlRequested, args[0], headers); | ||
}, function(target, args, probeData, ret) { | ||
@@ -86,2 +93,3 @@ // Don't need to do anything after the callback | ||
var urlRequested= ""; | ||
var headers = ""; | ||
if(typeof options === 'object') { | ||
@@ -92,2 +100,5 @@ urlRequested = formatURL(options) | ||
} | ||
if(options.headers) { | ||
headers = options.headers; | ||
} | ||
} else if (typeof options === 'string') { | ||
@@ -99,7 +110,10 @@ urlRequested = options; | ||
} | ||
if(parsedOptions.headers) { | ||
headers = parsedOptions.headers; | ||
} | ||
} | ||
// End metrics (no response available so pass empty object) | ||
that.metricsProbeEnd(probeData, requestMethod, urlRequested, {}); | ||
that.requestProbeEnd(probeData, requestMethod, urlRequested, {}); | ||
that.metricsProbeEnd(probeData, requestMethod, urlRequested, {}, headers); | ||
that.requestProbeEnd(probeData, requestMethod, urlRequested, {}, headers); | ||
} | ||
@@ -148,13 +162,16 @@ return rc; | ||
* These provide: | ||
* time: time event started | ||
* method: HTTP method, eg. GET, POST, etc | ||
* url: The url requested | ||
* duration: the time for the request to respond | ||
* contentType: HTTP content-type | ||
* statusCode: HTTP status code | ||
* time: time event started | ||
* method: HTTP method, eg. GET, POST, etc | ||
* url: The url requested | ||
* requestHeaders: The HTTP headers for the request | ||
* duration: The time for the request to respond | ||
* contentType: HTTP content-type | ||
* statusCode: HTTP status code | ||
*/ | ||
HttpOutboundProbe.prototype.metricsEnd = function(probeData, method, url, res) { | ||
probeData.timer.stop(); | ||
am.emit('http-outbound', {time: probeData.timer.startTimeMillis, method: method, url: url, | ||
duration: probeData.timer.timeDelta, statusCode: res.statusCode, contentType:res.headers?res.headers['content-type']:"undefined"}); | ||
HttpOutboundProbe.prototype.metricsEnd = function(probeData, method, url, res, headers) { | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
am.emit('http-outbound', {time: probeData.timer.startTimeMillis, method: method, url: url, | ||
duration: probeData.timer.timeDelta, statusCode: res.statusCode, contentType:res.headers?res.headers['content-type']:"undefined", requestHeaders: headers}); | ||
} | ||
}; | ||
@@ -166,3 +183,3 @@ | ||
HttpOutboundProbe.prototype.requestStart = function (probeData, method, url) { | ||
var reqType = 'HTTP Outbound'; | ||
var reqType = 'http-outbound'; | ||
// Do not mark as a root request | ||
@@ -172,4 +189,5 @@ probeData.req = request.startRequest(reqType, url, false, probeData.timer); | ||
HttpOutboundProbe.prototype.requestEnd = function (probeData, method, url, res) { | ||
probeData.req.stop({url: url, statusCode: res.statusCode, contentType:res.headers?res.headers['content-type']:"undefined"}); | ||
HttpOutboundProbe.prototype.requestEnd = function (probeData, method, url, res, headers) { | ||
if(probeData && probeData.req) | ||
probeData.req.stop({url: url, statusCode: res.statusCode, contentType:res.headers?res.headers['content-type']:"undefined", requestHeaders: headers}); | ||
}; | ||
@@ -176,0 +194,0 @@ |
@@ -52,4 +52,4 @@ /******************************************************************************* | ||
aspect.after(res, 'end', probeData, function(obj, methodName, args, probeData, ret) { | ||
that.metricsProbeEnd(probeData, httpReq.method, traceUrl, res); | ||
that.requestProbeEnd(probeData, httpReq.method, traceUrl); | ||
that.metricsProbeEnd(probeData, httpReq.method, traceUrl, res, httpReq); | ||
that.requestProbeEnd(probeData, httpReq.method, traceUrl, res, httpReq); | ||
}); | ||
@@ -102,5 +102,7 @@ } | ||
HttpProbe.prototype.metricsEnd = function(probeData, method, url, res) { | ||
probeData.timer.stop(); | ||
am.emit('http', {time: probeData.timer.startTimeMillis, method: method, url: url, duration: probeData.timer.timeDelta, header: res._header, statusCode: res.statusCode, contentType: res.getHeader('content-type')}); | ||
HttpProbe.prototype.metricsEnd = function(probeData, method, url, res, httpReq) { | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
am.emit('http', {time: probeData.timer.startTimeMillis, method: method, url: url, duration: probeData.timer.timeDelta, header: res._header, statusCode: res.statusCode, contentType: res.getHeader('content-type'), requestHeader: httpReq.headers}); | ||
} | ||
}; | ||
@@ -113,3 +115,3 @@ | ||
HttpProbe.prototype.requestStart = function (probeData, method, url) { | ||
var reqType = 'HTTP'; | ||
var reqType = 'http'; | ||
// Mark as a root request as this happens due to an external event | ||
@@ -119,6 +121,7 @@ probeData.req = request.startRequest(reqType, url, true, probeData.timer); | ||
HttpProbe.prototype.requestEnd = function (probeData, method, url) { | ||
probeData.req.stop({url: url }); | ||
HttpProbe.prototype.requestEnd = function (probeData, method, url, res, httpReq) { | ||
if(probeData && probeData.req) | ||
probeData.req.stop({url: url, method: method, requestHeader: httpReq.headers, statusCode: res.statusCode, header: res._header, contentType: res.getHeader('content-type')}); | ||
}; | ||
/* | ||
@@ -142,2 +145,2 @@ * Set configuration by merging passed in config with current one | ||
module.exports = HttpProbe; | ||
module.exports = HttpProbe; |
@@ -82,12 +82,14 @@ /******************************************************************************* | ||
LeveldownProbe.prototype.metricsEnd = function(probeData, method, methodArgs) { | ||
probeData.timer.stop(); | ||
if (method == 'put'){ | ||
am.emit('leveldown', {time: probeData.timer.startTimeMillis, method: method, key: methodArgs[0], value: methodArgs[1], duration: probeData.timer.timeDelta}); | ||
} | ||
else if (method == 'del' || method == 'get'){ | ||
am.emit('leveldown', {time: probeData.timer.startTimeMillis, method: method, key: methodArgs[0], duration: probeData.timer.timeDelta}); | ||
} | ||
else if(method == 'batch'){ | ||
am.emit('leveldown', {time: probeData.timer.startTimeMillis, method: method, opCount: methodArgs[0].length, duration: probeData.timer.timeDelta}); | ||
} | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
if (method == 'put'){ | ||
am.emit('leveldown', {time: probeData.timer.startTimeMillis, method: method, key: methodArgs[0], value: methodArgs[1], duration: probeData.timer.timeDelta}); | ||
} | ||
else if (method == 'del' || method == 'get'){ | ||
am.emit('leveldown', {time: probeData.timer.startTimeMillis, method: method, key: methodArgs[0], duration: probeData.timer.timeDelta}); | ||
} | ||
else if(method == 'batch'){ | ||
am.emit('leveldown', {time: probeData.timer.startTimeMillis, method: method, opCount: methodArgs[0].length, duration: probeData.timer.timeDelta}); | ||
} | ||
} | ||
}; | ||
@@ -99,3 +101,3 @@ | ||
LeveldownProbe.prototype.requestStart = function (probeData, dbTarget, method, methodArgs) { | ||
req = request.startRequest( 'DB', "query" ); | ||
req = request.startRequest( 'leveldown', "query" ); | ||
req.setContext({leveldown: methodArgs[0]}); | ||
@@ -105,5 +107,6 @@ }; | ||
LeveldownProbe.prototype.requestEnd = function (probeData, method, methodArgs) { | ||
req.stop({leveldown: methodArgs[0]}); | ||
if(probeData && probeData.req) | ||
req.stop({leveldown: methodArgs[0]}); | ||
}; | ||
module.exports = LeveldownProbe; | ||
module.exports = LeveldownProbe; |
@@ -75,5 +75,7 @@ /******************************************************************************* | ||
loopbackDJProbe.prototype.metricsEnd = function(probeData, method, methodArgs) { | ||
probeData.timer.stop(); | ||
eventTimer = probeData.timer; | ||
am.emit('loopback-datasource-juggler', {time: eventTimer.startTimeMillis, method: method, duration: eventTimer.timeDelta}); | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
eventTimer = probeData.timer; | ||
am.emit('loopback-datasource-juggler', {time: eventTimer.startTimeMillis, method: method, duration: eventTimer.timeDelta}); | ||
} | ||
} | ||
@@ -85,11 +87,11 @@ | ||
loopbackDJProbe.prototype.requestStart = function (probeData, target, method, methodArgs) { | ||
req = request.startRequest( 'DB', "query" ); | ||
req.setContext({loopbackDJProbe: methodArgs[0]}); | ||
probeData.req = request.startRequest( 'loopback', "query" ); | ||
probeData.req.setContext({loopbackDJProbe: methodArgs[0]}); | ||
}; | ||
loopbackDJProbe.prototype.requestEnd = function (probeData, method, methodArgs) { | ||
console.log("requestEnd called"); | ||
req.stop({loopbackDJProbe: methodArgs[0]}); | ||
if(probeData && probeData.req) | ||
probeData.req.stop({loopbackDJProbe: methodArgs[0]}); | ||
}; | ||
module.exports = loopbackDJProbe; | ||
module.exports = loopbackDJProbe; |
@@ -89,4 +89,6 @@ /******************************************************************************* | ||
MemcachedProbe.prototype.metricsEnd = function(context, method, methodArgs) { | ||
context.timer.stop(); | ||
am.emit('memcached', {time: context.timer.startTimeMillis, method: method, key: methodArgs[0], duration: context.timer.timeDelta}); | ||
if(context && context.timer) { | ||
context.timer.stop(); | ||
am.emit('memcached', {time: context.timer.startTimeMillis, method: method, key: methodArgs[0], duration: context.timer.timeDelta}); | ||
} | ||
}; | ||
@@ -98,9 +100,10 @@ | ||
MemcachedProbe.prototype.requestStart = function (context, methodName, methodArgs) { | ||
context.req = request.startRequest( 'Memcached', methodName, false, context.timer); | ||
context.req = request.startRequest( 'memcached', methodName, false, context.timer); | ||
}; | ||
MemcachedProbe.prototype.requestEnd = function (context, methodName, methodArgs) { | ||
context.req.stop({key: methodArgs[0]}); | ||
if(context && context.req) | ||
context.req.stop({key: methodArgs[0]}); | ||
}; | ||
module.exports = MemcachedProbe; | ||
module.exports = MemcachedProbe; |
@@ -117,5 +117,7 @@ /******************************************************************************* | ||
MongoProbe.prototype.metricsEnd = function(probeData, collectionName, method, methodArgs) { | ||
probeData.timer.stop(); | ||
am.emit('mongo', {time: probeData.timer.startTimeMillis, query: JSON.stringify(methodArgs[0]), duration: probeData.timer.timeDelta, | ||
method: method, collection: collectionName}); | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
am.emit('mongo', {time: probeData.timer.startTimeMillis, query: JSON.stringify(methodArgs[0]), duration: probeData.timer.timeDelta, | ||
method: method, collection: collectionName}); | ||
} | ||
}; | ||
@@ -127,9 +129,10 @@ | ||
MongoProbe.prototype.requestStart = function (probeData, target, method, methodArgs) { | ||
probeData.req = request.startRequest( 'DB', method + "("+target.collectionName+")", false, probeData.timer ); | ||
probeData.req = request.startRequest( 'mongo', method + "("+target.collectionName+")", false, probeData.timer ); | ||
}; | ||
MongoProbe.prototype.requestEnd = function (probeData, method, methodArgs) { | ||
probeData.req.stop( { query: JSON.stringify(methodArgs[0]) } ); | ||
if(probeData && probeData.req) | ||
probeData.req.stop( { query: JSON.stringify(methodArgs[0]) } ); | ||
}; | ||
module.exports = MongoProbe; |
@@ -102,38 +102,40 @@ /******************************************************************************* | ||
MQLightProbe.prototype.metricsEnd = function(probeData, method, methodArgs, client) { | ||
probeData.timer.stop(); | ||
if(method == 'message') { | ||
var data = methodArgs[0]; | ||
if(data.length > 25) { | ||
data = data.substring(0, 22) + "..."; | ||
} | ||
var topic = methodArgs[1].message.topic; | ||
am.emit('mqlight', { | ||
time : probeData.timer.startTimeMillis, | ||
clientid : client.id, | ||
data : data, | ||
method : method, | ||
topic : topic, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
} else if(method == 'send') { | ||
var data = methodArgs[1]; | ||
if(data.length > 25) { | ||
data = data.substring(0, 22) + "..."; | ||
} | ||
var qos; | ||
var options; // options are optional - check number of arguments. | ||
if(methodArgs.length > 3) { | ||
options = methodArgs[2]; | ||
qos = options[0]; | ||
} | ||
am.emit('mqlight', { | ||
time : probeData.timer.startTimeMillis, | ||
clientid : client.id, | ||
data : data, | ||
method : method, | ||
topic : methodArgs[0], | ||
qos : qos, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
} | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
if(method == 'message') { | ||
var data = methodArgs[0]; | ||
if(data.length > 25) { | ||
data = data.substring(0, 22) + "..."; | ||
} | ||
var topic = methodArgs[1].message.topic; | ||
am.emit('mqlight', { | ||
time : probeData.timer.startTimeMillis, | ||
clientid : client.id, | ||
data : data, | ||
method : method, | ||
topic : topic, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
} else if(method == 'send') { | ||
var data = methodArgs[1]; | ||
if(data.length > 25) { | ||
data = data.substring(0, 22) + "..."; | ||
} | ||
var qos; | ||
var options; // options are optional - check number of arguments. | ||
if(methodArgs.length > 3) { | ||
options = methodArgs[2]; | ||
qos = options[0]; | ||
} | ||
am.emit('mqlight', { | ||
time : probeData.timer.startTimeMillis, | ||
clientid : client.id, | ||
data : data, | ||
method : method, | ||
topic : methodArgs[0], | ||
qos : qos, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
} | ||
} | ||
}; | ||
@@ -146,5 +148,5 @@ | ||
if(method == 'message') { | ||
probeData.req = request.startRequest('MQLight', method, true, probeData.timer); | ||
probeData.req = request.startRequest('mqlight', method, true, probeData.timer); | ||
} else { | ||
probeData.req = request.startRequest('MQLight', method, false, probeData.timer); | ||
probeData.req = request.startRequest('mqlight', method, false, probeData.timer); | ||
} | ||
@@ -154,24 +156,26 @@ }; | ||
MQLightProbe.prototype.requestEnd = function (probeData, method, methodArgs, client) { | ||
if(method == 'message') { | ||
var data = methodArgs[0]; | ||
if(data.length > 25) { | ||
data = data.substring(0, 22) + "..."; | ||
} | ||
var topic = methodArgs[1].message.topic; | ||
probeData.req.stop({clientid: client.id, data: data, method: method, topic: methodArgs[0]}); | ||
} else if(method == 'send') { | ||
var data = methodArgs[1]; | ||
if(data.length > 25) { | ||
data = data.substring(0, 22) + "..."; | ||
} | ||
var qos; | ||
var options; // options are optional - check number of arguments. | ||
if(methodArgs.length > 3) { | ||
options = methodArgs[2]; | ||
qos = options[0]; | ||
} | ||
probeData.req.stop({clientid: client.id, data: data, method: method, topic: methodArgs[0], qos: qos}); | ||
} | ||
if(probeData && probeData.req) { | ||
if(method == 'message') { | ||
var data = methodArgs[0]; | ||
if(data.length > 25) { | ||
data = data.substring(0, 22) + "..."; | ||
} | ||
var topic = methodArgs[1].message.topic; | ||
probeData.req.stop({clientid: client.id, data: data, method: method, topic: methodArgs[0]}); | ||
} else if(method == 'send') { | ||
var data = methodArgs[1]; | ||
if(data.length > 25) { | ||
data = data.substring(0, 22) + "..."; | ||
} | ||
var qos; | ||
var options; // options are optional - check number of arguments. | ||
if(methodArgs.length > 3) { | ||
options = methodArgs[2]; | ||
qos = options[0]; | ||
} | ||
probeData.req.stop({clientid: client.id, data: data, method: method, topic: methodArgs[0], qos: qos}); | ||
} | ||
} | ||
}; | ||
module.exports = MQLightProbe; | ||
module.exports = MQLightProbe; |
@@ -104,9 +104,11 @@ /******************************************************************************* | ||
MqttProbe.prototype.metricsEnd = function(context, methodName, methodArgs) { | ||
context.timer.stop(); | ||
// default to quality of service (qos) 0, as that's what the mqtt module does | ||
var qos = 0; | ||
if (methodArgs[2] && (typeof(methodArgs[2]) !== 'function')) { | ||
qos = methodArgs[2].qos; | ||
} | ||
am.emit('mqtt', {time: context.timer.startTimeMillis, method: methodName, topic: methodArgs[0], qos: qos, duration: context.timer.timeDelta}); | ||
if(context && context.timer) { | ||
context.timer.stop(); | ||
// default to quality of service (qos) 0, as that's what the mqtt module does | ||
var qos = 0; | ||
if (methodArgs[2] && (typeof(methodArgs[2]) !== 'function')) { | ||
qos = methodArgs[2].qos; | ||
} | ||
am.emit('mqtt', {time: context.timer.startTimeMillis, method: methodName, topic: methodArgs[0], qos: qos, duration: context.timer.timeDelta}); | ||
} | ||
}; | ||
@@ -119,5 +121,5 @@ | ||
if (methodName === 'message') { | ||
context.req = request.startRequest('MQTT', methodName, true, context.timer); | ||
context.req = request.startRequest('mqtt', methodName, true, context.timer); | ||
} else { | ||
context.req = request.startRequest('MQTT', methodName, false, context.timer); | ||
context.req = request.startRequest('mqtt', methodName, false, context.timer); | ||
} | ||
@@ -127,9 +129,11 @@ }; | ||
MqttProbe.prototype.requestEnd = function (context, methodName, methodArgs) { | ||
var qos = 0; | ||
if (methodArgs[2] && (typeof(methodArgs[2]) !== 'function')) { | ||
qos = methodArgs[2].qos; | ||
} | ||
context.req.stop({topic: methodArgs[0], qos: qos}); | ||
if(context && context.req) { | ||
var qos = 0; | ||
if (methodArgs[2] && (typeof(methodArgs[2]) !== 'function')) { | ||
qos = methodArgs[2].qos; | ||
} | ||
context.req.stop({topic: methodArgs[0], qos: qos}); | ||
} | ||
}; | ||
module.exports = MqttProbe; | ||
module.exports = MqttProbe; |
@@ -68,5 +68,7 @@ /******************************************************************************* | ||
MySqlProbe.prototype.metricsEnd = function(probeData, method, methodArgs) { | ||
probeData.timer.stop(); | ||
eventTimer = probeData.timer; | ||
am.emit('mysql', {time: eventTimer.startTimeMillis, query: JSON.stringify(methodArgs[0]), duration: eventTimer.timeDelta}); | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
eventTimer = probeData.timer; | ||
am.emit('mysql', {time: eventTimer.startTimeMillis, query: JSON.stringify(methodArgs[0]), duration: eventTimer.timeDelta}); | ||
} | ||
}; | ||
@@ -78,9 +80,10 @@ | ||
MySqlProbe.prototype.requestStart = function (probeData, method, methodArgs) { | ||
probeData.req = request.startRequest( 'DB', "query", false, probeData.timer ); | ||
probeData.req = request.startRequest( 'mysql', "query", false, probeData.timer ); | ||
}; | ||
MySqlProbe.prototype.requestEnd = function (probeData, method, methodArgs) { | ||
probeData.req.stop({sql: JSON.stringify(methodArgs[0])}); | ||
if(probeData && probeData.req) | ||
probeData.req.stop({sql: JSON.stringify(methodArgs[0])}); | ||
}; | ||
module.exports = MySqlProbe; | ||
module.exports = MySqlProbe; |
@@ -92,9 +92,11 @@ /******************************************************************************* | ||
OracleProbe.prototype.metricsEnd = function(probeData, method, methodArgs) { | ||
probeData.timer.stop(); | ||
var query = methodArgs[0]; | ||
am.emit('oracle', { | ||
time : probeData.timer.startTimeMillis, | ||
query : query, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
var query = methodArgs[0]; | ||
am.emit('oracle', { | ||
time : probeData.timer.startTimeMillis, | ||
query : query, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
} | ||
}; | ||
@@ -106,10 +108,11 @@ | ||
OracleProbe.prototype.requestStart = function (probeData, method, methodArgs) { | ||
probeData.req = request.startRequest('Oracle', method, false, probeData.timer); | ||
probeData.req = request.startRequest('oracle', method, false, probeData.timer); | ||
}; | ||
OracleProbe.prototype.requestEnd = function (probeData, method, methodArgs) { | ||
var query = methodArgs[0]; | ||
probeData.req.stop({query:query}); | ||
if(probeData && probeData.req) | ||
var query = methodArgs[0]; | ||
probeData.req.stop({query:query}); | ||
}; | ||
module.exports = OracleProbe; | ||
module.exports = OracleProbe; |
@@ -109,9 +109,11 @@ /******************************************************************************* | ||
OracleDBProbe.prototype.metricsEnd = function(probeData, method, methodArgs) { | ||
probeData.timer.stop(); | ||
var query = methodArgs[0]; | ||
am.emit('oracledb', { | ||
time : probeData.timer.startTimeMillis, | ||
query : query, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
var query = methodArgs[0]; | ||
am.emit('oracledb', { | ||
time : probeData.timer.startTimeMillis, | ||
query : query, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
} | ||
}; | ||
@@ -123,10 +125,12 @@ | ||
OracleDBProbe.prototype.requestStart = function (probeData, method, methodArgs) { | ||
probeData.req = request.startRequest('OracleDB', method, false, probeData.timer); | ||
probeData.req = request.startRequest('oracledb', method, false, probeData.timer); | ||
}; | ||
OracleDBProbe.prototype.requestEnd = function (probeData, method, methodArgs) { | ||
var query = methodArgs[0]; | ||
probeData.req.stop({query:query}); | ||
if(probeData && probeData.req) { | ||
var query = methodArgs[0]; | ||
probeData.req.stop({query:query}); | ||
} | ||
}; | ||
module.exports = OracleDBProbe; |
@@ -116,4 +116,6 @@ /******************************************************************************* | ||
PostgresProbe.prototype.metricsEnd = function(probeData, method, methodArgs) { | ||
probeData.timer.stop(); | ||
am.emit('postgres', {time: probeData.timer.startTimeMillis, query: methodArgs[0], duration: probeData.timer.timeDelta}); | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
am.emit('postgres', {time: probeData.timer.startTimeMillis, query: methodArgs[0], duration: probeData.timer.timeDelta}); | ||
} | ||
}; | ||
@@ -125,3 +127,3 @@ | ||
PostgresProbe.prototype.requestStart = function (probeData, target, method, methodArgs) { | ||
probeData.req = request.startRequest( 'DB', "query", false, probeData.timer ); | ||
probeData.req = request.startRequest( 'postgres', "query", false, probeData.timer ); | ||
probeData.req.setContext({sql: methodArgs[0]}); | ||
@@ -131,5 +133,6 @@ }; | ||
PostgresProbe.prototype.requestEnd = function (probeData, method, methodArgs) { | ||
probeData.req.stop({sql: methodArgs[0]}); | ||
if(probeData && probeData.req) | ||
probeData.req.stop({sql: methodArgs[0]}); | ||
}; | ||
module.exports = PostgresProbe; | ||
module.exports = PostgresProbe; |
@@ -142,4 +142,6 @@ /******************************************************************************* | ||
RedisProbe.prototype.metricsEnd = function(probeData, cmd, methodArgs) { | ||
probeData.timer.stop(); | ||
am.emit('redis', {time: probeData.timer.startTimeMillis, cmd: cmd, duration: probeData.timer.timeDelta}); | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
am.emit('redis', {time: probeData.timer.startTimeMillis, cmd: cmd, duration: probeData.timer.timeDelta}); | ||
} | ||
}; | ||
@@ -156,7 +158,9 @@ | ||
RedisProbe.prototype.requestEnd = function (probeData, cmd, methodArgs) { | ||
var context = {}; | ||
context.cmd = cmd; | ||
probeData.req.stop(context); | ||
if(probeData && probeData.req) { | ||
var context = {}; | ||
context.cmd = cmd; | ||
probeData.req.stop(context); | ||
} | ||
}; | ||
module.exports = RedisProbe; |
@@ -138,4 +138,6 @@ /******************************************************************************* | ||
SocketioProbe.prototype.metricsEnd = function(context, methodName, methodArgs) { | ||
context.timer.stop(); | ||
am.emit('socketio', {time: context.timer.startTimeMillis, method: methodName, event: methodArgs[0], duration: context.timer.timeDelta}); | ||
if(context && context.timer) { | ||
context.timer.stop(); | ||
am.emit('socketio', {time: context.timer.startTimeMillis, method: methodName, event: methodArgs[0], duration: context.timer.timeDelta}); | ||
} | ||
}; | ||
@@ -158,5 +160,6 @@ | ||
SocketioProbe.prototype.requestEnd = function (context, methodName, methodArgs) { | ||
context.req.stop({method: methodName, event: methodArgs[0]}); | ||
if(context && context.req) | ||
context.req.stop({method: methodName, event: methodArgs[0]}); | ||
}; | ||
module.exports = SocketioProbe; |
@@ -120,11 +120,13 @@ /******************************************************************************* | ||
Strong_MQProbe.prototype.metricsEnd = function(context, methodName, methodArgs, eventType) { | ||
context.timer.stop(); | ||
// default to quality of service (qos) 0, as that's what the strong-mq module does | ||
var eventData ={time: context.timer.startTimeMillis, duration: context.timer.timeDelta, type: eventType} | ||
if( methodName == 'publish') { | ||
eventData.method = methodName; | ||
} else { | ||
eventData.event = 'message'; | ||
} | ||
am.emit('strong-mq', eventData); | ||
if(context && context.timer) { | ||
context.timer.stop(); | ||
// default to quality of service (qos) 0, as that's what the strong-mq module does | ||
var eventData ={time: context.timer.startTimeMillis, duration: context.timer.timeDelta, type: eventType} | ||
if( methodName == 'publish') { | ||
eventData.method = methodName; | ||
} else { | ||
eventData.event = 'message'; | ||
} | ||
am.emit('strong-mq', eventData); | ||
} | ||
}; | ||
@@ -137,6 +139,6 @@ | ||
if (methodName === 'publish') { | ||
context.req = request.startRequest('STRONG-MQ', methodName, false, context.timer); | ||
context.req = request.startRequest('strong-mq', methodName, false, context.timer); | ||
} else { | ||
/* Received messages mark the start of requests. */ | ||
context.req = request.startRequest('STRONG-MQ', 'message', true, context.timer); | ||
context.req = request.startRequest('strong-mq', 'message', true, context.timer); | ||
} | ||
@@ -146,5 +148,6 @@ }; | ||
Strong_MQProbe.prototype.requestEnd = function (context, methodName, methodArgs, socketType) { | ||
context.req.stop({topic: methodArgs[0]}); | ||
if(context && context.req) | ||
context.req.stop({topic: methodArgs[0]}); | ||
}; | ||
module.exports = Strong_MQProbe; | ||
module.exports = Strong_MQProbe; |
@@ -94,9 +94,11 @@ /******************************************************************************* | ||
StrongOracleProbe.prototype.metricsEnd = function(probeData, method, methodArgs) { | ||
probeData.timer.stop(); | ||
var query = methodArgs[0]; | ||
am.emit('strong-oracle', { | ||
time : probeData.timer.startTimeMillis, | ||
query : query, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
if(probeData && probeData.timer) { | ||
probeData.timer.stop(); | ||
var query = methodArgs[0]; | ||
am.emit('strong-oracle', { | ||
time : probeData.timer.startTimeMillis, | ||
query : query, | ||
duration : probeData.timer.timeDelta | ||
}); | ||
} | ||
}; | ||
@@ -108,10 +110,12 @@ | ||
StrongOracleProbe.prototype.requestStart = function (probeData, method, methodArgs) { | ||
probeData.req = request.startRequest('StrongOracle', method, false, probeData.timer); | ||
probeData.req = request.startRequest('strong-oracle', method, false, probeData.timer); | ||
}; | ||
StrongOracleProbe.prototype.requestEnd = function (probeData, method, methodArgs) { | ||
var query = methodArgs[0]; | ||
probeData.req.stop({query:query}); | ||
if(probeData && probeData.req) { | ||
var query = methodArgs[0]; | ||
probeData.req.stop({query:query}); | ||
} | ||
}; | ||
module.exports = StrongOracleProbe; | ||
module.exports = StrongOracleProbe; |
220
README.md
@@ -20,3 +20,2 @@ # Node Application Metrics | ||
Event Loop | Event loop latency information | ||
Express | Express 4.x Web Framework application request monitoring | ||
Loop | Event loop timing metrics | ||
@@ -65,7 +64,7 @@ Function profiling | Node/V8 function profiling (disabled by default) | ||
<a name="install"></a> | ||
### Installation | ||
Node Application Metrics can be installed using **npm** either locally or globally. | ||
**When installed locally** you can access monitoring data via both the API and the Health Center client by modifying your application to use appmetrics (see *[Modifying your application to use the local installation](#run-local)*). | ||
**When installed locally** you can access monitoring data via both the API and the Health Center client by modifying your application to use appmetrics (see *[Modifying your application to use the local installation](#modifying-your-application-to-use-the-local-installation)*). | ||
@@ -78,3 +77,3 @@ To perform a local install: | ||
**When installed globally** you can access monitoring data via the Health Center client (but not the API) by using the `node-hc` command-line utility (see *[The `node-hc` command](#run-global)*). | ||
**When installed globally** you can access monitoring data via the Health Center client (but not the API) by using the `node-hc` command-line utility (see *[The `node-hc` command](#the-node-hc-command)*). | ||
@@ -101,3 +100,2 @@ To perform a global install: | ||
<a name="config"></a> | ||
### Configuring Node Application Metrics | ||
@@ -107,3 +105,3 @@ | ||
Node Application Metrics comes with a configuration file inside the [module installation directory](#install) (`.../node_modules/appmetrics/appmetrics.properties`). This can be used to configure connection options, logging and data source options. | ||
Node Application Metrics comes with a configuration file inside the [module installation directory](#installation) (`.../node_modules/appmetrics/appmetrics.properties`). This can be used to configure connection options, logging and data source options. | ||
@@ -126,5 +124,5 @@ Node Application Metrics will attempt to load `appmetrics.properties` from one of the following locations (in order): | ||
## Running Node Application Metrics | ||
<a name="run-global"></a> | ||
### The `node-hc` command | ||
If you [globally installed](#install) this module with npm, you can use the `node-hc` command to run your application instead of the `node` command. This will run your application as it would normally under node (including any node options) but additionally load and start `appmetrics`. | ||
If you [globally installed](#installation) this module with npm, you can use the `node-hc` command to run your application instead of the `node` command. This will run your application as it would normally under node (including any node options) but additionally load and start `appmetrics`. | ||
@@ -137,5 +135,4 @@ ```sh | ||
<a name="run-local"></a> | ||
### Modifying your application to use the local installation | ||
If you [locally install](#install) this module with npm then you will additionally have access to the monitoring data via the `appmetrics` API (see *[API Documentation](#api-doc)*). | ||
If you [locally install](#installation) this module with npm then you will additionally have access to the monitoring data via the `appmetrics` API (see *[API Documentation](#api-documentation)*). | ||
@@ -173,7 +170,6 @@ To load `appmetrics` and get the monitoring API object, add the following to the start-up code for your application: | ||
Note that both the API and the Health Center client can be used at the same time and will receive the same data. Use of the API requires a local install and application modification (see *[Modifying your application to use the local installation](#run-local)*). | ||
Note that both the API and the Health Center client can be used at the same time and will receive the same data. Use of the API requires a local install and application modification (see *[Modifying your application to use the local installation](#modifying-your-application-to-use-the-local-installation)*). | ||
Further information regarding the use of the Health Center client with Node Application Metrics can be found on the [appmetrics wiki][3]: [Using Node Application Metrics with the Health Center client](https://github.com/RuntimeTools/appmetrics/wiki/Using-Node-Application-Metrics-with-the-Health-Center-client). | ||
<a name="api-doc"></a> | ||
## API Documentation | ||
@@ -200,5 +196,5 @@ ### appmetrics.configure(options) | ||
### appmetrics.enable(`type`, `config`) | ||
Enable data generation of the specified data type. | ||
* `type` (String) the type of event to start generating data for. Values of `eventloop`, `express`, `profiling`, `http`, `http-outbound`, `mongo`, `socketio`, `mqlight`, `postgresql`, `mqtt`, `mysql`, `redis`, `riak`, `memcached`, `oracledb`, `oracle`, `strong-oracle`, `requests` and `trace` are currently supported. As `trace` is added to request data, both `requests` and `trace` must be enabled in order to receive trace data. | ||
* `config` (Object) (optional) configuration map to be added for the data type being enabled. (see *[setConfig](#set-config)*) for more information. | ||
Enable data generation of the specified data type. Cannot be called until the agent has been started by calling `start()` or `monitor()`. | ||
* `type` (String) the type of event to start generating data for. Values of `eventloop`, `profiling`, `http`, `http-outbound`, `mongo`, `socketio`, `mqlight`, `postgresql`, `mqtt`, `mysql`, `redis`, `riak`, `memcached`, `oracledb`, `oracle`, `strong-oracle`, `requests` and `trace` are currently supported. As `trace` is added to request data, both `requests` and `trace` must be enabled in order to receive trace data. | ||
* `config` (Object) (optional) configuration map to be added for the data type being enabled. (see *[setConfig](#appmetricssetconfigtype-config)*) for more information. | ||
@@ -208,6 +204,5 @@ The following data types are disabled by default: `profiling`, `requests`, `trace` | ||
### appmetrics.disable(`type`) | ||
Disable data generation of the specified data type. | ||
* `type` (String) the type of event to stop generating data for. Values of `eventloop`, `express`, `profiling`, `http`, `mongo`, `socketio`, `mqlight`, `postgresql`, `mqtt`, `mysql`, `redis`, `riak`, `memcached`, `oracledb`, `oracle`, `strong-oracle`, `requests` and `trace` are currently supported. | ||
Disable data generation of the specified data type. Cannot be called until the agent has been started by calling `start()` or `monitor()`. | ||
* `type` (String) the type of event to stop generating data for. Values of `eventloop`, `profiling`, `http`, `mongo`, `socketio`, `mqlight`, `postgresql`, `mqtt`, `mysql`, `redis`, `riak`, `memcached`, `oracledb`, `oracle`, `strong-oracle`, `requests` and `trace` are currently supported. | ||
<a name="set-config"></a> | ||
### appmetrics.setConfig(`type`, `config`) | ||
@@ -249,16 +244,10 @@ Set the configuration to be applied to a specific data type. The configuration available is specific to the data type. | ||
### Event: 'memory' | ||
Emitted when a memory monitoring sample is taken. | ||
* `data` (Object) the data from the memory sample: | ||
* `time` (Number) the milliseconds when the sample was taken. This can be converted to a Date using `new Date(data.time)`. | ||
* `physical_total` (Number) the total amount of RAM available on the system in bytes. | ||
* `physical_used` (Number) the total amount of RAM in use on the system in bytes. | ||
* `physical_free` (Number) the total amount of free RAM available on the system in bytes. | ||
* `virtual` (Number) the memory address space used by the Node.js application in bytes. | ||
* `private` (Number) the amount of memory used by the Node.js application that cannot be shared with other processes, in bytes. | ||
* `physical` (Number) the amount of RAM used by the Node.js application in bytes. | ||
### Event: 'eventloop' | ||
Emitted every 5 seconds, summarising sample based information of the event loop latency | ||
* `data` (Object) the data from the event loop sample: | ||
* `time` (Number) the milliseconds when the event was emitted. This can be converted to a Date using `new Date(data.time)`. | ||
* `latency.min` (Number) the shortest sampled latency, in milliseconds. | ||
* `latency.max` (Number) the longest sampled latency, in milliseconds. | ||
* `latency.avg` (Number) the average sampled latency, in milliseconds. | ||
### Event: 'initialized' | ||
Emitted when all possible environment variables have been collected. Use `appmetrics.monitor.getEnvironment()` to access the available environment variables. | ||
### Event: 'gc' | ||
@@ -273,9 +262,4 @@ Emitted when a garbage collection (GC) cycle occurs in the underlying V8 runtime. | ||
### Event: 'eventloop' | ||
Emitted every 5 seconds, summarising sample based information of the event loop latency | ||
* `data` (Object) the data from the event loop sample: | ||
* `time` (Number) the milliseconds when the event was emitted. This can be converted to a Date using `new Date(data.time)`. | ||
* `latency.min` (Number) the shortest sampled latency, in milliseconds. | ||
* `latency.max` (Number) the longest sampled latency, in milliseconds. | ||
* `latency.avg` (Number) the average sampled latency, in milliseconds. | ||
### Event: 'initialized' | ||
Emitted when all possible environment variables have been collected. Use `appmetrics.monitor.getEnvironment()` to access the available environment variables. | ||
@@ -290,2 +274,13 @@ ### Event: 'loop' | ||
### Event: 'memory' | ||
Emitted when a memory monitoring sample is taken. | ||
* `data` (Object) the data from the memory sample: | ||
* `time` (Number) the milliseconds when the sample was taken. This can be converted to a Date using `new Date(data.time)`. | ||
* `physical_total` (Number) the total amount of RAM available on the system in bytes. | ||
* `physical_used` (Number) the total amount of RAM in use on the system in bytes. | ||
* `physical_free` (Number) the total amount of free RAM available on the system in bytes. | ||
* `virtual` (Number) the memory address space used by the Node.js application in bytes. | ||
* `private` (Number) the amount of memory used by the Node.js application that cannot be shared with other processes, in bytes. | ||
* `physical` (Number) the amount of RAM used by the Node.js application in bytes. | ||
### Event: 'profiling' | ||
@@ -303,2 +298,4 @@ Emitted when a profiling sample is available from the underlying V8 runtime. | ||
## API: Dependency Events (probes) | ||
### Event: 'http' | ||
@@ -311,4 +308,5 @@ Emitted when a HTTP request is made of the application. | ||
* `duration` (Number) the time taken for the HTTP request to be responded to in ms. | ||
* `header` (String) the header for the HTTP request. | ||
* `header` (String) the response header for the HTTP request. | ||
* `contentType` (String) the content type of the HTTP request. | ||
* `requestHeader` (Object) the request header for HTTP request. | ||
@@ -324,17 +322,21 @@ ### Event: 'http-outbound' | ||
* `duration` (Number) the time taken for the HTTP request to be responded to in ms. | ||
* 'requestHeaders' (Object) the HTTP request headers. | ||
### Event: 'socketio' | ||
Emitted when WebSocket data is sent or received by the application using socketio. | ||
* `data` (Object) the data from the socket.io request: | ||
* `time` (Number) the milliseconds when the event occurred. This can be converted to a Date using `new Date(data.time)`. | ||
* `method` (String) whether the event is a `broadcast` or `emit` from the application, or a `receive` from a client . | ||
* `event` (String) the name used for the event. | ||
* `duration` (Number) the time taken for event to be sent or for a received event to be handled. | ||
### Event: 'leveldown' | ||
Emitted when a LevelDB query is made using the `leveldown` module. | ||
* `data` (Object) the data from the LevelDB query: | ||
* `time` (Number) the time in milliseconds when the LevelDB query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `method` (String) The leveldown method being used. | ||
* `key` (Object) The key being used for a call to `get`, `put` or `del` (Undefined for other methods) | ||
* `value` (Object) The value being added to the LevelDB database using the `put` method (Undefined for other methods) | ||
* `opCount` (Number) The number of operations carried out by a `batch` method (Undefined for other methods) | ||
* `duration` (Number) the time taken for the LevelDB query to be responded to in ms. | ||
### Event: 'mysql' | ||
Emitted when a MySQL query is made using the `mysql` module. | ||
* `data` (Object) the data from the MySQL query: | ||
* `time` (Number) the milliseconds when the MySQL query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `query` (String) the query made of the MySQL database. | ||
* `duration` (Number) the time taken for the MySQL query to be responded to in ms. | ||
### Event: 'memcached' | ||
Emitted when a data is stored, retrieved or modified in Memcached using the `memcached` module. | ||
* `data` (Object) the data from the memcached event: | ||
* `time` (Number) the milliseconds when the memcached event occurred. This can be converted to a Date using `new Date(data.time)` | ||
* `method` (String) the method used in the memcached client, eg `set`, `get`, `append`, `delete`, etc. | ||
* `key` (String) the key associated with the data. | ||
* `duration` (Number) the time taken for the operation on the memcached data to occur. | ||
@@ -350,11 +352,2 @@ ### Event: 'mongo' | ||
### Event: 'mqtt' | ||
Emitted when a MQTT message is sent or received. | ||
* `data` (Object) the data from the MQTT event: | ||
* `time` (Number) the time in milliseconds when the MQTT event occurred. This can be converted to a Date using new Date(data.time). | ||
* `method` (String) the name of the call or event (will be one of 'publish' or 'message'). | ||
* `topic` (String) the topic on which a message is published or received. | ||
* `qos` (Number) the QoS level for the message. | ||
* `duration` (Number) the time taken in milliseconds. | ||
### Event: 'mqlight' | ||
@@ -371,12 +364,39 @@ Emitted when a MQLight message is sent or received. | ||
### Event: 'leveldown' | ||
Emitted when a LevelDB query is made using the `leveldown` module. | ||
* `data` (Object) the data from the LevelDB query: | ||
* `time` (Number) the time in milliseconds when the LevelDB query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `method` (String) The leveldown method being used. | ||
* `key` (Object) The key being used for a call to `get`, `put` or `del` (Undefined for other methods) | ||
* `value` (Object) The value being added to the LevelDB database using the `put` method (Undefined for other methods) | ||
* `opCount` (Number) The number of operations carried out by a `batch` method (Undefined for other methods) | ||
* `duration` (Number) the time taken for the LevelDB query to be responded to in ms. | ||
### Event: 'mqtt' | ||
Emitted when a MQTT message is sent or received. | ||
* `data` (Object) the data from the MQTT event: | ||
* `time` (Number) the time in milliseconds when the MQTT event occurred. This can be converted to a Date using new Date(data.time). | ||
* `method` (String) the name of the call or event (will be one of 'publish' or 'message'). | ||
* `topic` (String) the topic on which a message is published or received. | ||
* `qos` (Number) the QoS level for the message. | ||
* `duration` (Number) the time taken in milliseconds. | ||
### Event: 'mysql' | ||
Emitted when a MySQL query is made using the `mysql` module. | ||
* `data` (Object) the data from the MySQL query: | ||
* `time` (Number) the milliseconds when the MySQL query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `query` (String) the query made of the MySQL database. | ||
* `duration` (Number) the time taken for the MySQL query to be responded to in ms. | ||
### Event: 'oracle' | ||
Emitted when a query is executed using the `oracle` module. | ||
* `data` (Object) the data from the Oracle query: | ||
* `time` (Number) the milliseconds when the Oracle query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `query` (String) the query made of the Oracle database. | ||
* `duration` (Number) the time taken for the Oracle query to be responded to in ms. | ||
### Event: 'oracledb' | ||
Emitted when a query is executed using the `oracledb` module. | ||
* `data` (Object) the data from the OracleDB query: | ||
* `time` (Number) the milliseconds when the OracleDB query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `query` (String) the query made of the OracleDB database. | ||
* `duration` (Number) the time taken for the OracleDB query to be responded to in ms. | ||
### Event: 'postgres' | ||
Emitted when a PostgreSQL query is made to the `pg` module. | ||
* `data` (Object) the data from the PostgreSQL query: | ||
* `time` (Number) the milliseconds when the PostgreSQL query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `query` (String) the query made of the PostgreSQL database. | ||
* `duration` (Number) the time taken for the PostgreSQL query to be responded to in ms. | ||
### Event: 'redis' | ||
@@ -399,24 +419,10 @@ Emitted when a Redis command is sent. | ||
### Event: 'memcached' | ||
Emitted when a data is stored, retrieved or modified in Memcached using the `memcached` module. | ||
* `data` (Object) the data from the memcached event: | ||
* `time` (Number) the milliseconds when the memcached event occurred. This can be converted to a Date using `new Date(data.time)` | ||
* `method` (String) the method used in the memcached client, eg `set`, `get`, `append`, `delete`, etc. | ||
* `key` (String) the key associated with the data. | ||
* `duration` (Number) the time taken for the operation on the memcached data to occur. | ||
### Event: 'socketio' | ||
Emitted when WebSocket data is sent or received by the application using socketio. | ||
* `data` (Object) the data from the socket.io request: | ||
* `time` (Number) the milliseconds when the event occurred. This can be converted to a Date using `new Date(data.time)`. | ||
* `method` (String) whether the event is a `broadcast` or `emit` from the application, or a `receive` from a client . | ||
* `event` (String) the name used for the event. | ||
* `duration` (Number) the time taken for event to be sent or for a received event to be handled. | ||
### Event: 'oracledb' | ||
Emitted when a query is executed using the `oracledb` module. | ||
* `data` (Object) the data from the OracleDB query: | ||
* `time` (Number) the milliseconds when the OracleDB query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `query` (String) the query made of the OracleDB database. | ||
* `duration` (Number) the time taken for the OracleDB query to be responded to in ms. | ||
### Event: 'oracle' | ||
Emitted when a query is executed using the `oracle` module. | ||
* `data` (Object) the data from the Oracle query: | ||
* `time` (Number) the milliseconds when the Oracle query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `query` (String) the query made of the Oracle database. | ||
* `duration` (Number) the time taken for the Oracle query to be responded to in ms. | ||
### Event: 'strong-oracle' | ||
@@ -428,13 +434,15 @@ Emitted when a query is executed using the `strong-oracle` module. | ||
* `duration` (Number) the time taken for the Strong Oracle query to be responded to in ms. | ||
## API: Requests | ||
### Event: 'request' | ||
Emitted when a request is made of the application that involves one or more monitored application level events. Request events are disabled by default. | ||
Requests are a special type of event emitted by appmetrics. All the probes named above can also create request events if requests are enabled. Howver requests are nested within a root incoming request (usually http). Request events are disabled by default. | ||
* `data` (Object) the data from the request: | ||
* `time` (Number) the milliseconds when the request occurred. This can be converted to a Date using `new Date(data.time)`. | ||
* `type` (String) The type of the request event. This can currently be set to 'HTTP' or 'DB'. | ||
* `type` (String) The type of the request event. This is the name of the probe that sent the request data, e.g. `http`, `socketio` etc. | ||
* `name` (String) The name of the request event. This is the request task, eg. the url, or the method being used. | ||
* `request` (Object) the detailed data for the root request event: | ||
* `type` (String) The type of the request event. This can currently be set to 'HTTP' or 'DB'. | ||
* `type` (String) The type of the request event. This is the name of the probe that sent the request data, e.g. `http`, `socketio` etc. | ||
* `name` (String) The name of the request event. This is the request task, eg. the url, or the method being used. | ||
* `context` (Object) A map of any additional context information for the request event. | ||
* `context` (Object) Additional context data (usually contains the same data as the associated non-request metric event). | ||
* `stack` (String) An optional stack trace for the event call. | ||
@@ -445,17 +453,2 @@ * `children` (Array) An array of child request events that occurred as part of the overall request event. Child request events may include function trace entries, which will have a `type` of null. | ||
### Event: 'postgres' | ||
Emitted when a PostgreSQL query is made to the `pg` module. | ||
* `data` (Object) the data from the PostgreSQL query: | ||
* `time` (Number) the milliseconds when the PostgreSQL query was made. This can be converted to a Date using `new Date(data.time)`. | ||
* `query` (String) the query made of the PostgreSQL database. | ||
* `duration` (Number) the time taken for the PostgreSQL query to be responded to in ms. | ||
### Event: 'express' | ||
Emitted when an express request finishes its response. Note. appmetrics has only been tested with express 4.x, support is not guaranteed for lower versions. | ||
* `data` (Object) the data from the Express request/response. | ||
* `method` (String) The HTTP method for this request. | ||
* `url` (String) The target URL for this request. | ||
* `statusCode` (Number) The HTTP status code of the response. | ||
* `duration` (Number) The time in ms between receiving the request and sending the response. | ||
## Troubleshooting | ||
@@ -470,3 +463,3 @@ Find below some possible problem scenarios and corresponding diagnostic steps. Updates to troubleshooting information will be made available on the [appmetrics wiki][3]: [Troubleshooting](https://github.com/RuntimeTools/appmetrics/wiki/Troubleshooting). If these resources do not help you resolve the issue, you can open an issue on the Node Application Metrics [appmetrics issue tracker][5]. | ||
### Error "Conflicting appmetrics module was already loaded by node-hc. Try running with node instead." when using `node-hc` | ||
This error indicates you are using `node-hc` to run an application that uses the Node Application Metrics monitoring API (see *[Modifying your application to use the local installation](#run-local)*). Resolve this by using `node` to run the application instead. **Alternatively**, you could remove (or disable temporarily) the use of the Node Application Metrics monitoring API in your application. | ||
This error indicates you are using `node-hc` to run an application that uses the Node Application Metrics monitoring API (see *[Modifying your application to use the local installation](#modifying-your-application-to-use-the-local-installation)*). Resolve this by using `node` to run the application instead. **Alternatively**, you could remove (or disable temporarily) the use of the Node Application Metrics monitoring API in your application. | ||
@@ -495,3 +488,3 @@ This error was added to prevent the scenario where 2 instances of the agent can be accidentally created and started in parallel -- the globally installed one created by `node-hc` and the locally installed one created by the `require('appmetrics');` call in an application modified to use the Node Application Metrics monitoring API. | ||
### No profiling data present for Node.js applications | ||
Method profiling data is not collected by default, check *[Configuring Node Application Metrics](#config)* for information on how to enable it. | ||
Method profiling data is not collected by default, check *[Configuring Node Application Metrics](#configuring-node-application-metrics)* for information on how to enable it. | ||
@@ -515,5 +508,6 @@ If collection is enabled, an absence of method profiling data from a Node.js application could be caused by the type of tasks that are being run by your application -- it may be running long, synchronous tasks that prevent collection events from being scheduled on the event loop. | ||
## Version | ||
2.0.1 | ||
3.0.0 | ||
## Release History | ||
`3.0.0` - Remove express probe. | ||
`2.0.1` - Remove support for Node.js 0.10, 0.12, 5. Add heapdump api call. | ||
@@ -520,0 +514,0 @@ `1.2.0` - Add file data collection capability and option configuration via api. |
@@ -16,6 +16,8 @@ /******************************************************************************* | ||
*******************************************************************************/ | ||
'use strict' | ||
var app = require('./test_app'); | ||
var appmetrics = app.start(); | ||
var monitor = app.appmetrics.monitor(); | ||
var semver = require('semver'); | ||
app.appmetrics.enable("profiling"); | ||
@@ -225,3 +227,3 @@ | ||
var ARCHS = ['x86', 'x86_64', 'ppc32', 'ppc64', 'ppc64le', 's390', 's390x']; | ||
var OSES = ['AIX', 'Linux', 'Windows 7', 'Mac OS X']; | ||
var OSES = ['AIX', 'Linux', 'Windows', 'Mac OS X']; | ||
@@ -231,4 +233,10 @@ t.ok(ARCHS.indexOf(commonEnvData['os.arch']) != -1, | ||
t.ok(OSES.indexOf(commonEnvData['os.name']) != -1, | ||
"Contains a recognised value for os.name"); | ||
var found = false; | ||
for (var entry in OSES) { | ||
if ((commonEnvData['os.name']).indexOf(OSES[entry]) > -1) { | ||
found = true; | ||
break; | ||
} | ||
} | ||
t.ok(found, "Contains a recognised value for os.name"); | ||
@@ -328,4 +336,3 @@ t.match(commonEnvData['os.version'],/\S/, | ||
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); | ||
if(nodeVersion >= 6.5) { // issue 283 | ||
if(semver.gt(process.version, '6.5.0')) { // issue 283 | ||
t.ok(2*parseInt(nodeEnvData['max.semi.space.size']) + parseInt(nodeEnvData['max.old.space.size']) === parseInt(nodeEnvData['heap.size.limit']), | ||
@@ -332,0 +339,0 @@ 'Values for max.old.space.size and max.semi.space.size match heap.size.limit'); |
@@ -24,3 +24,3 @@ /******************************************************************************* | ||
tap.plan(2); | ||
tap.plan(3); | ||
@@ -34,3 +34,3 @@ tap.tearDown(function() { | ||
monitor.on('http-outbound', function(data) { | ||
if (completedTests < 2) { | ||
if (completedTests < 3) { | ||
tap.test("HTTP Outbound Event", function(t) { | ||
@@ -49,4 +49,8 @@ checkHttpOutboundData(data, t); | ||
"Should report GET as HTTP request method"); | ||
t.equals(data.url, "http://localhost:8000", | ||
"Should report http://localhost:8000 as URL"); | ||
t.equals(data.url, "http://localhost:8000/", | ||
"Should report http://localhost:8000/ as URL"); | ||
if (data.requestHeaders) { | ||
t.equals(data.requestHeaders.hello, "world", | ||
"Should report world as value of hello header"); | ||
} | ||
} | ||
@@ -62,7 +66,18 @@ | ||
var options = { | ||
host: "localhost", | ||
port: 8000, | ||
headers: { | ||
hello: "world" | ||
} | ||
} | ||
// Request with a callback | ||
http.get('http://localhost:8000', function (res) {}); | ||
http.get('http://localhost:8000/', function (res) {}); | ||
// Request without a callback | ||
http.get('http://localhost:8000') | ||
http.get('http://localhost:8000/') | ||
// Request with headers | ||
http.request(options).end() | ||
@@ -29,1 +29,10 @@ /******************************************************************************* | ||
}); | ||
tap.test('Appmetrics should be a global singleton', function(t) { | ||
var appmetrics = require('../'); | ||
// Delete cached module | ||
delete require.cache[require.resolve('../')] | ||
var appmetrics2 = require('../'); | ||
t.equals(appmetrics, appmetrics2); | ||
t.end(); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Copyleft License
License(Experimental) Copyleft license information was found.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
Non-permissive License
License(Experimental) A license not known to be considered permissive was found.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 12 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
9094574
531
17501
3
15
60
515
60