Skip to content

Commit

Permalink
Merge branch 'sentry-error-fixes' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
adamgall committed May 8, 2024
2 parents 69b2d17 + 14fb5d0 commit 8c30496
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 261 deletions.
5 changes: 5 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ COINGECKO_API_KEY=""
# Minutes to cache prices for token addresses
TOKEN_PRICE_CACHE_INTERVAL_MINUTES=""

# Configuration for Netlify Sentry plugin, not needed in development
SENTRY_ORG=""
SENTRY_PROJECT=""
SENTRY_AUTH_TOKEN=""

# App name displayed as Title
VITE_APP_NAME="Fractal"

Expand Down
301 changes: 79 additions & 222 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@safe-global/safe-deployments": "^1.34.0",
"@safe-global/safe-ethers-lib": "^1.9.2",
"@safe-global/safe-service-client": "^1.5.2",
"@sentry/react": "^7.104.0",
"@sentry/react": "^7.112.2",
"@shutter-network/shutter-crypto": "^1.0.1",
"@snapshot-labs/snapshot.js": "^0.7.3",
"@tanstack/react-query": "^5.28.4",
Expand Down Expand Up @@ -63,7 +63,7 @@
"dev": "VITE_APP_GIT_HASH=`git rev-parse HEAD` vite --force",
"start": "vite start",
"preview": "vite preview",
"build": "VITE_APP_GIT_HASH=`git rev-parse HEAD` vite build",
"build": "VITE_APP_GIT_HASH=`git rev-parse HEAD` NODE_OPTIONS=--max-old-space-size=8192 vite build",
"graphql:build": "graphclient build",
"graphql:dev-server": "graphclient serve-dev",
"test": "vitest --dir=test",
Expand Down
9 changes: 8 additions & 1 deletion src/components/ui/page/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Box, Container, Grid, GridItem } from '@chakra-ui/react';
import { Outlet } from 'react-router-dom';
import { CONTENT_HEIGHT, HEADER_HEIGHT } from '../../../../constants/common';
import { ErrorBoundary } from '../../utils/ErrorBoundary';
import { TopErrorFallback } from '../../utils/TopErrorFallback';
import Header from '../Header';
import Navigation from '../Navigation';

