123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- import {Component} from 'react';
- import {withRouter, WithRouterProps} from 'react-router';
- import styled from '@emotion/styled';
- import * as Sentry from '@sentry/react';
- import Alert from 'app/components/alert';
- import {IconWarning} from 'app/icons';
- import {t, tct} from 'app/locale';
- import space from 'app/styles/space';
- import {LightWeightOrganization, Project} from 'app/types';
- import getRouteStringFromRoutes from 'app/utils/getRouteStringFromRoutes';
- import withOrganization from 'app/utils/withOrganization';
- import withProject from 'app/utils/withProject';
- type Props = WithRouterProps & {
- organization: LightWeightOrganization;
- error: Error | undefined;
- /**
- * Disable logging to Sentry
- */
- disableLogSentry?: boolean;
- disableReport?: boolean;
- project?: Project;
- };
- class RouteError extends Component<Props> {
- UNSAFE_componentWillMount() {
- const {error} = this.props;
- const {disableLogSentry, disableReport, organization, project, routes} = this.props;
- if (disableLogSentry) {
- return;
- }
- if (!error) {
- return;
- }
- const route = getRouteStringFromRoutes(routes);
- const enrichScopeContext = scope => {
- scope.setExtra('route', route);
- scope.setExtra('orgFeatures', (organization && organization.features) || []);
- scope.setExtra('orgAccess', (organization && organization.access) || []);
- scope.setExtra('projectFeatures', (project && project.features) || []);
- return scope;
- };
- if (route) {
- /**
- * Unexpectedly, error.message would sometimes not have a setter property, causing another exception to be thrown,
- * and losing the original error in the process. Wrapping the mutation in a try-catch in an attempt to preserve
- * the original error for logging.
- * See https://github.com/getsentry/sentry/issues/16314 for more details.
- */
- try {
- error.message = `${error.message}: ${route}`;
- } catch (e) {
- Sentry.withScope(scope => {
- enrichScopeContext(scope);
- Sentry.captureException(e);
- });
- }
- }
- // TODO(dcramer): show something in addition to embed (that contains it?)
- // throw this in a timeout so if it errors we don't fall over
- this._timeout = window.setTimeout(() => {
- Sentry.withScope(scope => {
- enrichScopeContext(scope);
- Sentry.captureException(error);
- });
- if (!disableReport) {
- Sentry.showReportDialog();
- }
- });
- }
- componentWillUnmount() {
- if (this._timeout) {
- window.clearTimeout(this._timeout);
- }
- document.querySelector('.sentry-error-embed-wrapper')?.remove();
- }
- private _timeout: undefined | number;
- render() {
- // TODO(dcramer): show additional resource links
- return (
- <Alert icon={<IconWarning size="md" />} type="error">
- <Heading>
- <span>{t('Oops! Something went wrong')}</span>
- </Heading>
- <p>
- {t(`
- It looks like you've hit an issue in our client application. Don't worry though!
- We use Sentry to monitor Sentry and it's likely we're already looking into this!
- `)}
- </p>
- <p>{t("If you're daring, you may want to try the following:")}</p>
- <ul>
- {window && window.adblockSuspected && (
- <li>
- {t(
- "We detected something AdBlock-like. Try disabling it, as it's known to cause issues."
- )}
- </li>
- )}
- <li>
- {tct(`Give it a few seconds and [link:reload the page].`, {
- link: (
- <a
- onClick={() => {
- window.location.href = window.location.href;
- }}
- />
- ),
- })}
- </li>
- <li>
- {tct(`If all else fails, [link:contact us] with more details.`, {
- link: <a href="https://github.com/getsentry/sentry/issues/new/choose" />,
- })}
- </li>
- </ul>
- </Alert>
- );
- }
- }
- const Heading = styled('h3')`
- display: flex;
- align-items: center;
- font-size: ${p => p.theme.headerFontSize};
- font-weight: normal;
- margin-bottom: ${space(1.5)};
- `;
- export default withRouter(withOrganization(withProject(RouteError)));
- export {RouteError};
|