diff --git a/frontend/package.json b/frontend/package.json index ff11513b49..2b6a36af8b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -80,6 +80,7 @@ "react-dnd-html5-backend": "16.0.1", "react-dom": "18.2.0", "react-drag-listview": "2.0.0", + "react-error-boundary": "4.0.11", "react-force-graph": "^1.43.0", "react-grid-layout": "^1.3.4", "react-helmet-async": "1.3.0", diff --git a/frontend/public/locales/en/errorDetails.json b/frontend/public/locales/en/errorDetails.json index f29f4993c8..da68ed48ca 100644 --- a/frontend/public/locales/en/errorDetails.json +++ b/frontend/public/locales/en/errorDetails.json @@ -3,5 +3,7 @@ "see_error_in_trace_graph": "See the error in trace graph", "stack_trace": "Stacktrace", "older": "Older", - "newer": "Newer" + "newer": "Newer", + "something_went_wrong": "Oops !!! Something went wrong", + "contact_if_issue_exists": "Don't worry, our team is here to help. Please contact support if the issue persists." } diff --git a/frontend/src/container/AppLayout/index.tsx b/frontend/src/container/AppLayout/index.tsx index b47885cf7b..15f71fc692 100644 --- a/frontend/src/container/AppLayout/index.tsx +++ b/frontend/src/container/AppLayout/index.tsx @@ -6,7 +6,9 @@ import Header from 'container/Header'; import SideNav from 'container/SideNav'; import TopNav from 'container/TopNav'; import { useNotifications } from 'hooks/useNotifications'; +import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { ReactNode, useEffect, useMemo, useRef } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; import { Helmet } from 'react-helmet-async'; import { useTranslation } from 'react-i18next'; import { useQueries } from 'react-query'; @@ -203,12 +205,15 @@ function AppLayout(props: AppLayoutProps): JSX.Element { {isToDisplayLayout &&
} {isToDisplayLayout && !renderFullScreen && } - - - {isToDisplayLayout && !renderFullScreen && } - {children} - - + + + + + {isToDisplayLayout && !renderFullScreen && } + {children} + + + ); diff --git a/frontend/src/container/ServiceApplication/index.tsx b/frontend/src/container/ServiceApplication/index.tsx index 5cfce03ee2..9a5157061d 100644 --- a/frontend/src/container/ServiceApplication/index.tsx +++ b/frontend/src/container/ServiceApplication/index.tsx @@ -1,5 +1,7 @@ import { FeatureKeys } from 'constants/features'; import useFeatureFlag from 'hooks/useFeatureFlag'; +import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; +import { ErrorBoundary } from 'react-error-boundary'; import ServiceMetrics from './ServiceMetrics'; import ServiceTraces from './ServiceTraces'; @@ -10,9 +12,11 @@ function Services(): JSX.Element { ?.active; return ( - - {isSpanMetricEnabled ? : } - + + + {isSpanMetricEnabled ? : } + + ); } diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 7ef3d47bb9..d872b6adc2 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -3,7 +3,9 @@ import 'styles.scss'; import AppRoutes from 'AppRoutes'; import { ThemeProvider } from 'hooks/useDarkMode'; +import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { createRoot } from 'react-dom/client'; +import { ErrorBoundary } from 'react-error-boundary'; import { HelmetProvider } from 'react-helmet-async'; import { QueryClient, QueryClientProvider } from 'react-query'; import { ReactQueryDevtools } from 'react-query/devtools'; @@ -24,17 +26,20 @@ if (container) { const root = createRoot(container); root.render( - - - - - - - {process.env.NODE_ENV === 'development' && ( - - )} - - - , + + + + + + + + {process.env.NODE_ENV === 'development' && ( + + )} + + + + , + , ); } diff --git a/frontend/src/pages/ErrorBoundaryFallback/ErrorBoundaryFallback.styles.scss b/frontend/src/pages/ErrorBoundaryFallback/ErrorBoundaryFallback.styles.scss new file mode 100644 index 0000000000..78fd73bf0f --- /dev/null +++ b/frontend/src/pages/ErrorBoundaryFallback/ErrorBoundaryFallback.styles.scss @@ -0,0 +1,16 @@ +.error-boundary-fallback-container { + width: 100%; + + .actionBtn { + display: flex; + align-items: center; + gap: 4px; + } + + .title, + .actions { + display: flex; + align-items: center; + gap: 8px; + } +} diff --git a/frontend/src/pages/ErrorBoundaryFallback/ErrorBoundaryFallback.tsx b/frontend/src/pages/ErrorBoundaryFallback/ErrorBoundaryFallback.tsx new file mode 100644 index 0000000000..d8ceb5890f --- /dev/null +++ b/frontend/src/pages/ErrorBoundaryFallback/ErrorBoundaryFallback.tsx @@ -0,0 +1,54 @@ +import './ErrorBoundaryFallback.styles.scss'; + +import { BugOutlined, UndoOutlined } from '@ant-design/icons'; +import { Button, Card, Typography } from 'antd'; +import Slack from 'container/SideNav/Slack'; +import { useTranslation } from 'react-i18next'; + +function ErrorBoundaryFallback(): JSX.Element { + const { t } = useTranslation(['errorDetails']); + + const onClickSlackHandler = (): void => { + window.open('https://signoz.io/slack', '_blank'); + }; + + const handleReload = (): void => { + window.location.reload(); + }; + return ( + +
+ + + {t('something_went_wrong')} + +
+ + <> +

{t('contact_if_issue_exists')}

+ +
+ + + +
+ +
+ ); +} + +export default ErrorBoundaryFallback; diff --git a/frontend/src/pages/LogsExplorer/index.tsx b/frontend/src/pages/LogsExplorer/index.tsx index 3aa0f95d1b..d18eee199b 100644 --- a/frontend/src/pages/LogsExplorer/index.tsx +++ b/frontend/src/pages/LogsExplorer/index.tsx @@ -3,13 +3,15 @@ import ExplorerCard from 'components/ExplorerCard/ExplorerCard'; import LogExplorerQuerySection from 'container/LogExplorerQuerySection'; import LogsExplorerViews from 'container/LogsExplorerViews'; import LogsTopNav from 'container/LogsTopNav'; +import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; +import { ErrorBoundary } from 'react-error-boundary'; import { DataSource } from 'types/common/queryBuilder'; import { WrapperStyled } from './styles'; function LogsExplorer(): JSX.Element { return ( - <> + @@ -23,7 +25,7 @@ function LogsExplorer(): JSX.Element { - + ); } diff --git a/frontend/src/pages/Trace/index.tsx b/frontend/src/pages/Trace/index.tsx index acf8ec2eff..75bf58f1bd 100644 --- a/frontend/src/pages/Trace/index.tsx +++ b/frontend/src/pages/Trace/index.tsx @@ -9,7 +9,9 @@ import TraceTable from 'container/Trace/TraceTable'; import { useNotifications } from 'hooks/useNotifications'; import getStep from 'lib/getStep'; import history from 'lib/history'; +import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { MouseEventHandler, useCallback, useEffect, useState } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; import { connect, useDispatch, useSelector } from 'react-redux'; import { bindActionCreators, Dispatch } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; @@ -144,7 +146,7 @@ function Trace({ ); return ( - <> +
@@ -167,7 +169,7 @@ function Trace({ - + ); } diff --git a/frontend/src/pages/TracesExplorer/index.tsx b/frontend/src/pages/TracesExplorer/index.tsx index c83ade514a..42cbe1028b 100644 --- a/frontend/src/pages/TracesExplorer/index.tsx +++ b/frontend/src/pages/TracesExplorer/index.tsx @@ -13,7 +13,9 @@ import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange'; import { useNotifications } from 'hooks/useNotifications'; import history from 'lib/history'; +import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { useCallback, useEffect, useMemo } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; import { Dashboard } from 'types/api/dashboard/getAll'; import { DataSource } from 'types/common/queryBuilder'; import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink'; @@ -168,28 +170,30 @@ function TracesExplorer(): JSX.Element { ]); return ( - <> - - - + + <> + + + - - - + + + + + - - - - - + + + ); } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 920498669d..6ef8667b8a 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -12733,6 +12733,13 @@ react-draggable@^4.0.0, react-draggable@^4.0.3: clsx "^1.1.1" prop-types "^15.8.1" +react-error-boundary@4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.11.tgz#36bf44de7746714725a814630282fee83a7c9a1c" + integrity sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw== + dependencies: + "@babel/runtime" "^7.12.5" + react-fast-compare@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"