Files
zeekayandHanzo Dev f888991a7a drop the Sentry wordmark from the react app
FSL-1.0-Apache-2.0 grants us the code, not the name. "Sentry" is
Functional Software's trademark, so every place the running app says it
to a user -- page titles, onboarding, empty states, toasts, settings
copy, the self-hosted footer -- now says Sentinel.

Attribution is the other half of the deal and stays untouched: upstream
copyright headers, LICENSE, NOTICE. So does anything where the mark is a
fact rather than a brand -- @sentry/* packages, sentry-cli, the wizard
and bundler plugins, docs.sentry.io, the whole gettingStartedDocs tree.
Renaming those would leave instructions that no longer work.

Nothing structural moved. No import, identifier, route path, feature
flag, API field or test id changed; the diff is 312 lines in and 312
out. Colocated specs were updated in lockstep with the copy they assert.
Marketing and community links point at hanzo.ai, only where a real page
exists to point at.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-10 18:01:22 -07:00

140 lines
4.3 KiB
TypeScript

import {useEffect} from 'react';
import styled from '@emotion/styled';
import * as Sentry from '@sentry/react';
import {Alert} from 'sentry/components/alert';
import ExternalLink from 'sentry/components/links/externalLink';
import List from 'sentry/components/list';
import ListItem from 'sentry/components/list/listItem';
import {t, tct} from 'sentry/locale';
import OrganizationStore from 'sentry/stores/organizationStore';
import {useLegacyStore} from 'sentry/stores/useLegacyStore';
import {space} from 'sentry/styles/space';
import type {Project} from 'sentry/types';
import getRouteStringFromRoutes from 'sentry/utils/getRouteStringFromRoutes';
import {useRoutes} from 'sentry/utils/useRoutes';
import withProject from 'sentry/utils/withProject';
type Props = {
/**
* Disable logging to Sentry
*/
disableLogSentry?: boolean;
/**
* Disable the report dialog
*/
disableReport?: boolean;
error?: Error;
project?: Project;
};
function RouteError({error, disableLogSentry, disableReport, project}: Props) {
const routes = useRoutes();
const {organization} = useLegacyStore(OrganizationStore);
useEffect(() => {
if (disableLogSentry) {
return undefined;
}
if (!error) {
return undefined;
}
const route = getRouteStringFromRoutes(routes);
const enrichScopeContext = (scope: Sentry.Scope) => {
scope.setExtra('route', route);
scope.setExtra('orgFeatures', organization?.features ?? []);
scope.setExtra('orgAccess', organization?.access ?? []);
scope.setExtra('projectFeatures', 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);
scope.setExtra('cannotSetMessage', true);
});
}
}
// 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
const reportDialogTimeout = window.setTimeout(() => {
Sentry.withScope(scope => {
enrichScopeContext(scope);
Sentry.captureException(error);
});
if (!disableReport) {
Sentry.showReportDialog();
}
});
return function cleanup() {
window.clearTimeout(reportDialogTimeout);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [error, disableLogSentry]);
// Remove the report dialog on unmount
useEffect(() => () => document.querySelector('.sentry-error-embed-wrapper')?.remove());
// TODO(dcramer): show additional resource links
return (
<Alert type="error">
<Heading>{t('Oops! Something went wrong')}</Heading>
<p>
{t(`
It looks like you've hit an issue in our client application. Don't worry though!
We use Sentinel to monitor Sentinel 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>
<List symbol="bullet">
{window?.adblockSuspected && (
<ListItem>
{t(
"We detected something AdBlock-like. Try disabling it, as it's known to cause issues."
)}
</ListItem>
)}
<ListItem>
{tct(`Give it a few seconds and [link:reload the page].`, {
link: (
<a
onClick={() => {
window.location.href = window.location.href;
}}
/>
),
})}
</ListItem>
<ListItem>
{tct(`If all else fails, [link:contact us] with more details.`, {
link: (
<ExternalLink href="https://github.com/getsentry/sentry/issues/new/choose" />
),
})}
</ListItem>
</List>
</Alert>
);
}
const Heading = styled('h1')`
font-size: ${p => p.theme.fontSizeLarge};
line-height: 1.4;
margin-bottom: ${space(1)};
`;
export default withProject(RouteError);