From 4c337f3d700913b951c5ebdaa25031259df5352c Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Thu, 18 May 2023 13:29:19 -0400 Subject: [PATCH] synthetics - filters - remove public so client usage --- .../common/constants/synthetics/rest_api.ts | 1 + .../monitor_management/filters.ts | 25 ++++ .../runtime_types/monitor_management/index.ts | 1 + .../common/monitor_filters/filter_button.tsx | 4 +- .../common/monitor_filters/filter_group.tsx | 19 ++- .../common/monitor_filters/use_filters.ts | 132 ++---------------- .../synthetics/state/monitor_list/actions.ts | 9 +- .../apps/synthetics/state/monitor_list/api.ts | 7 +- .../synthetics/state/monitor_list/effects.ts | 16 ++- .../synthetics/state/monitor_list/index.ts | 10 ++ .../state/monitor_list/selectors.ts | 5 + .../state/overview_status/actions.ts | 3 - .../synthetics/state/overview_status/index.ts | 12 +- .../state/overview_status/selectors.ts | 3 - .../apps/synthetics/state/root_effect.ts | 2 + .../server/routes/filters/filters.ts | 124 ++++++++++++++++ .../plugins/synthetics/server/routes/index.ts | 2 + 17 files changed, 224 insertions(+), 151 deletions(-) create mode 100644 x-pack/plugins/synthetics/common/runtime_types/monitor_management/filters.ts create mode 100644 x-pack/plugins/synthetics/server/routes/filters/filters.ts diff --git a/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts b/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts index 51b550066821c9..b148adbe9e67c6 100644 --- a/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts +++ b/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts @@ -22,4 +22,5 @@ export enum SYNTHETICS_API_URLS { NETWORK_EVENTS = `/internal/synthetics/network_events`, JOURNEY_SCREENSHOT = `/internal/synthetics/journey/screenshot/{checkGroup}/{stepIndex}`, DELETE_PACKAGE_POLICY = `/internal/synthetics/monitor/policy/{packagePolicyId}`, + FILTERS = '/internal/synthetics/monitor/filters', } diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/filters.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/filters.ts new file mode 100644 index 00000000000000..0a56f849edac42 --- /dev/null +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/filters.ts @@ -0,0 +1,25 @@ +/* + * 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 * as t from 'io-ts'; + +const MonitorFilterCodec = t.interface({ + label: t.string, + count: t.number, +}); + +export type MonitorFilter = t.TypeOf; + +export const MonitorFiltersResultCodec = t.interface({ + monitorTypes: t.array(MonitorFilterCodec), + tags: t.array(MonitorFilterCodec), + locations: t.array(MonitorFilterCodec), + projects: t.array(MonitorFilterCodec), + schedules: t.array(MonitorFilterCodec), +}); + +export type MonitorFiltersResult = t.TypeOf; diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/index.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/index.ts index b3a06e80062220..7922a423313e1b 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/index.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/index.ts @@ -15,3 +15,4 @@ export * from './locations'; export * from './synthetics_private_locations'; export * from './synthetics_overview_status'; export * from './synthetics_params'; +export * from './filters'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_button.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_button.tsx index bd96ede9a18c0b..506ac1cb3d7187 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_button.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_button.tsx @@ -18,9 +18,11 @@ import { useMonitorFiltersState } from './use_filters'; export const FilterButton = ({ filter, handleFilterChange, + loading, }: { filter: SyntheticsMonitorFilterItem; handleFilterChange: ReturnType['handleFilterChange']; + loading: boolean; }) => { const { label, values, field } = filter; @@ -48,7 +50,7 @@ export const FilterButton = ({ setQuery={setQuery} onChange={(selectedValues) => handleFilterChange(field, selectedValues)} allowExclusions={false} - loading={false} + loading={loading} asFilterButton={true} /> ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_group.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_group.tsx index a59a26613a427a..5faa0d324c1b97 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_group.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/filter_group.tsx @@ -52,7 +52,7 @@ export const FilterGroup = ({ label: TYPE_LABEL, field: 'monitorTypes', values: getSyntheticsFilterDisplayValues( - mixUrlValues(data.monitorTypes, urlParams.monitorTypes), + mixUrlValues(data?.monitorTypes, urlParams.monitorTypes), 'monitorTypes', locations ), @@ -62,7 +62,7 @@ export const FilterGroup = ({ field: 'locations', values: getSyntheticsFilterDisplayValues( mixUrlValues( - data.locations.map((locationData) => { + data?.locations.map((locationData) => { const matchingLocation = locations.find( (location) => location.id === locationData.label ); @@ -81,7 +81,7 @@ export const FilterGroup = ({ label: TAGS_LABEL, field: 'tags', values: getSyntheticsFilterDisplayValues( - mixUrlValues(data.tags, urlParams.tags), + mixUrlValues(data?.tags, urlParams.tags), 'tags', locations ), @@ -90,19 +90,19 @@ export const FilterGroup = ({ label: SCHEDULE_LABEL, field: 'schedules', values: getSyntheticsFilterDisplayValues( - mixUrlValues(data.schedules, urlParams.schedules), + mixUrlValues(data?.schedules, urlParams.schedules), 'schedules', locations ), }, ]; - if (data.projects.length > 0) { + if ((data?.projects?.length || 0) > 0) { filters.push({ label: PROJECT_LABEL, field: 'projects', values: getSyntheticsFilterDisplayValues( - mixUrlValues(data.projects, urlParams.projects), + mixUrlValues(data?.projects, urlParams.projects), 'projects', locations ), @@ -112,7 +112,12 @@ export const FilterGroup = ({ return ( {filters.map((filter, index) => ( - + ))} ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.ts index d6f9f93eeda2f5..333ccf62e15324 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.ts @@ -7,18 +7,17 @@ import { useMemo, useEffect, useCallback, useRef } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { useFetcher } from '@kbn/observability-shared-plugin/public'; -import { selectFiltersData, setListOfFiltersActions } from '../../../../state/overview_status'; -import { ConfigKey } from '../../../../../../../common/runtime_types'; -import { syntheticsMonitorType } from '../../../../../../../common/types/saved_objects'; +import { MonitorFiltersResult } from '../../../../../../../common/runtime_types'; import { MonitorFilterState, selectMonitorFiltersAndQueryState, setOverviewPageStateAction, updateManagementPageStateAction, + fetchMonitorFiltersAction, + selectMonitorFilterOptions, } from '../../../../state'; +import { useSyntheticsRefreshContext } from '../../../../contexts'; import { SyntheticsUrlParams } from '../../../../utils/url_params'; import { useUrlParams } from '../../../../hooks'; import { @@ -28,127 +27,16 @@ import { SyntheticsMonitorFilterField, } from './filter_fields'; -const aggs = { - monitorTypes: { - terms: { - field: `${syntheticsMonitorType}.attributes.${ConfigKey.MONITOR_TYPE}.keyword`, - size: 10000, - }, - }, - tags: { - terms: { - field: `${syntheticsMonitorType}.attributes.${ConfigKey.TAGS}`, - size: 10000, - }, - }, - locations: { - terms: { - field: `${syntheticsMonitorType}.attributes.${ConfigKey.LOCATIONS}.id`, - size: 10000, - }, - }, - projects: { - terms: { - field: `${syntheticsMonitorType}.attributes.${ConfigKey.PROJECT_ID}`, - size: 10000, - }, - }, - schedules: { - terms: { - field: `${syntheticsMonitorType}.attributes.${ConfigKey.SCHEDULE}.number`, - size: 10000, - }, - }, -}; - -type Buckets = Array<{ - key: string; - doc_count: number; -}>; - -interface AggsResponse { - monitorTypes: { - buckets: Buckets; - }; - locations: { - buckets: Buckets; - }; - tags: { - buckets: Buckets; - }; - projects: { - buckets: Buckets; - }; - schedules: { - buckets: Buckets; - }; -} - -export type FiltersList = Record< - SyntheticsMonitorFilterField, - Array<{ label: string; count: number }> ->; - -export const useFilters = (): FiltersList => { - const { savedObjects } = useKibana().services; - - const { data } = useFetcher(async () => { - return savedObjects?.client.find({ - type: syntheticsMonitorType, - perPage: 0, - aggs, - }); - }, []); - - const filtersData = useSelector(selectFiltersData); - +export const useFilters = (): MonitorFiltersResult | null => { const dispatch = useDispatch(); - - const newFiltersData = useMemo(() => { - const { monitorTypes, tags, locations, projects, schedules } = - (data?.aggregations as AggsResponse) ?? {}; - return { - monitorTypes: - monitorTypes?.buckets?.map(({ key, doc_count: count }) => ({ - label: key, - count, - })) ?? [], - tags: - tags?.buckets?.map(({ key, doc_count: count }) => ({ - label: key, - count, - })) ?? [], - locations: - locations?.buckets?.map(({ key, doc_count: count }) => ({ - label: key, - count, - })) ?? [], - projects: - projects?.buckets - ?.filter(({ key }) => key) - .map(({ key, doc_count: count }) => ({ - label: key, - count, - })) ?? [], - schedules: - schedules?.buckets?.map(({ key, doc_count: count }) => ({ - label: String(key), - count, - })) ?? [], - }; - }, [data]); + const filtersData = useSelector(selectMonitorFilterOptions); + const { lastRefresh } = useSyntheticsRefreshContext(); useEffect(() => { - if (data) { - dispatch(setListOfFiltersActions(newFiltersData)); - } - }, [data, dispatch, newFiltersData]); - - if (!data && filtersData) { - return filtersData; - } + dispatch(fetchMonitorFiltersAction.get()); + }, [lastRefresh, dispatch]); - return newFiltersData; + return filtersData; }; type FilterFieldWithQuery = SyntheticsMonitorFilterField | 'query'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/actions.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/actions.ts index 928361a3bd52de..67d7febba9fc3c 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/actions.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/actions.ts @@ -7,7 +7,10 @@ import { createAction } from '@reduxjs/toolkit'; import { UpsertMonitorError, UpsertMonitorRequest, UpsertMonitorResponse } from '..'; -import { MonitorManagementListResult } from '../../../../../common/runtime_types'; +import { + MonitorManagementListResult, + MonitorFiltersResult, +} from '../../../../../common/runtime_types'; import { createAsyncAction } from '../utils/actions'; import { MonitorListPageState } from './models'; @@ -42,3 +45,7 @@ export const updateManagementPageStateAction = createAction( + 'fetchMonitorFiltersAction' +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/api.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/api.ts index 9d1f7c21f56963..d92d26ce47ad8e 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/api.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/api.ts @@ -7,7 +7,7 @@ import { SavedObject } from '@kbn/core-saved-objects-common'; import { UpsertMonitorRequest } from '..'; -import { API_URLS } from '../../../../../common/constants'; +import { API_URLS, SYNTHETICS_API_URLS } from '../../../../../common/constants'; import { EncryptedSyntheticsMonitor, FetchMonitorManagementListQueryArgs, @@ -15,6 +15,7 @@ import { MonitorManagementListResultCodec, ServiceLocationErrors, SyntheticsMonitor, + MonitorFiltersResult, } from '../../../../../common/runtime_types'; import { apiService } from '../../../../utils/api_service'; @@ -76,3 +77,7 @@ export const fetchCreateMonitor = async ({ }): Promise<{ attributes: { errors: ServiceLocationErrors } } | SyntheticsMonitor> => { return await apiService.post(API_URLS.SYNTHETICS_MONITORS, monitor); }; + +export const fetchMonitorFilters = async (): Promise => { + return await apiService.get(SYNTHETICS_API_URLS.FILTERS); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/effects.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/effects.ts index def068c7db03a3..60affc55b88659 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/effects.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/effects.ts @@ -6,7 +6,7 @@ */ import { PayloadAction } from '@reduxjs/toolkit'; -import { call, put, takeEvery, select, debounce } from 'redux-saga/effects'; +import { call, put, takeEvery, select, takeLatest, debounce } from 'redux-saga/effects'; import { SavedObject } from '@kbn/core-saved-objects-common'; import { quietFetchOverviewStatusAction } from '../overview_status'; import { enableDefaultAlertingAction } from '../alert_rules'; @@ -25,8 +25,9 @@ import { fetchUpsertMonitorAction, fetchUpsertSuccessAction, quietFetchMonitorListAction, + fetchMonitorFiltersAction, } from './actions'; -import { fetchMonitorManagementList, fetchUpsertMonitor } from './api'; +import { fetchMonitorManagementList, fetchUpsertMonitor, fetchMonitorFilters } from './api'; import { toastTitle } from './toast_title'; import { UpsertMonitorRequest } from './models'; @@ -117,3 +118,14 @@ export function* upsertMonitorEffect() { function hasPageState(value: any): value is { pageState: MonitorOverviewPageState } { return Object.keys(value).includes('pageState'); } + +export function* fetchMonitorFiltersEffect() { + yield takeLatest( + fetchMonitorFiltersAction.get, + fetchEffectFactory( + fetchMonitorFilters, + fetchMonitorFiltersAction.success, + fetchMonitorFiltersAction.fail + ) + ); +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/index.ts index a78c9f48f30578..bd13e3006c7902 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/index.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/index.ts @@ -13,6 +13,7 @@ import { ConfigKey, MonitorManagementListResult, SyntheticsMonitor, + MonitorFiltersResult, } from '../../../../../common/runtime_types'; import { IHttpSerializedFetchError } from '../utils/http_error'; @@ -27,6 +28,7 @@ import { fetchUpsertMonitorAction, fetchUpsertSuccessAction, updateManagementPageStateAction, + fetchMonitorFiltersAction, } from './actions'; export interface MonitorListState { @@ -39,6 +41,7 @@ export interface MonitorListState { loading: boolean; loaded: boolean; error: IHttpSerializedFetchError | null; + monitorFilterOptions: MonitorFiltersResult | null; } const initialState: MonitorListState = { @@ -53,6 +56,7 @@ const initialState: MonitorListState = { loading: false, loaded: false, error: null, + monitorFilterOptions: null, }; export const monitorListReducer = createReducer(initialState, (builder) => { @@ -120,6 +124,12 @@ export const monitorListReducer = createReducer(initialState, (builder) => { }) .addCase(cleanMonitorListState, (state) => { return { ...initialState, pageState: state.pageState }; + }) + .addCase(fetchMonitorFiltersAction.success, (state, action) => { + state.monitorFilterOptions = action.payload; + }) + .addCase(fetchMonitorFiltersAction.fail, (state, action) => { + state.error = action.payload; }); }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/selectors.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/selectors.ts index 4f1b26dec51424..eca1cf7f59cdf2 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/selectors.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_list/selectors.ts @@ -36,3 +36,8 @@ export const selectMonitorUpsertStatuses = (state: SyntheticsAppState) => export const selectMonitorUpsertStatus = (configId: string) => (state: SyntheticsAppState) => state.monitorList.monitorUpsertStatuses?.[configId] ?? null; + +export const selectMonitorFilterOptions = createSelector( + selectMonitorListState, + (state) => state.monitorFilterOptions +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/actions.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/actions.ts index 0ca6e0c308f416..1e8f9e019098cd 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/actions.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/actions.ts @@ -5,7 +5,6 @@ * 2.0. */ import { createAction } from '@reduxjs/toolkit'; -import { FiltersList } from '../../components/monitors_page/common/monitor_filters/use_filters'; import { MonitorOverviewPageState } from '..'; import { createAsyncAction } from '../utils/actions'; @@ -21,6 +20,4 @@ export const quietFetchOverviewStatusAction = createAsyncAction< OverviewStatus >('quietFetchOverviewStatusAction'); -export const setListOfFiltersActions = createAction('setListOfFiltersActions'); - export const clearOverviewStatusErrorAction = createAction('clearOverviewStatusErrorAction'); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/index.ts index a5140e499205bc..5125e723f13db6 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/index.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/index.ts @@ -7,21 +7,15 @@ import { createReducer } from '@reduxjs/toolkit'; -import { FiltersList } from '../../components/monitors_page/common/monitor_filters/use_filters'; import { OverviewStatusState } from '../../../../../common/runtime_types'; import { IHttpSerializedFetchError } from '..'; -import { - clearOverviewStatusErrorAction, - fetchOverviewStatusAction, - setListOfFiltersActions, -} from './actions'; +import { clearOverviewStatusErrorAction, fetchOverviewStatusAction } from './actions'; export interface OverviewStatusStateReducer { loading: boolean; loaded: boolean; status: OverviewStatusState | null; error: IHttpSerializedFetchError | null; - filtersData?: FiltersList | null; } const initialState: OverviewStatusStateReducer = { @@ -29,7 +23,6 @@ const initialState: OverviewStatusStateReducer = { loaded: false, status: null, error: null, - filtersData: null, }; export const overviewStatusReducer = createReducer(initialState, (builder) => { @@ -47,9 +40,6 @@ export const overviewStatusReducer = createReducer(initialState, (builder) => { .addCase(fetchOverviewStatusAction.fail, (state, action) => { state.error = action.payload; }) - .addCase(setListOfFiltersActions, (state, action) => { - state.filtersData = action.payload; - }) .addCase(clearOverviewStatusErrorAction, (state) => { state.error = null; }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/selectors.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/selectors.ts index 00778674d9c4bc..07745420b86c80 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/selectors.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/overview_status/selectors.ts @@ -10,6 +10,3 @@ import { SyntheticsAppState } from '../root_reducer'; export const selectOverviewStatus = ({ overviewStatus: { status, error, loaded }, }: SyntheticsAppState) => ({ status, error, loaded }); - -export const selectFiltersData = ({ overviewStatus: { filtersData } }: SyntheticsAppState) => - filtersData; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts index 98bac242a12a4f..3e3b6407b2080f 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts @@ -24,6 +24,7 @@ import { enableMonitorAlertEffect, fetchMonitorListEffect, upsertMonitorEffect, + fetchMonitorFiltersEffect, } from './monitor_list'; import { fetchMonitorOverviewEffect } from './overview'; import { fetchServiceLocationsEffect } from './service_locations'; @@ -35,6 +36,7 @@ export const rootEffect = function* root(): Generator { yield all([ fork(fetchSyntheticsEnablementEffect), fork(upsertMonitorEffect), + fork(fetchMonitorFiltersEffect), fork(fetchServiceLocationsEffect), fork(fetchMonitorListEffect), fork(fetchSyntheticsMonitorEffect), diff --git a/x-pack/plugins/synthetics/server/routes/filters/filters.ts b/x-pack/plugins/synthetics/server/routes/filters/filters.ts new file mode 100644 index 00000000000000..cf44c18b317764 --- /dev/null +++ b/x-pack/plugins/synthetics/server/routes/filters/filters.ts @@ -0,0 +1,124 @@ +/* + * 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 { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; +import { syntheticsMonitorType } from '../../../common/types/saved_objects'; +import { ConfigKey } from '../../../common/runtime_types'; +import { SYNTHETICS_API_URLS } from '../../../common/constants'; +import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types'; + +type Buckets = Array<{ + key: string; + doc_count: number; +}>; + +interface AggsResponse { + monitorTypes: { + buckets: Buckets; + }; + locations: { + buckets: Buckets; + }; + tags: { + buckets: Buckets; + }; + projects: { + buckets: Buckets; + }; + schedules: { + buckets: Buckets; + }; +} + +export const getSyntheticsFilters: SyntheticsRestApiRouteFactory = () => ({ + method: 'GET', + path: SYNTHETICS_API_URLS.FILTERS, + validate: {}, + handler: async ({ savedObjectsClient, request, response, server }): Promise => { + try { + await server.spaces?.spacesService.getActiveSpace(request); + + const data = await savedObjectsClient.find({ + type: syntheticsMonitorType, + perPage: 0, + aggs, + }); + + const { monitorTypes, tags, locations, projects, schedules } = + (data?.aggregations as AggsResponse) ?? {}; + const result = { + monitorTypes: + monitorTypes?.buckets?.map(({ key, doc_count: count }) => ({ + label: key, + count, + })) ?? [], + tags: + tags?.buckets?.map(({ key, doc_count: count }) => ({ + label: key, + count, + })) ?? [], + locations: + locations?.buckets?.map(({ key, doc_count: count }) => ({ + label: key, + count, + })) ?? [], + projects: + projects?.buckets + ?.filter(({ key }) => key) + .map(({ key, doc_count: count }) => ({ + label: key, + count, + })) ?? [], + schedules: + schedules?.buckets?.map(({ key, doc_count: count }) => ({ + label: String(key), + count, + })) ?? [], + }; + return result; + } catch (error) { + if (error.output?.statusCode === 404) { + const spaceId = server.spaces?.spacesService.getSpaceId(request) ?? DEFAULT_SPACE_ID; + return response.notFound({ body: { message: `Kibana space '${spaceId}' does not exist` } }); + } + + throw error; + } + }, +}); + +const aggs = { + monitorTypes: { + terms: { + field: `${syntheticsMonitorType}.attributes.${ConfigKey.MONITOR_TYPE}.keyword`, + size: 10000, + }, + }, + tags: { + terms: { + field: `${syntheticsMonitorType}.attributes.${ConfigKey.TAGS}`, + size: 10000, + }, + }, + locations: { + terms: { + field: `${syntheticsMonitorType}.attributes.${ConfigKey.LOCATIONS}.id`, + size: 10000, + }, + }, + projects: { + terms: { + field: `${syntheticsMonitorType}.attributes.${ConfigKey.PROJECT_ID}`, + size: 10000, + }, + }, + schedules: { + terms: { + field: `${syntheticsMonitorType}.attributes.${ConfigKey.SCHEDULE}.number`, + size: 10000, + }, + }, +}; diff --git a/x-pack/plugins/synthetics/server/routes/index.ts b/x-pack/plugins/synthetics/server/routes/index.ts index 836143d55f014e..d68a277517a0df 100644 --- a/x-pack/plugins/synthetics/server/routes/index.ts +++ b/x-pack/plugins/synthetics/server/routes/index.ts @@ -51,6 +51,7 @@ import { createNetworkEventsRoute } from './network_events'; import { addPrivateLocationRoute } from './settings/private_locations/add_private_location'; import { deletePrivateLocationRoute } from './settings/private_locations/delete_private_location'; import { getPrivateLocationsRoute } from './settings/private_locations/get_private_locations'; +import { getSyntheticsFilters } from './filters/filters'; export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [ addSyntheticsMonitorRoute, @@ -92,6 +93,7 @@ export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [ addPrivateLocationRoute, deletePrivateLocationRoute, getPrivateLocationsRoute, + getSyntheticsFilters, ]; export const syntheticsAppStreamingApiRoutes: SyntheticsStreamingRouteFactory[] = [