Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support error cause #1012

Merged
merged 1 commit into from
Apr 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/browser/transforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ function addErrorContext(item) {

chain.push(err);

while (err.nested) {
err = err.nested;
while (err.nested || err.cause) {
err = err.nested || err.cause;
chain.push(err);
}

Expand Down
4 changes: 2 additions & 2 deletions src/errorParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ function Stack(exception, skip) {
function parse(e, skip) {
var err = e;

if (err.nested) {
if (err.nested || err.cause) {
var traceChain = [];
while (err) {
traceChain.push(new Stack(err, skip));
err = err.nested;
err = err.nested || err.cause;

skip = 0; // Only apply skip value to primary error
}
Expand Down
2 changes: 1 addition & 1 deletion src/server/transforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function handleItemWithError(item, options, callback) {
var chain = [];
do {
errors.push(err);
err = err.nested;
err = err.nested || err.cause;
} while (err);
item.stackInfo = chain;

Expand Down
43 changes: 43 additions & 0 deletions test/browser.transforms.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ function itemFromArgs(args) {
return item;
}

function chromeMajorVersion() {
return parseInt(navigator.userAgent.match(/Chrome\/([0-9]+)\./)[1]);
}

describe('handleDomException', function() {
it('should do nothing if not a DOMException', function(done) {
var err = new Error('test');
Expand Down Expand Up @@ -452,6 +456,45 @@ describe('addBody', function() {
});
});
});
describe('with error cause', function() {
// Error cause was introduced in Chrome 93.
if (chromeMajorVersion() < 93) return;

it('should create trace_chain', function(done) {
var causeErr = new Error('cause error');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know all old tests use the old var syntax but is there a reason to continue using them as opposed to const/let?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just consistency. I'd rather not have a mix until we're actually switching over to const/let.

var err = new Error('test error', { cause: causeErr});
var args = ['a message', err];
var item = itemFromArgs(args);
var options = {};
t.handleItemWithError(item, options, function(e, i) {
expect(i.stackInfo).to.be.ok();
});
t.addBody(item, options, function(e, i) {
expect(i.data.body.trace_chain.length).to.eql(2);
expect(i.data.body.trace_chain[0].exception.message).to.eql('test error');
expect(i.data.body.trace_chain[1].exception.message).to.eql('cause error');
done(e);
});
});
it('should create add error context as custom data', function(done) {
var causeErr = new Error('cause error');
causeErr.rollbarContext = { err1: 'cause context' };
var err = new Error('test error', { cause: causeErr});
err.rollbarContext = { err2: 'error context' };
var args = ['a message', err];
var item = itemFromArgs(args);
var options = { addErrorContext: true };
t.handleItemWithError(item, options, function(e, i) {
expect(i.stackInfo).to.be.ok();
});
t.addBody(item, options, function(e, i) {
expect(i.data.body.trace_chain.length).to.eql(2);
expect(i.data.custom.err1).to.eql('cause context');
expect(i.data.custom.err2).to.eql('error context');
done(e);
});
});
});
});

describe('scrubPayload', function() {
Expand Down
53 changes: 52 additions & 1 deletion test/server.transforms.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@ async function throwInScriptFile(rollbar, filepath, callback) {
callback(rollbar);
}

var nodeVersion = function () {
var version = process.versions.node.split('.');

return [
parseInt(version[0]),
parseInt(version[1]),
parseInt(version[2]),
];
}();

var isMinNodeVersion = function(major, minor) {
return (
nodeVersion[0] > major || (nodeVersion[0] === major && nodeVersion[1] >= minor)
);
}

vows.describe('transforms')
.addBatch({
'baseData': {
Expand Down Expand Up @@ -494,7 +510,42 @@ vows.describe('transforms')
assert.equal(item.data.custom.err1, 'nested context');
assert.equal(item.data.custom.err2, 'error context');
}
}
},
'with an error cause': {
topic: function (options) {
var test = function() {
var x = thisVariableIsNotDefined;
};
var err;
try {
test();
} catch (e) {
err = new Error('cause message', { cause: e });
e.rollbarContext = { err1: 'cause context' };
err.rollbarContext = { err2: 'error context' };
}
var item = {
data: {body: {}},
err: err
};
t.handleItemWithError(item, options, this.callback);
},
'should not error': function(err, item) {
assert.ifError(err);
},
'should have the right data in the trace_chain': function(err, item) {
// Error cause was introduced in Node 16.9.
if (!isMinNodeVersion(16, 9)) return;

var trace_chain = item.stackInfo;
assert.lengthOf(trace_chain, 2);
assert.equal(trace_chain[0].exception.class, 'Error');
assert.equal(trace_chain[0].exception.message, 'cause message');
assert.equal(trace_chain[1].exception.class, 'ReferenceError');
assert.equal(item.data.custom.err1, 'cause context');
assert.equal(item.data.custom.err2, 'error context');
}
},
}
}
}
Expand Down