sentry-javascript icon indicating copy to clipboard operation
sentry-javascript copied to clipboard

[Crash-Report Modal] User feedback not linked to Sentry error

Open LeAnsman opened this issue 1 year ago • 5 comments

Is there an existing issue for this?

  • [X] I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
  • [X] I have reviewed the documentation https://docs.sentry.io/
  • [X] I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/react

SDK Version

7.80.0

Framework Version

React 17.0.2

Link to Sentry event

No response

SDK Setup

!!! SDK is v7.80.0

import * as Sentry from '@sentry/react'
import { matchPath, useHistory } from 'react-router-dom'
import { ExtraErrorData } from '@sentry/integrations'
import { RoutePath } from './routes/RoutePath'
import { version } from '../package.json'

const routes = Object.values(RoutePath).map(path => ({ path }))

Sentry.init({
    enabled: true,
    dsn: REACT_APP_DSN,
    integrations: [
        new Sentry.BrowserTracing({
            routingInstrumentation: Sentry.reactRouterV5Instrumentation(useHistory, routes, matchPath),
        }),
        new ExtraErrorData({ depth: 5 }),
    ],
    tracesSampleRate: 1.0,
    tracePropagationTargets: [
        // ...
    ],
    replaysOnErrorSampleRate: 1.0,
    environment: process.env.NODE_ENV === 'production' ? process.env.REACT_APP_ENV_NAME : process.env.NODE_ENV,
    release: version,
})

if (process.env.REACT_APP_ENV_NAME === 'production' || process.env.REACT_APP_ENV_NAME === 'sandbox') {
    Sentry.addIntegration(new Sentry.Replay())
}

Steps to Reproduce

I'm using Error boundary from Sentry like so :

import React, { useContext } from 'react'
import { ErrorBoundary } from '@sentry/react'
import SideMenu from './SideMenu'
import NavigationBar from './NavigationBar'
import ErrorToast from '../ui/errors/ErrorToast'
import Routes from '../../routes/Routes'
import AppContext from '../../contexts/AppContext'
import ErrorPage from '../../pages/ErrorPage'
import SessionTimeout from '../login/SessionTimeout'
import FullScreenLoader from './FullScreenLoader'

const AppContent = () => {
    const { isLoggedIn, isFullScreenLoading } = useContext(AppContext)

    return (
        <>
            <SideMenu />
            <div style={{ paddingLeft: isLoggedIn ? '60px' : 0, width: '100%' }}>
                {isLoggedIn && <SessionTimeout countDownDurationInSec={60} />}
                <NavigationBar />
                <ErrorToast />
                {isFullScreenLoading && <FullScreenLoader />}
                <ErrorBoundary fallback={({ resetError, eventId }) => <ErrorPage resetError={resetError} eventId={eventId} />}>
                    <Routes />
                </ErrorBoundary>
            </div>
        </>
    )
}

export default AppContent

Here is my ErrorPage :

import React, { useEffect, useRef } from 'react'
import { Button, Container } from 'react-bootstrap'
import { useHistory } from 'react-router-dom'
import { showReportDialog } from '@sentry/react'
import BackButton from '../components/ui/buttons/BackButton'

interface Props {
    resetError: () => void
    eventId: string
}

const ErrorPage = ({ resetError, eventId }: Props) => {
    const history = useHistory()
    const errorLocation = useRef(history.location.pathname)

    useEffect(() => {
        if (history.location.pathname !== errorLocation.current) {
            resetError()
        }
    }, [history.location.pathname])

    const handleClick = () => {
        showReportDialog({ eventId })
    }

    return (
        <Container>
            <div className="page-title-box">
                <h2 className="page-title">It looks like something went wrong... </h2>
            </div>
            <p>
                We apologize for the inconvenience, but it seems that something unexpected has occurred.
            </p>
            <p>
                Our team is actively addressing the issue, and we appreciate your patience as we work to resolve it.
            </p>
            <p>
                In the meantime, you have the option to go back or provide us with valuable feedback to assist us in improving.
            </p>
            <div className="d-flex gap-2 mt-3">
                <BackButton />
                <Button onClick={handleClick}>Report Feedback</Button>
            </div>
        </Container>
    )
}
export default ErrorPage

The issue I'm having is capturing the user feedback. The feedback itself is captured, but the eventId is not the same in the error in sentry and in the report dialog.

