mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ErrorHandling: Error boundary for every container (#18845)
* ErrorHandling: Error boundary for every container * Remvoe custom query editor errors
This commit is contained in:
parent
b0237c6b7e
commit
490a1d6fc9
@ -1,13 +1,14 @@
|
||||
import React, { PureComponent, ReactNode } from 'react';
|
||||
import { Alert } from '@grafana/ui';
|
||||
import { Alert } from '../Alert/Alert';
|
||||
import { css } from 'emotion';
|
||||
|
||||
interface ErrorInfo {
|
||||
componentStack: string;
|
||||
}
|
||||
|
||||
interface RenderProps {
|
||||
error: Error;
|
||||
errorInfo: ErrorInfo;
|
||||
error: Error | null;
|
||||
errorInfo: ErrorInfo | null;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
@ -15,8 +16,8 @@ interface Props {
|
||||
}
|
||||
|
||||
interface State {
|
||||
error: Error;
|
||||
errorInfo: ErrorInfo;
|
||||
error: Error | null;
|
||||
errorInfo: ErrorInfo | null;
|
||||
}
|
||||
|
||||
export class ErrorBoundary extends PureComponent<Props, State> {
|
||||
@ -35,6 +36,7 @@ export class ErrorBoundary extends PureComponent<Props, State> {
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
const { error, errorInfo } = this.state;
|
||||
|
||||
return children({
|
||||
error,
|
||||
errorInfo,
|
||||
@ -42,18 +44,28 @@ export class ErrorBoundary extends PureComponent<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
function getAlertPageStyle() {
|
||||
return css`
|
||||
width: 500px;
|
||||
margin: 64px auto;
|
||||
`;
|
||||
}
|
||||
|
||||
interface WithAlertBoxProps {
|
||||
title?: string;
|
||||
children: ReactNode;
|
||||
style?: 'page' | 'alertbox';
|
||||
}
|
||||
|
||||
export class ErrorBoundaryAlert extends PureComponent<WithAlertBoxProps> {
|
||||
static defaultProps: Partial<WithAlertBoxProps> = {
|
||||
title: 'An unexpected error happened',
|
||||
style: 'alertbox',
|
||||
};
|
||||
|
||||
render() {
|
||||
const { title, children } = this.props;
|
||||
const { title, children, style } = this.props;
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
{({ error, errorInfo }) => {
|
||||
@ -61,15 +73,28 @@ export class ErrorBoundaryAlert extends PureComponent<WithAlertBoxProps> {
|
||||
return children;
|
||||
}
|
||||
|
||||
return (
|
||||
<Alert title={title}>
|
||||
<details style={{ whiteSpace: 'pre-wrap' }}>
|
||||
{error && error.toString()}
|
||||
<br />
|
||||
{errorInfo.componentStack}
|
||||
</details>
|
||||
</Alert>
|
||||
);
|
||||
if (style === 'alertbox') {
|
||||
return (
|
||||
<Alert title={title || ''}>
|
||||
<details style={{ whiteSpace: 'pre-wrap' }}>
|
||||
{error && error.toString()}
|
||||
<br />
|
||||
{errorInfo.componentStack}
|
||||
</details>
|
||||
</Alert>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className={getAlertPageStyle()}>
|
||||
<h2>{title}</h2>
|
||||
<details style={{ whiteSpace: 'pre-wrap' }}>
|
||||
{error && error.toString()}
|
||||
<br />
|
||||
{errorInfo.componentStack}
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}}
|
||||
</ErrorBoundary>
|
||||
);
|
@ -78,3 +78,5 @@ export { VariableSuggestion, VariableOrigin } from './DataLinks/DataLinkSuggesti
|
||||
export { DataLinksEditor } from './DataLinks/DataLinksEditor';
|
||||
export { DataLinksContextMenu } from './DataLinks/DataLinksContextMenu';
|
||||
export { SeriesIcon } from './Legend/SeriesIcon';
|
||||
|
||||
export { ErrorBoundary, ErrorBoundaryAlert } from './ErrorBoundary/ErrorBoundary';
|
||||
|
@ -5,7 +5,7 @@ import { Unsubscribable } from 'rxjs';
|
||||
|
||||
// Components
|
||||
import { PanelHeader } from './PanelHeader/PanelHeader';
|
||||
import { ErrorBoundary } from 'app/core/components/ErrorBoundary/ErrorBoundary';
|
||||
import { ErrorBoundary } from '@grafana/ui';
|
||||
|
||||
// Utils & Services
|
||||
import { getTimeSrv, TimeSrv } from '../services/TimeSrv';
|
||||
|
@ -8,11 +8,10 @@ import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
import { AngularComponent, getAngularLoader } from '@grafana/runtime';
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { ErrorBoundaryAlert } from 'app/core/components/ErrorBoundary/ErrorBoundary';
|
||||
|
||||
// Types
|
||||
import { PanelModel } from '../state/PanelModel';
|
||||
import { DataQuery, DataSourceApi, PanelData, DataQueryRequest } from '@grafana/ui';
|
||||
import { DataQuery, DataSourceApi, PanelData, DataQueryRequest, ErrorBoundaryAlert } from '@grafana/ui';
|
||||
import { TimeRange, LoadingState } from '@grafana/data';
|
||||
import { DashboardModel } from '../state/DashboardModel';
|
||||
|
||||
@ -259,7 +258,7 @@ export class QueryEditorRow extends PureComponent<Props, State> {
|
||||
</div>
|
||||
</div>
|
||||
<div className={bodyClasses}>
|
||||
<ErrorBoundaryAlert title="Data source query editor failed">{this.renderPluginEditor()}</ErrorBoundaryAlert>
|
||||
<ErrorBoundaryAlert>{this.renderPluginEditor()}</ErrorBoundaryAlert>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,34 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export class ErrorBoundary extends Component<{}, any> {
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
this.state = { error: null, errorInfo: null };
|
||||
}
|
||||
|
||||
componentDidCatch(error: any, errorInfo: any) {
|
||||
// Catch errors in any components below and re-render with error message
|
||||
this.setState({
|
||||
error,
|
||||
errorInfo,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.errorInfo) {
|
||||
// Error path
|
||||
return (
|
||||
<div className="explore-container">
|
||||
<h3>An unexpected error happened.</h3>
|
||||
<details style={{ whiteSpace: 'pre-wrap' }}>
|
||||
{this.state.error && this.state.error.toString()}
|
||||
<br />
|
||||
{this.state.errorInfo.componentStack}
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// Normally, just render children
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
@ -9,8 +9,7 @@ import memoizeOne from 'memoize-one';
|
||||
// Services & Utils
|
||||
import store from 'app/core/store';
|
||||
// Components
|
||||
import { Alert, DataQuery, ExploreStartPageProps, DataSourceApi, PanelData } from '@grafana/ui';
|
||||
import { ErrorBoundary } from './ErrorBoundary';
|
||||
import { Alert, ErrorBoundaryAlert, DataQuery, ExploreStartPageProps, DataSourceApi, PanelData } from '@grafana/ui';
|
||||
import LogsContainer from './LogsContainer';
|
||||
import QueryRows from './QueryRows';
|
||||
import TableContainer from './TableContainer';
|
||||
@ -275,7 +274,7 @@ export class Explore extends React.PureComponent<ExploreProps> {
|
||||
|
||||
return (
|
||||
<main className="m-t-2" style={{ width }}>
|
||||
<ErrorBoundary>
|
||||
<ErrorBoundaryAlert>
|
||||
{showingStartPage && <StartPage onClickExample={this.onClickExample} />}
|
||||
{!showingStartPage && (
|
||||
<>
|
||||
@ -310,7 +309,7 @@ export class Explore extends React.PureComponent<ExploreProps> {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundaryAlert>
|
||||
</main>
|
||||
);
|
||||
}}
|
||||
|
@ -5,9 +5,8 @@ import { connect } from 'react-redux';
|
||||
import { StoreState } from 'app/types';
|
||||
import { ExploreId } from 'app/types/explore';
|
||||
|
||||
import { ErrorBoundary } from './ErrorBoundary';
|
||||
import Explore from './Explore';
|
||||
import { CustomScrollbar } from '@grafana/ui';
|
||||
import { CustomScrollbar, ErrorBoundaryAlert } from '@grafana/ui';
|
||||
import { resetExploreAction } from './state/actionTypes';
|
||||
|
||||
interface WrapperProps {
|
||||
@ -27,13 +26,13 @@ export class Wrapper extends Component<WrapperProps> {
|
||||
<div className="page-scrollbar-wrapper">
|
||||
<CustomScrollbar autoHeightMin={'100%'} autoHeightMax={''} className="custom-scrollbar--page">
|
||||
<div className="explore-wrapper">
|
||||
<ErrorBoundary>
|
||||
<ErrorBoundaryAlert style="page">
|
||||
<Explore exploreId={ExploreId.left} />
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundaryAlert>
|
||||
{split && (
|
||||
<ErrorBoundary>
|
||||
<ErrorBoundaryAlert style="page">
|
||||
<Explore exploreId={ExploreId.right} />
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundaryAlert>
|
||||
)}
|
||||
</div>
|
||||
</CustomScrollbar>
|
||||
|
@ -8,11 +8,14 @@ import coreModule from 'app/core/core_module';
|
||||
import { store } from 'app/store/store';
|
||||
import { ContextSrv } from 'app/core/services/context_srv';
|
||||
import { provideTheme } from 'app/core/utils/ConfigProvider';
|
||||
import { ErrorBoundaryAlert } from '@grafana/ui';
|
||||
|
||||
function WrapInProvider(store: any, Component: any, props: any) {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<Component {...props} />
|
||||
<ErrorBoundaryAlert style="page">
|
||||
<Component {...props} />
|
||||
</ErrorBoundaryAlert>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user