mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Use alerting-specific error boundary for page components (#99980)
Use alerting-specific error boundary for page components
This commit is contained in:
parent
df64dd0762
commit
fbf96916aa
@ -21,6 +21,8 @@ interface Props {
|
||||
onError?: (error: Error) => void;
|
||||
/** Callback error state is cleared due to recover props change */
|
||||
onRecover?: () => void;
|
||||
/** Default error logger - Faro by default */
|
||||
errorLogger?: (error: Error) => void;
|
||||
}
|
||||
|
||||
interface State {
|
||||
@ -35,7 +37,12 @@ export class ErrorBoundary extends PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
faro?.api?.pushError(error);
|
||||
const logger = this.props.errorLogger ?? faro?.api?.pushError;
|
||||
|
||||
if (logger) {
|
||||
logger(error);
|
||||
}
|
||||
|
||||
this.setState({ error, errorInfo });
|
||||
|
||||
if (this.props.onError) {
|
||||
@ -89,6 +96,8 @@ export interface ErrorBoundaryAlertProps {
|
||||
|
||||
/** Will re-render children after error if recover values changes */
|
||||
dependencies?: unknown[];
|
||||
/** Default error logger - Faro by default */
|
||||
errorLogger?: (error: Error) => void;
|
||||
}
|
||||
|
||||
export class ErrorBoundaryAlert extends PureComponent<ErrorBoundaryAlertProps> {
|
||||
@ -98,10 +107,10 @@ export class ErrorBoundaryAlert extends PureComponent<ErrorBoundaryAlertProps> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { title, children, style, dependencies } = this.props;
|
||||
const { title, children, style, dependencies, errorLogger } = this.props;
|
||||
|
||||
return (
|
||||
<ErrorBoundary dependencies={dependencies}>
|
||||
<ErrorBoundary dependencies={dependencies} errorLogger={errorLogger}>
|
||||
{({ error, errorInfo }) => {
|
||||
if (!errorInfo) {
|
||||
return children;
|
||||
|
@ -19,6 +19,7 @@ import { NOTIFICATIONS_POLL_INTERVAL_MS } from './utils/constants';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
|
||||
import { getFiltersFromUrlParams } from './utils/misc';
|
||||
import { initialAsyncRequestState } from './utils/redux';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const AlertGroups = () => {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
@ -89,10 +90,12 @@ const AlertGroups = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const AlertGroupsPage = () => (
|
||||
<AlertmanagerPageWrapper navId="groups" accessType="instance">
|
||||
<AlertGroups />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function AlertGroupsPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="groups" accessType="instance">
|
||||
<AlertGroups />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default AlertGroupsPage;
|
||||
export default withPageErrorBoundary(AlertGroupsPage);
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { NavModel } from '@grafana/data';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
export default function FeatureTogglePage() {
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
function FeatureTogglePage() {
|
||||
const navModel: NavModel = {
|
||||
node: {
|
||||
text: 'Alerting is not enabled',
|
||||
@ -25,3 +27,5 @@ enabled = true
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(FeatureTogglePage);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { useLocation } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
import {
|
||||
defaultsFromQuery,
|
||||
getDefaultSilenceFormValues,
|
||||
@ -12,6 +11,7 @@ import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning';
|
||||
import { SilencesEditor } from './components/silences/SilencesEditor';
|
||||
import { useAlertmanager } from './state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const SilencesEditorComponent = () => {
|
||||
const location = useLocation();
|
||||
@ -48,4 +48,5 @@ function NewSilencePage() {
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
export default withErrorBoundary(NewSilencePage, { style: 'page' });
|
||||
|
||||
export default withPageErrorBoundary(NewSilencePage);
|
||||
|
@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { GrafanaTheme2, UrlQueryMap } from '@grafana/data';
|
||||
import { Tab, TabContent, TabsBar, useStyles2, withErrorBoundary } from '@grafana/ui';
|
||||
import { Tab, TabContent, TabsBar, useStyles2 } from '@grafana/ui';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { useMuteTimings } from 'app/features/alerting/unified/components/mute-timings/useMuteTimings';
|
||||
import { NotificationPoliciesList } from 'app/features/alerting/unified/components/notification-policies/NotificationPoliciesList';
|
||||
@ -12,6 +12,7 @@ import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning';
|
||||
import { MuteTimingsTable } from './components/mute-timings/MuteTimingsTable';
|
||||
import { useAlertmanager } from './state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
enum ActiveTab {
|
||||
NotificationPolicies = 'notification_policies',
|
||||
@ -104,10 +105,12 @@ function getActiveTabFromUrl(queryParams: UrlQueryMap, defaultTab: ActiveTab): Q
|
||||
};
|
||||
}
|
||||
|
||||
const NotificationPoliciesPage = () => (
|
||||
<AlertmanagerPageWrapper navId="am-routes" accessType="notification">
|
||||
<NotificationPoliciesTabs />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function NotificationPoliciesPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="am-routes" accessType="notification">
|
||||
<NotificationPoliciesTabs />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NotificationPoliciesPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(NotificationPoliciesPage);
|
||||
|
@ -5,7 +5,7 @@ import { useLocation } from 'react-use';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { config, isFetchError } from '@grafana/runtime';
|
||||
import { Alert, Card, Icon, LoadingPlaceholder, useStyles2, withErrorBoundary } from '@grafana/ui';
|
||||
import { Alert, Card, Icon, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { AlertLabels } from './components/AlertLabels';
|
||||
import { RuleViewerLayout } from './components/rule-viewer/RuleViewerLayout';
|
||||
@ -13,6 +13,7 @@ import { useCloudCombinedRulesMatching } from './hooks/useCombinedRule';
|
||||
import { getRulesSourceByName } from './utils/datasource';
|
||||
import { createViewLink } from './utils/misc';
|
||||
import { unescapePathSeparators } from './utils/rule-id';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const pageTitle = 'Find rule';
|
||||
const subUrl = config.appSubUrl;
|
||||
@ -153,4 +154,4 @@ function getStyles(theme: GrafanaTheme2) {
|
||||
};
|
||||
}
|
||||
|
||||
export default withErrorBoundary(RedirectToRuleViewer, { style: 'page' });
|
||||
export default withPageErrorBoundary(RedirectToRuleViewer);
|
||||
|
@ -3,6 +3,7 @@ import { Suspense, lazy } from 'react';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
import RuleListV1 from './rule-list/RuleList.v1';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
const RuleListV2 = lazy(() => import('./rule-list/RuleList.v2'));
|
||||
|
||||
const RuleList = () => {
|
||||
@ -11,4 +12,4 @@ const RuleList = () => {
|
||||
return <Suspense>{newView ? <RuleListV2 /> : <RuleListV1 />}</Suspense>;
|
||||
};
|
||||
|
||||
export default RuleList;
|
||||
export default withPageErrorBoundary(RuleList);
|
||||
|
@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { NavModelItem } from '@grafana/data';
|
||||
import { isFetchError } from '@grafana/runtime';
|
||||
import { Alert, withErrorBoundary } from '@grafana/ui';
|
||||
import { Alert } from '@grafana/ui';
|
||||
import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound';
|
||||
|
||||
import { AlertingPageWrapper } from './components/AlertingPageWrapper';
|
||||
@ -12,6 +12,7 @@ import DetailView, { ActiveTab, useActiveTab } from './components/rule-viewer/Ru
|
||||
import { useCombinedRule } from './hooks/useCombinedRule';
|
||||
import { stringifyErrorLike } from './utils/misc';
|
||||
import { getRuleIdFromPathname, parse as parseRuleId } from './utils/rule-id';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const RuleViewer = (): JSX.Element => {
|
||||
const params = useParams();
|
||||
@ -86,4 +87,4 @@ function ErrorMessage({ error }: ErrorMessageProps) {
|
||||
return <Alert title={'Something went wrong loading the rule'}>{stringifyErrorLike(error)}</Alert>;
|
||||
}
|
||||
|
||||
export default withErrorBoundary(RuleViewer, { style: 'page' });
|
||||
export default withPageErrorBoundary(RuleViewer);
|
||||
|
@ -6,8 +6,9 @@ import { useEditConfigurationDrawer } from './components/settings/ConfigurationD
|
||||
import { ExternalAlertmanagers } from './components/settings/ExternalAlertmanagers';
|
||||
import InternalAlertmanager from './components/settings/InternalAlertmanager';
|
||||
import { SettingsProvider, useSettings } from './components/settings/SettingsContext';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
export default function SettingsPage() {
|
||||
function SettingsPage() {
|
||||
return (
|
||||
<SettingsProvider>
|
||||
<SettingsContent />
|
||||
@ -47,3 +48,5 @@ function SettingsContent() {
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(SettingsPage);
|
||||
|
@ -1,28 +1,29 @@
|
||||
import { Route, Routes } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { AlertmanagerPageWrapper } from './components/AlertingPageWrapper';
|
||||
import DuplicateMessageTemplate from './components/contact-points/DuplicateMessageTemplate';
|
||||
import EditMessageTemplate from './components/contact-points/EditMessageTemplate';
|
||||
import NewMessageTemplate from './components/contact-points/NewMessageTemplate';
|
||||
import { withPageErrorBoundary } from './withPageErrorBoundary';
|
||||
|
||||
const NotificationTemplates = (): JSX.Element => (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="receivers"
|
||||
accessType="notification"
|
||||
pageNav={{
|
||||
id: 'templates',
|
||||
text: 'Notification templates',
|
||||
subTitle: 'Create and edit a group of notification templates',
|
||||
}}
|
||||
>
|
||||
<Routes>
|
||||
<Route path=":name/edit" element={<EditMessageTemplate />} />
|
||||
<Route path="new" element={<NewMessageTemplate />} />
|
||||
<Route path=":name/duplicate" element={<DuplicateMessageTemplate />} />
|
||||
</Routes>
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function NotificationTemplates() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="receivers"
|
||||
accessType="notification"
|
||||
pageNav={{
|
||||
id: 'templates',
|
||||
text: 'Notification templates',
|
||||
subTitle: 'Create and edit a group of notification templates',
|
||||
}}
|
||||
>
|
||||
<Routes>
|
||||
<Route path=":name/edit" element={<EditMessageTemplate />} />
|
||||
<Route path="new" element={<NewMessageTemplate />} />
|
||||
<Route path=":name/duplicate" element={<DuplicateMessageTemplate />} />
|
||||
</Routes>
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NotificationTemplates, { style: 'page' });
|
||||
export default withPageErrorBoundary(NotificationTemplates);
|
||||
|
@ -12,7 +12,6 @@ import {
|
||||
TabContent,
|
||||
TabsBar,
|
||||
Text,
|
||||
withErrorBoundary,
|
||||
} from '@grafana/ui';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
import { Trans, t } from 'app/core/internationalization';
|
||||
@ -25,6 +24,7 @@ import { usePagination } from '../../hooks/usePagination';
|
||||
import { useURLSearchParams } from '../../hooks/useURLSearchParams';
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from '../GrafanaAlertmanagerDeliveryWarning';
|
||||
|
||||
@ -270,4 +270,4 @@ function ContactPointsPage() {
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(ContactPointsPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(ContactPointsPage);
|
||||
|
@ -8,13 +8,15 @@ import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { generateCopiedName } from '../../utils/duplicate';
|
||||
import { stringifyErrorLike } from '../../utils/misc';
|
||||
import { updateDefinesWithUniqueValue } from '../../utils/templates';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { TemplateForm } from '../receivers/TemplateForm';
|
||||
|
||||
import { useGetNotificationTemplate, useNotificationTemplates } from './useNotificationTemplates';
|
||||
|
||||
const notFoundComponent = <EntityNotFound entity="Notification template" />;
|
||||
|
||||
const DuplicateMessageTemplate = () => {
|
||||
const DuplicateMessageTemplateComponent = () => {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
const { name } = useParams<{ name: string }>();
|
||||
const templateUid = name ? decodeURIComponent(name) : undefined;
|
||||
@ -63,4 +65,12 @@ const DuplicateMessageTemplate = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default DuplicateMessageTemplate;
|
||||
function DuplicateMessageTemplate() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<DuplicateMessageTemplateComponent />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(DuplicateMessageTemplate);
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { Alert, LoadingPlaceholder, withErrorBoundary } from '@grafana/ui';
|
||||
import { Alert, LoadingPlaceholder } from '@grafana/ui';
|
||||
import { useGetContactPoint } from 'app/features/alerting/unified/components/contact-points/useContactPoints';
|
||||
import { stringifyErrorLike } from 'app/features/alerting/unified/utils/misc';
|
||||
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { EditReceiverView } from '../receivers/EditReceiverView';
|
||||
|
||||
@ -50,4 +51,4 @@ function EditContactPointPage() {
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(EditContactPointPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(EditContactPointPage);
|
||||
|
@ -6,13 +6,15 @@ import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound'
|
||||
import { isNotFoundError } from '../../api/util';
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { stringifyErrorLike } from '../../utils/misc';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { TemplateForm } from '../receivers/TemplateForm';
|
||||
|
||||
import { useGetNotificationTemplate } from './useNotificationTemplates';
|
||||
|
||||
const notFoundComponent = <EntityNotFound entity="Notification template" />;
|
||||
|
||||
const EditMessageTemplate = () => {
|
||||
const EditMessageTemplateComponent = () => {
|
||||
const { name } = useParams<{ name: string }>();
|
||||
const templateUid = name ? decodeURIComponent(name) : undefined;
|
||||
|
||||
@ -47,4 +49,12 @@ const EditMessageTemplate = () => {
|
||||
return <TemplateForm alertmanager={selectedAlertmanager ?? ''} originalTemplate={currentData} />;
|
||||
};
|
||||
|
||||
export default EditMessageTemplate;
|
||||
function EditMessageTemplate() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<EditMessageTemplateComponent />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(EditMessageTemplate);
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound';
|
||||
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { TemplateForm } from '../receivers/TemplateForm';
|
||||
|
||||
const NewMessageTemplate = () => {
|
||||
function NewMessageTemplate() {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
|
||||
if (!selectedAlertmanager) {
|
||||
return <EntityNotFound entity="Alertmanager" />;
|
||||
}
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<TemplateForm alertmanager={selectedAlertmanager ?? ''} />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return <TemplateForm alertmanager={selectedAlertmanager} />;
|
||||
};
|
||||
|
||||
export default NewMessageTemplate;
|
||||
export default withPageErrorBoundary(NewMessageTemplate);
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { Alert, withErrorBoundary } from '@grafana/ui';
|
||||
import { Alert } from '@grafana/ui';
|
||||
|
||||
import { useAlertmanagerConfig } from '../../../hooks/useAlertmanagerConfig';
|
||||
import { useAlertmanager } from '../../../state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from '../../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../../AlertingPageWrapper';
|
||||
import { GlobalConfigForm } from '../../receivers/GlobalConfigForm';
|
||||
|
||||
const NewMessageTemplate = () => {
|
||||
const GlobalConfig = () => {
|
||||
const { selectedAlertmanager } = useAlertmanager();
|
||||
const { data, isLoading, error } = useAlertmanagerConfig(selectedAlertmanager);
|
||||
|
||||
@ -28,12 +29,12 @@ const NewMessageTemplate = () => {
|
||||
return <GlobalConfigForm config={data} alertManagerSourceName={selectedAlertmanager!} />;
|
||||
};
|
||||
|
||||
function NewMessageTemplatePage() {
|
||||
function GlobalConfigPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper navId="receivers" accessType="notification">
|
||||
<NewMessageTemplate />
|
||||
<GlobalConfig />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NewMessageTemplatePage, { style: 'page' });
|
||||
export default withPageErrorBoundary(GlobalConfigPage);
|
||||
|
@ -1,21 +1,8 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertingPageWrapper } from '../AlertingPageWrapper';
|
||||
import { ModifyExportRuleForm } from '../rule-editor/alert-rule-form/ModifyExportRuleForm';
|
||||
|
||||
export default function ExportNewGrafanaRule() {
|
||||
return (
|
||||
<ExportNewGrafanaRuleWrapper>
|
||||
<ModifyExportRuleForm />
|
||||
</ExportNewGrafanaRuleWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
interface ExportNewGrafanaRuleWrapperProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
function ExportNewGrafanaRuleWrapper({ children }: ExportNewGrafanaRuleWrapperProps) {
|
||||
function ExportNewGrafanaRulePage() {
|
||||
return (
|
||||
<AlertingPageWrapper
|
||||
navId="alert-list"
|
||||
@ -24,7 +11,9 @@ function ExportNewGrafanaRuleWrapper({ children }: ExportNewGrafanaRuleWrapperPr
|
||||
subTitle: 'Export a new rule definition in Terraform(HCL) format. Any changes you make will not be saved.',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
<ModifyExportRuleForm />
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(ExportNewGrafanaRulePage);
|
||||
|
@ -1,4 +1,3 @@
|
||||
import * as React from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
@ -12,10 +11,11 @@ import { stringifyErrorLike } from '../../utils/misc';
|
||||
import * as ruleId from '../../utils/rule-id';
|
||||
import { isGrafanaRulerRule } from '../../utils/rules';
|
||||
import { createRelativeUrl } from '../../utils/url';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertingPageWrapper } from '../AlertingPageWrapper';
|
||||
import { ModifyExportRuleForm } from '../rule-editor/alert-rule-form/ModifyExportRuleForm';
|
||||
|
||||
export default function GrafanaModifyExport() {
|
||||
function GrafanaModifyExport() {
|
||||
const { id } = useParams();
|
||||
const ruleIdentifier = useMemo<RuleIdentifier | undefined>(() => {
|
||||
return ruleId.tryParse(id, true);
|
||||
@ -23,38 +23,13 @@ export default function GrafanaModifyExport() {
|
||||
|
||||
if (!ruleIdentifier) {
|
||||
return (
|
||||
<ModifyExportWrapper>
|
||||
<Alert title="Invalid rule ID" severity="error">
|
||||
The rule UID in the page URL is invalid. Please check the URL and try again.
|
||||
</Alert>
|
||||
</ModifyExportWrapper>
|
||||
<Alert title="Invalid rule ID" severity="error">
|
||||
The rule UID in the page URL is invalid. Please check the URL and try again.
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ModifyExportWrapper>
|
||||
<RuleModifyExport ruleIdentifier={ruleIdentifier} />
|
||||
</ModifyExportWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
interface ModifyExportWrapperProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
function ModifyExportWrapper({ children }: ModifyExportWrapperProps) {
|
||||
return (
|
||||
<AlertingPageWrapper
|
||||
navId="alert-list"
|
||||
pageNav={{
|
||||
text: 'Modify export',
|
||||
subTitle:
|
||||
'Modify the current alert rule and export the rule definition in the format of your choice. Any changes you make will not be saved.',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
return <RuleModifyExport ruleIdentifier={ruleIdentifier} />;
|
||||
}
|
||||
|
||||
function RuleModifyExport({ ruleIdentifier }: { ruleIdentifier: RuleIdentifier }) {
|
||||
@ -105,3 +80,20 @@ function RuleModifyExport({ ruleIdentifier }: { ruleIdentifier: RuleIdentifier }
|
||||
|
||||
return <Alert title="Unknown error" />;
|
||||
}
|
||||
|
||||
function GrafanaModifyExportPage() {
|
||||
return (
|
||||
<AlertingPageWrapper
|
||||
navId="alert-list"
|
||||
pageNav={{
|
||||
text: 'Modify export',
|
||||
subTitle:
|
||||
'Modify the current alert rule and export the rule definition in the format of your choice. Any changes you make will not be saved.',
|
||||
}}
|
||||
>
|
||||
<GrafanaModifyExport />
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(GrafanaModifyExportPage);
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Navigate } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
import { useGetMuteTiming } from 'app/features/alerting/unified/components/mute-timings/useMuteTimings';
|
||||
import { useURLSearchParams } from 'app/features/alerting/unified/hooks/useURLSearchParams';
|
||||
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
|
||||
import MuteTimingForm from './MuteTimingForm';
|
||||
@ -38,17 +38,16 @@ const EditTimingRoute = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const EditMuteTimingPage = () => (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="am-routes"
|
||||
pageNav={{
|
||||
id: 'alert-policy-edit',
|
||||
text: 'Edit mute timing',
|
||||
}}
|
||||
accessType="notification"
|
||||
>
|
||||
<EditTimingRoute />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function EditMuteTimingPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="am-routes"
|
||||
pageNav={{ id: 'alert-policy-edit', text: 'Edit mute timing' }}
|
||||
accessType="notification"
|
||||
>
|
||||
<EditTimingRoute />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(EditMuteTimingPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(EditMuteTimingPage);
|
||||
|
@ -1,20 +1,18 @@
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
|
||||
import MuteTimingForm from './MuteTimingForm';
|
||||
|
||||
const NewMuteTimingPage = () => (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="am-routes"
|
||||
pageNav={{
|
||||
id: 'alert-policy-new',
|
||||
text: 'Add mute timing',
|
||||
}}
|
||||
accessType="notification"
|
||||
>
|
||||
<MuteTimingForm />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
function NewMuteTimingPage() {
|
||||
return (
|
||||
<AlertmanagerPageWrapper
|
||||
navId="am-routes"
|
||||
pageNav={{ id: 'alert-policy-new', text: 'Add mute timing' }}
|
||||
accessType="notification"
|
||||
>
|
||||
<MuteTimingForm />
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NewMuteTimingPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(NewMuteTimingPage);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
import { useAlertmanager } from 'app/features/alerting/unified/state/AlertmanagerContext';
|
||||
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
|
||||
import { CloudReceiverForm } from './form/CloudReceiverForm';
|
||||
@ -24,4 +24,4 @@ function NewReceiverViewPage() {
|
||||
);
|
||||
}
|
||||
|
||||
export default withErrorBoundary(NewReceiverViewPage, { style: 'page' });
|
||||
export default withPageErrorBoundary(NewReceiverViewPage);
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { withPageErrorBoundary } from '../../../withPageErrorBoundary';
|
||||
import { AlertingPageWrapper } from '../../AlertingPageWrapper';
|
||||
|
||||
import { CentralAlertHistoryScene } from './CentralAlertHistoryScene';
|
||||
|
||||
const HistoryPage = () => {
|
||||
function HistoryPage() {
|
||||
return (
|
||||
<AlertingPageWrapper navId="alerts-history" isLoading={false}>
|
||||
<CentralAlertHistoryScene />
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
};
|
||||
export default withErrorBoundary(HistoryPage, { style: 'page' });
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(HistoryPage);
|
||||
|
@ -25,7 +25,6 @@ import {
|
||||
Stack,
|
||||
TextArea,
|
||||
useStyles2,
|
||||
withErrorBoundary,
|
||||
} from '@grafana/ui';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
import { SilenceCreatedResponse, alertSilencesApi } from 'app/features/alerting/unified/api/alertSilencesApi';
|
||||
@ -38,6 +37,7 @@ import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { SilenceFormFields } from '../../types/silence-form';
|
||||
import { matcherFieldToMatcher } from '../../utils/alertmanager';
|
||||
import { makeAMLink } from '../../utils/misc';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from '../GrafanaAlertmanagerDeliveryWarning';
|
||||
|
||||
@ -296,4 +296,5 @@ function ExistingSilenceEditorPage() {
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
export default withErrorBoundary(ExistingSilenceEditorPage, { style: 'page' });
|
||||
|
||||
export default withPageErrorBoundary(ExistingSilenceEditorPage);
|
||||
|
@ -12,7 +12,6 @@ import {
|
||||
LoadingPlaceholder,
|
||||
Stack,
|
||||
useStyles2,
|
||||
withErrorBoundary,
|
||||
} from '@grafana/ui';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
@ -27,6 +26,7 @@ import { AlertmanagerAction, useAlertmanagerAbility } from '../../hooks/useAbili
|
||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
||||
import { parsePromQLStyleMatcherLooseSafe } from '../../utils/matchers';
|
||||
import { getSilenceFiltersFromUrlParams, makeAMLink, stringifyErrorLike } from '../../utils/misc';
|
||||
import { withPageErrorBoundary } from '../../withPageErrorBoundary';
|
||||
import { AlertmanagerPageWrapper } from '../AlertingPageWrapper';
|
||||
import { Authorize } from '../Authorize';
|
||||
import { DynamicTable, DynamicTableColumnProps, DynamicTableItemProps } from '../DynamicTable';
|
||||
@ -393,4 +393,5 @@ function SilencesTablePage() {
|
||||
</AlertmanagerPageWrapper>
|
||||
);
|
||||
}
|
||||
export default withErrorBoundary(SilencesTablePage, { style: 'page' });
|
||||
|
||||
export default withPageErrorBoundary(SilencesTablePage);
|
||||
|
@ -5,12 +5,13 @@ import { Box, Stack, Tab, TabContent, TabsBar } from '@grafana/ui';
|
||||
|
||||
import { AlertingPageWrapper } from '../components/AlertingPageWrapper';
|
||||
import { isLocalDevEnv } from '../utils/misc';
|
||||
import { withPageErrorBoundary } from '../withPageErrorBoundary';
|
||||
|
||||
import GettingStarted, { WelcomeHeader } from './GettingStarted';
|
||||
import { getInsightsScenes, insightsIsAvailable } from './Insights';
|
||||
import { PluginIntegrations } from './PluginIntegrations';
|
||||
|
||||
export default function Home() {
|
||||
function Home() {
|
||||
const insightsEnabled = (insightsIsAvailable() || isLocalDevEnv()) && Boolean(config.featureToggles.alertingInsights);
|
||||
|
||||
const [activeTab, setActiveTab] = useState<'insights' | 'overview'>(insightsEnabled ? 'insights' : 'overview');
|
||||
@ -51,3 +52,5 @@ export default function Home() {
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageErrorBoundary(Home);
|
||||
|
@ -2,7 +2,6 @@ import { useCallback } from 'react';
|
||||
import { useParams } from 'react-router-dom-v5-compat';
|
||||
|
||||
import { NavModelItem } from '@grafana/data';
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
import { RuleIdentifier } from 'app/types/unified-alerting';
|
||||
|
||||
import { AlertWarning } from '../AlertWarning';
|
||||
@ -11,6 +10,7 @@ import { AlertRuleForm } from '../components/rule-editor/alert-rule-form/AlertRu
|
||||
import { useURLSearchParams } from '../hooks/useURLSearchParams';
|
||||
import { useRulesAccess } from '../utils/accessControlHooks';
|
||||
import * as ruleId from '../utils/rule-id';
|
||||
import { withPageErrorBoundary } from '../withPageErrorBoundary';
|
||||
|
||||
import { CloneRuleEditor } from './CloneRuleEditor';
|
||||
import { ExistingRuleEditor } from './ExistingRuleEditor';
|
||||
@ -78,7 +78,9 @@ const RuleEditor = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withErrorBoundary(RuleEditor, { style: 'page' });
|
||||
// The pageNav property makes it difficult to only rely on AlertingPageWrapper
|
||||
// to catch errors.
|
||||
export default withPageErrorBoundary(RuleEditor);
|
||||
|
||||
function useRuleEditorPathParams() {
|
||||
const params = useParams<RuleEditorPathParams>();
|
||||
|
@ -4,7 +4,7 @@ import { useAsyncFn, useInterval } from 'react-use';
|
||||
|
||||
import { urlUtil } from '@grafana/data';
|
||||
import { logInfo } from '@grafana/runtime';
|
||||
import { Button, LinkButton, Stack, withErrorBoundary } from '@grafana/ui';
|
||||
import { Button, LinkButton, Stack } from '@grafana/ui';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { Trans } from 'app/core/internationalization';
|
||||
import { useDispatch } from 'app/types';
|
||||
@ -155,7 +155,7 @@ const RuleListV1 = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withErrorBoundary(RuleListV1, { style: 'page' });
|
||||
export default RuleListV1;
|
||||
|
||||
export function CreateAlertButton() {
|
||||
const [createRuleSupported, createRuleAllowed] = useAlertingAbility(AlertingAction.CreateAlertRule);
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { AlertingPageWrapper } from '../components/AlertingPageWrapper';
|
||||
import RulesFilter from '../components/rules/Filter/RulesFilter';
|
||||
import { SupportedView } from '../components/rules/Filter/RulesViewModeSelector';
|
||||
@ -9,24 +7,25 @@ import { useURLSearchParams } from '../hooks/useURLSearchParams';
|
||||
import { FilterView } from './FilterView';
|
||||
import { GroupedView } from './GroupedView';
|
||||
|
||||
const RuleList = withErrorBoundary(
|
||||
() => {
|
||||
const [queryParams] = useURLSearchParams();
|
||||
const { filterState, hasActiveFilters } = useRulesFilter();
|
||||
function RuleList() {
|
||||
const [queryParams] = useURLSearchParams();
|
||||
const { filterState, hasActiveFilters } = useRulesFilter();
|
||||
|
||||
const view: SupportedView = queryParams.get('view') === 'list' ? 'list' : 'grouped';
|
||||
const showListView = hasActiveFilters || view === 'list';
|
||||
const view: SupportedView = queryParams.get('view') === 'list' ? 'list' : 'grouped';
|
||||
const showListView = hasActiveFilters || view === 'list';
|
||||
|
||||
return (
|
||||
// We don't want to show the Loading... indicator for the whole page.
|
||||
// We show separate indicators for Grafana-managed and Cloud rules
|
||||
<AlertingPageWrapper navId="alert-list" isLoading={false} actions={null}>
|
||||
<RulesFilter onClear={() => {}} />
|
||||
{showListView ? <FilterView filterState={filterState} /> : <GroupedView />}
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
},
|
||||
{ style: 'page' }
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<RulesFilter onClear={() => {}} />
|
||||
{showListView ? <FilterView filterState={filterState} /> : <GroupedView />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default RuleList;
|
||||
export default function RuleListPage() {
|
||||
return (
|
||||
<AlertingPageWrapper navId="alert-list" isLoading={false} actions={null}>
|
||||
<RuleList />
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
import { ComponentType } from 'react';
|
||||
|
||||
import { ErrorBoundaryAlertProps, withErrorBoundary } from '@grafana/ui';
|
||||
|
||||
import { logError } from './Analytics';
|
||||
|
||||
/**
|
||||
* HOC for wrapping alerting page in an error boundary.
|
||||
* It provides alerting-specific error handling.
|
||||
*
|
||||
* @param Component - the react component to wrap in error boundary
|
||||
* @param errorBoundaryProps - error boundary options
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function withPageErrorBoundary<P extends {} = {}>(
|
||||
Component: ComponentType<P>,
|
||||
errorBoundaryProps: Omit<ErrorBoundaryAlertProps, 'children' | 'errorLogger' | 'style'> = {}
|
||||
): ComponentType<P> {
|
||||
return withErrorBoundary(Component, {
|
||||
...errorBoundaryProps,
|
||||
style: 'page',
|
||||
errorLogger: logError,
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user