Expected Result

I was expecting the ids to be the same (actual error send to Sentry and prop passed to the my custom fallback ErrorPage) so that I could link the error and the user feedback (if provided).

Actual Result

It is not linked :

The issue has this id : image

The user feedback (is captured but is not linked) has this id : image

As you can see, the id are different, any idea why ?

FYI : This has been tried in dev but also in prod.

Thanks to y'all!

LeAnsman avatar Dec 21 '23 10:12 LeAnsman

Do you have react strict mode enabled?

lforst avatar Dec 21 '23 14:12 lforst

@lforst We do have strict mode enabled, but this issue is also happening in production.

EDIT : I disabled the strict mode, sentry issue is still not linked with the user feedback.

LeAnsman avatar Dec 22 '23 08:12 LeAnsman

@LeAnsman Alright. I think I need to reproduce this to see how to fix this. If you want to speed up the process you could provide a small reproduction example in a GitHub repo, otherwise I'll get to it myself in the upcoming weeks.

lforst avatar Dec 27 '23 08:12 lforst

Running into the same issue. Very similar implementation with ErrorBoundary and a fallback with showReportDialog. Haven't changed any of our sentry config recently and worked as expected up until around the time the new user-feedback ui got introduced.

stratty7 avatar Jan 31 '24 01:01 stratty7

I ran into a similar issue and it might be due to this... https://github.com/getsentry/sentry-javascript/issues/8281

There are some thoughts around this being only for a React dev server, however the sentry code does call captureException twice and seems to generate a new id on each call... however the dedupe instrumentation cancels the second call, leaving the error boundary/feedback dialog with a non-existent event id...

MFoster avatar Feb 05 '24 16:02 MFoster

+1, same issue

atrudeau-vitall avatar Mar 20 '24 21:03 atrudeau-vitall

@billyvg Would you mind taking a look?

lforst avatar Mar 21 '24 09:03 lforst

Running into the same issue. Very similar implementation with ErrorBoundary and a fallback with showReportDialog. Haven't changed any of our sentry config recently and worked as expected up until around the time the new user-feedback ui got introduced.

@stratty7 Do the reports behave differently in the old user feedback UI?

@lforst This seems related to https://github.com/getsentry/sentry-javascript/issues/8281 rather than user feedback.

From @LeAnsman's screenshot of the issue, it looks like there is also feedback item in the User Feedback tab (which our new feedback would not have changed). So seems likely it's the issue with ErrorBoundary where the event ids are different and thus link is .

That being said, I tried to repro this here and was unsuccessful, both methods worked fine.

billyvg avatar Mar 21 '24 16:03 billyvg

I am also seeing this issue. Interestingly, it seems to be the eventId passed to the fallback page which is not correct. I am not using the feedback UI, but my fallback component gets an eventId which is different to that recorded.

I can actually see that the event ID rendered in the browser playback is different to that recorded in the event.

roberttod avatar Jul 12 '24 19:07 roberttod

I realize this was caused by one of the many global integrations capturing the error, and then the fallback component getting an event ID which was ignored due to it already being recorded.

I am assuming this is what OP was seeing too. Perhaps the captureexception call would be able to return the event ID of the event that is actually sent, rather than the one that has been deduped?

For now I have fixed this by using defaultIntegrations: false in the sentry config.

roberttod avatar Jul 12 '24 20:07 roberttod

Hey @roberttod

I can actually see that the event ID rendered in the browser playback is different to that recorded in the event.

What do you mean by "brower playback"? Did you check the requests in chrome dev tools?

For now I have fixed this by using defaultIntegrations: false in the sentry config.

This very likely disables more than you want, unless you manually add all integrations that e.g. add data to your error. What would really help us with this issue would be a minimal reproduction that we can look into.

Perhaps the captureexception call would be able to return the event ID of the event that is actually sent, rather than the one that has been deduped?

The problem here is that multiple calls to captureException are completely independent from each other. The dedupe integration is the exception which always compares the fingerprint of the last known issue with the one it's currently processing.

I'd prefer finding out which integrations cancel each other out first.

Last question: Can you confirm this only happens in dev mode or also if you build for prod?

Lms24 avatar Jul 15 '24 07:07 Lms24

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you remove the label Waiting for: Community, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

getsantry[bot] avatar Aug 09 '24 07:08 getsantry[bot]