From 1a1cfc65e6b2e95d91179be8813456596a45834b Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Mon, 30 Jan 2023 11:54:28 +0100 Subject: [PATCH] [AO] Add alert summary widget to overview page (#149581) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #138887 ## ๐Ÿ“ Summary This PR adds the Alert Summary Widget to the overview page. ![image](https://user-images.githubusercontent.com/12370520/215071851-5d48d80a-401e-49fa-8c6e-7a4ca33850a6.png) ## ๐Ÿงช How to test Generate alerts and check the Alert Summary Widget component on the overview page. ## ๐Ÿž Kown issues - The loading state will be covered in a separate ticket: https://github.com/elastic/kibana/issues/149237 - At start, when there is no rule, the Alert Summary Widget shows an error that will be fixed in this ticket: https://github.com/elastic/kibana/issues/148653 --------- Co-authored-by: Katrin Freihofner --- .../public/hooks/use_time_buckets.ts | 23 ++++++++ .../containers/alerts_page/alerts_page.tsx | 12 +--- .../containers/overview_page/helpers/index.ts | 1 + .../overview_page/overview_page.tsx | 58 ++++++++++++++----- .../public/pages/rule_details/index.tsx | 2 +- .../get_alert_summary_time_range.test.tsx | 0 .../get_alert_summary_time_range.tsx | 6 +- .../alert_summary_widget}/index.ts | 0 8 files changed, 75 insertions(+), 27 deletions(-) create mode 100644 x-pack/plugins/observability/public/hooks/use_time_buckets.ts rename x-pack/plugins/observability/public/{pages/rule_details/helpers => utils/alert_summary_widget}/get_alert_summary_time_range.test.tsx (100%) rename x-pack/plugins/observability/public/{pages/rule_details/helpers => utils/alert_summary_widget}/get_alert_summary_time_range.tsx (89%) rename x-pack/plugins/observability/public/{pages/rule_details/helpers => utils/alert_summary_widget}/index.ts (100%) diff --git a/x-pack/plugins/observability/public/hooks/use_time_buckets.ts b/x-pack/plugins/observability/public/hooks/use_time_buckets.ts new file mode 100644 index 000000000000..1dc6a635f259 --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/use_time_buckets.ts @@ -0,0 +1,23 @@ +/* + * 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 { useMemo } from 'react'; +import { TimeBuckets, UI_SETTINGS } from '@kbn/data-plugin/common'; +import { useKibana } from '../utils/kibana_react'; + +export const useTimeBuckets = () => { + const { uiSettings } = useKibana().services; + + return useMemo(() => { + return new TimeBuckets({ + 'histogram:maxBars': uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS), + 'histogram:barTarget': uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET), + dateFormat: uiSettings.get('dateFormat'), + 'dateFormat:scaled': uiSettings.get('dateFormat:scaled'), + }); + }, [uiSettings]); +}; diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx index 3cb7fcc64996..1d68fa947f9c 100644 --- a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx @@ -7,7 +7,6 @@ import React, { useEffect, useState } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { TimeBuckets, UI_SETTINGS } from '@kbn/data-plugin/common'; import { BoolQuery } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { useKibana } from '@kbn/kibana-react-plugin/public'; @@ -22,7 +21,6 @@ import { Provider, useAlertSearchBarStateContainer, } from '../../../../components/shared/alert_search_bar/containers'; -import { getAlertSummaryTimeRange } from '../../../rule_details/helpers'; import { ObservabilityAlertSearchBar } from '../../../../components/shared/alert_search_bar'; import { observabilityAlertFeatureIds } from '../../../../config'; import { useGetUserCasesPermissions } from '../../../../hooks/use_get_user_cases_permissions'; @@ -30,7 +28,9 @@ import { observabilityFeatureId } from '../../../../../common'; import { useBreadcrumbs } from '../../../../hooks/use_breadcrumbs'; import { useHasData } from '../../../../hooks/use_has_data'; import { usePluginContext } from '../../../../hooks/use_plugin_context'; +import { useTimeBuckets } from '../../../../hooks/use_time_buckets'; import { getNoDataConfig } from '../../../../utils/no_data_config'; +import { getAlertSummaryTimeRange } from '../../../../utils/alert_summary_widget'; import { LoadingObservability } from '../../../overview'; import './styles.scss'; import { renderRuleStats } from '../../components/rule_stats'; @@ -62,7 +62,6 @@ function InternalAlertsPage() { getAlertsStateTable: AlertsStateTable, getAlertSummaryWidget: AlertSummaryWidget, }, - uiSettings, } = useKibana().services; const alertSearchBarStateProps = useAlertSearchBarStateContainer(URL_STORAGE_KEY); @@ -80,12 +79,7 @@ function InternalAlertsPage() { }); const { hasAnyData, isAllRequestsComplete } = useHasData(); const [esQuery, setEsQuery] = useState<{ bool: BoolQuery }>(); - const timeBuckets = new TimeBuckets({ - 'histogram:maxBars': uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS), - 'histogram:barTarget': uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET), - dateFormat: uiSettings.get('dateFormat'), - 'dateFormat:scaled': uiSettings.get('dateFormat:scaled'), - }); + const timeBuckets = useTimeBuckets(); const alertSummaryTimeRange: AlertSummaryTimeRange = getAlertSummaryTimeRange( { from: alertSearchBarStateProps.rangeFrom, diff --git a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/index.ts b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/index.ts index 565f52674214..1f0a06b802da 100644 --- a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/index.ts +++ b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/index.ts @@ -6,3 +6,4 @@ */ export { calculateBucketSize } from './calculate_bucket_size'; +export { useOverviewMetrics } from './use_metrics'; diff --git a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/overview_page.tsx b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/overview_page.tsx index 0627fc364561..fe2e08d26760 100644 --- a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/overview_page.tsx +++ b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/overview_page.tsx @@ -10,12 +10,10 @@ import { BoolQuery } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { AlertConsumers } from '@kbn/rule-data-utils'; -import React, { useMemo, useRef, useCallback, useState } from 'react'; - -import { calculateBucketSize } from './helpers'; -import { buildEsQuery } from '../../../../utils/build_es_query'; -import { getNewsFeed } from '../../../../services/get_news_feed'; +import React, { useEffect, useMemo, useCallback, useState } from 'react'; +import { observabilityFeatureId } from '../../../../../common'; +import type { ObservabilityAppServices } from '../../../../application/types'; import { DataSections, LoadingObservability, @@ -28,29 +26,34 @@ import { Resources } from '../../../../components/app/resources'; import { NewsFeed } from '../../../../components/app/news_feed'; import { SectionContainer } from '../../../../components/app/section'; import { ObservabilityStatusProgress } from '../../../../components/app/observability_status/observability_status_progress'; - +import { observabilityAlertFeatureIds, paths } from '../../../../config'; import { useBreadcrumbs } from '../../../../hooks/use_breadcrumbs'; import { useDatePickerContext } from '../../../../hooks/use_date_picker_context'; import { useFetcher } from '../../../../hooks/use_fetcher'; import { useGetUserCasesPermissions } from '../../../../hooks/use_get_user_cases_permissions'; import { useGuidedSetupProgress } from '../../../../hooks/use_guided_setup_progress'; import { useHasData } from '../../../../hooks/use_has_data'; -import { useOverviewMetrics } from './helpers/use_metrics'; import { usePluginContext } from '../../../../hooks/use_plugin_context'; +import { useTimeBuckets } from '../../../../hooks/use_time_buckets'; +import { getNewsFeed } from '../../../../services/get_news_feed'; +import { buildEsQuery } from '../../../../utils/build_es_query'; +import { getAlertSummaryTimeRange } from '../../../../utils/alert_summary_widget'; -import { observabilityFeatureId } from '../../../../../common'; -import { observabilityAlertFeatureIds, paths } from '../../../../config'; import { ALERTS_PER_PAGE, ALERTS_TABLE_ID } from './constants'; - -import type { ObservabilityAppServices } from '../../../../application/types'; +import { calculateBucketSize, useOverviewMetrics } from './helpers'; export function OverviewPage() { const { cases: { ui: { getCasesContext }, }, + charts, http, - triggersActionsUi: { alertsTableConfigurationRegistry, getAlertsStateTable: AlertsStateTable }, + triggersActionsUi: { + alertsTableConfigurationRegistry, + getAlertsStateTable: AlertsStateTable, + getAlertSummaryWidget: AlertSummaryWidget, + }, } = useKibana().services; const { ObservabilityPageTemplate } = usePluginContext(); @@ -65,7 +68,6 @@ export function OverviewPage() { const { data: newsFeed } = useFetcher(() => getNewsFeed({ http }), [http]); const { hasAnyData, isAllRequestsComplete } = useHasData(); - const refetch = useRef<() => void>(); const { trackMetric } = useOverviewMetrics({ hasAnyData }); @@ -85,6 +87,19 @@ export function OverviewPage() { to: relativeEnd, }) ); + const timeBuckets = useTimeBuckets(); + const alertSummaryTimeRange = getAlertSummaryTimeRange( + { + from: relativeStart, + to: relativeEnd, + }, + timeBuckets + ); + + const chartThemes = { + theme: charts.theme.useChartsTheme(), + baseTheme: charts.theme.useChartsBaseTheme(), + }; const bucketSize = useMemo( () => @@ -95,6 +110,15 @@ export function OverviewPage() { [absoluteStart, absoluteEnd] ); + useEffect(() => { + setEsQuery( + buildEsQuery({ + from: relativeStart, + to: relativeEnd, + }) + ); + }, [relativeEnd, relativeStart]); + const handleTimeRangeRefresh = useCallback(() => { setEsQuery( buildEsQuery({ @@ -102,7 +126,6 @@ export function OverviewPage() { to: relativeEnd, }) ); - return refetch.current && refetch.current(); }, [relativeEnd, relativeStart]); const handleCloseGuidedSetupTour = () => { @@ -170,6 +193,13 @@ export function OverviewPage() { permissions={userCasesPermissions} features={{ alerts: { sync: false } }} > + { const { to, from } = getAbsoluteTimeRange({ @@ -48,7 +48,7 @@ export const getAlertSummaryTimeRange = ( }; }; -const getFixedInterval = ({ to, from }: TimeRange) => { +const getFixedInterval = ({ from, to }: TimeRange) => { const start = getAbsoluteTime(from); const end = getAbsoluteTime(to, { roundUp: true }); diff --git a/x-pack/plugins/observability/public/pages/rule_details/helpers/index.ts b/x-pack/plugins/observability/public/utils/alert_summary_widget/index.ts similarity index 100% rename from x-pack/plugins/observability/public/pages/rule_details/helpers/index.ts rename to x-pack/plugins/observability/public/utils/alert_summary_widget/index.ts