Skip to content

Commit

Permalink
[Observability] New "No Data" screens (#107709)
Browse files Browse the repository at this point in the history
Adds empty states for all of Obs that lead to their various ingest flows.
  • Loading branch information
cchaos authored Oct 6, 2021
1 parent fa59b52 commit 74da7d3
Show file tree
Hide file tree
Showing 32 changed files with 193 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
* 2.0.
*/

import { EuiPageHeaderProps, EuiPageTemplateProps } from '@elastic/eui';
import { EuiPageHeaderProps } from '@elastic/eui';
import React from 'react';
import { useLocation } from 'react-router-dom';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
import {
useKibana,
KibanaPageTemplateProps,
} from '../../../../../../../src/plugins/kibana_react/public';
import { useFetcher } from '../../../hooks/use_fetcher';
import { ApmPluginStartDeps } from '../../../plugin';
import { ApmEnvironmentFilter } from '../../shared/EnvironmentFilter';
Expand All @@ -35,7 +38,7 @@ export function ApmMainTemplate({
pageTitle?: React.ReactNode;
pageHeader?: EuiPageHeaderProps;
children: React.ReactNode;
} & EuiPageTemplateProps) {
} & KibanaPageTemplateProps) {
const location = useLocation();

const { services } = useKibana<ApmPluginStartDeps>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { LogEntryCategoriesResultsContent } from './page_results_content';
import { LogEntryCategoriesSetupContent } from './page_setup_content';
import { LogsPageTemplate } from '../page_template';
import type { LazyObservabilityPageTemplateProps } from '../../../../../observability/public';
import { useLogSourceContext } from '../../../containers/logs/log_source';

const logCategoriesTitle = i18n.translate('xpack.infra.logs.logCategoriesTitle', {
defaultMessage: 'Categories',
Expand Down Expand Up @@ -114,8 +115,10 @@ const CategoriesPageTemplate: React.FC<LazyObservabilityPageTemplateProps> = ({
children,
...rest
}) => {
const { sourceStatus } = useLogSourceContext();
return (
<LogsPageTemplate
hasData={sourceStatus?.logIndexStatus !== 'missing'}
data-test-subj="logsLogEntryCategoriesPage"
pageHeader={
rest.isEmptyState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { RecreateJobButton } from '../../../components/logging/log_analysis_setu
import { AnalyzeInMlButton } from '../../../components/logging/log_analysis_results';
import { useMlHref, ML_PAGES } from '../../../../../ml/public';
import { DatasetsSelector } from '../../../components/logging/log_analysis_results/datasets_selector';
import { useLogSourceContext } from '../../../containers/logs/log_source';
import { MLJobsAwaitingNodeWarning } from '../../../../../ml/public';

const JOB_STATUS_POLLING_INTERVAL = 30000;
Expand All @@ -50,6 +51,7 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent<LogEntryC
services: { ml, http },
} = useKibanaContextForPlugin();

const { sourceStatus } = useLogSourceContext();
const { hasLogAnalysisSetupCapabilities } = useLogAnalysisCapabilitiesContext();

const {
Expand Down Expand Up @@ -211,6 +213,7 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent<LogEntryC
endTimestamp={categoryQueryTimeRange.timeRange.endTime}
>
<LogsPageTemplate
hasData={sourceStatus?.logIndexStatus !== 'missing'}
pageHeader={{
pageTitle,
rightSideItems: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
useLogAnalysisSetupFlyoutStateContext,
} from '../../../components/logging/log_analysis_setup/setup_flyout';
import { SubscriptionSplashPage } from '../../../components/subscription_splash_content';
import { useLogSourceContext } from '../../../containers/logs/log_source';
import { useLogAnalysisCapabilitiesContext } from '../../../containers/logs/log_analysis';
import { useLogEntryCategoriesModuleContext } from '../../../containers/logs/log_analysis/modules/log_entry_categories';
import { useLogEntryRateModuleContext } from '../../../containers/logs/log_analysis/modules/log_entry_rate';
Expand Down Expand Up @@ -155,8 +156,10 @@ const AnomaliesPageTemplate: React.FC<LazyObservabilityPageTemplateProps> = ({
children,
...rest
}) => {
const { sourceStatus } = useLogSourceContext();
return (
<LogsPageTemplate
hasData={sourceStatus?.logIndexStatus !== 'missing'}
data-test-subj="logsLogEntryRatePage"
pageHeader={
rest.isEmptyState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const LogEntryRateResultsContent: React.FunctionComponent<{

const navigateToApp = useKibana().services.application?.navigateToApp;

const { sourceId } = useLogSourceContext();
const { sourceId, sourceStatus } = useLogSourceContext();

const { hasLogAnalysisSetupCapabilities } = useLogAnalysisCapabilitiesContext();

Expand Down Expand Up @@ -196,6 +196,7 @@ export const LogEntryRateResultsContent: React.FunctionComponent<{

return (
<LogsPageTemplate
hasData={sourceStatus?.logIndexStatus !== 'missing'}
pageHeader={{
pageTitle,
rightSideItems: [<ManageJobsButton onClick={showModuleList} size="s" />],
Expand Down
50 changes: 46 additions & 4 deletions x-pack/plugins/infra/public/pages/logs/page_template.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,61 @@
*/

import React from 'react';
import { i18n } from '@kbn/i18n';
import { useKibanaContextForPlugin } from '../../hooks/use_kibana';
import type { LazyObservabilityPageTemplateProps } from '../../../../observability/public';
import {
KibanaPageTemplateProps,
useKibana,
} from '../../../../../../src/plugins/kibana_react/public';

export const LogsPageTemplate: React.FC<LazyObservabilityPageTemplateProps> = (
pageTemplateProps
) => {
interface LogsPageTemplateProps extends LazyObservabilityPageTemplateProps {
hasData?: boolean;
}

export const LogsPageTemplate: React.FC<LogsPageTemplateProps> = ({
hasData = true,
'data-test-subj': _dataTestSubj,
...pageTemplateProps
}) => {
const {
services: {
observability: {
navigation: { PageTemplate },
},
docLinks,
},
} = useKibanaContextForPlugin();

return <PageTemplate {...pageTemplateProps} />;
const { http } = useKibana().services;
const basePath = http!.basePath.get();

const noDataConfig: KibanaPageTemplateProps['noDataConfig'] = hasData
? undefined
: {
solution: i18n.translate('xpack.infra.logs.noDataConfig.solutionName', {
defaultMessage: 'Observability',
}),
actions: {
beats: {
title: i18n.translate('xpack.infra.logs.noDataConfig.beatsCard.title', {
defaultMessage: 'Add logs with Beats',
}),
description: i18n.translate('xpack.infra.logs.noDataConfig.beatsCard.description', {
defaultMessage:
'Use Beats to send logs to Elasticsearch. We make it easy with modules for many popular systems and apps.',
}),
href: basePath + `/app/home#/tutorial_directory/logging`,
},
},
docsLink: docLinks.links.observability.guide,
};

return (
<PageTemplate
data-test-subj={hasData ? _dataTestSubj : 'noDataPage'}
noDataConfig={noDataConfig}
{...pageTemplateProps}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { LogSourceErrorPage } from '../../../components/logging/log_source_error
import { SourceLoadingPage } from '../../../components/source_loading_page';
import { useLogSourceContext } from '../../../containers/logs/log_source';
import { LogsPageLogsContent } from './page_logs_content';
import { LogsPageNoIndicesContent } from './page_no_indices_content';
import { LogsPageTemplate } from '../page_template';
import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
import { APP_WRAPPER_CLASS } from '../../../../../../../src/core/public';
Expand All @@ -34,10 +33,11 @@ export const StreamPageContent: React.FunctionComponent = () => {
return <SourceLoadingPage />;
} else if (hasFailedLoading) {
return <LogSourceErrorPage errors={latestLoadSourceFailures} onRetry={loadSource} />;
} else if (sourceStatus?.logIndexStatus !== 'missing') {
} else {
return (
<LogStreamPageWrapper className={APP_WRAPPER_CLASS}>
<LogsPageTemplate
hasData={sourceStatus?.logIndexStatus !== 'missing'}
pageHeader={{
pageTitle: streamTitle,
}}
Expand All @@ -46,8 +46,6 @@ export const StreamPageContent: React.FunctionComponent = () => {
</LogsPageTemplate>
</LogStreamPageWrapper>
);
} else {
return <LogsPageNoIndicesContent />;
}
};

Expand Down
51 changes: 3 additions & 48 deletions x-pack/plugins/infra/public/pages/metrics/inventory_view/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,19 @@
* 2.0.
*/

import { EuiButton, EuiErrorBoundary, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { EuiErrorBoundary } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useContext } from 'react';
import { FilterBar } from './components/filter_bar';

import { DocumentTitle } from '../../../components/document_title';
import { NoIndices } from '../../../components/empty_states/no_indices';

import { SourceErrorPage } from '../../../components/source_error_page';
import { SourceLoadingPage } from '../../../components/source_loading_page';
import { ViewSourceConfigurationButton } from '../../../components/source_configuration/view_source_configuration_button';
import { Source } from '../../../containers/metrics_source';
import { useTrackPageview } from '../../../../../observability/public';
import { useMetricsBreadcrumbs } from '../../../hooks/use_metrics_breadcrumbs';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
import { LayoutView } from './components/layout_view';
import { useLinkProps } from '../../../hooks/use_link_props';
import { SavedViewProvider } from '../../../containers/saved_view/saved_view';
import { DEFAULT_WAFFLE_VIEW_STATE } from './hooks/use_waffle_view_state';
import { useWaffleOptionsContext } from './hooks/use_waffle_options';
Expand All @@ -32,7 +28,6 @@ import { inventoryTitle } from '../../../translations';
import { SavedViews } from './components/saved_views';

export const SnapshotPage = () => {
const uiCapabilities = useKibana().services.application?.capabilities;
const {
hasFailedLoadingSource,
isLoading,
Expand All @@ -45,11 +40,6 @@ export const SnapshotPage = () => {
useTrackPageview({ app: 'infra_metrics', path: 'inventory', delay: 15000 });
const { source: optionsSource } = useWaffleOptionsContext();

const tutorialLinkProps = useLinkProps({
app: 'home',
hash: '/tutorial_directory/metrics',
});

useMetricsBreadcrumbs([
{
text: inventoryTitle,
Expand Down Expand Up @@ -79,6 +69,7 @@ export const SnapshotPage = () => {
defaultViewState={DEFAULT_WAFFLE_VIEW_STATE}
>
<MetricsPageTemplate
hasData={metricIndicesExist}
pageHeader={{
pageTitle: inventoryTitle,
rightSideItems: [<SavedViews />],
Expand All @@ -96,43 +87,7 @@ export const SnapshotPage = () => {
) : 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"
/>
<MetricsPageTemplate hasData={metricIndicesExist} data-test-subj="noMetricsIndicesPrompt" />
)}
</EuiErrorBoundary>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
* 2.0.
*/

import React, { useCallback, useEffect, useState } from 'react';
import React, { useCallback, useEffect, useState, useContext } from 'react';
import dateMath from '@elastic/datemath';
import moment from 'moment';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { Source } from '../../../../containers/metrics_source';
import { InventoryMetric, InventoryItemType } from '../../../../../common/inventory_models/types';
import { useNodeDetails } from '../hooks/use_node_details';
import { MetricsSideNav } from './side_nav';
Expand Down Expand Up @@ -52,6 +53,7 @@ const parseRange = (range: MetricsTimeInput) => {
};

export const NodeDetailsPage = (props: Props) => {
const { metricIndicesExist } = useContext(Source.Context);
const [parsedTimeRange, setParsedTimeRange] = useState(parseRange(props.timeRange));
const { metrics, loading, makeRequest, error } = useNodeDetails(
props.requiredMetrics,
Expand Down Expand Up @@ -80,6 +82,7 @@ export const NodeDetailsPage = (props: Props) => {

return (
<MetricsPageTemplate
hasData={metricIndicesExist}
pageHeader={{
pageTitle: props.name,
rightSideItems: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const MetricDetail = withMetricPageProviders(
const nodeId = match.params.node;
const nodeType = match.params.type as InventoryItemType;
const inventoryModel = findInventoryModel(nodeType);
const { sourceId } = useContext(Source.Context);
const { sourceId, metricIndicesExist } = useContext(Source.Context);

const {
timeRange,
Expand Down Expand Up @@ -86,7 +86,7 @@ export const MetricDetail = withMetricPageProviders(

if (metadataLoading && !filteredRequiredMetrics.length) {
return (
<MetricsPageTemplate>
<MetricsPageTemplate hasData={metricIndicesExist}>
<InfraLoadingPanel
height="100vh"
width="100%"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@

import { EuiErrorBoundary } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useEffect } from 'react';
import React, { useEffect, useContext } from 'react';
import { IIndexPattern } from 'src/plugins/data/public';
import { MetricsSourceConfigurationProperties } from '../../../../common/metrics_sources';
import { useTrackPageview } from '../../../../../observability/public';
import { useMetricsBreadcrumbs } from '../../../hooks/use_metrics_breadcrumbs';

import { DocumentTitle } from '../../../components/document_title';
import { NoData } from '../../../components/empty_states';
import { MetricsExplorerCharts } from './components/charts';
import { MetricsExplorerToolbar } from './components/toolbar';
import { useMetricsExplorerState } from './hooks/use_metric_explorer_state';
import { Source } from '../../../containers/metrics_source';
import { useSavedViewContext } from '../../../containers/saved_view/saved_view';
import { MetricsPageTemplate } from '../page_template';
import { metricsExplorerTitle } from '../../../translations';
Expand Down Expand Up @@ -52,6 +52,7 @@ export const MetricsExplorerPage = ({ source, derivedIndexPattern }: MetricsExpl
useTrackPageview({ app: 'infra_metrics', path: 'metrics_explorer' });
useTrackPageview({ app: 'infra_metrics', path: 'metrics_explorer', delay: 15000 });

const { metricIndicesExist } = useContext(Source.Context);
useEffect(() => {
if (currentView) {
onViewStateChange(currentView);
Expand Down Expand Up @@ -85,6 +86,7 @@ export const MetricsExplorerPage = ({ source, derivedIndexPattern }: MetricsExpl
}
/>
<MetricsPageTemplate
hasData={metricIndicesExist}
pageHeader={{
pageTitle: metricsExplorerTitle,
rightSideItems: [
Expand Down
Loading

0 comments on commit 74da7d3

Please sign in to comment.