getsentry / raven-node

A standalone (Node.js) client for Sentry
https://sentry.io/
BSD 2-Clause "Simplified" License
454 stars 135 forks source link

`captureException` mutates (not merges) and does not send original `context` when first argument is not an Error instance #442

Open newhouse opened 6 years ago

newhouse commented 6 years ago

Hi there, sometime the things I want to capture with Raven/Sentry are not Error instances (but sometimes they are).

I was having an issue with raven ^2.30 going into an infinite loop while doing the following-ish:

const channelInstance = new Channel(); // This is from my ORM, Objection.js and this is psuedocode
const jsonNotError = { foo: 'bar' };
const usefulContext = { area: 'blah', channel: channelInstance };
ravenClient.captureException(jsonNotError, usefulContext);

I guess raven's parser somehow went into an infinite loop trying to stringify channelInstance and eventually the max frames were reached. So, I updated to latest raven 2.4.2 and now the infinite loop is gone, but if I pass a non-Error instance to captureException, any additional context I pass is overwritten and not sent to Sentry.

Example:

const Raven = require('raven');
const SENTRY_DSN = 'xxxx;

const client = Raven.config(SENTRY_DSN, {environment: 'debug'}).install();

const json = {
  message: 'You did something stupid with our API',
  code: 690,
  name: 'StupidError'
};

const someContext = {
  extra: {
    foo: 'bar',
    importantStuff: 'foobar, yo'
  }
};

console.log('json:', json); // outputs what you'd expect
console.log('context:', someContext); // outputs what you'd expect

client.captureException(json, someContext);
console.log('json:', json); // outputs what you'd expect
console.log('context:', someContext); // Outputs something like { extra: { __serialized__:  /* my json object */ , message: 'Non-Error exception captured with keys: code, message, name', fingerprint: [ 'xxxxx' ] } }

setTimeout(process.exit, 4000);

It seems like when a non-Error instance is passed to captureException that Raven will not only NOT merge/use the original someContext that was passed BUT ALSO will overwrite the someContext object. The someContext does not make it to Sentry in my issues, which means that information is lost.

I would expect that it would merge the someContext I passed with whatever stuff it wants to (__serialized__, etc) but it doesn't.

Am I doing something wrong, or is this a bug?

newhouse commented 6 years ago

actually, i lied: updating to 2.4.2 didn't fix the infinite loop issue (something else I changed did), and that's probably another issue I should file besides this one. Will need to dig into that one more when I have time.

Nevertheless, the issue in the title still remains.