Expand Down Expand Up @@ -28,7 +30,12 @@ export default function Layout() {
minH={CONTENT_HEIGHT}
paddingBottom="2rem"
>
<Outlet />
<ErrorBoundary
fallback={<TopErrorFallback />}
showDialog
>
<Outlet />
</ErrorBoundary>
</Container>
</GridItem>
<GridItem area={'header'}>
Expand Down
21 changes: 21 additions & 0 deletions src/components/ui/utils/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as Sentry from '@sentry/react';
import { JSXElementConstructor, ReactElement } from 'react';

export function ErrorBoundary({
children,
fallback,
showDialog,
}: {
children: React.ReactNode;
fallback?: ReactElement<any, string | JSXElementConstructor<any>> | Sentry.FallbackRender;
showDialog?: boolean;
}) {
return (
<Sentry.ErrorBoundary
fallback={fallback}
showDialog={showDialog}
>
{children}
</Sentry.ErrorBoundary>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ import { Alert } from '@decent-org/fractal-ui';
import { Trans, useTranslation } from 'react-i18next';
import { CONTENT_HEIGHT } from '../../../constants/common';
import { URL_DISCORD } from '../../../constants/url';
import { InfoBox } from '../containers/InfoBox';

export function ErrorFallback() {
export function TopErrorFallback() {
const { t } = useTranslation();
return (
<Center h={CONTENT_HEIGHT}>
<Box maxWidth="fit-content">
<InfoBox>
<Box
minWidth="100%"
h="100%"
minHeight="10.6rem"
bg="black.900-semi-transparent"
p="1rem"
borderRadius="0.5rem"
>
<Flex
alignItems="center"
direction="column"
Expand All @@ -37,7 +43,7 @@ export function ErrorFallback() {
</Text>
<Button onClick={() => window.location.reload()}>{t('reload')}</Button>
</Flex>
</InfoBox>
</Box>
</Box>
</Center>
);
Expand Down
46 changes: 20 additions & 26 deletions src/helpers/errorLogging.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import * as Sentry from '@sentry/react';
import { useEffect } from 'react';
import {
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
} from 'react-router-dom';

/**
* Initializes error logging.
*/
function initErrorLogging() {
if (
process.env.NODE_ENV === 'development' ||
import.meta.env.VITE_APP_SENTRY_DSN_URL === undefined
) {
return;
}

Sentry.init({
dsn: import.meta.env.VITE_APP_SENTRY_DSN_URL,
integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()],
integrations: [
Sentry.reactRouterV6BrowserTracingIntegration({
useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
}),
Sentry.replayIntegration(),
Sentry.feedbackIntegration({
colorScheme: 'dark',
}),
],

// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for performance monitoring.
Expand All @@ -36,27 +48,9 @@ initErrorLogging();
*/
export function logError(error: any, ...optionalParams: any[]) {
console.error(error, optionalParams);
if (process.env.NODE_ENV === 'development') return;
if (typeof error === 'string' || error instanceof String) {
Sentry.captureMessage(error + ': ' + optionalParams);
} else {
Sentry.captureException(error);
}
}

/**
* Extension of Sentry's ErrorBoundary class which simply logs the error to
* console as well.
*/
export class FractalErrorBoundary extends Sentry.ErrorBoundary {
componentDidCatch(
error: Error & {
cause?: Error;
},
errorInfo: React.ErrorInfo,
) {
logError(error, errorInfo);
if (process.env.NODE_ENV === 'development') return;
super.componentDidCatch(error, errorInfo);
}
}
6 changes: 5 additions & 1 deletion src/providers/App/useReadOnlyValues.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ERC721__factory } from '@fractal-framework/fractal-contracts';
import * as Sentry from '@sentry/react';
import { useEffect, useState, useCallback } from 'react';
import { getAddress } from 'viem';
import useSignerOrProvider from '../../hooks/utils/useSignerOrProvider';
Expand Down Expand Up @@ -57,9 +58,12 @@ export const useReadOnlyValues = ({ node, governance }: Fractal, _account?: stri
}
};

const address = _account ? getAddress(_account) : undefined;
Sentry.setUser(address ? { id: address } : null);

setReadOnlyValues({
user: {
address: _account ? getAddress(_account) : undefined,
address,
votingWeight: await getVotingWeight(),
},
dao: !node.daoAddress
Expand Down
11 changes: 7 additions & 4 deletions src/providers/Providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { ReactNode } from 'react';
import { ToastContainer } from 'react-toastify';
import { WagmiProvider } from 'wagmi';
import { theme } from '../assets/theme';
import { ErrorFallback } from '../components/ui/utils/ErrorFallback';
import { ErrorBoundary } from '../components/ui/utils/ErrorBoundary';
import { TopErrorFallback } from '../components/ui/utils/TopErrorFallback';
import graphQLClient from '../graphql';
import { FractalErrorBoundary } from '../helpers/errorLogging';
import { AppProvider } from './App/AppProvider';
import EthersContextProvider from './Ethers';
import { NetworkConfigProvider } from './NetworkConfig/NetworkConfigProvider';
Expand All @@ -19,7 +19,10 @@ export default function Providers({ children }: { children: ReactNode }) {
theme={theme}
resetCSS
>
<FractalErrorBoundary fallback={<ErrorFallback />}>
<ErrorBoundary
fallback={<TopErrorFallback />}
showDialog
>
<ApolloProvider client={graphQLClient}>
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
Expand All @@ -39,7 +42,7 @@ export default function Providers({ children }: { children: ReactNode }) {
</QueryClientProvider>
</WagmiProvider>
</ApolloProvider>
</FractalErrorBoundary>
</ErrorBoundary>
</ChakraProvider>
);
}
4 changes: 3 additions & 1 deletion src/router.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { wrapCreateBrowserRouter } from '@sentry/react';
import { createBrowserRouter, redirect } from 'react-router-dom';
import { ModalProvider } from './components/ui/modals/ModalProvider';
import Layout from './components/ui/page/Layout';
Expand All @@ -18,7 +19,7 @@ import SettingsPage from './pages/daos/[daoAddress]/settings';
import Treasury from './pages/daos/[daoAddress]/treasury';

export const router = (addressPrefix: string) =>
createBrowserRouter([
wrapCreateBrowserRouter(createBrowserRouter)([
{
path: '/',
element: (
Expand Down Expand Up @@ -102,6 +103,7 @@ export const router = (addressPrefix: string) =>
// this exists to keep old links working
// /daos/0x0123/* will redirect to /home?dao=0x0123
path: 'daos/:daoAddress/*',
// @ts-ignore:next-line
loader: ({ params: { daoAddress } }) =>
redirect(`/home?dao=${addressPrefix}:${daoAddress}`),
},
Expand Down
3 changes: 3 additions & 0 deletions vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ export default defineConfig({
server: {
port: 3000,
},
build: {
sourcemap: true,
},
});

0 comments on commit 8c30496

Please sign in to comment.