Skip to content

Commit

Permalink
merge dev into master
Browse files Browse the repository at this point in the history
  • Loading branch information
vmarchaud committed Feb 20, 2017
2 parents 1ab2b65 + 499522f commit cf45c77
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 66 deletions.
9 changes: 9 additions & 0 deletions examples/throw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

var pmx = require('..');

pmx.catchAll();


setTimeout(function() {
throw new Error('ok');
}, 1000);
17 changes: 13 additions & 4 deletions lib/notify.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ var util = require('util');
var Common = require('./common.js');

var Options = require('./configuration.js');

var Transport = require('./utils/transport.js');

var Notify = {};
Expand All @@ -24,14 +23,16 @@ var jsonize = function(err, filter, space) {

Notify.catchAll = function(opts) {

var callsites = require('./utils/error-callsites')

if (opts === undefined)
opts = { errors : true };

Options.configureModule({
error : opts.errors
});

if (process.env.exec_mode == 'cluster_mode')
if (process.env.exec_mode === 'cluster_mode')
return false;

function getUncaughtExceptionListener(listener) {
Expand All @@ -48,9 +49,8 @@ Notify.catchAll = function(opts) {
}

console.error(error);

if (err)
var errObj = jsonize(err);
var errObj = Notify._interpretError(err);

Transport.send({
type : 'process:exception',
Expand Down Expand Up @@ -93,6 +93,15 @@ Notify._interpretError = function(err) {
}
else if (err instanceof Error) {
// Error object type processing
err.stack;
if (err.__error_callsites) {
var stackFrames = [];
err.__error_callsites.forEach(function(callSite) {
stackFrames.push({ file_name: callSite.getFileName(), line_number: callSite.getLineNumber()});
});
err.stackframes = stackFrames;
delete err.__error_callsites;
}
s_err = err;
}

Expand Down
20 changes: 20 additions & 0 deletions lib/utils/error-callsites/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict'

var formatter = require('./node-0.10-formatter')

var orig = Error.prepareStackTrace
Error.prepareStackTrace = function (err, callsites) {
Object.defineProperty(err, '__error_callsites', {
enumerable: false,
configurable: true,
writable: false,
value: callsites
})

return (orig || formatter)(err, callsites)
}

module.exports = function (err) {
err.stack
return err.__error_callsites
}
32 changes: 32 additions & 0 deletions lib/utils/error-callsites/node-0.10-formatter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict'

// Lifted from Node.js 0.10.40:
// https://github.com/nodejs/node/blob/0439a28d519fb6efe228074b0588a59452fc1677/deps/v8/src/messages.js#L1053-L1080
module.exports = function FormatStackTrace (error, frames) {
var lines = []
try {
lines.push(error.toString())
} catch (e) {
try {
lines.push('<error: ' + e + '>')
} catch (ee) {
lines.push('<error>')
}
}
for (var i = 0; i < frames.length; i++) {
var frame = frames[i]
var line
try {
line = frame.toString()
} catch (e) {
try {
line = '<error: ' + e + '>'
} catch (ee) {
// Any code that reaches this point is seriously nasty!
line = '<error>'
}
}
lines.push(' at ' + line)
}
return lines.join('\n')
}
5 changes: 3 additions & 2 deletions test/notify.mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ describe('Notify exceptions', function() {

should.exist(ret.stack);
should.exist(ret.message);

ret.stack.line.should.eql('ok');
ret.stack.env.should.eql('sisi');
done();
Expand All @@ -87,7 +86,6 @@ describe('Notify exceptions', function() {

should.exist(ret.stack);
should.exist(ret.message);

done();
});

Expand Down Expand Up @@ -161,6 +159,9 @@ describe('Notify exceptions', function() {
app.once('message', function(data) {
data.type.should.eql('axm:option:configuration');
app.once('message', function(data) {
should.exist(data.data.stackframes);
should.exist(data.data.stackframes[0].file_name);
should.exist(data.data.stackframes[0].line_number);
data.type.should.eql('process:exception');
data.data.message.should.eql('global error');
process.kill(app.pid);
Expand Down
124 changes: 64 additions & 60 deletions test/vxx.e2e.mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ describe('Programmatically test interactor', function() {
});

describe('application testing', function() {
afterEach(function() {
//console.log(sub);
//sub.unsubscribe();
});

it('should start test application', function(done) {
sub.once('message', function(data) {
var packet = JSON.parse(data);
Expand All @@ -58,15 +63,15 @@ describe('Programmatically test interactor', function() {
pm2.start({
script : 'app.js',
name : 'API',
trace : true
env: {
"DEBUG": "*"
}
}, function(err, data) {
if (err) done(err);

});
});

it('should get transaction trace via interactor output', function(done) {
pm2.trigger('API', 'launchMock');

(function callAgain() {
sub.once('message', function(data) {
var packet = JSON.parse(data);
Expand All @@ -75,78 +80,78 @@ describe('Programmatically test interactor', function() {

// Only one app
packet.data['axm:transaction'].length.should.eql(1);
var data = packet.data['axm:transaction'][0].data;

// Should only find 3 different routes
Object.keys(packet.data['axm:transaction'][0].data.routes).length.should.eql(3);
Object.keys(data.routes).length.should.eql(3);
data.routes[0].should.have.properties(['meta', 'variances', 'path']);
data.routes[0].meta.should.have.properties(['min', 'max', 'mean', 'count']);
var route = data.routes[0].variances[0];

var route;

packet.data['axm:transaction'][0].data.routes.forEach(function(_route) {
if (_route.path == '/')
route = _route;
});

route.meta.should.have.properties(['mean', 'max', 'min', 'count']);
route.variances.length.should.eql(1);
// Right property keys
route.should.have.properties(['min', 'max', 'mean', 'meter', 'count', 'spans']);
done();
}
else callAgain();
});
})()

pm2.trigger('API', 'launchMock');
});

it('should get database transaction trace (save)', function(done) {
pm2.trigger('API', 'launchQueryToDbRoutes');

(function callAgain() {
sub.once('message', function(data) {
var packet = JSON.parse(data);

if (packet.data['axm:transaction']) {
packet.data['axm:transaction'][0].data.routes.length.should.eql(4);

packet.data['axm:transaction'][0].data.routes.forEach(function(_route) {
if (_route.path == '/db1/save') {
_route.variances.length.should.eql(1);
_route.meta.should.have.properties(['mean', 'max', 'min', 'count']);
_route.variances[0].spans[1].name.should.eql('mongo-insert');
}
});
var data = packet.data['axm:transaction'][0].data;
// Should now route summary contains 4 routes
Object.keys(data.routes).length.should.eql(4);

var route = data.routes.filter(function (route) {
return route.path === '/db1/save';
})[0];
// Should count 10 transactions
route.variances[0].count.should.eql(10);
//console.log(packet.data['axm:transaction'][0].data.routes['/db1/save']);
route.variances[0].spans.length.should.eql(2);
route.variances[0].spans[1].name.should.eql('mongo-insert');
done();
}
else
callAgain();
});
})()

pm2.trigger('API', 'launchQueryToDbRoutes');
});

it('should get simple database transaction trace (find)', function(done) {
pm2.trigger('API', 'db1get');
(function callAgain() {
sub.once('message', function(data) {
var packet = JSON.parse(data);

setTimeout(function() {
(function callAgain() {
sub.once('message', function(data) {
var packet = JSON.parse(data);

if (packet.data['axm:transaction']) {
// Should now route summary contains 5 routes
Object.keys(packet.data['axm:transaction'][0].data.routes).length.should.eql(5);

// @bug: should contain only 1 transaction not 2 (only find)
packet.data['axm:transaction'][0].data.routes.forEach(function(_route) {
if (_route.path == '/db1/get') {
_route.variances.forEach(function(vari) {
vari.spans.length.should.eql(2);
});
}
});
done();
}
else
callAgain();
});
})()
}, 1000);
if (packet.data['axm:transaction']) {
var data = packet.data['axm:transaction'][0].data;
// Should now route summary contains 5 routes
Object.keys(data.routes).length.should.eql(5);

var route = data.routes.filter(function (route) {
return route.path === '/db1/get';
})[0];

// @bug: should contain only 1 transaction not 2 (only find)
route.variances[0].spans.length.should.eql(2);

done();
}
else
callAgain();
});
})()

pm2.trigger('API', 'db1get');
});

it('should get multi database transaction trace (find + findOne)', function(done) {
Expand All @@ -155,17 +160,16 @@ describe('Programmatically test interactor', function() {
var packet = JSON.parse(data);

if (packet.data['axm:transaction']) {
var data = packet.data['axm:transaction'][0].data;
// Should now route summary contains 5 routes
Object.keys(packet.data['axm:transaction'][0].data.routes).length.should.eql(6);
Object.keys(data.routes).length.should.eql(6);

// @bug: should contain only 1 transaction not 2 (only find)
packet.data['axm:transaction'][0].data.routes.forEach(function(_route) {
if (_route.path == '/db1/multi') {
_route.variances.forEach(function(vari) {
vari.spans.length.should.eql(3);
});
}
});
var route = data.routes.filter(function (route) {
return route.path === '/db1/multi';
})[0];

// @bug: should contain only 2 transactions not 3 (find + findOne)
route.variances[0].spans.length.should.eql(3);

done();
}
Expand All @@ -180,4 +184,4 @@ describe('Programmatically test interactor', function() {

});

});
});

0 comments on commit cf45c77

Please sign in to comment.