Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to call Sentry.configureScope?

I am using sentry browser with my CRA react application. I create an error-boundary component and I am using it to catch errors.

So far so good, I catch the error and successfully log it to sentry.

The problem comes when I want to pass user information, or set tags; those information are not passed, unless I set it in my index file (but in that way I do no have access to the store, and therefore the current user info).

So, where should I call Sentry.configureScope() to set those information?

EDIT: I realized that sentry.configureScope() in fact works fine inside my logger function. The problem is that I am trying to wrap App with ErrorBoundary, and unless the error is already present at start up, it would not be cathed.

Now, provided that I would like to keep a basic granularity, how can I avoid to wrap every component in ErrorBoundary?

My code below:

INDEX:

Sentry.init({
  dsn: "https://xxxxx.yyyyyyyyy",
  environment: process.env.NODE_ENV,
  release: '0.1.0'
})

// HERE IT WOULD WORK --------- BUT I HAVE NO STORE ACCESS
/* Sentry.configureScope(scope => {
     scope.setExtra('battery', 0.7);
     scope.setTag('user_access', 'admin');
     scope.setUser({ id: '555' });
}); */

ReactDOM.render(
<Provider store={store}>
    <LocalizeProvider store={store}>
        <PersistGate loading={<Spinner />} persistor={persistor}>
            <ErrorBoundary>
                <App />
            </ErrorBoundary>
        </PersistGate>
    </LocalizeProvider>
</Provider>,
document.getElementById('root'));

ERROR-BOUNDARY.JS

import * as React from 'react'
import * as Sentry from '@sentry/browser';


function logError(error, extraContext = {}) {
    Sentry.configureScope(scope => {
        scope.setExtra('battery', 0.7);
        scope.setTag('user_mode', 'admin');
        scope.setUser({ 'id': '4711' });

        if(extraContext.extra) {
            Object.keys(extraContext.extra).forEach(key => {
                scope.setExtra(key, extraContext.extra[key])
            })
        }
        Sentry.captureException(error)
    })
}


export default class ErrorBoundary extends React.Component {
  state = { error: null }

  static getDerivedStateFromError(error) {
    return {
        error: {
            timestamp: new Date().toJSON(),
            message: error.message,
        }
    }
  }

componentDidCatch(error, info) {
    logError(error, { extra: { ...info } })
}

render() {
    const { error } = this.state
    if (error != null) {
        return <div className="container-fluid">
            <h2>An error has occurred</h2>
            <div><strong>Message</strong>: {error.message}</div>
            <div><strong>Timestamp</strong>: {error.timestamp}</div>
        </div>
    }

    return this.props.children
  }
}
like image 510
gianni Avatar asked Jun 24 '19 14:06

gianni


1 Answers

I think you should use Sentry.withScope in your ErrorBoundary, this is what works in my app:

function logError(error, extraContext = {}) {
  Sentry.withScope(scope => {
    scope.setExtra('battery', 0.7);
    scope.setTag('user_mode', 'admin');
    scope.setUser({ 'id', '4711' });

    if(extraContext.extra) {
      Object.keys(extraContext.extra).forEach(key => {
        scope.setExtra(key, extraContext.extra[key])
      });
    }

    Sentry.captureException(error);
  });

Reference : https://docs.sentry.io/enriching-error-data/scopes/?platform=javascript#local-scopes

like image 190
adesurirey Avatar answered Nov 18 '22 12:11

adesurirey