Sentry-javascript: Clarify "passing extra data"

Created on 10 Dec 2013  ·  15Comments  ·  Source: getsentry/sentry-javascript

According to the docs,

captureException, context, wrap, and captureMessage functions all allow passing additional data to be tagged onto the error, such as tags.

However, I don't think this means _arbitrary_ data. For example, you can't do this:

Raven.captureMessage('Hello world', {planet: {name: 'Earth'}});

It would be nice if the docs were more clear on what additional data is allowed.

Most helpful comment

@mattrobenolt does this work in the same way for captureException? and btw, I think it would be better if in the docs you specify something like:

Raven.captureException(e, {extra: { foo: { bar: "baz" }}})

All 15 comments

Ah, I'll clarify in documentation. You _can_ actually pass arbitrary information like that through extra.

Raven.captureMessage('Hello world', {extra: {planet: {name: 'Earth'}}})

And you get this inside Sentry:

image

Thanks!

@mattrobenolt does this work in the same way for captureException? and btw, I think it would be better if in the docs you specify something like:

Raven.captureException(e, {extra: { foo: { bar: "baz" }}})

It works the same for captureException, just tested that!

I try to use it with captureException and it doesn't work, I have two lines as below:

Raven.captureException(error, {extra: { captureException: 'captureException' }})
Raven.captureMessage(error, {extra: { captureMessage: 'captureMessage' }})

and I can see both errors in sentry, but only capture message has extra tag.

screen shot 2018-06-25 at 11 57 00

@zywyz just tested it and everything works fine. Can you provide repro case that doesn't work for you?

I found another solution which works for me, so I don't need help anymore.

But according to reason why it doesn't work for me I have no idea as I can see for you it works.

Raven.config(`https://${key}`, { environment, release }).install()

export function logError(errOrMessage) {
  const error = is(String, errOrMessage) ? new Error(errOrMessage) : errOrMessage

  Raven.captureException(error, {extra: { captureException: 'captureException' }})
}

and in index.html

<script src="https://cdn.ravenjs.com/3.26.3/raven.min.js" crossorigin="anonymous"></script>

@kamilogorek it works for me only if I put captureMessage before captureException (so weird):

Raven.captureMessage('Something happened', {extra: {some: 'data'}});
Raven.captureException(error, {extra: {some: 'data'}});

If I don't put captureMessage, I don't get {extra: {some: 'data'}} in my captureException

Can someone in May 2019 clarify how we can pass extra data via captureMessage or captureException ?

We are using,

import * as Sentry from '@sentry/browser';
Sentry.init({
    dsn: sentry_url
})
Sentry.captureMessage(message, {extra: {some: 'data'}})

But I do not see any extra data coming through with these events.

The docs for the newest version of the library make lots of references to contexts & things like that so maybe this functionality has moved?

@econner
https://docs.sentry.io/enriching-error-data/scopes/
https://docs.sentry.io/enriching-error-data/context/#extra-context

Sentry.withScope(scope => {
  scope.setExtra('some', 'data');
  Sentry.captureMessage(message);
});

@kamilogorek
Followup on econner's question. Lets say that I need all exceptions to include the local state and/or props of the component that threw an error, would I then need to include this code in each of my components? or is there a way of handling this globally?

Sentry.withScope(scope => {
  scope.setExtra('localProps', this.props);
  scope.setExtra('localState', this.state);
  Sentry.captureException(error);
});

Extra question: Should I manually call Sentry.captureException() when an exception happens? or is the code above simply a way to append these extra parameters, so that they are included when an exception happens?

@woba-ko

is there a way of handling this globally?

In this case, I'd use ExtraErrorData integration and attach those two things to the error itself, letting the integration extract it:

https://docs.sentry.io/platforms/javascript/#extraerrordata

error.localProps = this.props;
error.localState = this.state;
Sentry.captureException(error);

You should also use rather shallow serialization depth for it, as props and state can be quite large.

Should I manually call Sentry.captureException() when an exception happens?

It depends whether you use Reacts errorBoundary or let the error bubble to the global onerror handler.

is the code above simply a way to append these extra parameters, so that they are included when an exception happens?

Correct. Every captured event has the scope it was captured in attached when it's sent to Sentry.

@kamilogorek

Thank you for the fast reply, I apologize if this is not the correct forum for these questions.

Your idea of ExtraErrorData seems to fit my case, but I am a bit confused about the actual implementation of it, as I am unsure where your error-object comes from, is it just an arbitrary object that you created in the component or is there a specific error-object needed from sentry? Also, where in the component should this be placed?

It depends whether you use Reacts errorBoundary or let the error bubble to the global onerror handler.

Lets assume that I don't want to use Reacts errorBoundary atm. and just want a react component to include this.props and this.state in the error sent to sentry, could this be accomplished like below?

  1. Add integrations to my Sentry.init():
Sentry.init({
  dsn: 'my-dsn-here',
  integrations: [new Integrations.ExtraErrorData({ depth: 1 })] 
})
  1. Add this to componentDidMount() of all the components that should include props and state when that component throws an unhandled error:
const error = {localProps: this.props, localState: this.state}
Sentry.captureException(error)

where your error-object comes from

It's what errorBoundary gives you. You have to either capture or create an error object somewhere.

If you don't use error boundries, we are not able to co-relate state or props with a given error, as there's no relationship between them and something that was captured by global onerror handler.

Sentry.captureException accepts the error object, so what you have to pass to it is an instance of Error, for example.

componentDidMount() {
  try {
    somethingThatBreaks()
  } catch (e) {
    e.localProps = this.props;
    e.localState = this.state;
    Sentry.captureException(e)
  }
}

or

componentDidMount() {
  if (someCondition()) {
    const someError = new Error('something broke')
    someError.localProps = this.props;
    someError.localState = this.state;
    Sentry.captureException(someError)
  }
}

or

componentDidMount() {
  if (someCondition()) {
    const someError = new Error('something broke')
    someError.localProps = this.props;
    someError.localState = this.state;
    throw someError;
  }
}

Aah that makes sense, thank you for the clarification!

Was this page helpful?
0 / 5 - 0 ratings