From f3c8b1c09f5cb48cc864bb57c07ec8b52b0194a2 Mon Sep 17 00:00:00 2001 From: shahzad31 Date: Mon, 28 Oct 2024 20:11:50 +0100 Subject: [PATCH] handle large number of monitors --- .../hooks/use_errors_histogram.ts | 117 +++++++++++++----- .../overview_errors/overview_errors.tsx | 39 ++---- .../overview_errors/overview_errors_count.tsx | 31 ----- .../overview_errors_sparklines.tsx | 15 +-- 4 files changed, 103 insertions(+), 99 deletions(-) delete mode 100644 x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_count.tsx diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_errors_histogram.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_errors_histogram.ts index aaf92943a10d4..e2254afa1b77e 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_errors_histogram.ts +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_errors_histogram.ts @@ -7,7 +7,10 @@ import { useSelector } from 'react-redux'; import { useMemo } from 'react'; -import { useEsSearch } from '@kbn/observability-shared-plugin/public'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import { useKibanaSpace } from '../../../../../hooks/use_kibana_space'; +import { useReduxEsSearch } from '../../../hooks/use_redux_es_search'; +import { useGetUrlParams } from '../../../hooks'; import { selectEncryptedSyntheticsSavedMonitors } from '../../../state'; import { EXCLUDE_RUN_ONCE_FILTER, @@ -16,37 +19,76 @@ import { import { useSyntheticsRefreshContext } from '../../../contexts/synthetics_refresh_context'; import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants'; -export const getErrorFilters = () => [ - { - exists: { - field: 'summary', +export const useErrorFilters = (spaceId?: string) => { + const { locations, monitorTypes, tags, query, projects } = useGetUrlParams(); + + const filters: QueryDslQueryContainer[] = [ + { + exists: { + field: 'summary', + }, }, - }, - { - exists: { - field: 'error', + { + term: { + 'meta.space_id': spaceId, + }, }, - }, - EXCLUDE_RUN_ONCE_FILTER, - getRangeFilter({ - from: 'now-24h', - to: 'now', - }), -]; + { + exists: { + field: 'error', + }, + }, + EXCLUDE_RUN_ONCE_FILTER, + getRangeFilter({ + from: 'now-6h', + to: 'now', + }), + + ...(projects && projects.length > 0 ? [{ terms: { 'monitor.project.id': projects } }] : []), + ...(monitorTypes && monitorTypes.length > 0 + ? [{ terms: { 'monitor.type': monitorTypes } }] + : []), + ...(tags && tags.length > 0 ? [{ terms: { tags } }] : []), + ...(locations && locations.length > 0 ? [{ terms: { 'observer.geo.name': locations } }] : []), + ...(query + ? [ + { + query_string: { + query: `${query}*`, + fields: [ + 'monitor.name', + 'tags', + 'observer.geo.name', + 'observer.name', + 'urls', + 'hosts', + 'monitor.project.id', + ], + }, + }, + ] + : []), + ]; + + return filters; +}; export function useErrorsHistogram() { const syntheticsMonitors = useSelector(selectEncryptedSyntheticsSavedMonitors); const { lastRefresh } = useSyntheticsRefreshContext(); + const { space } = useKibanaSpace(); + + const filters = useErrorFilters(space?.id); - const { data } = useEsSearch( + const { data, loading } = useReduxEsSearch( { index: SYNTHETICS_INDEX_PATTERN, body: { size: 0, query: { bool: { - filter: getErrorFilters(), + filter: filters, }, }, sort: { @@ -59,29 +101,48 @@ export function useErrorsHistogram() { date_histogram: { field: '@timestamp', min_doc_count: 0, - fixed_interval: '1h', + fixed_interval: '30m', extended_bounds: { min: 'now-24h', max: 'now', }, }, + aggs: { + errors: { + cardinality: { + field: 'state.id', + }, + }, + }, + }, + totalErrors: { + cardinality: { + field: 'state.id', + }, }, }, }, }, - [syntheticsMonitors, lastRefresh], - { name: 'getMonitorErrors' } + [syntheticsMonitors, lastRefresh, JSON.stringify(filters)], + { name: 'getMonitorErrors', isRequestReady: !!space?.id } ); return useMemo(() => { const histogram = - data?.aggregations?.errorsHistogram.buckets.map((bucket) => ({ - x: bucket.key, - y: bucket.doc_count, - })) ?? []; + data?.aggregations?.errorsHistogram.buckets.map((bucket) => { + const count = bucket.errors.value; + return { + x: bucket.key, + y: count, + }; + }) ?? []; - const totalErrors = histogram.reduce((acc, { y }) => acc + y, 0); + const totalErrors = data?.aggregations?.totalErrors.value ?? 0; - return { histogram, totalErrors }; - }, [data]); + return { histogram, totalErrors, loading }; + }, [ + data?.aggregations?.errorsHistogram?.buckets, + data?.aggregations?.totalErrors?.value, + loading, + ]); } diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors.tsx index aadf2f16297a1..ee98e64d162d1 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors.tsx @@ -12,29 +12,16 @@ import { EuiPanel, EuiSpacer, EuiTitle, + EuiStat, } from '@elastic/eui'; import React from 'react'; -import { useSelector } from 'react-redux'; import { i18n } from '@kbn/i18n'; +import { ERRORS_LABEL } from '../../../../monitor_details/monitor_summary/monitor_errors_count'; import { useErrorsHistogram } from '../../../hooks/use_errors_histogram'; -import { useMonitorQueryIds } from '../overview_alerts'; -import { selectOverviewStatus } from '../../../../../state/overview_status'; import { OverviewErrorsSparklines } from './overview_errors_sparklines'; -import { useRefreshedRange, useGetUrlParams } from '../../../../../hooks'; -import { OverviewErrorsCount } from './overview_errors_count'; export function OverviewErrors() { - const { status } = useSelector(selectOverviewStatus); - - const loading = !status?.allIds || status?.allIds.length === 0; - - const { from, to } = useRefreshedRange(6, 'hours'); - - const { locations } = useGetUrlParams(); - - const monitorIds = useMonitorQueryIds(); - - const { histogram, totalErrors } = useErrorsHistogram(); + const { histogram, totalErrors, loading } = useErrorsHistogram(); return ( @@ -47,22 +34,16 @@ export function OverviewErrors() { ) : ( - - + )} diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_count.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_count.tsx deleted file mode 100644 index ede3ac3a69c5e..0000000000000 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_count.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 React, { useMemo } from 'react'; -import { EuiStat } from '@elastic/eui'; -import { ERRORS_LABEL } from '../../../../monitor_details/monitor_summary/monitor_errors_count'; - -interface MonitorErrorsCountProps { - from: string; - to: string; - locationLabel?: string; - monitorIds: string[]; - locations?: string[]; - totalErrors: number; -} - -export const OverviewErrorsCount = ({ - monitorIds, - from, - to, - locations, - totalErrors, -}: MonitorErrorsCountProps) => { - const time = useMemo(() => ({ from, to }), [from, to]); - - return ; -}; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_sparklines.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_sparklines.tsx index 386fde6fe3aea..062aab4a5de87 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_sparklines.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_errors/overview_errors_sparklines.tsx @@ -6,28 +6,21 @@ */ import { useKibana } from '@kbn/kibana-react-plugin/public'; -import React, { useMemo } from 'react'; +import React from 'react'; import { useEuiTheme, formatDate } from '@elastic/eui'; -import { Axis, BarSeries, Chart, ScaleType, Settings, Position } from '@elastic/charts'; +import { Axis, Chart, ScaleType, Settings, Position, AreaSeries } from '@elastic/charts'; import { ClientPluginsStart } from '../../../../../../../plugin'; import { ERRORS_LABEL } from '../../../../monitor_details/monitor_summary/monitor_errors_count'; interface Props { - from: string; - to: string; - monitorIds: string[]; - locations?: string[]; histogram: Array<{ x: number; y: number }>; } -export const OverviewErrorsSparklines = ({ from, to, monitorIds, locations, histogram }: Props) => { +export const OverviewErrorsSparklines = ({ histogram }: Props) => { const { charts } = useKibana().services; const baseTheme = charts.theme.useChartsBaseTheme(); - const { euiTheme } = useEuiTheme(); - const time = useMemo(() => ({ from, to }), [from, to]); - return ( <> -