[Logs + Metrics UI] Prevent component errors from breaking the whole UI (#65456)
This commit is contained in:
parent
f53b147097
commit
8a8647ab95
|
@ -4,18 +4,20 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
|
||||
import { ColumnarPage } from '../../../components/page';
|
||||
import { LogEntryCategoriesPageContent } from './page_content';
|
||||
import { LogEntryCategoriesPageProviders } from './page_providers';
|
||||
|
||||
export const LogEntryCategoriesPage = () => {
|
||||
return (
|
||||
<LogEntryCategoriesPageProviders>
|
||||
<ColumnarPage data-test-subj="logsLogEntryCategoriesPage">
|
||||
<LogEntryCategoriesPageContent />
|
||||
</ColumnarPage>
|
||||
</LogEntryCategoriesPageProviders>
|
||||
<EuiErrorBoundary>
|
||||
<LogEntryCategoriesPageProviders>
|
||||
<ColumnarPage data-test-subj="logsLogEntryCategoriesPage">
|
||||
<LogEntryCategoriesPageContent />
|
||||
</ColumnarPage>
|
||||
</LogEntryCategoriesPageProviders>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,18 +4,20 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
|
||||
import { ColumnarPage } from '../../../components/page';
|
||||
import { LogEntryRatePageContent } from './page_content';
|
||||
import { LogEntryRatePageProviders } from './page_providers';
|
||||
|
||||
export const LogEntryRatePage = () => {
|
||||
return (
|
||||
<LogEntryRatePageProviders>
|
||||
<ColumnarPage data-test-subj="logsLogEntryRatePage">
|
||||
<LogEntryRatePageContent />
|
||||
</ColumnarPage>
|
||||
</LogEntryRatePageProviders>
|
||||
<EuiErrorBoundary>
|
||||
<LogEntryRatePageProviders>
|
||||
<ColumnarPage data-test-subj="logsLogEntryRatePage">
|
||||
<LogEntryRatePageContent />
|
||||
</ColumnarPage>
|
||||
</LogEntryRatePageProviders>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,16 +4,18 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
import { LogsPageContent } from './page_content';
|
||||
import { LogsPageProviders } from './page_providers';
|
||||
|
||||
export const LogsPage: React.FunctionComponent<RouteComponentProps> = ({ match }) => {
|
||||
export const LogsPage: React.FunctionComponent<RouteComponentProps> = () => {
|
||||
return (
|
||||
<LogsPageProviders>
|
||||
<LogsPageContent />
|
||||
</LogsPageProviders>
|
||||
<EuiErrorBoundary>
|
||||
<LogsPageProviders>
|
||||
<LogsPageContent />
|
||||
</LogsPageProviders>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import {
|
||||
EuiButton,
|
||||
EuiCallOut,
|
||||
EuiErrorBoundary,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiPanel,
|
||||
|
@ -74,7 +75,7 @@ export const LogsSettingsPage = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiErrorBoundary>
|
||||
<EuiPage>
|
||||
<EuiPageBody
|
||||
className="eui-displayBlock"
|
||||
|
@ -181,7 +182,7 @@ export const LogsSettingsPage = () => {
|
|||
</EuiFlexGroup>
|
||||
</EuiPageBody>
|
||||
</EuiPage>
|
||||
</>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
import { ColumnarPage } from '../../../components/page';
|
||||
|
@ -15,11 +16,13 @@ export const StreamPage = () => {
|
|||
useTrackPageview({ app: 'infra_logs', path: 'stream' });
|
||||
useTrackPageview({ app: 'infra_logs', path: 'stream', delay: 15000 });
|
||||
return (
|
||||
<LogsPageProviders>
|
||||
<ColumnarPage data-test-subj="infraLogsPage">
|
||||
<StreamPageHeader />
|
||||
<StreamPageContent />
|
||||
</ColumnarPage>
|
||||
</LogsPageProviders>
|
||||
<EuiErrorBoundary>
|
||||
<LogsPageProviders>
|
||||
<ColumnarPage data-test-subj="infraLogsPage">
|
||||
<StreamPageHeader />
|
||||
<StreamPageContent />
|
||||
</ColumnarPage>
|
||||
</LogsPageProviders>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import React from 'react';
|
||||
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
|
||||
|
||||
import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
|
||||
import { EuiErrorBoundary, EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
|
||||
import { DocumentTitle } from '../../components/document_title';
|
||||
import { HelpCenterContent } from '../../components/help_center_content';
|
||||
import { RoutedTabs } from '../../components/navigation/routed_tabs';
|
||||
|
@ -36,103 +36,105 @@ export const InfrastructurePage = ({ match }: RouteComponentProps) => {
|
|||
const uiCapabilities = useKibana().services.application?.capabilities;
|
||||
|
||||
return (
|
||||
<Source.Provider sourceId="default">
|
||||
<WaffleOptionsProvider>
|
||||
<WaffleTimeProvider>
|
||||
<WaffleFiltersProvider>
|
||||
<ColumnarPage>
|
||||
<DocumentTitle
|
||||
title={i18n.translate('xpack.infra.homePage.documentTitle', {
|
||||
defaultMessage: 'Metrics',
|
||||
})}
|
||||
/>
|
||||
|
||||
<HelpCenterContent
|
||||
feedbackLink="https://discuss.elastic.co/c/metrics"
|
||||
appName={i18n.translate('xpack.infra.header.infrastructureHelpAppName', {
|
||||
defaultMessage: 'Metrics',
|
||||
})}
|
||||
/>
|
||||
|
||||
<Header
|
||||
breadcrumbs={[
|
||||
{
|
||||
text: i18n.translate('xpack.infra.header.infrastructureTitle', {
|
||||
defaultMessage: 'Metrics',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
readOnlyBadge={!uiCapabilities?.infrastructure?.save}
|
||||
/>
|
||||
<AppNavigation
|
||||
aria-label={i18n.translate('xpack.infra.header.infrastructureNavigationTitle', {
|
||||
defaultMessage: 'Metrics',
|
||||
})}
|
||||
>
|
||||
<EuiFlexGroup gutterSize={'none'} alignItems={'center'}>
|
||||
<EuiFlexItem>
|
||||
<RoutedTabs
|
||||
tabs={[
|
||||
{
|
||||
app: 'metrics',
|
||||
title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', {
|
||||
defaultMessage: 'Inventory',
|
||||
}),
|
||||
pathname: '/inventory',
|
||||
},
|
||||
{
|
||||
app: 'metrics',
|
||||
title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', {
|
||||
defaultMessage: 'Metrics Explorer',
|
||||
}),
|
||||
pathname: '/explorer',
|
||||
},
|
||||
{
|
||||
app: 'metrics',
|
||||
title: i18n.translate('xpack.infra.homePage.settingsTabTitle', {
|
||||
defaultMessage: 'Settings',
|
||||
}),
|
||||
pathname: '/settings',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<Route path={'/explorer'} component={MetricsAlertDropdown} />
|
||||
<Route path={'/inventory'} component={InventoryAlertDropdown} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AppNavigation>
|
||||
|
||||
<Switch>
|
||||
<Route path={'/inventory'} component={SnapshotPage} />
|
||||
<Route
|
||||
path={'/explorer'}
|
||||
render={props => (
|
||||
<WithSource>
|
||||
{({ configuration, createDerivedIndexPattern }) => (
|
||||
<MetricsExplorerOptionsContainer.Provider>
|
||||
<WithMetricsExplorerOptionsUrlState />
|
||||
{configuration ? (
|
||||
<MetricsExplorerPage
|
||||
derivedIndexPattern={createDerivedIndexPattern('metrics')}
|
||||
source={configuration}
|
||||
{...props}
|
||||
/>
|
||||
) : (
|
||||
<SourceLoadingPage />
|
||||
)}
|
||||
</MetricsExplorerOptionsContainer.Provider>
|
||||
)}
|
||||
</WithSource>
|
||||
)}
|
||||
<EuiErrorBoundary>
|
||||
<Source.Provider sourceId="default">
|
||||
<WaffleOptionsProvider>
|
||||
<WaffleTimeProvider>
|
||||
<WaffleFiltersProvider>
|
||||
<ColumnarPage>
|
||||
<DocumentTitle
|
||||
title={i18n.translate('xpack.infra.homePage.documentTitle', {
|
||||
defaultMessage: 'Metrics',
|
||||
})}
|
||||
/>
|
||||
<Route path={'/settings'} component={MetricsSettingsPage} />
|
||||
</Switch>
|
||||
</ColumnarPage>
|
||||
</WaffleFiltersProvider>
|
||||
</WaffleTimeProvider>
|
||||
</WaffleOptionsProvider>
|
||||
</Source.Provider>
|
||||
|
||||
<HelpCenterContent
|
||||
feedbackLink="https://discuss.elastic.co/c/metrics"
|
||||
appName={i18n.translate('xpack.infra.header.infrastructureHelpAppName', {
|
||||
defaultMessage: 'Metrics',
|
||||
})}
|
||||
/>
|
||||
|
||||
<Header
|
||||
breadcrumbs={[
|
||||
{
|
||||
text: i18n.translate('xpack.infra.header.infrastructureTitle', {
|
||||
defaultMessage: 'Metrics',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
readOnlyBadge={!uiCapabilities?.infrastructure?.save}
|
||||
/>
|
||||
<AppNavigation
|
||||
aria-label={i18n.translate('xpack.infra.header.infrastructureNavigationTitle', {
|
||||
defaultMessage: 'Metrics',
|
||||
})}
|
||||
>
|
||||
<EuiFlexGroup gutterSize={'none'} alignItems={'center'}>
|
||||
<EuiFlexItem>
|
||||
<RoutedTabs
|
||||
tabs={[
|
||||
{
|
||||
app: 'metrics',
|
||||
title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', {
|
||||
defaultMessage: 'Inventory',
|
||||
}),
|
||||
pathname: '/inventory',
|
||||
},
|
||||
{
|
||||
app: 'metrics',
|
||||
title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', {
|
||||
defaultMessage: 'Metrics Explorer',
|
||||
}),
|
||||
pathname: '/explorer',
|
||||
},
|
||||
{
|
||||
app: 'metrics',
|
||||
title: i18n.translate('xpack.infra.homePage.settingsTabTitle', {
|
||||
defaultMessage: 'Settings',
|
||||
}),
|
||||
pathname: '/settings',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<Route path={'/explorer'} component={MetricsAlertDropdown} />
|
||||
<Route path={'/inventory'} component={InventoryAlertDropdown} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AppNavigation>
|
||||
|
||||
<Switch>
|
||||
<Route path={'/inventory'} component={SnapshotPage} />
|
||||
<Route
|
||||
path={'/explorer'}
|
||||
render={props => (
|
||||
<WithSource>
|
||||
{({ configuration, createDerivedIndexPattern }) => (
|
||||
<MetricsExplorerOptionsContainer.Provider>
|
||||
<WithMetricsExplorerOptionsUrlState />
|
||||
{configuration ? (
|
||||
<MetricsExplorerPage
|
||||
derivedIndexPattern={createDerivedIndexPattern('metrics')}
|
||||
source={configuration}
|
||||
{...props}
|
||||
/>
|
||||
) : (
|
||||
<SourceLoadingPage />
|
||||
)}
|
||||
</MetricsExplorerOptionsContainer.Provider>
|
||||
)}
|
||||
</WithSource>
|
||||
)}
|
||||
/>
|
||||
<Route path={'/settings'} component={MetricsSettingsPage} />
|
||||
</Switch>
|
||||
</ColumnarPage>
|
||||
</WaffleFiltersProvider>
|
||||
</WaffleTimeProvider>
|
||||
</WaffleOptionsProvider>
|
||||
</Source.Provider>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { EuiButton, EuiErrorBoundary, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useContext } from 'react';
|
||||
|
||||
|
@ -41,65 +41,70 @@ export const SnapshotPage = () => {
|
|||
});
|
||||
|
||||
return (
|
||||
<ColumnarPage>
|
||||
<DocumentTitle
|
||||
title={(previousTitle: string) =>
|
||||
i18n.translate('xpack.infra.infrastructureSnapshotPage.documentTitle', {
|
||||
defaultMessage: '{previousTitle} | Inventory',
|
||||
values: {
|
||||
previousTitle,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
{isLoading ? (
|
||||
<SourceLoadingPage />
|
||||
) : metricIndicesExist ? (
|
||||
<>
|
||||
<FilterBar />
|
||||
<Layout />
|
||||
</>
|
||||
) : hasFailedLoadingSource ? (
|
||||
<SourceErrorPage errorMessage={loadSourceFailureMessage || ''} retry={loadSource} />
|
||||
) : (
|
||||
<NoIndices
|
||||
title={i18n.translate('xpack.infra.homePage.noMetricsIndicesTitle', {
|
||||
defaultMessage: "Looks like you don't have any metrics indices.",
|
||||
})}
|
||||
message={i18n.translate('xpack.infra.homePage.noMetricsIndicesDescription', {
|
||||
defaultMessage: "Let's add some!",
|
||||
})}
|
||||
actions={
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiButton
|
||||
{...tutorialLinkProps}
|
||||
color="primary"
|
||||
fill
|
||||
data-test-subj="infrastructureViewSetupInstructionsButton"
|
||||
>
|
||||
{i18n.translate('xpack.infra.homePage.noMetricsIndicesInstructionsActionLabel', {
|
||||
defaultMessage: 'View setup instructions',
|
||||
})}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
{uiCapabilities?.infrastructure?.configureSource ? (
|
||||
<EuiFlexItem>
|
||||
<ViewSourceConfigurationButton
|
||||
app="metrics"
|
||||
data-test-subj="configureSourceButton"
|
||||
>
|
||||
{i18n.translate('xpack.infra.configureSourceActionLabel', {
|
||||
defaultMessage: 'Change source configuration',
|
||||
})}
|
||||
</ViewSourceConfigurationButton>
|
||||
</EuiFlexItem>
|
||||
) : null}
|
||||
</EuiFlexGroup>
|
||||
<EuiErrorBoundary>
|
||||
<ColumnarPage>
|
||||
<DocumentTitle
|
||||
title={(previousTitle: string) =>
|
||||
i18n.translate('xpack.infra.infrastructureSnapshotPage.documentTitle', {
|
||||
defaultMessage: '{previousTitle} | Inventory',
|
||||
values: {
|
||||
previousTitle,
|
||||
},
|
||||
})
|
||||
}
|
||||
data-test-subj="noMetricsIndicesPrompt"
|
||||
/>
|
||||
)}
|
||||
</ColumnarPage>
|
||||
{isLoading ? (
|
||||
<SourceLoadingPage />
|
||||
) : metricIndicesExist ? (
|
||||
<>
|
||||
<FilterBar />
|
||||
<Layout />
|
||||
</>
|
||||
) : hasFailedLoadingSource ? (
|
||||
<SourceErrorPage errorMessage={loadSourceFailureMessage || ''} retry={loadSource} />
|
||||
) : (
|
||||
<NoIndices
|
||||
title={i18n.translate('xpack.infra.homePage.noMetricsIndicesTitle', {
|
||||
defaultMessage: "Looks like you don't have any metrics indices.",
|
||||
})}
|
||||
message={i18n.translate('xpack.infra.homePage.noMetricsIndicesDescription', {
|
||||
defaultMessage: "Let's add some!",
|
||||
})}
|
||||
actions={
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiButton
|
||||
{...tutorialLinkProps}
|
||||
color="primary"
|
||||
fill
|
||||
data-test-subj="infrastructureViewSetupInstructionsButton"
|
||||
>
|
||||
{i18n.translate(
|
||||
'xpack.infra.homePage.noMetricsIndicesInstructionsActionLabel',
|
||||
{
|
||||
defaultMessage: 'View setup instructions',
|
||||
}
|
||||
)}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
{uiCapabilities?.infrastructure?.configureSource ? (
|
||||
<EuiFlexItem>
|
||||
<ViewSourceConfigurationButton
|
||||
app="metrics"
|
||||
data-test-subj="configureSourceButton"
|
||||
>
|
||||
{i18n.translate('xpack.infra.configureSourceActionLabel', {
|
||||
defaultMessage: 'Change source configuration',
|
||||
})}
|
||||
</ViewSourceConfigurationButton>
|
||||
</EuiFlexItem>
|
||||
) : null}
|
||||
</EuiFlexGroup>
|
||||
}
|
||||
data-test-subj="noMetricsIndicesPrompt"
|
||||
/>
|
||||
)}
|
||||
</ColumnarPage>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,17 +4,19 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
|
||||
import { Source } from '../../../containers/source';
|
||||
import { MetricsTimeProvider } from './hooks/use_metrics_time';
|
||||
|
||||
export const withMetricPageProviders = <T extends object>(Component: React.ComponentType<T>) => (
|
||||
props: T
|
||||
) => (
|
||||
<Source.Provider sourceId="default">
|
||||
<MetricsTimeProvider>
|
||||
<Component {...props} />
|
||||
</MetricsTimeProvider>
|
||||
</Source.Provider>
|
||||
<EuiErrorBoundary>
|
||||
<Source.Provider sourceId="default">
|
||||
<MetricsTimeProvider>
|
||||
<Component {...props} />
|
||||
</MetricsTimeProvider>
|
||||
</Source.Provider>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
|
|
|
@ -4,17 +4,17 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import React from 'react';
|
||||
import { IIndexPattern } from 'src/plugins/data/public';
|
||||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
import { SourceQuery } from '../../../../common/graphql/types';
|
||||
import { DocumentTitle } from '../../../components/document_title';
|
||||
import { NoData } from '../../../components/empty_states';
|
||||
import { MetricsExplorerCharts } from './components/charts';
|
||||
import { MetricsExplorerToolbar } from './components/toolbar';
|
||||
import { SourceQuery } from '../../../../common/graphql/types';
|
||||
import { NoData } from '../../../components/empty_states';
|
||||
import { useMetricsExplorerState } from './hooks/use_metric_explorer_state';
|
||||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
|
||||
interface MetricsExplorerPageProps {
|
||||
source: SourceQuery.Query['source']['configuration'];
|
||||
|
@ -45,7 +45,7 @@ export const MetricsExplorerPage = ({ source, derivedIndexPattern }: MetricsExpl
|
|||
useTrackPageview({ app: 'infra_metrics', path: 'metrics_explorer', delay: 15000 });
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EuiErrorBoundary>
|
||||
<DocumentTitle
|
||||
title={(previousTitle: string) =>
|
||||
i18n.translate('xpack.infra.infrastructureMetricsExplorerPage.documentTitle', {
|
||||
|
@ -95,6 +95,6 @@ export const MetricsExplorerPage = ({ source, derivedIndexPattern }: MetricsExpl
|
|||
onTimeChange={handleTimeChange}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,16 +4,19 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { SourceConfigurationSettings } from '../../components/source_configuration/source_configuration_settings';
|
||||
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
|
||||
import { SourceConfigurationSettings } from '../../components/source_configuration/source_configuration_settings';
|
||||
|
||||
export const MetricsSettingsPage = () => {
|
||||
const uiCapabilities = useKibana().services.application?.capabilities;
|
||||
return (
|
||||
<SourceConfigurationSettings
|
||||
shouldAllowEdit={uiCapabilities?.infrastructure?.configureSource as boolean}
|
||||
displaySettings="metrics"
|
||||
/>
|
||||
<EuiErrorBoundary>
|
||||
<SourceConfigurationSettings
|
||||
shouldAllowEdit={uiCapabilities?.infrastructure?.configureSource as boolean}
|
||||
displaySettings="metrics"
|
||||
/>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue