mirror of
https://github.com/grafana/grafana.git
synced 2024-11-22 08:56:43 -06:00
Alerting: wrap top level components in ErrorBoundary (#34040)
This commit is contained in:
parent
8ecfad6995
commit
098b4fc319
@ -54,3 +54,21 @@ import { ErrorWithStack } from '@grafana/ui';
|
||||
<ArgsTable of={ErrorWithStack}/>
|
||||
|
||||
|
||||
# withErrorBoundary
|
||||
|
||||
a HOC to conveniently wrap component in an error boundary
|
||||
|
||||
### Usage
|
||||
|
||||
```jsx
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
interface MyCompProps {
|
||||
...
|
||||
}
|
||||
|
||||
const MyComp = withErrorBoundary((props: MyCompProps) => {
|
||||
return <>...</>
|
||||
}, { style: 'page' });
|
||||
|
||||
```
|
@ -1,4 +1,4 @@
|
||||
import React, { PureComponent, ReactNode } from 'react';
|
||||
import React, { PureComponent, ReactNode, ComponentType } from 'react';
|
||||
import { captureException } from '@sentry/browser';
|
||||
import { Alert } from '../Alert/Alert';
|
||||
import { ErrorWithStack } from './ErrorWithStack';
|
||||
@ -46,14 +46,24 @@ export class ErrorBoundary extends PureComponent<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
interface WithAlertBoxProps {
|
||||
/**
|
||||
* Props for the ErrorBoundaryAlert component
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface ErrorBoundaryAlertProps {
|
||||
/** Title for the error boundary alert */
|
||||
title?: string;
|
||||
|
||||
/** Component to be wrapped with an error boundary */
|
||||
children: ReactNode;
|
||||
|
||||
/** 'page' will render full page error with stacktrace. 'alertbox' will render an <Alert />. Default 'alertbox' */
|
||||
style?: 'page' | 'alertbox';
|
||||
}
|
||||
|
||||
export class ErrorBoundaryAlert extends PureComponent<WithAlertBoxProps> {
|
||||
static defaultProps: Partial<WithAlertBoxProps> = {
|
||||
export class ErrorBoundaryAlert extends PureComponent<ErrorBoundaryAlertProps> {
|
||||
static defaultProps: Partial<ErrorBoundaryAlertProps> = {
|
||||
title: 'An unexpected error happened',
|
||||
style: 'alertbox',
|
||||
};
|
||||
@ -86,3 +96,25 @@ export class ErrorBoundaryAlert extends PureComponent<WithAlertBoxProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HOC for wrapping a component in an error boundary.
|
||||
*
|
||||
* @param Component - the react component to wrap in error boundary
|
||||
* @param errorBoundaryProps - error boundary options
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function withErrorBoundary<P = {}>(
|
||||
Component: ComponentType<P>,
|
||||
errorBoundaryProps: Omit<ErrorBoundaryAlertProps, 'children'> = {}
|
||||
): ComponentType<P> {
|
||||
const comp = (props: P) => (
|
||||
<ErrorBoundaryAlert {...errorBoundaryProps}>
|
||||
<Component {...props} />
|
||||
</ErrorBoundaryAlert>
|
||||
);
|
||||
comp.displayName = 'WithErrorBoundary';
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
@ -132,7 +132,12 @@ export { FeatureBadge, FeatureInfoBox } from './InfoBox/FeatureInfoBox';
|
||||
|
||||
export { JSONFormatter } from './JSONFormatter/JSONFormatter';
|
||||
export { JsonExplorer } from './JSONFormatter/json_explorer/json_explorer';
|
||||
export { ErrorBoundary, ErrorBoundaryAlert } from './ErrorBoundary/ErrorBoundary';
|
||||
export {
|
||||
ErrorBoundary,
|
||||
ErrorBoundaryAlert,
|
||||
ErrorBoundaryAlertProps,
|
||||
withErrorBoundary,
|
||||
} from './ErrorBoundary/ErrorBoundary';
|
||||
export { ErrorWithStack } from './ErrorBoundary/ErrorWithStack';
|
||||
export { AlphaNotice } from './AlphaNotice/AlphaNotice';
|
||||
export { DataSourceHttpSettings } from './DataSourceSettings/DataSourceHttpSettings';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Alert, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
||||
import { Alert, LoadingPlaceholder, useStyles2, withErrorBoundary } from '@grafana/ui';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { Receiver } from 'app/plugins/datasource/alertmanager/types';
|
||||
@ -132,7 +132,7 @@ const AmRoutes: FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default AmRoutes;
|
||||
export default withErrorBoundary(AmRoutes, { style: 'page' });
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
break: css`
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Alert, LoadingPlaceholder } from '@grafana/ui';
|
||||
import { Alert, LoadingPlaceholder, withErrorBoundary } from '@grafana/ui';
|
||||
import React, { FC, useEffect } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Redirect, Route, RouteChildrenProps, Switch, useLocation } from 'react-router-dom';
|
||||
@ -104,4 +104,4 @@ const Receivers: FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Receivers;
|
||||
export default withErrorBoundary(Receivers, { style: 'page' });
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Alert, LinkButton, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
||||
import { Alert, LinkButton, LoadingPlaceholder, useStyles2, withErrorBoundary } from '@grafana/ui';
|
||||
import Page from 'app/core/components/Page/Page';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
import { useCleanup } from 'app/core/hooks/useCleanup';
|
||||
@ -82,4 +82,4 @@ const warningStyles = (theme: GrafanaTheme2) => ({
|
||||
`,
|
||||
});
|
||||
|
||||
export default RuleEditor;
|
||||
export default withErrorBoundary(RuleEditor, { style: 'page' });
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { DataSourceInstanceSettings, GrafanaTheme, urlUtil } from '@grafana/data';
|
||||
import { useStyles, ButtonGroup, ToolbarButton, Alert, LinkButton } from '@grafana/ui';
|
||||
import { useStyles, ButtonGroup, ToolbarButton, Alert, LinkButton, withErrorBoundary } from '@grafana/ui';
|
||||
import { SerializedError } from '@reduxjs/toolkit';
|
||||
import React, { FC, useEffect, useMemo } from 'react';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { AlertingPageWrapper } from './components/AlertingPageWrapper';
|
||||
import { NoRulesSplash } from './components/rules/NoRulesCTA';
|
||||
@ -25,7 +25,8 @@ const VIEWS = {
|
||||
state: RuleListStateView,
|
||||
};
|
||||
|
||||
export const RuleList: FC = () => {
|
||||
export const RuleList = withErrorBoundary(
|
||||
() => {
|
||||
const dispatch = useDispatch();
|
||||
const styles = useStyles(getStyles);
|
||||
const rulesDataSourceNames = useMemo(getAllRulesSourceNames, []);
|
||||
@ -144,7 +145,9 @@ export const RuleList: FC = () => {
|
||||
{haveResults && <ViewComponent namespaces={filteredNamespaces} />}
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
};
|
||||
},
|
||||
{ style: 'page' }
|
||||
);
|
||||
|
||||
const getStyles = (theme: GrafanaTheme) => ({
|
||||
break: css`
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { FC, useEffect, useCallback } from 'react';
|
||||
import { Alert, LoadingPlaceholder } from '@grafana/ui';
|
||||
import { Alert, LoadingPlaceholder, withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Redirect, Route, RouteChildrenProps, Switch, useLocation } from 'react-router-dom';
|
||||
@ -93,4 +93,4 @@ const Silences: FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Silences;
|
||||
export default withErrorBoundary(Silences, { style: 'page' });
|
||||
|
Loading…
Reference in New Issue
Block a user