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
}
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With