Skip to content

Commit

Permalink
[Actionable Observability] Integrate the shareable alert table in the…
Browse files Browse the repository at this point in the history
… Overview Page (#140024)

* Refactor observability overview page

* Fix type and file name

* Use shareable alert table in overview page

* Add functional test for overview page

* Fix functional tests

* Fix flaky test

* Remove only and add retry for opening alerts section

* Wait for the overview page to load before opening alerts section

* Add waitForAlertsSectionToAppear

* Add waiting for alerts table loading to disappear

* Add longer timeout for loading alerts table

* Increase timeout for alerts table to be loaded
  • Loading branch information
maryam-saeidi authored Sep 12, 2022
1 parent 9f0a9e7 commit 5a0313b
Show file tree
Hide file tree
Showing 18 changed files with 245 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export function SectionContainer({
initialIsOpen={initialIsOpen}
id={title}
buttonContentClassName="accordion-button"
data-test-subj={`accordion-${title}`}
buttonContent={
<>
<EuiFlexGroup gutterSize="s" alignItems="center" responsive={false}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import useAsync from 'react-use/lib/useAsync';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { loadRuleAggregations } from '@kbn/triggers-actions-ui-plugin/public';
import { AlertConsumers, AlertStatus } from '@kbn/rule-data-utils';
import { buildEsQuery } from './helpers';
import { AlertStatusFilterButton } from '../../../../../common/typings';
import { useGetUserCasesPermissions } from '../../../../hooks/use_get_user_cases_permissions';
import { observabilityFeatureId } from '../../../../../common';
Expand All @@ -23,6 +22,7 @@ import { useAlertIndexNames } from '../../../../hooks/use_alert_index_names';
import { useHasData } from '../../../../hooks/use_has_data';
import { usePluginContext } from '../../../../hooks/use_plugin_context';
import { getNoDataConfig } from '../../../../utils/no_data_config';
import { buildEsQuery } from '../../../../utils/build_es_query';
import { LoadingObservability } from '../../../overview';
import {
Provider,
Expand All @@ -35,6 +35,7 @@ import { renderRuleStats } from '../../components/rule_stats';
import { ObservabilityAppServices } from '../../../../application/types';
import {
ALERT_STATUS_REGEX,
ALERTS_PER_PAGE,
ALERTS_TABLE_ID,
BASE_ALERT_REGEX,
NO_INDEX_PATTERNS,
Expand Down Expand Up @@ -144,11 +145,6 @@ function AlertsPage() {
];
}, [indexNames]);

const timeRange = {
to: rangeTo,
from: rangeFrom,
};

const onRefresh = () => {
setRefreshNow(new Date().getTime());
};
Expand Down Expand Up @@ -264,9 +260,15 @@ function AlertsPage() {
AlertConsumers.LOGS,
AlertConsumers.UPTIME,
]}
query={buildEsQuery(timeRange, kuery)}
query={buildEsQuery(
{
to: rangeTo,
from: rangeFrom,
},
kuery
)}
showExpandToDetails={false}
pageSize={50}
pageSize={ALERTS_PER_PAGE}
refreshNow={refreshNow}
/>
</CasesContext>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { DataViewBase } from '@kbn/es-query';
import { ALERT_STATUS } from '@kbn/rule-data-utils';

export const ALERTS_PAGE_ID = 'alerts-o11y';
export const ALERTS_TABLE_ID = 'xpack.observability.alerts.table';
export const ALERTS_PER_PAGE = 50;
export const ALERTS_TABLE_ID = 'xpack.observability.alerts.alert.table';

const regExpEscape = (str: string) => str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
export const NO_INDEX_PATTERNS: DataViewBase[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@

export const CAPABILITIES_KEYS = ['logs', 'infrastructure', 'apm', 'uptime'];

export const ALERTS_TABLE_ID = 'xpack.observability.overview.alert.table';
export const ALERT_TABLE_STATE_STORAGE_KEY = 'xpack.observability.overview.alert.tableState';
export const ALERTS_PER_PAGE = 10;
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import {
EuiButton,
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiFlyout,
EuiFlyoutSize,
EuiFlyoutBody,
EuiFlyoutHeader,
EuiHorizontalRule,
Expand All @@ -21,7 +23,7 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { Storage } from '@kbn/kibana-utils-plugin/public';
import { AlertConsumers } from '@kbn/rule-data-utils';
import React, { useMemo, useRef, useCallback, useState, useEffect } from 'react';

import { calculateBucketSize } from './helpers';
Expand All @@ -38,10 +40,9 @@ import { useBreadcrumbs } from '../../../../hooks/use_breadcrumbs';
import { useFetcher } from '../../../../hooks/use_fetcher';
import { useHasData } from '../../../../hooks/use_has_data';
import { usePluginContext } from '../../../../hooks/use_plugin_context';
import { useAlertIndexNames } from '../../../../hooks/use_alert_index_names';
import { buildEsQuery } from '../../../../utils/build_es_query';
import { getNewsFeed } from '../../../../services/get_news_feed';
import { DataSections, LoadingObservability } from '../../components';
import { AlertsTableTGrid } from '../../../alerts/containers/alerts_table_t_grid/alerts_table_t_grid';
import { SectionContainer } from '../../../../components/app/section';
import { ObservabilityAppServices } from '../../../../application/types';
import { useGetUserCasesPermissions } from '../../../../hooks/use_get_user_cases_permissions';
Expand All @@ -51,7 +52,7 @@ import { ObservabilityStatusProgress } from '../../../../components/app/observab
import { ObservabilityStatus } from '../../../../components/app/observability_status';
import { useGuidedSetupProgress } from '../../../../hooks/use_guided_setup_progress';
import { useObservabilityTourContext } from '../../../../components/shared/tour';
import { CAPABILITIES_KEYS, ALERT_TABLE_STATE_STORAGE_KEY, ALERTS_PER_PAGE } from './constants';
import { CAPABILITIES_KEYS, ALERTS_PER_PAGE, ALERTS_TABLE_ID } from './constants';

export function OverviewPage() {
const trackMetric = useUiTracker({ app: 'observability-overview' });
Expand All @@ -65,12 +66,13 @@ export function OverviewPage() {
},
]);
const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);
const [refreshNow, setRefreshNow] = useState<number>();

const indexNames = useAlertIndexNames();
const {
cases,
http,
application: { capabilities },
triggersActionsUi: { alertsTableConfigurationRegistry, getAlertsStateTable: AlertsStateTable },
} = useKibana<ObservabilityAppServices>().services;

const { ObservabilityPageTemplate } = usePluginContext();
Expand All @@ -94,10 +96,6 @@ export function OverviewPage() {
[absoluteStart, absoluteEnd]
);

const setRefetch = useCallback((ref) => {
refetch.current = ref;
}, []);

const handleGuidedSetupClick = useCallback(() => {
if (isGuidedSetupProgressDismissed) {
trackMetric({ metric: 'guided_setup_view_details_after_dismiss' });
Expand All @@ -107,6 +105,7 @@ export function OverviewPage() {
}, [trackMetric, isGuidedSetupProgressDismissed, hideGuidedSetupTour]);

const onTimeRangeRefresh = useCallback(() => {
setRefreshNow(new Date().getTime());
return refetch.current && refetch.current();
}, []);

Expand Down Expand Up @@ -173,14 +172,24 @@ export function OverviewPage() {
permissions={userCasesPermissions}
features={{ alerts: { sync: false } }}
>
<AlertsTableTGrid
setRefetch={setRefetch}
rangeFrom={relativeStart}
rangeTo={relativeEnd}
indexNames={indexNames}
itemsPerPage={ALERTS_PER_PAGE}
stateStorageKey={ALERT_TABLE_STATE_STORAGE_KEY}
storage={new Storage(window.localStorage)}
<AlertsStateTable
alertsTableConfigurationRegistry={alertsTableConfigurationRegistry}
configurationId={AlertConsumers.OBSERVABILITY}
id={ALERTS_TABLE_ID}
flyoutSize={'s' as EuiFlyoutSize}
featureIds={[
AlertConsumers.APM,
AlertConsumers.INFRASTRUCTURE,
AlertConsumers.LOGS,
AlertConsumers.UPTIME,
]}
query={buildEsQuery({
from: relativeStart,
to: relativeEnd,
})}
showExpandToDetails={false}
pageSize={ALERTS_PER_PAGE}
refreshNow={refreshNow}
/>
</CasesContext>
</SectionContainer>
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ describe('buildEsQuery', () => {
timeRange: defaultTimeRange,
kuery: '',
},
{
timeRange: defaultTimeRange,
},
{
timeRange: defaultTimeRange,
kuery: 'nestedField: { child: "something" }',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import { buildEsQuery as kbnBuildEsQuery, TimeRange } from '@kbn/es-query';
import { TIMESTAMP } from '@kbn/rule-data-utils';
import { getTime } from '@kbn/data-plugin/common';

export function buildEsQuery(timeRange: TimeRange, kuery: string) {
export function buildEsQuery(timeRange: TimeRange, kuery?: string) {
const timeFilter =
timeRange &&
getTime(undefined, timeRange, {
fieldName: TIMESTAMP,
});
const filtersToUse = [...(timeFilter ? [timeFilter] : [])];
const queryToUse = kuery ? { query: kuery, language: 'kuery' } : [];

return kbnBuildEsQuery(undefined, { query: kuery, language: 'kuery' }, filtersToUse);
return kbnBuildEsQuery(undefined, queryToUse, filtersToUse);
}
3 changes: 3 additions & 0 deletions x-pack/test/functional/services/observability/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
import { FtrProviderContext } from '../../ftr_provider_context';
import { ObservabilityUsersProvider } from './users';
import { ObservabilityAlertsProvider } from './alerts';
import { ObservabilityOverviewProvider } from './overview';

export function ObservabilityProvider(context: FtrProviderContext) {
const alerts = ObservabilityAlertsProvider(context);
const users = ObservabilityUsersProvider(context);
const overview = ObservabilityOverviewProvider(context);

return {
alerts,
users,
overview,
};
}
89 changes: 89 additions & 0 deletions x-pack/test/functional/services/observability/overview/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { FtrProviderContext } from '../../../ftr_provider_context';

// Based on the x-pack/test/functional/es_archives/observability/alerts archive.
const DATE_WITH_DATA = {
rangeFrom: '2021-10-18T13:36:22.109Z',
rangeTo: '2021-10-20T13:36:22.109Z',
};

const ALERTS_TITLE = 'Alerts';
const ALERTS_ACCORDION_SELECTOR = `accordion-${ALERTS_TITLE}`;
const ALERTS_SECTION_BUTTON_SELECTOR = `button[aria-controls="${ALERTS_TITLE}"]`;
const ALERTS_TABLE_NO_DATA_SELECTOR = 'alertsStateTableEmptyState';
const ALERTS_TABLE_WITH_DATA_SELECTOR = 'alertsTable';
const ALERTS_TABLE_LOADING_SELECTOR = 'internalAlertsPageLoading';

export function ObservabilityOverviewCommonProvider({
getPageObjects,
getService,
}: FtrProviderContext) {
const find = getService('find');
const pageObjects = getPageObjects(['common']);
const testSubjects = getService('testSubjects');
const retry = getService('retry');

const navigateToOverviewPageWithAlerts = async () => {
return await pageObjects.common.navigateToUrlWithBrowserHistory(
'observability',
'/overview',
`?rangeFrom=${DATE_WITH_DATA.rangeFrom}&rangeTo=${DATE_WITH_DATA.rangeTo}`,
{ ensureCurrentUrl: false }
);
};

const navigateToOverviewPage = async () => {
return await pageObjects.common.navigateToUrlWithBrowserHistory(
'observability',
'/overview',
undefined,
{ ensureCurrentUrl: false }
);
};

const waitForAlertsAccordionToAppear = async () => {
await retry.waitFor('alert accordion to appear', async () => {
return await testSubjects.exists(ALERTS_ACCORDION_SELECTOR);
});
};

const waitForAlertsTableLoadingToDisappear = async () => {
await retry.try(async () => {
await testSubjects.missingOrFail(ALERTS_TABLE_LOADING_SELECTOR, { timeout: 10000 });
});
};

const openAlertsSection = async () => {
await waitForAlertsAccordionToAppear();
const alertSectionButton = await find.byCssSelector(ALERTS_SECTION_BUTTON_SELECTOR);
return await alertSectionButton.click();
};

const openAlertsSectionAndWaitToAppear = async () => {
await openAlertsSection();
await waitForAlertsTableLoadingToDisappear();
await retry.waitFor('alerts table to appear', async () => {
return (
(await testSubjects.exists(ALERTS_TABLE_NO_DATA_SELECTOR)) ||
(await testSubjects.exists(ALERTS_TABLE_WITH_DATA_SELECTOR))
);
});
};

const getAlertsTableNoDataOrFail = async () => {
return await testSubjects.existOrFail(ALERTS_TABLE_NO_DATA_SELECTOR);
};

return {
getAlertsTableNoDataOrFail,
navigateToOverviewPageWithAlerts,
navigateToOverviewPage,
openAlertsSectionAndWaitToAppear,
};
}
18 changes: 18 additions & 0 deletions x-pack/test/functional/services/observability/overview/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { ObservabilityOverviewCommonProvider } from './common';

import { FtrProviderContext } from '../../../ftr_provider_context';

export function ObservabilityOverviewProvider(context: FtrProviderContext) {
const common = ObservabilityOverviewCommonProvider(context);

return {
common,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('ObservabilityApp', function () {
loadTestFile(require.resolve('./pages/alerts'));
loadTestFile(require.resolve('./pages/cases/case_details'));
loadTestFile(require.resolve('./pages/alerts/add_to_case'));
loadTestFile(require.resolve('./pages/alerts/alert_status'));
loadTestFile(require.resolve('./pages/alerts/pagination'));
loadTestFile(require.resolve('./pages/alerts/rule_stats'));
loadTestFile(require.resolve('./pages/alerts/state_synchronization'));
loadTestFile(require.resolve('./pages/alerts/table_storage'));
loadTestFile(require.resolve('./pages/cases/case_details'));
loadTestFile(require.resolve('./pages/overview/alert_table'));
loadTestFile(require.resolve('./exploratory_view'));
loadTestFile(require.resolve('./feature_controls'));
loadTestFile(require.resolve('./pages/rules_page'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default ({ getService }: FtrProviderContext) => {
await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts');
const setup = async () => {
await observability.alerts.common.setKibanaTimeZoneToUTC();
await observability.alerts.common.navigateToTimeWithData();
await observability.alerts.common.navigateWithoutFilter();
};
await setup();
});
Expand Down
Loading

0 comments on commit 5a0313b

Please sign in to comment.