Skip to content

Commit aaf6770

Browse files
authored
feat: send error context as custom data (#870)
1 parent d50272d commit aaf6770

7 files changed

+124
-1
lines changed

src/browser/transforms.js

+18
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ function handleItemWithError(item, options, callback) {
1919
if (item.err) {
2020
try {
2121
item.stackInfo = item.err._savedStackTrace || errorParser.parse(item.err, item.skipFrames);
22+
23+
if (options.addErrorContext) {
24+
addErrorContext(item);
25+
}
2226
} catch (e) {
2327
logger.error('Error while parsing the error object.', e);
2428
try {
@@ -32,6 +36,20 @@ function handleItemWithError(item, options, callback) {
3236
callback(null, item);
3337
}
3438

39+
function addErrorContext(item) {
40+
var chain = [];
41+
var err = item.err;
42+
43+
chain.push(err);
44+
45+
while (err.nested) {
46+
err = err.nested;
47+
chain.push(err);
48+
}
49+
50+
_.addErrorContext(item, chain);
51+
}
52+
3553
function ensureItemHasSomethingToSay(item, options, callback) {
3654
if (!item.message && !item.stackInfo && !item.custom) {
3755
callback(new Error('No message, stack info, or custom data'), null);

src/react-native/transforms.js

+4
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ function handleItemWithError(item, options, callback) {
6464
return callback(null, item);
6565
}
6666

67+
if (options.addErrorContext) {
68+
_.addErrorContext(item, [item.err]);
69+
}
70+
6771
var err = item.err;
6872
var parsedError = errorParser.parse(err);
6973
var guess = errorParser.guessErrorClass(parsedError.message);

src/server/transforms.js

+4
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ function handleItemWithError(item, options, callback) {
8888
} while (err !== undefined);
8989
item.stackInfo = chain;
9090

91+
if (options.addErrorContext) {
92+
_.addErrorContext(item, errors);
93+
}
94+
9195
var cb = function(e) {
9296
if (e) {
9397
item.message = item.err.message || item.err.description || item.message || String(item.err);

src/utility.js

+22
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,27 @@ function setCustomItemKeys(item, custom) {
506506
}
507507
}
508508

509+
function addErrorContext(item, errors) {
510+
var custom = item.data.custom || {};
511+
var contextAdded = false;
512+
513+
try {
514+
for (var i = 0; i < errors.length; ++i) {
515+
if (errors[i].hasOwnProperty('rollbarContext')) {
516+
custom = merge(custom, errors[i].rollbarContext);
517+
contextAdded = true;
518+
}
519+
}
520+
521+
// Avoid adding an empty object to the data.
522+
if (contextAdded) {
523+
item.data.custom = custom;
524+
}
525+
} catch (e) {
526+
item.diagnostic.error_context = 'Failed: ' + e.message;
527+
}
528+
}
529+
509530
var TELEMETRY_TYPES = ['log', 'network', 'dom', 'navigation', 'error', 'manual'];
510531
var TELEMETRY_LEVELS = ['critical', 'error', 'warning', 'info', 'debug'];
511532

@@ -776,6 +797,7 @@ function handleOptions(current, input, payload) {
776797
module.exports = {
777798
addParamsAndAccessTokenToPath: addParamsAndAccessTokenToPath,
778799
createItem: createItem,
800+
addErrorContext: addErrorContext,
779801
createTelemetryEvent: createTelemetryEvent,
780802
filterIp: filterIp,
781803
formatArgsAsString: formatArgsAsString,

test/browser.rollbar.test.js

+27
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,33 @@ describe('log', function() {
744744
done();
745745
})
746746

747+
it('should add custom data when called with error context', function(done) {
748+
var server = window.server;
749+
stubResponse(server);
750+
server.requests.length = 0;
751+
752+
var options = {
753+
accessToken: 'POST_CLIENT_ITEM_TOKEN',
754+
addErrorContext: true
755+
};
756+
var rollbar = window.rollbar = new Rollbar(options);
757+
758+
var err = new Error('test error');
759+
err.rollbarContext = { err: 'test' };
760+
761+
rollbar.error(err, { 'foo': 'bar' });
762+
763+
server.respond();
764+
765+
var body = JSON.parse(server.requests[0].requestBody);
766+
767+
expect(body.data.body.trace.exception.message).to.eql('test error');
768+
expect(body.data.custom.foo).to.eql('bar');
769+
expect(body.data.custom.err).to.eql('test');
770+
771+
done();
772+
})
773+
747774
it('should send message when called with only null arguments', function(done) {
748775
var server = window.server;
749776
stubResponse(server);

test/browser.transforms.test.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -426,13 +426,31 @@ describe('addBody', function() {
426426
expect(i.stackInfo).to.be.ok();
427427
});
428428
t.addBody(item, options, function(e, i) {
429-
console.log('body:', i.data.body)
430429
expect(i.data.body.trace_chain.length).to.eql(2);
431430
expect(i.data.body.trace_chain[0].exception.message).to.eql('test error');
432431
expect(i.data.body.trace_chain[1].exception.message).to.eql('nested error');
433432
done(e);
434433
});
435434
});
435+
it('should create add error context as custom data', function(done) {
436+
var nestedErr = new Error('nested error');
437+
nestedErr.rollbarContext = { err1: 'nested context' };
438+
var err = new Error('test error');
439+
err.rollbarContext = { err2: 'error context' };
440+
err.nested = nestedErr;
441+
var args = ['a message', err];
442+
var item = itemFromArgs(args);
443+
var options = { addErrorContext: true };
444+
t.handleItemWithError(item, options, function(e, i) {
445+
expect(i.stackInfo).to.be.ok();
446+
});
447+
t.addBody(item, options, function(e, i) {
448+
expect(i.data.body.trace_chain.length).to.eql(2);
449+
expect(i.data.custom.err1).to.eql('nested context');
450+
expect(i.data.custom.err2).to.eql('error context');
451+
done(e);
452+
});
453+
});
436454
});
437455
});
438456

test/server.transforms.test.js

+30
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,36 @@ vows.describe('transforms')
382382
assert.equal(trace_chain[0].exception.message, 'nested-message');
383383
assert.equal(trace_chain[1].exception.class, 'ReferenceError');
384384
}
385+
},
386+
'with error context': {
387+
topic: function (options) {
388+
var test = function() {
389+
var x = thisVariableIsNotDefined;
390+
};
391+
var err;
392+
try {
393+
test();
394+
} catch (e) {
395+
err = new CustomError('nested-message', e);
396+
e.rollbarContext = { err1: 'nested context' };
397+
err.rollbarContext = { err2: 'error context' };
398+
}
399+
var item = {
400+
data: {body: {}},
401+
err: err
402+
};
403+
options.addErrorContext = true;
404+
t.handleItemWithError(item, options, this.callback);
405+
},
406+
'should not error': function(err, item) {
407+
assert.ifError(err);
408+
},
409+
'should add the error context': function(err, item) {
410+
var trace_chain = item.stackInfo;
411+
assert.lengthOf(trace_chain, 2);
412+
assert.equal(item.data.custom.err1, 'nested context');
413+
assert.equal(item.data.custom.err2, 'error context');
414+
}
385415
}
386416
}
387417
}

0 commit comments

Comments
 (0)