-
-
Notifications
You must be signed in to change notification settings - Fork 131
fix: Do not override context when capturing non-error exceptions #444
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -331,7 +331,8 @@ extend(Raven.prototype, { | |
| cb = kwargs; | ||
| kwargs = {}; | ||
| } else { | ||
| kwargs = kwargs || {}; | ||
| // Do not use reference, as we'll modify this object later on | ||
| kwargs = kwargs ? JSON.parse(stringify(kwargs)) : {}; | ||
| } | ||
|
|
||
| var eventId = this.generateEventId(); | ||
|
|
@@ -367,25 +368,24 @@ extend(Raven.prototype, { | |
| cb = kwargs; | ||
| kwargs = {}; | ||
| } else { | ||
| kwargs = kwargs || {}; | ||
| // Do not use reference, as we'll modify this object later on | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this a normal way to accomplish a multiple arity function with an optional second arg? it seems a bit complicated but it's worked well so far
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately yes :( |
||
| kwargs = kwargs ? JSON.parse(stringify(kwargs)) : {}; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there anything not serializable that we should be worried about being passed here, like functions?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. did you consider only copying this at the point of mutation to avoid this code running on all execution paths? not sure if that's actually a good idea or not.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we may run into issues with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I read through the codebase once again and it appears that we should be perfectly fine. https://github.com/getsentry/raven-node/blob/master/lib/client.js#L549-L562 This middleware is passing just an |
||
| } | ||
|
|
||
| if (!(err instanceof Error)) { | ||
| if (utils.isPlainObject(err)) { | ||
| // This will allow us to group events based on top-level keys | ||
| // which is much better than creating new group when any key/value change | ||
| var keys = Object.keys(err).sort(); | ||
| var hash = md5(keys); | ||
| var message = | ||
| 'Non-Error exception captured with keys: ' + | ||
| utils.serializeKeysForMessage(keys); | ||
| var serializedException = utils.serializeException(err); | ||
|
|
||
| kwargs.message = message; | ||
| kwargs.fingerprint = [hash]; | ||
| kwargs.extra = { | ||
| __serialized__: serializedException | ||
| }; | ||
| kwargs = extend(kwargs, { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| message: message, | ||
| fingerprint: [md5(keys)], | ||
| extra: kwargs.extra || {} | ||
| }); | ||
| kwargs.extra.__serialized__ = utils.serializeException(err); | ||
|
|
||
| err = new Error(message); | ||
| } else { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -223,6 +223,22 @@ describe('raven.Client', function() { | |
| done(); | ||
| }); | ||
| }); | ||
|
|
||
| it('should copy object with extra data instead of using its reference directly', function(done) { | ||
| var old = client.send; | ||
| var info = { | ||
| extra: { | ||
| hello: 'there' | ||
| } | ||
| }; | ||
| client.send = function mockSend(kwargs) { | ||
| client.send = old; | ||
| kwargs.extra.should.have.property('hello', 'there'); | ||
| kwargs.extra.should.not.equal(info); | ||
| done(); | ||
| }; | ||
| client.captureMessage('exception', info); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#captureException()', function() { | ||
|
|
@@ -259,13 +275,9 @@ describe('raven.Client', function() { | |
| var old = client.send; | ||
| client.send = function mockSend(kwargs) { | ||
| client.send = old; | ||
|
|
||
| kwargs.message.should.equal( | ||
| 'Non-Error exception captured with keys: aKeyOne, bKeyTwo, cKeyThree, dKeyFour\u2026' | ||
| ); | ||
|
|
||
| // Remove superfluous node version data to simplify the test itself | ||
| delete kwargs.extra.node; | ||
| kwargs.extra.should.have.property('__serialized__', { | ||
| aKeyOne: 'a', | ||
| bKeyTwo: 42, | ||
|
|
@@ -385,6 +397,41 @@ describe('raven.Client', function() { | |
| done(); | ||
| }); | ||
| }); | ||
|
|
||
| it('should use and merge provided extra data instead of overriding it', function(done) { | ||
| var old = client.send; | ||
| client.send = function mockSend(kwargs) { | ||
| client.send = old; | ||
| kwargs.extra.should.have.property('hello', 'there'); | ||
| kwargs.tags.should.deepEqual({'0': 'whoop'}); | ||
| done(); | ||
| }; | ||
| client.captureException( | ||
| {some: 'exception'}, | ||
| { | ||
| extra: { | ||
| hello: 'there' | ||
| }, | ||
| tags: ['whoop'] | ||
| } | ||
| ); | ||
| }); | ||
|
|
||
| it('should copy object with extra data instead of using its reference directly', function(done) { | ||
| var old = client.send; | ||
| var info = { | ||
| extra: { | ||
| hello: 'there' | ||
| } | ||
| }; | ||
| client.send = function mockSend(kwargs) { | ||
| client.send = old; | ||
| kwargs.extra.should.have.property('hello', 'there'); | ||
| kwargs.extra.should.not.equal(info); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this test be
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe this test should assert on the shape of info.extra anyway to be doubly sure
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We want to check the reference of a whole object that was passed to
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still think line 430 is a false positive and it should be (this test in its current form passes without your change)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're totally right. Fixed. |
||
| done(); | ||
| }; | ||
| client.captureException({some: 'exception'}, info); | ||
| }); | ||
| }); | ||
|
|
||
| describe('#install()', function() { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why did you need to do this one too? because of line 353?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, because, we don't want to mutate someone else's objects.
I also wanted to be consistent across
captureException/captureMessage.