From 1841495322d4abe63c3985e9c7456bda01652292 Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Thu, 1 Oct 2020 18:54:46 -0500 Subject: [PATCH 01/21] [Metrics UI] Override anomaly detection partition field (#79214) * Add ability to override datafeeds and job config for partition field * Remove debug * UX cleanup * Fix types, delete dead code * Fix types --- .../containers/ml/infra_ml_module_types.ts | 4 +- .../containers/ml/infra_ml_setup_state.ts | 289 ------------------ .../metrics_hosts/module_descriptor.ts | 135 +++++--- .../modules/metrics_k8s/module_descriptor.ts | 143 ++++++--- .../anomoly_detection_flyout.tsx | 4 +- .../ml/anomaly_detection/flyout_home.tsx | 113 +++---- .../ml/anomaly_detection/job_setup_screen.tsx | 3 +- 7 files changed, 247 insertions(+), 444 deletions(-) delete mode 100644 x-pack/plugins/infra/public/containers/ml/infra_ml_setup_state.ts diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_module_types.ts b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_types.ts index a9f2671de82598..e36f38add641aa 100644 --- a/x-pack/plugins/infra/public/containers/ml/infra_ml_module_types.ts +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_types.ts @@ -33,11 +33,11 @@ export interface ModuleDescriptor { partitionField?: string ) => Promise; cleanUpModule: (spaceId: string, sourceId: string) => Promise; - validateSetupIndices: ( + validateSetupIndices?: ( indices: string[], timestampField: string ) => Promise; - validateSetupDatasets: ( + validateSetupDatasets?: ( indices: string[], timestampField: string, startTime: number, diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_setup_state.ts b/x-pack/plugins/infra/public/containers/ml/infra_ml_setup_state.ts deleted file mode 100644 index 0dfe3b301f2400..00000000000000 --- a/x-pack/plugins/infra/public/containers/ml/infra_ml_setup_state.ts +++ /dev/null @@ -1,289 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { isEqual } from 'lodash'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { usePrevious } from 'react-use'; -import { - combineDatasetFilters, - DatasetFilter, - filterDatasetFilter, - isExampleDataIndex, -} from '../../../common/infra_ml'; -import { - AvailableIndex, - ValidationIndicesError, - ValidationUIError, -} from '../../components/logging/log_analysis_setup/initial_configuration_step'; -import { useTrackedPromise } from '../../utils/use_tracked_promise'; -import { ModuleDescriptor, ModuleSourceConfiguration } from './infra_ml_module_types'; - -type SetupHandler = ( - indices: string[], - startTime: number | undefined, - endTime: number | undefined, - datasetFilter: DatasetFilter -) => void; - -interface AnalysisSetupStateArguments { - cleanUpAndSetUpModule: SetupHandler; - moduleDescriptor: ModuleDescriptor; - setUpModule: SetupHandler; - sourceConfiguration: ModuleSourceConfiguration; -} - -const fourWeeksInMs = 86400000 * 7 * 4; - -export const useAnalysisSetupState = ({ - cleanUpAndSetUpModule, - moduleDescriptor: { validateSetupDatasets, validateSetupIndices }, - setUpModule, - sourceConfiguration, -}: AnalysisSetupStateArguments) => { - const [startTime, setStartTime] = useState(Date.now() - fourWeeksInMs); - const [endTime, setEndTime] = useState(undefined); - - const isTimeRangeValid = useMemo( - () => (startTime != null && endTime != null ? startTime < endTime : true), - [endTime, startTime] - ); - - const [validatedIndices, setValidatedIndices] = useState( - sourceConfiguration.indices.map((indexName) => ({ - name: indexName, - validity: 'unknown' as const, - })) - ); - - const updateIndicesWithValidationErrors = useCallback( - (validationErrors: ValidationIndicesError[]) => - setValidatedIndices((availableIndices) => - availableIndices.map((previousAvailableIndex) => { - const indexValiationErrors = validationErrors.filter( - ({ index }) => index === previousAvailableIndex.name - ); - - if (indexValiationErrors.length > 0) { - return { - validity: 'invalid', - name: previousAvailableIndex.name, - errors: indexValiationErrors, - }; - } else if (previousAvailableIndex.validity === 'valid') { - return { - ...previousAvailableIndex, - validity: 'valid', - errors: [], - }; - } else { - return { - validity: 'valid', - name: previousAvailableIndex.name, - isSelected: !isExampleDataIndex(previousAvailableIndex.name), - availableDatasets: [], - datasetFilter: { - type: 'includeAll' as const, - }, - }; - } - }) - ), - [] - ); - - const updateIndicesWithAvailableDatasets = useCallback( - (availableDatasets: Array<{ indexName: string; datasets: string[] }>) => - setValidatedIndices((availableIndices) => - availableIndices.map((previousAvailableIndex) => { - if (previousAvailableIndex.validity !== 'valid') { - return previousAvailableIndex; - } - - const availableDatasetsForIndex = availableDatasets.filter( - ({ indexName }) => indexName === previousAvailableIndex.name - ); - const newAvailableDatasets = availableDatasetsForIndex.flatMap( - ({ datasets }) => datasets - ); - - // filter out datasets that have disappeared if this index' datasets were updated - const newDatasetFilter: DatasetFilter = - availableDatasetsForIndex.length > 0 - ? filterDatasetFilter(previousAvailableIndex.datasetFilter, (dataset) => - newAvailableDatasets.includes(dataset) - ) - : previousAvailableIndex.datasetFilter; - - return { - ...previousAvailableIndex, - availableDatasets: newAvailableDatasets, - datasetFilter: newDatasetFilter, - }; - }) - ), - [] - ); - - const validIndexNames = useMemo( - () => validatedIndices.filter((index) => index.validity === 'valid').map((index) => index.name), - [validatedIndices] - ); - - const selectedIndexNames = useMemo( - () => - validatedIndices - .filter((index) => index.validity === 'valid' && index.isSelected) - .map((i) => i.name), - [validatedIndices] - ); - - const datasetFilter = useMemo( - () => - validatedIndices - .flatMap((validatedIndex) => - validatedIndex.validity === 'valid' - ? validatedIndex.datasetFilter - : { type: 'includeAll' as const } - ) - .reduce(combineDatasetFilters, { type: 'includeAll' as const }), - [validatedIndices] - ); - - const [validateIndicesRequest, validateIndices] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - return await validateSetupIndices( - sourceConfiguration.indices, - sourceConfiguration.timestampField - ); - }, - onResolve: ({ data: { errors } }) => { - updateIndicesWithValidationErrors(errors); - }, - onReject: () => { - setValidatedIndices([]); - }, - }, - [sourceConfiguration.indices, sourceConfiguration.timestampField] - ); - - const [validateDatasetsRequest, validateDatasets] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - if (validIndexNames.length === 0) { - return { data: { datasets: [] } }; - } - - return await validateSetupDatasets( - validIndexNames, - sourceConfiguration.timestampField, - startTime ?? 0, - endTime ?? Date.now() - ); - }, - onResolve: ({ data: { datasets } }) => { - updateIndicesWithAvailableDatasets(datasets); - }, - }, - [validIndexNames, sourceConfiguration.timestampField, startTime, endTime] - ); - - const setUp = useCallback(() => { - return setUpModule(selectedIndexNames, startTime, endTime, datasetFilter); - }, [setUpModule, selectedIndexNames, startTime, endTime, datasetFilter]); - - const cleanUpAndSetUp = useCallback(() => { - return cleanUpAndSetUpModule(selectedIndexNames, startTime, endTime, datasetFilter); - }, [cleanUpAndSetUpModule, selectedIndexNames, startTime, endTime, datasetFilter]); - - const isValidating = useMemo( - () => validateIndicesRequest.state === 'pending' || validateDatasetsRequest.state === 'pending', - [validateDatasetsRequest.state, validateIndicesRequest.state] - ); - - const validationErrors = useMemo(() => { - if (isValidating) { - return []; - } - - return [ - // validate request status - ...(validateIndicesRequest.state === 'rejected' || - validateDatasetsRequest.state === 'rejected' - ? [{ error: 'NETWORK_ERROR' as const }] - : []), - // validation request results - ...validatedIndices.reduce((errors, index) => { - return index.validity === 'invalid' && selectedIndexNames.includes(index.name) - ? [...errors, ...index.errors] - : errors; - }, []), - // index count - ...(selectedIndexNames.length === 0 ? [{ error: 'TOO_FEW_SELECTED_INDICES' as const }] : []), - // time range - ...(!isTimeRangeValid ? [{ error: 'INVALID_TIME_RANGE' as const }] : []), - ]; - }, [ - isValidating, - validateIndicesRequest.state, - validateDatasetsRequest.state, - validatedIndices, - selectedIndexNames, - isTimeRangeValid, - ]); - - const prevStartTime = usePrevious(startTime); - const prevEndTime = usePrevious(endTime); - const prevValidIndexNames = usePrevious(validIndexNames); - - useEffect(() => { - if (!isTimeRangeValid) { - return; - } - - validateIndices(); - }, [isTimeRangeValid, validateIndices]); - - useEffect(() => { - if (!isTimeRangeValid) { - return; - } - - if ( - startTime !== prevStartTime || - endTime !== prevEndTime || - !isEqual(validIndexNames, prevValidIndexNames) - ) { - validateDatasets(); - } - }, [ - endTime, - isTimeRangeValid, - prevEndTime, - prevStartTime, - prevValidIndexNames, - startTime, - validIndexNames, - validateDatasets, - ]); - - return { - cleanUpAndSetUp, - datasetFilter, - endTime, - isValidating, - selectedIndexNames, - setEndTime, - setStartTime, - setUp, - startTime, - validatedIndices, - setValidatedIndices, - validationErrors, - }; -}; diff --git a/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module_descriptor.ts b/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module_descriptor.ts index cec87fb1144e33..7ea87c3d21322d 100644 --- a/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module_descriptor.ts +++ b/x-pack/plugins/infra/public/containers/ml/modules/metrics_hosts/module_descriptor.ts @@ -10,17 +10,27 @@ import { cleanUpJobsAndDatafeeds } from '../../infra_ml_cleanup'; import { callJobsSummaryAPI } from '../../api/ml_get_jobs_summary_api'; import { callGetMlModuleAPI } from '../../api/ml_get_module'; import { callSetupMlModuleAPI } from '../../api/ml_setup_module_api'; -import { callValidateIndicesAPI } from '../../../logs/log_analysis/api/validate_indices'; -import { callValidateDatasetsAPI } from '../../../logs/log_analysis/api/validate_datasets'; import { metricsHostsJobTypes, getJobId, MetricsHostsJobType, DatasetFilter, bucketSpan, - partitionField, } from '../../../../../common/infra_ml'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import MemoryJob from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_hosts/ml/hosts_memory_usage.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import MemoryDatafeed from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_hosts/ml/datafeed_hosts_memory_usage.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import NetworkInJob from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_hosts/ml/hosts_network_in.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import NetworkInDatafeed from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_hosts/ml/datafeed_hosts_network_in.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import NetworkOutJob from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_hosts/ml/hosts_network_out.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import NetworkOutDatafeed from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_hosts/ml/datafeed_hosts_network_out.json'; +type JobType = 'hosts_memory_usage' | 'hosts_network_in' | 'hosts_network_out'; const moduleId = 'metrics_ui_hosts'; const moduleName = i18n.translate('xpack.infra.ml.metricsModuleName', { defaultMessage: 'Metrics anomanly detection', @@ -54,23 +64,68 @@ const setUpModule = async ( end: number | undefined, datasetFilter: DatasetFilter, { spaceId, sourceId, indices, timestampField }: ModuleSourceConfiguration, - pField?: string + partitionField?: string ) => { const indexNamePattern = indices.join(','); - const jobIds = ['hosts_memory_usage', 'hosts_network_in', 'hosts_network_out']; - const jobOverrides = jobIds.map((id) => ({ - job_id: id, - data_description: { - time_field: timestampField, - }, - custom_settings: { - metrics_source_config: { - indexPattern: indexNamePattern, - timestampField, - bucketSpan, + const jobIds: JobType[] = ['hosts_memory_usage', 'hosts_network_in', 'hosts_network_out']; + + const jobOverrides = jobIds.map((id) => { + const { job: defaultJobConfig } = getDefaultJobConfigs(id); + + // eslint-disable-next-line @typescript-eslint/naming-convention + const analysis_config: any = { + ...defaultJobConfig.analysis_config, + }; + + if (partitionField) { + analysis_config.detectors[0].partition_field_name = partitionField; + if (analysis_config.influencers.indexOf(partitionField) === -1) { + analysis_config.influencers.push(partitionField); + } + } + + return { + job_id: id, + data_description: { + time_field: timestampField, + }, + analysis_config, + custom_settings: { + metrics_source_config: { + indexPattern: indexNamePattern, + timestampField, + bucketSpan, + }, + }, + }; + }); + + const datafeedOverrides = jobIds.map((id) => { + const { datafeed: defaultDatafeedConfig } = getDefaultJobConfigs(id); + + if (!partitionField || id === 'hosts_memory_usage') { + // Since the host memory usage doesn't have custom aggs, we don't need to do anything to add a partition field + return defaultDatafeedConfig; + } + + // If we have a partition field, we need to change the aggregation to do a terms agg at the top level + const aggregations = { + [partitionField]: { + terms: { + field: partitionField, + }, + aggregations: { + ...defaultDatafeedConfig.aggregations, + }, }, - }, - })); + }; + + return { + ...defaultDatafeedConfig, + job_id: id, + aggregations, + }; + }); return callSetupMlModuleAPI( moduleId, @@ -80,34 +135,32 @@ const setUpModule = async ( sourceId, indexNamePattern, jobOverrides, - [] + datafeedOverrides ); }; -const cleanUpModule = async (spaceId: string, sourceId: string) => { - return await cleanUpJobsAndDatafeeds(spaceId, sourceId, metricsHostsJobTypes); -}; - -const validateSetupIndices = async (indices: string[], timestampField: string) => { - return await callValidateIndicesAPI(indices, [ - { - name: timestampField, - validTypes: ['date'], - }, - { - name: partitionField, - validTypes: ['keyword'], - }, - ]); +const getDefaultJobConfigs = (jobId: JobType): { datafeed: any; job: any } => { + switch (jobId) { + case 'hosts_memory_usage': + return { + datafeed: MemoryDatafeed, + job: MemoryJob, + }; + case 'hosts_network_in': + return { + datafeed: NetworkInDatafeed, + job: NetworkInJob, + }; + case 'hosts_network_out': + return { + datafeed: NetworkOutDatafeed, + job: NetworkOutJob, + }; + } }; -const validateSetupDatasets = async ( - indices: string[], - timestampField: string, - startTime: number, - endTime: number -) => { - return await callValidateDatasetsAPI(indices, timestampField, startTime, endTime); +const cleanUpModule = async (spaceId: string, sourceId: string) => { + return await cleanUpJobsAndDatafeeds(spaceId, sourceId, metricsHostsJobTypes); }; export const metricHostsModule: ModuleDescriptor = { @@ -121,6 +174,4 @@ export const metricHostsModule: ModuleDescriptor = { getModuleDefinition, setUpModule, cleanUpModule, - validateSetupDatasets, - validateSetupIndices, }; diff --git a/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module_descriptor.ts b/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module_descriptor.ts index cbcff1c307af6e..eaf7489c84eb4d 100644 --- a/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module_descriptor.ts +++ b/x-pack/plugins/infra/public/containers/ml/modules/metrics_k8s/module_descriptor.ts @@ -10,17 +10,28 @@ import { cleanUpJobsAndDatafeeds } from '../../infra_ml_cleanup'; import { callJobsSummaryAPI } from '../../api/ml_get_jobs_summary_api'; import { callGetMlModuleAPI } from '../../api/ml_get_module'; import { callSetupMlModuleAPI } from '../../api/ml_setup_module_api'; -import { callValidateIndicesAPI } from '../../../logs/log_analysis/api/validate_indices'; -import { callValidateDatasetsAPI } from '../../../logs/log_analysis/api/validate_datasets'; import { metricsK8SJobTypes, getJobId, MetricK8sJobType, DatasetFilter, bucketSpan, - partitionField, } from '../../../../../common/infra_ml'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import MemoryJob from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_k8s/ml/k8s_memory_usage.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import MemoryDatafeed from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_k8s/ml/datafeed_k8s_memory_usage.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import NetworkInJob from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_k8s/ml/k8s_network_in.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import NetworkInDatafeed from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_k8s/ml/datafeed_k8s_network_in.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import NetworkOutJob from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_k8s/ml/k8s_network_out.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import NetworkOutDatafeed from '../../../../../../ml/server/models/data_recognizer/modules/metrics_ui_k8s/ml/datafeed_k8s_network_out.json'; +type JobType = 'k8s_memory_usage' | 'k8s_network_in' | 'k8s_network_out'; +export const DEFAULT_K8S_PARTITION_FIELD = 'kubernetes.namespace'; const moduleId = 'metrics_ui_k8s'; const moduleName = i18n.translate('xpack.infra.ml.metricsModuleName', { defaultMessage: 'Metrics anomanly detection', @@ -54,26 +65,72 @@ const setUpModule = async ( end: number | undefined, datasetFilter: DatasetFilter, { spaceId, sourceId, indices, timestampField }: ModuleSourceConfiguration, - pField?: string + partitionField?: string ) => { const indexNamePattern = indices.join(','); - const jobIds = ['k8s_memory_usage', 'k8s_network_in', 'k8s_network_out']; - const jobOverrides = jobIds.map((id) => ({ - job_id: id, - analysis_config: { - bucket_span: `${bucketSpan}ms`, - }, - data_description: { - time_field: timestampField, - }, - custom_settings: { - metrics_source_config: { - indexPattern: indexNamePattern, - timestampField, - bucketSpan, + const jobIds: JobType[] = ['k8s_memory_usage', 'k8s_network_in', 'k8s_network_out']; + const jobOverrides = jobIds.map((id) => { + const { job: defaultJobConfig } = getDefaultJobConfigs(id); + + // eslint-disable-next-line @typescript-eslint/naming-convention + const analysis_config: any = { + ...defaultJobConfig.analysis_config, + }; + + if (partitionField) { + analysis_config.detectors[0].partition_field_name = partitionField; + if (analysis_config.influencers.indexOf(partitionField) === -1) { + analysis_config.influencers.push(partitionField); + } + } + + return { + job_id: id, + data_description: { + time_field: timestampField, + }, + analysis_config, + custom_settings: { + metrics_source_config: { + indexPattern: indexNamePattern, + timestampField, + bucketSpan, + }, + }, + }; + }); + + const datafeedOverrides = jobIds.map((id) => { + const { datafeed: defaultDatafeedConfig } = getDefaultJobConfigs(id); + + if (!partitionField || id === 'k8s_memory_usage') { + // Since the host memory usage doesn't have custom aggs, we don't need to do anything to add a partition field + return defaultDatafeedConfig; + } + + // Because the ML K8s jobs ship with a default partition field of {kubernetes.namespace}, ignore that agg and wrap it in our own agg. + const innerAggregation = + defaultDatafeedConfig.aggregations[DEFAULT_K8S_PARTITION_FIELD].aggregations; + + // If we have a partition field, we need to change the aggregation to do a terms agg to partition the data at the top level + const aggregations = { + [partitionField]: { + terms: { + field: partitionField, + size: 25, // 25 is arbitratry and only used to keep the number of buckets to a managable level in the event that the user choose a high cardinality partition field. + }, + aggregations: { + ...innerAggregation, + }, }, - }, - })); + }; + + return { + ...defaultDatafeedConfig, + job_id: id, + aggregations, + }; + }); return callSetupMlModuleAPI( moduleId, @@ -83,34 +140,32 @@ const setUpModule = async ( sourceId, indexNamePattern, jobOverrides, - [] + datafeedOverrides ); }; -const cleanUpModule = async (spaceId: string, sourceId: string) => { - return await cleanUpJobsAndDatafeeds(spaceId, sourceId, metricsK8SJobTypes); -}; - -const validateSetupIndices = async (indices: string[], timestampField: string) => { - return await callValidateIndicesAPI(indices, [ - { - name: timestampField, - validTypes: ['date'], - }, - { - name: partitionField, - validTypes: ['keyword'], - }, - ]); +const getDefaultJobConfigs = (jobId: JobType): { datafeed: any; job: any } => { + switch (jobId) { + case 'k8s_memory_usage': + return { + datafeed: MemoryDatafeed, + job: MemoryJob, + }; + case 'k8s_network_in': + return { + datafeed: NetworkInDatafeed, + job: NetworkInJob, + }; + case 'k8s_network_out': + return { + datafeed: NetworkOutDatafeed, + job: NetworkOutJob, + }; + } }; -const validateSetupDatasets = async ( - indices: string[], - timestampField: string, - startTime: number, - endTime: number -) => { - return await callValidateDatasetsAPI(indices, timestampField, startTime, endTime); +const cleanUpModule = async (spaceId: string, sourceId: string) => { + return await cleanUpJobsAndDatafeeds(spaceId, sourceId, metricsK8SJobTypes); }; export const metricHostsModule: ModuleDescriptor = { @@ -124,6 +179,4 @@ export const metricHostsModule: ModuleDescriptor = { getModuleDefinition, setUpModule, cleanUpModule, - validateSetupDatasets, - validateSetupIndices, }; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomoly_detection_flyout.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomoly_detection_flyout.tsx index b063713fa2c971..b5d224910e819d 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomoly_detection_flyout.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomoly_detection_flyout.tsx @@ -50,10 +50,10 @@ export const AnomalyDetectionFlyout = () => { return ( <> - + {showFlyout && ( diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/flyout_home.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/flyout_home.tsx index 801dff9c4a17a5..5b520084ebb744 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/flyout_home.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/flyout_home.tsx @@ -5,7 +5,7 @@ */ import React, { useState, useCallback, useEffect } from 'react'; -import { EuiFlyoutHeader, EuiTitle, EuiFlyoutBody, EuiTabs, EuiTab, EuiSpacer } from '@elastic/eui'; +import { EuiFlyoutHeader, EuiTitle, EuiFlyoutBody, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiText, EuiFlexGroup, EuiFlexItem, EuiCard, EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -30,7 +30,7 @@ interface Props { } export const FlyoutHome = (props: Props) => { - const [tab, setTab] = useState<'jobs' | 'anomalies'>('jobs'); + const [tab] = useState<'jobs' | 'anomalies'>('jobs'); const { goToSetup } = props; const { fetchJobStatus: fetchHostJobStatus, @@ -56,18 +56,10 @@ export const FlyoutHome = (props: Props) => { goToSetup('kubernetes'); }, [goToSetup]); - const goToJobs = useCallback(() => { - setTab('jobs'); - }, []); - const jobIds = [ ...(k8sJobSummaries || []).map((k) => k.id), ...(hostJobSummaries || []).map((h) => h.id), ]; - const anomaliesUrl = useLinkProps({ - app: 'ml', - pathname: `/explorer?_g=${createResultsUrl(jobIds)}`, - }); useEffect(() => { if (hasInfraMLReadCapabilities) { @@ -105,30 +97,24 @@ export const FlyoutHome = (props: Props) => { - - - - - - - - +
+ +

+ +

+
+
+ {hostJobSummaries.length > 0 && ( <> 0} hasK8sJobs={k8sJobSummaries.length > 0} + jobIds={jobIds} /> @@ -151,6 +137,7 @@ export const FlyoutHome = (props: Props) => { interface CalloutProps { hasHostJobs: boolean; hasK8sJobs: boolean; + jobIds: string[]; } const JobsEnabledCallout = (props: CalloutProps) => { let target = ''; @@ -175,8 +162,34 @@ const JobsEnabledCallout = (props: CalloutProps) => { pathname: '/jobs', }); + const anomaliesUrl = useLinkProps({ + app: 'ml', + pathname: `/explorer?_g=${createResultsUrl(props.jobIds)}`, + }); + return ( <> + + + + + + + + + + + + + + + { } iconType="check" /> - - - - ); }; @@ -211,30 +217,11 @@ interface CreateJobTab { const CreateJobTab = (props: CreateJobTab) => { return ( <> -
- -

- -

-
- -

- -

-
-
- - + {/* */} } // title="Hosts" title={ @@ -245,7 +232,7 @@ const CreateJobTab = (props: CreateJobTab) => { } description={ } @@ -254,7 +241,7 @@ const CreateJobTab = (props: CreateJobTab) => { {props.hasHostJobs && ( @@ -262,7 +249,7 @@ const CreateJobTab = (props: CreateJobTab) => { {!props.hasHostJobs && ( @@ -273,7 +260,7 @@ const CreateJobTab = (props: CreateJobTab) => { } title={ { } description={ } @@ -292,7 +279,7 @@ const CreateJobTab = (props: CreateJobTab) => { {props.hasK8sJobs && ( @@ -300,7 +287,7 @@ const CreateJobTab = (props: CreateJobTab) => { {!props.hasK8sJobs && ( diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx index 428c002da63838..c327d187f6bc20 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx @@ -20,6 +20,7 @@ import { useSourceViaHttp } from '../../../../../../containers/source/use_source import { useMetricK8sModuleContext } from '../../../../../../containers/ml/modules/metrics_k8s/module'; import { useMetricHostsModuleContext } from '../../../../../../containers/ml/modules/metrics_hosts/module'; import { FixedDatePicker } from '../../../../../../components/fixed_datepicker'; +import { DEFAULT_K8S_PARTITION_FIELD } from '../../../../../../containers/ml/modules/metrics_k8s/module_descriptor'; interface Props { jobType: 'hosts' | 'kubernetes'; @@ -107,7 +108,7 @@ export const JobSetupScreen = (props: Props) => { useEffect(() => { if (props.jobType === 'kubernetes') { - setPartitionField(['kubernetes.namespace']); + setPartitionField([DEFAULT_K8S_PARTITION_FIELD]); } }, [props.jobType]); From 6c015cfbef12189eb5aec8fa42f5ea2743be2971 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 1 Oct 2020 19:04:26 -0600 Subject: [PATCH 02/21] Convert VectorLayer to typescript (#78490) * [maps] convert VectorLayer to TS * more tslint fixes * clean up * more tslint fixes * more tslint fixes * remove unneeded casts * remove unneeded VectorStyle casts * revert changes to layer.getQuery * fix * update tile layer constructor * review feedback Co-authored-by: Elastic Machine --- .../data_request_descriptor_types.ts | 19 +- .../common/descriptor_types/map_descriptor.ts | 2 +- .../common/elasticsearch_util/es_agg_utils.ts | 4 +- .../public/actions/data_request_actions.ts | 2 +- .../maps/public/classes/joins/inner_join.d.ts | 23 +- .../plugins/maps/public/classes/joins/join.ts | 32 +- .../blended_vector_layer.ts | 11 +- .../layers/heatmap_layer/heatmap_layer.js | 12 + .../maps/public/classes/layers/layer.test.ts | 6 - .../maps/public/classes/layers/layer.tsx | 19 +- .../classes/layers/tile_layer/tile_layer.js | 15 +- .../tiled_vector_layer/tiled_vector_layer.tsx | 43 +-- .../layers/vector_layer/vector_layer.d.ts | 85 ----- .../{vector_layer.js => vector_layer.tsx} | 291 ++++++++++++------ .../sources/es_agg_source/es_agg_source.ts | 2 +- .../es_geo_grid_source.d.ts | 9 +- .../es_geo_grid_source.test.ts | 3 +- .../classes/sources/es_source/es_source.d.ts | 48 ++- .../classes/sources/es_source/es_source.js | 15 +- .../es_term_source/es_term_source.d.ts | 13 +- .../sources/es_term_source/es_term_source.js | 4 +- .../kibana_regionmap_source.js | 1 + .../mvt_single_layer_vector_source.tsx | 14 +- .../sources/vector_source/vector_source.d.ts | 28 +- .../classes/styles/vector/vector_style.tsx | 55 +++- .../toc_entry_actions_popover.test.tsx | 14 +- 26 files changed, 478 insertions(+), 292 deletions(-) delete mode 100644 x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.d.ts rename x-pack/plugins/maps/public/classes/layers/vector_layer/{vector_layer.js => vector_layer.tsx} (78%) diff --git a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts index f3521cca2e456f..16b60492c9b78c 100644 --- a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts @@ -38,15 +38,21 @@ export type VectorSourceRequestMeta = MapFilters & { applyGlobalQuery: boolean; fieldNames: string[]; geogridPrecision?: number; - sourceQuery: MapQuery; + sourceQuery?: MapQuery; sourceMeta: VectorSourceSyncMeta; }; +export type VectorJoinSourceRequestMeta = MapFilters & { + applyGlobalQuery: boolean; + fieldNames: string[]; + sourceQuery: MapQuery; +}; + export type VectorStyleRequestMeta = MapFilters & { dynamicStyleFields: string[]; isTimeAware: boolean; sourceQuery: MapQuery; - timeFilters: unknown; + timeFilters: TimeRange; }; export type ESSearchSourceResponseMeta = { @@ -59,9 +65,12 @@ export type ESSearchSourceResponseMeta = { }; // Partial because objects are justified downstream in constructors -export type DataMeta = Partial & - Partial & - Partial; +export type DataMeta = Partial< + VectorSourceRequestMeta & + VectorJoinSourceRequestMeta & + VectorStyleRequestMeta & + ESSearchSourceResponseMeta +>; type NumericalStyleFieldData = { avg: number; diff --git a/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts b/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts index d064dfb1c4a372..b769b125cf0f81 100644 --- a/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts +++ b/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts @@ -17,7 +17,7 @@ export type MapExtent = { }; export type MapQuery = Query & { - queryLastTriggeredAt: string; + queryLastTriggeredAt?: string; }; export type MapRefreshConfig = { diff --git a/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts b/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts index 7828c3cc6410b5..f157ffe9f1c809 100644 --- a/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts @@ -33,8 +33,10 @@ export function addFieldToDSL(dsl: object, field: IFieldType) { }; } +export type BucketProperties = Record; + export function extractPropertiesFromBucket(bucket: any, ignoreKeys: string[] = []) { - const properties: Record = {}; + const properties: BucketProperties = {}; for (const key in bucket) { if (ignoreKeys.includes(key) || !bucket.hasOwnProperty(key)) { continue; diff --git a/x-pack/plugins/maps/public/actions/data_request_actions.ts b/x-pack/plugins/maps/public/actions/data_request_actions.ts index 14d81969005068..d7d9259e1539e4 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -47,7 +47,7 @@ const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1; export type DataRequestContext = { startLoading(dataId: string, requestToken: symbol, meta: DataMeta): void; - stopLoading(dataId: string, requestToken: symbol, data: object, meta: DataMeta): void; + stopLoading(dataId: string, requestToken: symbol, data: object, meta?: DataMeta): void; onLoadError(dataId: string, requestToken: symbol, errorMessage: string): void; updateSourceData(newData: unknown): void; isRequestStillActive(dataId: string, requestToken: symbol): boolean; diff --git a/x-pack/plugins/maps/public/classes/joins/inner_join.d.ts b/x-pack/plugins/maps/public/classes/joins/inner_join.d.ts index befff0965fb70c..3e2ceac4971c45 100644 --- a/x-pack/plugins/maps/public/classes/joins/inner_join.d.ts +++ b/x-pack/plugins/maps/public/classes/joins/inner_join.d.ts @@ -4,19 +4,40 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Feature, GeoJsonProperties } from 'geojson'; import { IESTermSource } from '../sources/es_term_source'; -import { IJoin } from './join'; +import { IJoin, PropertiesMap } from './join'; import { JoinDescriptor } from '../../../common/descriptor_types'; import { ISource } from '../sources/source'; +import { ITooltipProperty } from '../tooltips/tooltip_property'; +import { IField } from '../fields/field'; export class InnerJoin implements IJoin { constructor(joinDescriptor: JoinDescriptor, leftSource: ISource); + destroy: () => void; + getRightJoinSource(): IESTermSource; toDescriptor(): JoinDescriptor; + getJoinFields: () => IField[]; + + getLeftField: () => IField; + + getIndexPatternIds: () => string[]; + + getQueryableIndexPatternIds: () => string[]; + + getSourceDataRequestId: () => string; + getSourceMetaDataRequestId(): string; getSourceFormattersDataRequestId(): string; + + getTooltipProperties(properties: GeoJsonProperties): Promise; + + hasCompleteConfig: () => boolean; + + joinPropertiesToFeature: (feature: Feature, propertiesMap?: PropertiesMap) => boolean; } diff --git a/x-pack/plugins/maps/public/classes/joins/join.ts b/x-pack/plugins/maps/public/classes/joins/join.ts index 5bcc4bfdec87e5..df6f6f684f4d2c 100644 --- a/x-pack/plugins/maps/public/classes/joins/join.ts +++ b/x-pack/plugins/maps/public/classes/joins/join.ts @@ -4,15 +4,39 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Feature, GeoJsonProperties } from 'geojson'; import { IESTermSource } from '../sources/es_term_source'; import { JoinDescriptor } from '../../../common/descriptor_types'; +import { ITooltipProperty } from '../tooltips/tooltip_property'; +import { IField } from '../fields/field'; +import { BucketProperties } from '../../../common/elasticsearch_util'; + +export type PropertiesMap = Map; export interface IJoin { - getRightJoinSource(): IESTermSource; + destroy: () => void; + + getRightJoinSource: () => IESTermSource; + + toDescriptor: () => JoinDescriptor; + + getJoinFields: () => IField[]; + + getLeftField: () => IField; + + getIndexPatternIds: () => string[]; + + getQueryableIndexPatternIds: () => string[]; + + getSourceDataRequestId: () => string; + + getSourceMetaDataRequestId: () => string; + + getSourceFormattersDataRequestId: () => string; - toDescriptor(): JoinDescriptor; + getTooltipProperties: (properties: GeoJsonProperties) => Promise; - getSourceMetaDataRequestId(): string; + hasCompleteConfig: () => boolean; - getSourceFormattersDataRequestId(): string; + joinPropertiesToFeature: (feature: Feature, propertiesMap?: PropertiesMap) => boolean; } diff --git a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts index 90e8d25a77958d..9b6a67ac28ad09 100644 --- a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts @@ -37,7 +37,6 @@ import { LayerDescriptor, VectorLayerDescriptor, } from '../../../../common/descriptor_types'; -import { IStyle } from '../../styles/style'; import { IVectorSource } from '../../sources/vector_source'; const ACTIVE_COUNT_DATA_ID = 'ACTIVE_COUNT_DATA_ID'; @@ -257,7 +256,7 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { return clonedDescriptor; } - getSource() { + getSource(): IVectorSource { return this._isClustered ? this._clusterSource : this._documentSource; } @@ -268,11 +267,11 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { return this._documentSource; } - getCurrentStyle(): IStyle { + getCurrentStyle(): IVectorStyle { return this._isClustered ? this._clusterStyle : this._documentStyle; } - getStyleForEditing(): IStyle { + getStyleForEditing(): IVectorStyle { return this._documentStyle; } @@ -281,8 +280,8 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { const requestToken = Symbol(`layer-active-count:${this.getId()}`); const searchFilters = this._getSearchFilters( syncContext.dataFilters, - this.getSource() as IVectorSource, - this.getCurrentStyle() as IVectorStyle + this.getSource(), + this.getCurrentStyle() ); const canSkipFetch = await canSkipSourceUpdate({ source: this.getSource(), diff --git a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.js b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.js index adcc86b9d1546e..33e82db79f3cfa 100644 --- a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.js +++ b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.js @@ -31,6 +31,18 @@ export class HeatmapLayer extends VectorLayer { } } + getStyleForEditing() { + return this._style; + } + + getStyle() { + return this._style; + } + + getCurrentStyle() { + return this._style; + } + _getPropKeyOfSelectedMetric() { const metricfields = this.getSource().getMetricFields(); return metricfields[0].getName(); diff --git a/x-pack/plugins/maps/public/classes/layers/layer.test.ts b/x-pack/plugins/maps/public/classes/layers/layer.test.ts index 7bc91d71f83e22..76df7c2af840a7 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/layer.test.ts @@ -7,7 +7,6 @@ import { AbstractLayer } from './layer'; import { ISource } from '../sources/source'; -import { IStyle } from '../styles/style'; import { AGG_TYPE, FIELD_ORIGIN, LAYER_STYLE_TYPE, VECTOR_STYLES } from '../../../common/constants'; import { ESTermSourceDescriptor, VectorStyleDescriptor } from '../../../common/descriptor_types'; import { getDefaultDynamicProperties } from '../styles/vector/vector_style_defaults'; @@ -38,8 +37,6 @@ class MockSource { } } -class MockStyle {} - describe('cloneDescriptor', () => { describe('with joins', () => { const styleDescriptor = { @@ -84,7 +81,6 @@ describe('cloneDescriptor', () => { const layer = new MockLayer({ layerDescriptor, source: (new MockSource() as unknown) as ISource, - style: (new MockStyle() as unknown) as IStyle, }); const clonedDescriptor = await layer.cloneDescriptor(); const clonedStyleProps = (clonedDescriptor.style as VectorStyleDescriptor).properties; @@ -122,7 +118,6 @@ describe('cloneDescriptor', () => { const layer = new MockLayer({ layerDescriptor, source: (new MockSource() as unknown) as ISource, - style: (new MockStyle() as unknown) as IStyle, }); const clonedDescriptor = await layer.cloneDescriptor(); const clonedStyleProps = (clonedDescriptor.style as VectorStyleDescriptor).properties; @@ -165,7 +160,6 @@ describe('isFittable', () => { const layer = new MockLayer({ layerDescriptor, source: (new MockSource({ fitToBounds: test.fitToBounds }) as unknown) as ISource, - style: (new MockStyle() as unknown) as IStyle, }); expect(await layer.isFittable()).toBe(test.canFit); }); diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index cd720063c67031..d6bd5180375ce5 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -110,13 +110,11 @@ export type CustomIconAndTooltipContent = { export interface ILayerArguments { layerDescriptor: LayerDescriptor; source: ISource; - style: IStyle; } export class AbstractLayer implements ILayer { protected readonly _descriptor: LayerDescriptor; protected readonly _source: ISource; - protected readonly _style: IStyle; protected readonly _dataRequests: DataRequest[]; static createDescriptor(options: Partial): LayerDescriptor { @@ -140,10 +138,9 @@ export class AbstractLayer implements ILayer { } } - constructor({ layerDescriptor, source, style }: ILayerArguments) { + constructor({ layerDescriptor, source }: ILayerArguments) { this._descriptor = AbstractLayer.createDescriptor(layerDescriptor); this._source = source; - this._style = style; if (this._descriptor.__dataRequests) { this._dataRequests = this._descriptor.__dataRequests.map( (dataRequest) => new DataRequest(dataRequest) @@ -257,11 +254,15 @@ export class AbstractLayer implements ILayer { } getStyleForEditing(): IStyle { - return this._style; + throw new Error('Should implement AbstractLayer#getStyleForEditing'); } - getStyle() { - return this._style; + getStyle(): IStyle { + throw new Error('Should implement AbstractLayer#getStyle'); + } + + getCurrentStyle(): IStyle { + throw new Error('Should implement AbstractLayer#getCurrentStyle'); } getLabel(): string { @@ -412,10 +413,6 @@ export class AbstractLayer implements ILayer { return this._descriptor.query ? this._descriptor.query : null; } - getCurrentStyle(): IStyle { - return this._style; - } - async getImmutableSourceProperties() { const source = this.getSource(); return await source.getImmutableProperties(); diff --git a/x-pack/plugins/maps/public/classes/layers/tile_layer/tile_layer.js b/x-pack/plugins/maps/public/classes/layers/tile_layer/tile_layer.js index 3e2009c24a2e4d..fa60017f0eaf7b 100644 --- a/x-pack/plugins/maps/public/classes/layers/tile_layer/tile_layer.js +++ b/x-pack/plugins/maps/public/classes/layers/tile_layer/tile_layer.js @@ -21,7 +21,20 @@ export class TileLayer extends AbstractLayer { } constructor({ source, layerDescriptor }) { - super({ source, layerDescriptor, style: new TileStyle() }); + super({ source, layerDescriptor }); + this._style = new TileStyle(); + } + + getStyleForEditing() { + return this._style; + } + + getStyle() { + return this._style; + } + + getCurrentStyle() { + return this._style; } async syncData({ startLoading, stopLoading, onLoadError, dataFilters }) { diff --git a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx index 70bf8ea3883b72..68b9f2931f398c 100644 --- a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx @@ -5,9 +5,14 @@ */ import React from 'react'; +import { + Map as MbMap, + GeoJSONSource as MbGeoJSONSource, + VectorSource as MbVectorSource, +} from 'mapbox-gl'; import { EuiIcon } from '@elastic/eui'; import { Feature } from 'geojson'; -import { VectorStyle } from '../../styles/vector/vector_style'; +import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; import { SOURCE_DATA_REQUEST_ID, LAYER_TYPE } from '../../../../common/constants'; import { VectorLayer, VectorLayerArguments } from '../vector_layer/vector_layer'; import { ITiledSingleLayerVectorSource } from '../../sources/vector_source'; @@ -59,7 +64,7 @@ export class TiledVectorLayer extends VectorLayer { const searchFilters: VectorSourceRequestMeta = this._getSearchFilters( dataFilters, this.getSource(), - this._style + this._style as IVectorStyle ); const prevDataRequest = this.getSourceDataRequest(); @@ -88,13 +93,12 @@ export class TiledVectorLayer extends VectorLayer { } async syncData(syncContext: DataRequestContext) { - await this._syncSourceStyleMeta(syncContext, this._source, this._style); - await this._syncSourceFormatters(syncContext, this._source, this._style); + await this._syncSourceStyleMeta(syncContext, this._source, this._style as IVectorStyle); + await this._syncSourceFormatters(syncContext, this._source, this._style as IVectorStyle); await this._syncMVTUrlTemplate(syncContext); } - _syncSourceBindingWithMb(mbMap: unknown) { - // @ts-expect-error + _syncSourceBindingWithMb(mbMap: MbMap) { const mbSource = mbMap.getSource(this._getMbSourceId()); if (mbSource) { return; @@ -113,7 +117,6 @@ export class TiledVectorLayer extends VectorLayer { } const mbSourceId = this._getMbSourceId(); - // @ts-expect-error mbMap.addSource(mbSourceId, { type: 'vector', tiles: [sourceMeta.urlTemplate], @@ -126,7 +129,7 @@ export class TiledVectorLayer extends VectorLayer { return this._getMbSourceId() === mbSourceId; } - _syncStylePropertiesWithMb(mbMap: unknown) { + _syncStylePropertiesWithMb(mbMap: MbMap) { // @ts-ignore const mbSource = mbMap.getSource(this._getMbSourceId()); if (!mbSource) { @@ -146,12 +149,16 @@ export class TiledVectorLayer extends VectorLayer { this._setMbLinePolygonProperties(mbMap, sourceMeta.layerName); } - _requiresPrevSourceCleanup(mbMap: unknown): boolean { - // @ts-expect-error - const mbTileSource = mbMap.getSource(this._getMbSourceId()); - if (!mbTileSource) { + _requiresPrevSourceCleanup(mbMap: MbMap): boolean { + const mbSource = mbMap.getSource(this._getMbSourceId()) as MbVectorSource | MbGeoJSONSource; + if (!mbSource) { return false; } + if (!('tiles' in mbSource)) { + // Expected source is not compatible, so remove. + return true; + } + const mbTileSource = mbSource as MbVectorSource; const dataRequest = this.getSourceDataRequest(); if (!dataRequest) { @@ -163,13 +170,8 @@ export class TiledVectorLayer extends VectorLayer { return false; } - if (!mbTileSource.tiles) { - // Expected source is not compatible, so remove. - return true; - } - const isSourceDifferent = - mbTileSource.tiles[0] !== tiledSourceMeta.urlTemplate || + mbTileSource.tiles?.[0] !== tiledSourceMeta.urlTemplate || mbTileSource.minzoom !== tiledSourceMeta.minSourceZoom || mbTileSource.maxzoom !== tiledSourceMeta.maxSourceZoom; @@ -179,9 +181,8 @@ export class TiledVectorLayer extends VectorLayer { const layerIds = this.getMbLayerIds(); for (let i = 0; i < layerIds.length; i++) { - // @ts-expect-error const mbLayer = mbMap.getLayer(layerIds[i]); - if (mbLayer && mbLayer.sourceLayer !== tiledSourceMeta.layerName) { + if (mbLayer && mbLayer['source-layer'] !== tiledSourceMeta.layerName) { // If the source-pointer of one of the layers is stale, they will all be stale. // In this case, all the mb-layers need to be removed and re-added. return true; @@ -191,7 +192,7 @@ export class TiledVectorLayer extends VectorLayer { return false; } - syncLayerWithMB(mbMap: unknown) { + syncLayerWithMB(mbMap: MbMap) { this._removeStaleMbSourcesAndLayers(mbMap); this._syncSourceBindingWithMb(mbMap); this._syncStylePropertiesWithMb(mbMap); diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.d.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.d.ts deleted file mode 100644 index fa614ae87b2905..00000000000000 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.d.ts +++ /dev/null @@ -1,85 +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; - * you may not use this file except in compliance with the Elastic License. - */ -/* eslint-disable @typescript-eslint/consistent-type-definitions */ - -import { Feature, GeoJsonProperties } from 'geojson'; -import { AbstractLayer } from '../layer'; -import { IVectorSource } from '../../sources/vector_source'; -import { - MapFilters, - VectorLayerDescriptor, - VectorSourceRequestMeta, -} from '../../../../common/descriptor_types'; -import { ILayer } from '../layer'; -import { IJoin } from '../../joins/join'; -import { IVectorStyle } from '../../styles/vector/vector_style'; -import { IField } from '../../fields/field'; -import { DataRequestContext } from '../../../actions'; -import { ITooltipProperty } from '../../tooltips/tooltip_property'; - -export type VectorLayerArguments = { - source: IVectorSource; - joins?: IJoin[]; - layerDescriptor: VectorLayerDescriptor; -}; - -export interface IVectorLayer extends ILayer { - getFields(): Promise; - getStyleEditorFields(): Promise; - getJoins(): IJoin[]; - getValidJoins(): IJoin[]; - getSource(): IVectorSource; - getFeatureById(id: string | number): Feature | null; - getPropertiesForTooltip(properties: GeoJsonProperties): Promise; - hasJoins(): boolean; -} - -export class VectorLayer extends AbstractLayer implements IVectorLayer { - static type: string; - - protected readonly _style: IVectorStyle; - static createDescriptor( - options: Partial, - mapColors?: string[] - ): VectorLayerDescriptor; - - constructor(options: VectorLayerArguments); - getLayerTypeIconName(): string; - getFields(): Promise; - getStyleEditorFields(): Promise; - getJoins(): IJoin[]; - getValidJoins(): IJoin[]; - _syncSourceStyleMeta( - syncContext: DataRequestContext, - source: IVectorSource, - style: IVectorStyle - ): Promise; - _syncSourceFormatters( - syncContext: DataRequestContext, - source: IVectorSource, - style: IVectorStyle - ): Promise; - syncLayerWithMB(mbMap: unknown): void; - _getSearchFilters( - dataFilters: MapFilters, - source: IVectorSource, - style: IVectorStyle - ): VectorSourceRequestMeta; - _syncData( - syncContext: DataRequestContext, - source: IVectorSource, - style: IVectorStyle - ): Promise; - ownsMbSourceId(sourceId: string): boolean; - ownsMbLayerId(sourceId: string): boolean; - _setMbPointsProperties(mbMap: unknown, mvtSourceLayer?: string): void; - _setMbLinePolygonProperties(mbMap: unknown, mvtSourceLayer?: string): void; - getSource(): IVectorSource; - getFeatureById(id: string | number): Feature | null; - getPropertiesForTooltip(properties: GeoJsonProperties): Promise; - hasJoins(): boolean; - isFittable(): Promise; -} diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.js b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx similarity index 78% rename from x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.js rename to x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 27c344b713a60f..a2532d4e7b10ef 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.js +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -5,8 +5,13 @@ */ import React from 'react'; +import { Map as MbMap, Layer as MbLayer, GeoJSONSource as MbGeoJSONSource } from 'mapbox-gl'; +import { Feature, FeatureCollection, GeoJsonProperties } from 'geojson'; +import _ from 'lodash'; +import { EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { AbstractLayer } from '../layer'; -import { VectorStyle } from '../../styles/vector/vector_style'; +import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; import { FEATURE_ID_PROPERTY_NAME, SOURCE_DATA_REQUEST_ID, @@ -20,11 +25,9 @@ import { FIELD_ORIGIN, LAYER_STYLE_TYPE, KBN_TOO_MANY_FEATURES_IMAGE_ID, + FieldFormatter, } from '../../../../common/constants'; -import _ from 'lodash'; import { JoinTooltipProperty } from '../../tooltips/join_tooltip_property'; -import { EuiIcon } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { DataRequestAbortError } from '../../util/data_request'; import { canSkipSourceUpdate, @@ -39,15 +42,66 @@ import { getPointFilterExpression, } from '../../util/mb_filter_expressions'; +import { + DynamicStylePropertyOptions, + MapFilters, + MapQuery, + VectorLayerDescriptor, + VectorSourceRequestMeta, + VectorStyleRequestMeta, +} from '../../../../common/descriptor_types'; +import { IVectorSource } from '../../sources/vector_source'; +import { CustomIconAndTooltipContent, ILayer } from '../layer'; +import { IJoin, PropertiesMap } from '../../joins/join'; +import { IField } from '../../fields/field'; +import { DataRequestContext } from '../../../actions'; +import { ITooltipProperty } from '../../tooltips/tooltip_property'; +import { IDynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property'; +import { IESSource } from '../../sources/es_source'; + +interface SourceResult { + refreshed: boolean; + featureCollection?: FeatureCollection; +} + +interface JoinState { + dataHasChanged: boolean; + join: IJoin; + propertiesMap?: PropertiesMap; +} + +export interface VectorLayerArguments { + source: IVectorSource; + joins?: IJoin[]; + layerDescriptor: VectorLayerDescriptor; +} + +export interface IVectorLayer extends ILayer { + getFields(): Promise; + getStyleEditorFields(): Promise; + getJoins(): IJoin[]; + getValidJoins(): IJoin[]; + getSource(): IVectorSource; + getFeatureById(id: string | number): Feature | null; + getPropertiesForTooltip(properties: GeoJsonProperties): Promise; + hasJoins(): boolean; +} + export class VectorLayer extends AbstractLayer { static type = LAYER_TYPE.VECTOR; - static createDescriptor(options, mapColors) { + protected readonly _style: IVectorStyle; + private readonly _joins: IJoin[]; + + static createDescriptor( + options: Partial, + mapColors?: string[] + ): VectorLayerDescriptor { const layerDescriptor = super.createDescriptor(options); layerDescriptor.type = VectorLayer.type; if (!options.style) { - const styleProperties = VectorStyle.createDefaultStyleProperties(mapColors); + const styleProperties = VectorStyle.createDefaultStyleProperties(mapColors ? mapColors : []); layerDescriptor.style = VectorStyle.createDescriptor(styleProperties); } @@ -55,16 +109,31 @@ export class VectorLayer extends AbstractLayer { layerDescriptor.joins = []; } - return layerDescriptor; + return layerDescriptor as VectorLayerDescriptor; } - constructor({ layerDescriptor, source, joins = [] }) { - super({ layerDescriptor, source }); + constructor({ layerDescriptor, source, joins = [] }: VectorLayerArguments) { + super({ + layerDescriptor, + source, + }); this._joins = joins; - this._style = new VectorStyle(this._descriptor.style, source, this); + this._style = new VectorStyle(layerDescriptor.style, source, this); + } + + getSource(): IVectorSource { + return super.getSource() as IVectorSource; + } + + getStyleForEditing(): IVectorStyle { + return this._style; + } + + getStyle(): IVectorStyle { + return this._style; } - getStyle() { + getCurrentStyle(): IVectorStyle { return this._style; } @@ -108,7 +177,7 @@ export class VectorLayer extends AbstractLayer { return true; } - getCustomIconAndTooltipContent() { + getCustomIconAndTooltipContent(): CustomIconAndTooltipContent { const featureCollection = this._getSourceFeatureCollection(); const noResultsIcon = ; @@ -124,7 +193,7 @@ export class VectorLayer extends AbstractLayer { if ( this.getJoins().length && !featureCollection.features.some( - (feature) => feature.properties[FEATURE_VISIBLE_PROPERTY_NAME] + (feature) => feature.properties?.[FEATURE_VISIBLE_PROPERTY_NAME] ) ) { return { @@ -141,8 +210,8 @@ export class VectorLayer extends AbstractLayer { ); return { icon: this.getCurrentStyle().getIcon(), - tooltipContent: tooltipContent, - areResultsTrimmed: areResultsTrimmed, + tooltipContent, + areResultsTrimmed, }; } @@ -158,7 +227,12 @@ export class VectorLayer extends AbstractLayer { return this.getCurrentStyle().renderLegendDetails(); } - async getBounds({ startLoading, stopLoading, registerCancelCallback, dataFilters }) { + async getBounds({ + startLoading, + stopLoading, + registerCancelCallback, + dataFilters, + }: DataRequestContext) { const isStaticLayer = !this.getSource().isBoundsAware(); if (isStaticLayer || this.hasJoins()) { return getFeatureCollectionBounds(this._getSourceFeatureCollection(), this.hasJoins()); @@ -190,7 +264,7 @@ export class VectorLayer extends AbstractLayer { } finally { // Use stopLoading callback instead of onLoadError callback. // Function is loading bounds and not feature data. - stopLoading(SOURCE_BOUNDS_DATA_REQUEST_ID, requestToken, bounds, boundsFilters); + stopLoading(SOURCE_BOUNDS_DATA_REQUEST_ID, requestToken, bounds ? bounds : {}, boundsFilters); } return bounds; } @@ -205,7 +279,7 @@ export class VectorLayer extends AbstractLayer { } _getJoinFields() { - const joinFields = []; + const joinFields: IField[] = []; this.getValidJoins().forEach((join) => { const fields = join.getJoinFields(); joinFields.push(...fields); @@ -219,7 +293,7 @@ export class VectorLayer extends AbstractLayer { } async getStyleEditorFields() { - const sourceFields = await this.getSourceForEditing().getFields(); + const sourceFields = await (this.getSourceForEditing() as IVectorSource).getFields(); return [...sourceFields, ...this._getJoinFields()]; } @@ -246,7 +320,7 @@ export class VectorLayer extends AbstractLayer { onLoadError, registerCancelCallback, dataFilters, - }) { + }: { join: IJoin } & DataRequestContext): Promise { const joinSource = join.getRightJoinSource(); const sourceDataId = join.getSourceDataRequestId(); const requestToken = Symbol(`layer-join-refresh:${this.getId()} - ${sourceDataId}`); @@ -266,15 +340,15 @@ export class VectorLayer extends AbstractLayer { if (canSkipFetch) { return { dataHasChanged: false, - join: join, - propertiesMap: prevDataRequest.getData(), + join, + propertiesMap: prevDataRequest?.getData() as PropertiesMap, }; } try { startLoading(sourceDataId, requestToken, searchFilters); const leftSourceName = await this._source.getDisplayName(); - const { propertiesMap } = await joinSource.getPropertiesMap( + const propertiesMap = await joinSource.getPropertiesMap( searchFilters, leftSourceName, join.getLeftField().getName(), @@ -283,8 +357,8 @@ export class VectorLayer extends AbstractLayer { stopLoading(sourceDataId, requestToken, propertiesMap); return { dataHasChanged: true, - join: join, - propertiesMap: propertiesMap, + join, + propertiesMap, }; } catch (e) { if (!(e instanceof DataRequestAbortError)) { @@ -292,13 +366,12 @@ export class VectorLayer extends AbstractLayer { } return { dataHasChanged: true, - join: join, - propertiesMap: null, + join, }; } } - async _syncJoins(syncContext, style) { + async _syncJoins(syncContext: DataRequestContext, style: IVectorStyle) { const joinSyncs = this.getValidJoins().map(async (join) => { await this._syncJoinStyleMeta(syncContext, join, style); await this._syncJoinFormatters(syncContext, join, style); @@ -308,28 +381,37 @@ export class VectorLayer extends AbstractLayer { return await Promise.all(joinSyncs); } - _getSearchFilters(dataFilters, source, style) { + _getSearchFilters( + dataFilters: MapFilters, + source: IVectorSource, + style: IVectorStyle + ): VectorSourceRequestMeta { const fieldNames = [ ...source.getFieldNames(), ...(style.getType() === LAYER_STYLE_TYPE.VECTOR ? style.getSourceFieldNames() : []), ...this.getValidJoins().map((join) => join.getLeftField().getName()), ]; + const sourceQuery = this.getQuery() as MapQuery; return { ...dataFilters, fieldNames: _.uniq(fieldNames).sort(), geogridPrecision: source.getGeoGridPrecision(dataFilters.zoom), - sourceQuery: this.getQuery(), + sourceQuery: sourceQuery ? sourceQuery : undefined, applyGlobalQuery: source.getApplyGlobalQuery(), sourceMeta: source.getSyncMeta(), }; } - async _performInnerJoins(sourceResult, joinStates, updateSourceData) { - //should update the store if - //-- source result was refreshed - //-- any of the join configurations changed (joinState changed) - //-- visibility of any of the features has changed + async _performInnerJoins( + sourceResult: SourceResult, + joinStates: JoinState[], + updateSourceData: DataRequestContext['updateSourceData'] + ) { + // should update the store if + // -- source result was refreshed + // -- any of the join configurations changed (joinState changed) + // -- visibility of any of the features has changed let shouldUpdateStore = sourceResult.refreshed || joinStates.some((joinState) => joinState.dataHasChanged); @@ -338,8 +420,11 @@ export class VectorLayer extends AbstractLayer { return; } - for (let i = 0; i < sourceResult.featureCollection.features.length; i++) { - const feature = sourceResult.featureCollection.features[i]; + for (let i = 0; i < sourceResult.featureCollection!.features.length; i++) { + const feature = sourceResult.featureCollection!.features[i]; + if (!feature.properties) { + feature.properties = {}; + } const oldVisbility = feature.properties[FEATURE_VISIBLE_PROPERTY_NAME]; let isFeatureVisible = true; for (let j = 0; j < joinStates.length; j++) { @@ -364,7 +449,11 @@ export class VectorLayer extends AbstractLayer { } } - async _syncSource(syncContext, source, style) { + async _syncSource( + syncContext: DataRequestContext, + source: IVectorSource, + style: IVectorStyle + ): Promise { const { startLoading, stopLoading, @@ -385,7 +474,9 @@ export class VectorLayer extends AbstractLayer { if (canSkipFetch) { return { refreshed: false, - featureCollection: prevDataRequest.getData(), + featureCollection: prevDataRequest + ? (prevDataRequest.getData() as FeatureCollection) + : EMPTY_FEATURE_COLLECTION, }; } @@ -416,15 +507,20 @@ export class VectorLayer extends AbstractLayer { } } - async _syncSourceStyleMeta(syncContext, source, style) { + async _syncSourceStyleMeta( + syncContext: DataRequestContext, + source: IVectorSource, + style: IVectorStyle + ) { if (this.getCurrentStyle().getType() !== LAYER_STYLE_TYPE.VECTOR) { return; } + const sourceQuery = this.getQuery() as MapQuery; return this._syncStyleMeta({ source, style, - sourceQuery: this.getQuery(), + sourceQuery: sourceQuery ? sourceQuery : undefined, dataRequestId: SOURCE_META_DATA_REQUEST_ID, dynamicStyleProps: style.getDynamicPropertiesArray().filter((dynamicStyleProp) => { return ( @@ -436,7 +532,7 @@ export class VectorLayer extends AbstractLayer { }); } - async _syncJoinStyleMeta(syncContext, join, style) { + async _syncJoinStyleMeta(syncContext: DataRequestContext, join: IJoin, style: IVectorStyle) { const joinSource = join.getRightJoinSource(); return this._syncStyleMeta({ source: joinSource, @@ -446,9 +542,7 @@ export class VectorLayer extends AbstractLayer { dynamicStyleProps: this.getCurrentStyle() .getDynamicPropertiesArray() .filter((dynamicStyleProp) => { - const matchingField = joinSource.getMetricFieldForName( - dynamicStyleProp.getField().getName() - ); + const matchingField = joinSource.getMetricFieldForName(dynamicStyleProp.getFieldName()); return ( dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.JOIN && !!matchingField && @@ -470,13 +564,19 @@ export class VectorLayer extends AbstractLayer { stopLoading, onLoadError, registerCancelCallback, - }) { + }: { + dataRequestId: string; + dynamicStyleProps: Array>; + source: IVectorSource; + sourceQuery?: MapQuery; + style: IVectorStyle; + } & DataRequestContext) { if (!source.isESSource() || dynamicStyleProps.length === 0) { return; } const dynamicStyleFields = dynamicStyleProps.map((dynamicStyleProp) => { - return `${dynamicStyleProp.getField().getName()}${dynamicStyleProp.getNumberOfCategories()}`; + return `${dynamicStyleProp.getFieldName()}${dynamicStyleProp.getNumberOfCategories()}`; }); const nextMeta = { @@ -484,7 +584,7 @@ export class VectorLayer extends AbstractLayer { sourceQuery, isTimeAware: this.getCurrentStyle().isTimeAware() && (await source.isTimeAware()), timeFilters: dataFilters.timeFilters, - }; + } as VectorStyleRequestMeta; const prevDataRequest = this.getDataRequest(dataRequestId); const canSkipFetch = canSkipStyleMetaUpdate({ prevDataRequest, nextMeta }); if (canSkipFetch) { @@ -496,14 +596,14 @@ export class VectorLayer extends AbstractLayer { startLoading(dataRequestId, requestToken, nextMeta); const layerName = await this.getDisplayName(source); - //todo: cast source to ESSource when migrating to TS - const styleMeta = await source.loadStylePropsMeta( + const styleMeta = await (source as IESSource).loadStylePropsMeta({ layerName, style, dynamicStyleProps, - registerCancelCallback.bind(null, requestToken), - nextMeta - ); + registerCancelCallback: registerCancelCallback.bind(null, requestToken), + sourceQuery: nextMeta.sourceQuery, + timeFilters: nextMeta.timeFilters, + }); stopLoading(dataRequestId, requestToken, styleMeta, nextMeta); } catch (error) { if (!(error instanceof DataRequestAbortError)) { @@ -512,7 +612,11 @@ export class VectorLayer extends AbstractLayer { } } - async _syncSourceFormatters(syncContext, source, style) { + async _syncSourceFormatters( + syncContext: DataRequestContext, + source: IVectorSource, + style: IVectorStyle + ) { if (style.getType() !== LAYER_STYLE_TYPE.VECTOR) { return; } @@ -526,13 +630,13 @@ export class VectorLayer extends AbstractLayer { return dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE; }) .map((dynamicStyleProp) => { - return dynamicStyleProp.getField(); + return dynamicStyleProp.getField()!; }), ...syncContext, }); } - async _syncJoinFormatters(syncContext, join, style) { + async _syncJoinFormatters(syncContext: DataRequestContext, join: IJoin, style: IVectorStyle) { const joinSource = join.getRightJoinSource(); return this._syncFormatters({ source: joinSource, @@ -540,19 +644,28 @@ export class VectorLayer extends AbstractLayer { fields: style .getDynamicPropertiesArray() .filter((dynamicStyleProp) => { - const matchingField = joinSource.getMetricFieldForName( - dynamicStyleProp.getField().getName() - ); + const matchingField = joinSource.getMetricFieldForName(dynamicStyleProp.getFieldName()); return dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.JOIN && !!matchingField; }) .map((dynamicStyleProp) => { - return dynamicStyleProp.getField(); + return dynamicStyleProp.getField()!; }), ...syncContext, }); } - async _syncFormatters({ source, dataRequestId, fields, startLoading, stopLoading, onLoadError }) { + async _syncFormatters({ + source, + dataRequestId, + fields, + startLoading, + stopLoading, + onLoadError, + }: { + dataRequestId: string; + fields: IField[]; + source: IVectorSource; + } & DataRequestContext) { if (fields.length === 0) { return; } @@ -573,7 +686,7 @@ export class VectorLayer extends AbstractLayer { try { startLoading(dataRequestId, requestToken, nextMeta); - const formatters = {}; + const formatters: { [key: string]: FieldFormatter | null } = {}; const promises = fields .filter((field) => { return field.canValueBeFormatted(); @@ -589,7 +702,7 @@ export class VectorLayer extends AbstractLayer { } } - async syncData(syncContext) { + async syncData(syncContext: DataRequestContext) { await this._syncData(syncContext, this.getSource(), this.getCurrentStyle()); } @@ -603,7 +716,7 @@ export class VectorLayer extends AbstractLayer { // Given 1 above, which source/style to use can not be stored in Layer instance state. // Given 2 above, which source/style to use can not be pulled from data request state. // Therefore, source and style are provided as arugments and must be used instead of calling getSource or getCurrentStyle. - async _syncData(syncContext, source, style) { + async _syncData(syncContext: DataRequestContext, source: IVectorSource, style: IVectorStyle) { if (this.isLoadingBounds()) { return; } @@ -624,11 +737,11 @@ export class VectorLayer extends AbstractLayer { _getSourceFeatureCollection() { const sourceDataRequest = this.getSourceDataRequest(); - return sourceDataRequest ? sourceDataRequest.getData() : null; + return sourceDataRequest ? (sourceDataRequest.getData() as FeatureCollection) : null; } - _syncFeatureCollectionWithMb(mbMap) { - const mbGeoJSONSource = mbMap.getSource(this.getId()); + _syncFeatureCollectionWithMb(mbMap: MbMap) { + const mbGeoJSONSource = mbMap.getSource(this.getId()) as MbGeoJSONSource; const featureCollection = this._getSourceFeatureCollection(); const featureCollectionOnMap = AbstractLayer.getBoundDataForSource(mbMap, this.getId()); @@ -653,7 +766,7 @@ export class VectorLayer extends AbstractLayer { } } - _setMbPointsProperties(mbMap, mvtSourceLayer) { + _setMbPointsProperties(mbMap: MbMap, mvtSourceLayer?: string) { const pointLayerId = this._getMbPointLayerId(); const symbolLayerId = this._getMbSymbolLayerId(); const pointLayer = mbMap.getLayer(pointLayerId); @@ -689,12 +802,12 @@ export class VectorLayer extends AbstractLayer { } } - _setMbCircleProperties(mbMap, mvtSourceLayer) { + _setMbCircleProperties(mbMap: MbMap, mvtSourceLayer?: string) { const sourceId = this.getId(); const pointLayerId = this._getMbPointLayerId(); const pointLayer = mbMap.getLayer(pointLayerId); if (!pointLayer) { - const mbLayer = { + const mbLayer: MbLayer = { id: pointLayerId, type: 'circle', source: sourceId, @@ -710,7 +823,7 @@ export class VectorLayer extends AbstractLayer { const textLayerId = this._getMbTextLayerId(); const textLayer = mbMap.getLayer(textLayerId); if (!textLayer) { - const mbLayer = { + const mbLayer: MbLayer = { id: textLayerId, type: 'symbol', source: sourceId, @@ -740,13 +853,13 @@ export class VectorLayer extends AbstractLayer { }); } - _setMbSymbolProperties(mbMap, mvtSourceLayer) { + _setMbSymbolProperties(mbMap: MbMap, mvtSourceLayer?: string) { const sourceId = this.getId(); const symbolLayerId = this._getMbSymbolLayerId(); const symbolLayer = mbMap.getLayer(symbolLayerId); if (!symbolLayer) { - const mbLayer = { + const mbLayer: MbLayer = { id: symbolLayerId, type: 'symbol', source: sourceId, @@ -775,7 +888,7 @@ export class VectorLayer extends AbstractLayer { }); } - _setMbLinePolygonProperties(mbMap, mvtSourceLayer) { + _setMbLinePolygonProperties(mbMap: MbMap, mvtSourceLayer?: string) { const sourceId = this.getId(); const fillLayerId = this._getMbPolygonLayerId(); const lineLayerId = this._getMbLineLayerId(); @@ -783,7 +896,7 @@ export class VectorLayer extends AbstractLayer { const hasJoins = this.hasJoins(); if (!mbMap.getLayer(fillLayerId)) { - const mbLayer = { + const mbLayer: MbLayer = { id: fillLayerId, type: 'fill', source: sourceId, @@ -795,7 +908,7 @@ export class VectorLayer extends AbstractLayer { mbMap.addLayer(mbLayer); } if (!mbMap.getLayer(lineLayerId)) { - const mbLayer = { + const mbLayer: MbLayer = { id: lineLayerId, type: 'line', source: sourceId, @@ -807,7 +920,7 @@ export class VectorLayer extends AbstractLayer { mbMap.addLayer(mbLayer); } if (!mbMap.getLayer(tooManyFeaturesLayerId)) { - const mbLayer = { + const mbLayer: MbLayer = { id: tooManyFeaturesLayerId, type: 'fill', source: sourceId, @@ -855,12 +968,12 @@ export class VectorLayer extends AbstractLayer { mbMap.setLayerZoomRange(tooManyFeaturesLayerId, this.getMinZoom(), this.getMaxZoom()); } - _syncStylePropertiesWithMb(mbMap) { + _syncStylePropertiesWithMb(mbMap: MbMap) { this._setMbPointsProperties(mbMap); this._setMbLinePolygonProperties(mbMap); } - _syncSourceBindingWithMb(mbMap) { + _syncSourceBindingWithMb(mbMap: MbMap) { const mbSource = mbMap.getSource(this._getMbSourceId()); if (!mbSource) { mbMap.addSource(this._getMbSourceId(), { @@ -883,7 +996,7 @@ export class VectorLayer extends AbstractLayer { } } - syncLayerWithMB(mbMap) { + syncLayerWithMB(mbMap: MbMap) { this._syncSourceBindingWithMb(mbMap); this._syncFeatureCollectionWithMb(mbMap); this._syncStylePropertiesWithMb(mbMap); @@ -924,15 +1037,15 @@ export class VectorLayer extends AbstractLayer { ]; } - ownsMbLayerId(mbLayerId) { + ownsMbLayerId(mbLayerId: string) { return this.getMbLayerIds().includes(mbLayerId); } - ownsMbSourceId(mbSourceId) { + ownsMbSourceId(mbSourceId: string) { return this.getId() === mbSourceId; } - _addJoinsToSourceTooltips(tooltipsFromSource) { + _addJoinsToSourceTooltips(tooltipsFromSource: ITooltipProperty[]) { for (let i = 0; i < tooltipsFromSource.length; i++) { const tooltipProperty = tooltipsFromSource[i]; const matchingJoins = []; @@ -947,7 +1060,7 @@ export class VectorLayer extends AbstractLayer { } } - async getPropertiesForTooltip(properties) { + async getPropertiesForTooltip(properties: GeoJsonProperties) { const vectorSource = this.getSource(); let allProperties = await vectorSource.getTooltipProperties(properties); this._addJoinsToSourceTooltips(allProperties); @@ -961,18 +1074,20 @@ export class VectorLayer extends AbstractLayer { canShowTooltip() { return ( - this.isVisible() && (this.getSource().canFormatFeatureProperties() || this.getJoins().length) + this.isVisible() && + (this.getSource().canFormatFeatureProperties() || this.getJoins().length > 0) ); } - getFeatureById(id) { + getFeatureById(id: string | number) { const featureCollection = this._getSourceFeatureCollection(); if (!featureCollection) { return null; } - return featureCollection.features.find((feature) => { - return feature.properties[FEATURE_ID_PROPERTY_NAME] === id; + const targetFeature = featureCollection.features.find((feature) => { + return feature.properties?.[FEATURE_ID_PROPERTY_NAME] === id; }); + return targetFeature ? targetFeature : null; } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts index be947d79f4e395..5c062f3419e28d 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts @@ -29,7 +29,7 @@ export interface IESAggSource extends IESSource { getValueAggsDsl(indexPattern: IndexPattern): { [key: string]: unknown }; } -export class AbstractESAggSource extends AbstractESSource { +export abstract class AbstractESAggSource extends AbstractESSource { private readonly _metricFields: IESAggField[]; private readonly _canReadFromGeoJson: boolean; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts index ada76b8e4e674e..b221d13bb0f8ac 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -10,6 +10,7 @@ import { MapFilters, MapQuery, VectorSourceSyncMeta, + VectorSourceRequestMeta, } from '../../../../common/descriptor_types'; import { GRID_RESOLUTION } from '../../../../common/constants'; import { IField } from '../../fields/field'; @@ -35,13 +36,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingle getLayerName(): string; getUrlTemplateWithMeta( - searchFilters: MapFilters & { - applyGlobalQuery: boolean; - fieldNames: string[]; - geogridPrecision?: number; - sourceQuery: MapQuery; - sourceMeta: VectorSourceSyncMeta; - } + searchFilters: VectorSourceRequestMeta ): Promise<{ layerName: string; urlTemplate: string; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts index 189e7dea1b0c1b..06df68283c434e 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts @@ -160,7 +160,8 @@ describe('ESGeoGridSource', () => { const { data, meta } = await geogridSource.getGeoJsonWithMeta( 'foobarLayer', vectorSourceRequestMeta, - () => {} + () => {}, + () => true ); expect(meta && meta.areResultsTrimmed).toEqual(false); diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.d.ts index 01fde589dcb84d..c11b6f0853cc7a 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.d.ts @@ -6,12 +6,14 @@ import { AbstractVectorSource } from '../vector_source'; import { IVectorSource } from '../vector_source'; +import { TimeRange } from '../../../../../../../src/plugins/data/common'; import { IndexPattern, ISearchSource } from '../../../../../../../src/plugins/data/public'; import { DynamicStylePropertyOptions, + MapQuery, VectorSourceRequestMeta, } from '../../../../common/descriptor_types'; -import { VectorStyle } from '../../styles/vector/vector_style'; +import { IVectorStyle } from '../../styles/vector/vector_style'; import { IDynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property'; export interface IESSource extends IVectorSource { @@ -25,13 +27,21 @@ export interface IESSource extends IVectorSource { limit: number, initialSearchContext?: object ): Promise; - loadStylePropsMeta( - layerName: string, - style: VectorStyle, - dynamicStyleProps: Array>, - registerCancelCallback: (requestToken: symbol, callback: () => void) => void, - searchFilters: VectorSourceRequestMeta - ): Promise; + loadStylePropsMeta({ + layerName, + style, + dynamicStyleProps, + registerCancelCallback, + sourceQuery, + timeFilters, + }: { + layerName: string; + style: IVectorStyle; + dynamicStyleProps: Array>; + registerCancelCallback: (callback: () => void) => void; + sourceQuery?: MapQuery; + timeFilters: TimeRange; + }): Promise; } export class AbstractESSource extends AbstractVectorSource implements IESSource { @@ -45,13 +55,21 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource limit: number, initialSearchContext?: object ): Promise; - loadStylePropsMeta( - layerName: string, - style: VectorStyle, - dynamicStyleProps: Array>, - registerCancelCallback: (requestToken: symbol, callback: () => void) => void, - searchFilters: VectorSourceRequestMeta - ): Promise; + loadStylePropsMeta({ + layerName, + style, + dynamicStyleProps, + registerCancelCallback, + sourceQuery, + timeFilters, + }: { + layerName: string; + style: IVectorStyle; + dynamicStyleProps: Array>; + registerCancelCallback: (callback: () => void) => void; + sourceQuery?: MapQuery; + timeFilters: TimeRange; + }): Promise; _runEsQuery: ({ requestId, requestName, diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js index ab56ceeab4e771..0c8cb5f5142470 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js @@ -284,13 +284,14 @@ export class AbstractESSource extends AbstractVectorSource { return indexPattern.getFormatterForField(fieldFromIndexPattern).getConverterFor('text'); } - async loadStylePropsMeta( + async loadStylePropsMeta({ layerName, style, dynamicStyleProps, registerCancelCallback, - searchFilters - ) { + sourceQuery, + timeFilters, + }) { const promises = dynamicStyleProps.map((dynamicStyleProp) => { return dynamicStyleProp.getFieldMetaRequest(); }); @@ -307,13 +308,11 @@ export class AbstractESSource extends AbstractVectorSource { searchSource.setField('index', indexPattern); searchSource.setField('size', 0); searchSource.setField('aggs', aggs); - if (searchFilters.sourceQuery) { - searchSource.setField('query', searchFilters.sourceQuery); + if (sourceQuery) { + searchSource.setField('query', sourceQuery); } if (style.isTimeAware() && (await this.isTimeAware())) { - searchSource.setField('filter', [ - getTimeFilter().createFilter(indexPattern, searchFilters.timeFilters), - ]); + searchSource.setField('filter', [getTimeFilter().createFilter(indexPattern, timeFilters)]); } const resp = await this._runEsQuery({ diff --git a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.d.ts index 248ca2b9212b4d..ef1ada8da82899 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.d.ts @@ -4,10 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ +import { MapQuery, VectorJoinSourceRequestMeta } from '../../../../common/descriptor_types'; import { IField } from '../../fields/field'; import { IESAggSource } from '../es_agg_source'; +import { PropertiesMap } from '../../joins/join'; export interface IESTermSource extends IESAggSource { - getTermField(): IField; - hasCompleteConfig(): boolean; + getTermField: () => IField; + hasCompleteConfig: () => boolean; + getWhereQuery: () => MapQuery; + getPropertiesMap: ( + searchFilters: VectorJoinSourceRequestMeta, + leftSourceName: string, + leftFieldName: string, + registerCancelCallback: (callback: () => void) => void + ) => PropertiesMap; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js index 359d22d2c44ce7..ff52dccdd2ef40 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js @@ -119,9 +119,7 @@ export class ESTermSource extends AbstractESAggSource { }); const countPropertyName = this.getAggKey(AGG_TYPE.COUNT); - return { - propertiesMap: extractPropertiesMap(rawEsData, countPropertyName), - }; + return extractPropertiesMap(rawEsData, countPropertyName); } isFilterByMapBounds() { diff --git a/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_source.js b/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_source.js index eeb34ed672221c..d937edb4ed3620 100644 --- a/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_source.js +++ b/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_source.js @@ -74,6 +74,7 @@ export class KibanaRegionmapSource extends AbstractVectorSource { }); return { data: featureCollection, + meta: {}, }; } diff --git a/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source.tsx index 3e515613b3fd03..440f0cb4457e84 100644 --- a/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source.tsx @@ -179,7 +179,7 @@ export class MVTSingleLayerVectorSource getBoundsForFilters( boundsFilters: BoundsFilters, - registerCancelCallback: (requestToken: symbol, callback: () => void) => void + registerCancelCallback: (callback: () => void) => void ): MapExtent | null { return null; } @@ -192,6 +192,18 @@ export class MVTSingleLayerVectorSource return false; } + isBoundsAware() { + return false; + } + + getSourceTooltipContent() { + return { tooltipContent: null, areResultsTrimmed: false }; + } + + async getLeftJoinFields() { + return []; + } + async getTooltipProperties( properties: GeoJsonProperties, featureId?: string | number diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.d.ts b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.d.ts index a481e273bc33e0..7bf1db43c28712 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.d.ts @@ -19,6 +19,12 @@ import { } from '../../../../common/descriptor_types'; import { VECTOR_SHAPE_TYPE } from '../../../../common/constants'; import { ITooltipProperty } from '../../tooltips/tooltip_property'; +import { DataRequest } from '../../util/data_request'; + +export interface SourceTooltipConfig { + tooltipContent: string | null; + areResultsTrimmed: boolean; +} export type GeoJsonFetchMeta = ESSearchSourceResponseMeta; @@ -30,8 +36,8 @@ export type GeoJsonWithMeta = { export type BoundsFilters = { applyGlobalQuery: boolean; filters: Filter[]; - query: MapQuery; - sourceQuery: MapQuery; + query?: MapQuery; + sourceQuery?: MapQuery; timeFilters: TimeRange; }; @@ -39,44 +45,52 @@ export interface IVectorSource extends ISource { getTooltipProperties(properties: GeoJsonProperties): Promise; getBoundsForFilters( boundsFilters: BoundsFilters, - registerCancelCallback: (requestToken: symbol, callback: () => void) => void + registerCancelCallback: (callback: () => void) => void ): MapExtent | null; getGeoJsonWithMeta( - layerName: 'string', + layerName: string, searchFilters: MapFilters, - registerCancelCallback: (callback: () => void) => void + registerCancelCallback: (callback: () => void) => void, + isRequestStillActive: () => boolean ): Promise; getFields(): Promise; getFieldByName(fieldName: string): IField | null; + getLeftJoinFields(): Promise; getSyncMeta(): VectorSourceSyncMeta; getFieldNames(): string[]; getApplyGlobalQuery(): boolean; createField({ fieldName }: { fieldName: string }): IField; canFormatFeatureProperties(): boolean; getSupportedShapeTypes(): Promise; + isBoundsAware(): boolean; + getSourceTooltipContent(sourceDataRequest?: DataRequest): SourceTooltipConfig; } export class AbstractVectorSource extends AbstractSource implements IVectorSource { getTooltipProperties(properties: GeoJsonProperties): Promise; getBoundsForFilters( boundsFilters: BoundsFilters, - registerCancelCallback: (requestToken: symbol, callback: () => void) => void + registerCancelCallback: (callback: () => void) => void ): MapExtent | null; getGeoJsonWithMeta( layerName: string, searchFilters: VectorSourceRequestMeta, - registerCancelCallback: (callback: () => void) => void + registerCancelCallback: (callback: () => void) => void, + isRequestStillActive: () => boolean ): Promise; getFields(): Promise; getFieldByName(fieldName: string): IField | null; + getLeftJoinFields(): Promise; getSyncMeta(): VectorSourceSyncMeta; getSupportedShapeTypes(): Promise; canFormatFeatureProperties(): boolean; getApplyGlobalQuery(): boolean; getFieldNames(): string[]; createField({ fieldName }: { fieldName: string }): IField; + isBoundsAware(): boolean; + getSourceTooltipContent(sourceDataRequest?: DataRequest): SourceTooltipConfig; } export interface ITiledSingleLayerVectorSource extends IVectorSource { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 1244c53afe9a6c..5d0d9712ef988f 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -5,7 +5,7 @@ */ import _ from 'lodash'; -import React from 'react'; +import React, { ReactElement } from 'react'; import { Map as MbMap, FeatureIdentifier } from 'mapbox-gl'; import { FeatureCollection } from 'geojson'; // @ts-expect-error @@ -92,6 +92,55 @@ export interface IVectorStyle extends IStyle { mapColors: string[] ): { hasChanges: boolean; nextStyleDescriptor?: VectorStyleDescriptor }; pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest): Promise; + isTimeAware: () => boolean; + getIcon: () => ReactElement; + hasLegendDetails: () => Promise; + renderLegendDetails: () => ReactElement; + clearFeatureState: (featureCollection: FeatureCollection, mbMap: MbMap, sourceId: string) => void; + setFeatureStateAndStyleProps: ( + featureCollection: FeatureCollection, + mbMap: MbMap, + mbSourceId: string + ) => boolean; + arePointsSymbolizedAsCircles: () => boolean; + setMBPaintProperties: ({ + alpha, + mbMap, + fillLayerId, + lineLayerId, + }: { + alpha: number; + mbMap: MbMap; + fillLayerId: string; + lineLayerId: string; + }) => void; + setMBPaintPropertiesForPoints: ({ + alpha, + mbMap, + pointLayerId, + }: { + alpha: number; + mbMap: MbMap; + pointLayerId: string; + }) => void; + setMBPropertiesForLabelText: ({ + alpha, + mbMap, + textLayerId, + }: { + alpha: number; + mbMap: MbMap; + textLayerId: string; + }) => void; + setMBSymbolPropertiesForPoints: ({ + mbMap, + symbolLayerId, + alpha, + }: { + alpha: number; + mbMap: MbMap; + symbolLayerId: string; + }) => void; } export class VectorStyle implements IVectorStyle { @@ -594,12 +643,12 @@ export class VectorStyle implements IVectorStyle { mbSourceId: string ) { if (!featureCollection) { - return; + return false; } const dynamicStyleProps = this.getDynamicPropertiesArray(); if (dynamicStyleProps.length === 0) { - return; + return false; } const tmpFeatureIdentifier: FeatureIdentifier = { diff --git a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.test.tsx b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.test.tsx index 6c6cb6ba143cda..24728465de3bdd 100644 --- a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.test.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { shallow } from 'enzyme'; import { AbstractLayer, ILayer } from '../../../../../../classes/layers/layer'; import { AbstractSource, ISource } from '../../../../../../classes/sources/source'; -import { IStyle } from '../../../../../../classes/styles/style'; import { TOCEntryActionsPopover } from './toc_entry_actions_popover'; @@ -17,28 +16,17 @@ let supportsFitToBounds: boolean; class MockSource extends AbstractSource implements ISource {} -class MockStyle implements IStyle { - renderEditor() { - return null; - } - - getType() { - return 'mockStyle'; - } -} - class LayerMock extends AbstractLayer implements ILayer { constructor() { const sourceDescriptor = { type: 'mySourceType', }; const source = new MockSource(sourceDescriptor); - const style = new MockStyle(); const layerDescriptor = { id: 'testLayer', sourceDescriptor, }; - super({ layerDescriptor, source, style }); + super({ layerDescriptor, source }); } async supportsFitToBounds(): Promise { From e92a4ab4bf5ec175fc572f4d14b5da173de266a7 Mon Sep 17 00:00:00 2001 From: Ashik Meerankutty Date: Fri, 2 Oct 2020 07:34:22 +0530 Subject: [PATCH 03/21] [APM] Service Inventory Updated the `EuiBadge` to use the `behind_text` vars instead of the base colors for the health status badges (#77844) * Use behind_text colors in health status * Separated badge color usage from getSeverityColor --- .../plugins/apm/common/service_health_status.ts | 16 ++++++++++++++++ .../ServiceOverview/ServiceList/HealthBadge.tsx | 4 ++-- .../__snapshots__/ServiceOverview.test.tsx.snap | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/apm/common/service_health_status.ts b/x-pack/plugins/apm/common/service_health_status.ts index 1d4bcfb3b0e07b..f66e03a9733a3e 100644 --- a/x-pack/plugins/apm/common/service_health_status.ts +++ b/x-pack/plugins/apm/common/service_health_status.ts @@ -54,6 +54,22 @@ export function getServiceHealthStatusColor( } } +export function getServiceHealthStatusBadgeColor( + theme: EuiTheme, + status: ServiceHealthStatus +) { + switch (status) { + case ServiceHealthStatus.healthy: + return theme.eui.euiColorVis0_behindText; + case ServiceHealthStatus.warning: + return theme.eui.euiColorVis5_behindText; + case ServiceHealthStatus.critical: + return theme.eui.euiColorVis9_behindText; + case ServiceHealthStatus.unknown: + return theme.eui.euiColorMediumShade; + } +} + export function getServiceHealthStatusLabel(status: ServiceHealthStatus) { switch (status) { case ServiceHealthStatus.critical: diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/HealthBadge.tsx b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/HealthBadge.tsx index c6be0a352ef666..e8ad3e65b1a47e 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/HealthBadge.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/HealthBadge.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { EuiBadge } from '@elastic/eui'; import { - getServiceHealthStatusColor, + getServiceHealthStatusBadgeColor, getServiceHealthStatusLabel, ServiceHealthStatus, } from '../../../../../common/service_health_status'; @@ -20,7 +20,7 @@ export function HealthBadge({ const theme = useTheme(); return ( - + {getServiceHealthStatusLabel(healthStatus)} ); diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap index 40a2b6a5fa81b1..ee3a4fce0dbaae 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap @@ -153,7 +153,7 @@ NodeList [ > Date: Fri, 2 Oct 2020 09:03:08 +0300 Subject: [PATCH 04/21] [Functional] Add retry on custom formatter test (#78729) Co-authored-by: Elastic Machine --- test/functional/apps/visualize/_tsvb_time_series.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/functional/apps/visualize/_tsvb_time_series.ts b/test/functional/apps/visualize/_tsvb_time_series.ts index 0b2a52b367a20a..d4a079a38c8143 100644 --- a/test/functional/apps/visualize/_tsvb_time_series.ts +++ b/test/functional/apps/visualize/_tsvb_time_series.ts @@ -84,8 +84,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visualBuilder.clickSeriesOption(); await visualBuilder.enterSeriesTemplate('$ {{value}}'); - const actualCount = await visualBuilder.getRhythmChartLegendValue(); - expect(actualCount).to.be(expectedLegendValue); + await retry.try(async () => { + const actualCount = await visualBuilder.getRhythmChartLegendValue(); + expect(actualCount).to.be(expectedLegendValue); + }); }); it('should show the correct count in the legend with percent formatter', async () => { From 4ddcd1d2a6bf3ffbec37844468c4e4af827f739f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Fri, 2 Oct 2020 09:45:50 +0200 Subject: [PATCH 05/21] [APM] Fix anomalies not showing up on transaction charts (#76930) * [APM] Fix anomalies not showing up on transaction charts * Added API tests to check transaction groups charts for anomaly data * Improve test names and assertions from PR feedback * Updated the transaction groups chart API to make `environment` a required param while making `uiFilters` optional * updates the basic API tests for transaction_groups/charts with the required `environment` param * makes uiFIltersES default to [] on core setup and removes SetupUIFilters type * fixes vertical shade * - replaces uiFiltersES with esFilter & uiFilters and cleans up related code around these - deduplicates the required environment in the transaction_groups/charts API * updates basic apm_api_integration tests * pr feedback * updates api test snapshots with correct anomaly data * removed environment query param from useTransactionCharts and ensures it's included in uiFilters returned from useUrlParams Co-authored-by: Oliver Gupte --- .../example_response_opbeans_beats.json | 42 ++--- .../public/context/UrlParamsContext/index.tsx | 7 +- .../plugins/apm/public/utils/testHelpers.tsx | 7 +- .../errors/__snapshots__/queries.test.ts.snap | 6 +- .../__snapshots__/queries.test.ts.snap | 4 +- .../__tests__/get_buckets.test.ts | 5 +- .../lib/errors/distribution/get_buckets.ts | 12 +- .../errors/distribution/get_distribution.ts | 8 +- .../apm/server/lib/errors/get_error_group.ts | 12 +- .../apm/server/lib/errors/get_error_groups.ts | 8 +- ...{get_ui_filters_es.ts => get_es_filter.ts} | 2 +- .../get_parsed_ui_filters.ts | 23 --- .../apm/server/lib/helpers/setup_request.ts | 41 ++--- .../__snapshots__/queries.test.ts.snap | 54 +++--- .../server/lib/metrics/by_agent/default.ts | 8 +- .../java/gc/fetch_and_transform_gc_metrics.ts | 8 +- .../by_agent/java/gc/get_gc_rate_chart.ts | 8 +- .../by_agent/java/gc/get_gc_time_chart.ts | 8 +- .../by_agent/java/heap_memory/index.ts | 8 +- .../server/lib/metrics/by_agent/java/index.ts | 8 +- .../by_agent/java/non_heap_memory/index.ts | 8 +- .../by_agent/java/thread_count/index.ts | 8 +- .../lib/metrics/by_agent/shared/cpu/index.ts | 8 +- .../metrics/by_agent/shared/memory/index.ts | 10 +- .../metrics/fetch_and_transform_metrics.ts | 8 +- .../get_metrics_chart_data_by_agent.ts | 8 +- .../__snapshots__/queries.test.ts.snap | 14 +- .../lib/rum_client/get_client_metrics.ts | 8 +- .../server/lib/rum_client/get_js_errors.ts | 8 +- .../lib/rum_client/get_long_task_metrics.ts | 8 +- .../rum_client/get_page_load_distribution.ts | 10 +- .../lib/rum_client/get_page_view_trends.ts | 8 +- .../lib/rum_client/get_pl_dist_breakdown.ts | 8 +- .../server/lib/rum_client/get_rum_services.ts | 8 +- .../server/lib/rum_client/get_url_search.ts | 8 +- .../lib/rum_client/get_visitor_breakdown.ts | 8 +- .../lib/rum_client/get_web_core_vitals.ts | 8 +- .../server/lib/service_map/get_service_map.ts | 2 +- .../get_service_map_service_node_info.test.ts | 6 +- .../get_service_map_service_node_info.ts | 9 +- .../group_resource_nodes_grouped.json | 4 +- .../group_resource_nodes_pregrouped.json | 4 +- .../__snapshots__/queries.test.ts.snap | 6 +- .../apm/server/lib/service_nodes/index.ts | 8 +- .../__snapshots__/queries.test.ts.snap | 10 +- .../lib/services/get_service_node_metadata.ts | 8 +- .../get_services/get_services_items.ts | 12 +- .../server/lib/services/get_services/index.ts | 11 +- .../__snapshots__/queries.test.ts.snap | 14 +- .../server/lib/transaction_groups/fetcher.ts | 8 +- .../lib/transaction_groups/get_error_rate.ts | 12 +- .../get_transaction_sample_for_group.ts | 12 +- .../server/lib/transaction_groups/index.ts | 8 +- .../__snapshots__/queries.test.ts.snap | 12 +- .../lib/transactions/breakdown/index.test.ts | 3 +- .../lib/transactions/breakdown/index.ts | 12 +- .../charts/get_anomaly_data/fetcher.ts | 11 +- .../charts/get_anomaly_data/index.ts | 40 ++--- .../get_timeseries_data/fetcher.test.ts | 5 +- .../charts/get_timeseries_data/fetcher.ts | 12 +- .../charts/get_timeseries_data/index.ts | 8 +- .../server/lib/transactions/charts/index.ts | 10 +- .../distribution/get_buckets/index.ts | 12 +- .../distribution/get_distribution_max.ts | 12 +- .../lib/transactions/distribution/index.ts | 8 +- .../lib/transactions/get_transaction/index.ts | 8 +- .../server/lib/transactions/queries.test.ts | 3 - .../__snapshots__/queries.test.ts.snap | 2 +- .../get_local_filter_query.ts | 4 +- .../local_ui_filters/queries.test.ts | 2 +- .../plugins/apm/server/projections/errors.ts | 12 +- .../plugins/apm/server/projections/metrics.ts | 12 +- .../projections/rum_page_load_transactions.ts | 18 +- .../apm/server/projections/service_nodes.ts | 8 +- .../apm/server/projections/services.ts | 12 +- .../server/projections/transaction_groups.ts | 8 +- .../apm/server/projections/transactions.ts | 12 +- .../plugins/apm/server/routes/service_map.ts | 5 - x-pack/plugins/apm/server/routes/services.ts | 12 +- .../apm/server/routes/transaction_groups.ts | 21 +-- .../plugins/apm/server/routes/ui_filters.ts | 13 +- .../plugins/apm/server/utils/test_helpers.tsx | 7 +- .../basic/tests/feature_controls.ts | 6 +- .../transaction_groups/transaction_charts.ts | 2 +- .../apm_api_integration/trial/tests/index.ts | 1 + .../transaction_groups_charts.snap | 43 +++++ .../services/transaction_groups_charts.ts | 161 ++++++++++++++++++ 87 files changed, 528 insertions(+), 548 deletions(-) rename x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/{get_ui_filters_es.ts => get_es_filter.ts} (96%) delete mode 100644 x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_parsed_ui_filters.ts create mode 100644 x-pack/test/apm_api_integration/trial/tests/services/__snapshots__/transaction_groups_charts.snap create mode 100644 x-pack/test/apm_api_integration/trial/tests/services/transaction_groups_charts.ts diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_opbeans_beats.json b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_opbeans_beats.json index 153fa57bb05e70..cfd905f145fe2c 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_opbeans_beats.json +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_opbeans_beats.json @@ -83,7 +83,7 @@ "id": "opbeans-go~>postgresql", "sourceData": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go" }, @@ -103,7 +103,7 @@ "id": "opbeans-go~opbeans-java", "sourceData": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go" }, @@ -123,13 +123,13 @@ "id": "opbeans-go~opbeans-node", "sourceData": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go" }, "targetData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" }, @@ -143,7 +143,7 @@ "id": "opbeans-go~opbeans-ruby", "sourceData": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go" }, @@ -189,7 +189,7 @@ }, "targetData": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go" }, @@ -209,7 +209,7 @@ }, "targetData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" } @@ -242,7 +242,7 @@ "id": "opbeans-node~>postgresql", "sourceData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" }, @@ -262,7 +262,7 @@ "id": "opbeans-node~>redis", "sourceData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" }, @@ -282,13 +282,13 @@ "id": "opbeans-node~opbeans-go", "sourceData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" }, "targetData": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go" }, @@ -302,7 +302,7 @@ "id": "opbeans-node~opbeans-python", "sourceData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" }, @@ -322,7 +322,7 @@ "id": "opbeans-node~opbeans-ruby", "sourceData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" }, @@ -408,7 +408,7 @@ }, "targetData": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go" } @@ -427,7 +427,7 @@ }, "targetData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" }, @@ -487,7 +487,7 @@ }, "targetData": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go" }, @@ -527,7 +527,7 @@ }, "targetData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" }, @@ -566,7 +566,7 @@ }, "targetData": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go" } @@ -602,7 +602,7 @@ }, "targetData": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" } @@ -673,7 +673,7 @@ { "data": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs", "anomaly_score": 41.31593099784474, @@ -733,7 +733,7 @@ { "data": { "id": "opbeans-go", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-go", "agent.name": "go", "anomaly_score": 0.2633884161762746, diff --git a/x-pack/plugins/apm/public/context/UrlParamsContext/index.tsx b/x-pack/plugins/apm/public/context/UrlParamsContext/index.tsx index 9eb4704a2ca29a..5682009019d7f8 100644 --- a/x-pack/plugins/apm/public/context/UrlParamsContext/index.tsx +++ b/x-pack/plugins/apm/public/context/UrlParamsContext/index.tsx @@ -25,6 +25,7 @@ import { import { pickKeys } from '../../../common/utils/pick_keys'; import { useDeepObjectIdentity } from '../../hooks/useDeepObjectIdentity'; import { LocalUIFilterName } from '../../../common/ui_filter'; +import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; interface TimeRange { rangeFrom: string; @@ -38,7 +39,11 @@ function useUiFilters(params: IUrlParams): UIFilters { (val) => (val ? val.split(',') : []) ) as Partial>; - return useDeepObjectIdentity({ kuery, environment, ...localUiFilters }); + return useDeepObjectIdentity({ + kuery, + environment: environment || ENVIRONMENT_ALL.value, + ...localUiFilters, + }); } const defaultRefresh = (_time: TimeRange) => {}; diff --git a/x-pack/plugins/apm/public/utils/testHelpers.tsx b/x-pack/plugins/apm/public/utils/testHelpers.tsx index 971455fde39462..7826e9672a3bbe 100644 --- a/x-pack/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/plugins/apm/public/utils/testHelpers.tsx @@ -25,6 +25,7 @@ import { } from '../../typings/elasticsearch'; import { MockApmPluginContextWrapper } from '../context/ApmPluginContext/MockApmPluginContext'; import { UrlParamsProvider } from '../context/UrlParamsContext'; +import { UIFilters } from '../../typings/ui_filters'; const originalConsoleWarn = console.warn; // eslint-disable-line no-console /** @@ -118,7 +119,8 @@ interface MockSetup { apmEventClient: any; internalClient: any; config: APMConfig; - uiFiltersES: ESFilter[]; + uiFilters: UIFilters; + esFilter: ESFilter[]; indices: { /* eslint-disable @typescript-eslint/naming-convention */ 'apm_oss.sourcemapIndices': string; @@ -179,7 +181,8 @@ export async function inspectSearchParams( }, } ) as APMConfig, - uiFiltersES: [{ term: { 'my.custom.ui.filter': 'foo-bar' } }], + uiFilters: { environment: 'test' }, + esFilter: [{ term: { 'service.environment': 'test' } }], indices: { /* eslint-disable @typescript-eslint/naming-convention */ 'apm_oss.sourcemapIndices': 'myIndex', diff --git a/x-pack/plugins/apm/server/lib/errors/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/errors/__snapshots__/queries.test.ts.snap index 63b6c9cde4d0d1..632232ffb075d8 100644 --- a/x-pack/plugins/apm/server/lib/errors/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/errors/__snapshots__/queries.test.ts.snap @@ -32,7 +32,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -119,7 +119,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -194,7 +194,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/errors/distribution/__snapshots__/queries.test.ts.snap index ea142ca2acc002..b329499c8b0452 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/errors/distribution/__snapshots__/queries.test.ts.snap @@ -40,7 +40,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -91,7 +91,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts b/x-pack/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts index 1a83113de35f2a..50da1f9c20d16c 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts +++ b/x-pack/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts @@ -41,7 +41,10 @@ describe('timeseriesFetcher', () => { get: () => 'myIndex', } ) as APMConfig, - uiFiltersES: [ + uiFilters: { + environment: 'prod', + }, + esFilter: [ { term: { 'service.environment': 'prod' }, }, diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts index de6df15354e79c..a42710947a7924 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts +++ b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts @@ -11,11 +11,7 @@ import { SERVICE_NAME, } from '../../../../common/elasticsearch_fieldnames'; import { rangeFilter } from '../../../../common/utils/range_filter'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; export async function getBuckets({ serviceName, @@ -26,13 +22,13 @@ export async function getBuckets({ serviceName: string; groupId?: string; bucketSize: number; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { - const { start, end, uiFiltersES, apmEventClient } = setup; + const { start, end, esFilter, apmEventClient } = setup; const filter: ESFilter[] = [ { term: { [SERVICE_NAME]: serviceName } }, { range: rangeFilter(start, end) }, - ...uiFiltersES, + ...esFilter, ]; if (groupId) { diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_distribution.ts b/x-pack/plugins/apm/server/lib/errors/distribution/get_distribution.ts index 3b48b6c5be5944..dea518cad8e405 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/get_distribution.ts +++ b/x-pack/plugins/apm/server/lib/errors/distribution/get_distribution.ts @@ -5,11 +5,7 @@ */ import { PromiseReturnType } from '../../../../typings/common'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { getBuckets } from './get_buckets'; import { BUCKET_TARGET_COUNT } from '../../transactions/constants'; @@ -28,7 +24,7 @@ export async function getErrorDistribution({ }: { serviceName: string; groupId?: string; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { const bucketSize = getBucketSize({ start: setup.start, end: setup.end }); const { buckets, noHits } = await getBuckets({ diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_group.ts b/x-pack/plugins/apm/server/lib/errors/get_error_group.ts index b23c955b57183b..0fbc7720f7111f 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_group.ts +++ b/x-pack/plugins/apm/server/lib/errors/get_error_group.ts @@ -12,11 +12,7 @@ import { } from '../../../common/elasticsearch_fieldnames'; import { PromiseReturnType } from '../../../typings/common'; import { rangeFilter } from '../../../common/utils/range_filter'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getTransaction } from '../transactions/get_transaction'; export type ErrorGroupAPIResponse = PromiseReturnType; @@ -29,9 +25,9 @@ export async function getErrorGroup({ }: { serviceName: string; groupId: string; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { - const { start, end, uiFiltersES, apmEventClient } = setup; + const { start, end, esFilter, apmEventClient } = setup; const params = { apm: { @@ -45,7 +41,7 @@ export async function getErrorGroup({ { term: { [SERVICE_NAME]: serviceName } }, { term: { [ERROR_GROUP_ID]: groupId } }, { range: rangeFilter(start, end) }, - ...uiFiltersES, + ...esFilter, ], should: [{ term: { [TRANSACTION_SAMPLED]: true } }], }, diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts index ab1c2149be3436..006d2fae3d4fb1 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts +++ b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts @@ -13,11 +13,7 @@ import { ERROR_LOG_MESSAGE, } from '../../../common/elasticsearch_fieldnames'; import { PromiseReturnType } from '../../../typings/common'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getErrorGroupsProjection } from '../../projections/errors'; import { mergeProjection } from '../../projections/util/merge_projection'; import { SortOptions } from '../../../typings/elasticsearch/aggregations'; @@ -35,7 +31,7 @@ export async function getErrorGroups({ serviceName: string; sortField?: string; sortDirection?: 'asc' | 'desc'; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { const { apmEventClient } = setup; diff --git a/x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_ui_filters_es.ts b/x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_es_filter.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_ui_filters_es.ts rename to x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_es_filter.ts index c1405b44f2a8ac..1b8f32d4de8b93 100644 --- a/x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_ui_filters_es.ts +++ b/x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_es_filter.ts @@ -13,7 +13,7 @@ import { } from '../../ui_filters/local_ui_filters/config'; import { esKuery } from '../../../../../../../src/plugins/data/server'; -export function getUiFiltersES(uiFilters: UIFilters) { +export function getEsFilter(uiFilters: UIFilters) { const { kuery, environment, ...localFilterValues } = uiFilters; const mappedFilters = localUIFilterNames .filter((name) => name in localFilterValues) diff --git a/x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_parsed_ui_filters.ts b/x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_parsed_ui_filters.ts deleted file mode 100644 index 324da199807c7d..00000000000000 --- a/x-pack/plugins/apm/server/lib/helpers/convert_ui_filters/get_parsed_ui_filters.ts +++ /dev/null @@ -1,23 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Logger } from 'src/core/server'; -import { UIFilters } from '../../../../typings/ui_filters'; - -export function getParsedUiFilters({ - uiFilters, - logger, -}: { - uiFilters: string; - logger: Logger; -}): UIFilters { - try { - return JSON.parse(uiFilters); - } catch (error) { - logger.error(error); - } - return {}; -} diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts index eba75433a51486..26896a050dd882 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts @@ -5,6 +5,7 @@ */ import moment from 'moment'; +import { Logger } from 'kibana/server'; import { isActivePlatinumLicense } from '../../../common/service_map'; import { UI_SETTINGS } from '../../../../../../src/plugins/data/common'; import { KibanaRequest } from '../../../../../../src/core/server'; @@ -14,7 +15,7 @@ import { ApmIndicesConfig, } from '../settings/apm_indices/get_apm_indices'; import { ESFilter } from '../../../typings/elasticsearch'; -import { getUiFiltersES } from './convert_ui_filters/get_ui_filters_es'; +import { getEsFilter } from './convert_ui_filters/get_es_filter'; import { APMRequestHandlerContext } from '../../routes/typings'; import { ProcessorEvent } from '../../../common/processor_event'; import { @@ -25,14 +26,8 @@ import { APMInternalClient, createInternalESClient, } from './create_es_client/create_internal_es_client'; +import { UIFilters } from '../../../typings/ui_filters'; -function decodeUiFilters(uiFiltersEncoded?: string) { - if (!uiFiltersEncoded) { - return []; - } - const uiFilters = JSON.parse(uiFiltersEncoded); - return getUiFiltersES(uiFilters); -} // Explicitly type Setup to prevent TS initialization errors // https://github.com/microsoft/TypeScript/issues/34933 @@ -42,6 +37,8 @@ export interface Setup { ml?: ReturnType; config: APMConfig; indices: ApmIndicesConfig; + uiFilters: UIFilters; + esFilter: ESFilter[]; } export interface SetupTimeRange { @@ -49,10 +46,6 @@ export interface SetupTimeRange { end: number; } -export interface SetupUIFilters { - uiFiltersES: ESFilter[]; -} - interface SetupRequestParams { query?: { _debug?: boolean; @@ -65,16 +58,13 @@ interface SetupRequestParams { type InferSetup = Setup & (TParams extends { query: { start: string } } ? { start: number } : {}) & - (TParams extends { query: { end: string } } ? { end: number } : {}) & - (TParams extends { query: { uiFilters: string } } - ? { uiFiltersES: ESFilter[] } - : {}); + (TParams extends { query: { end: string } } ? { end: number } : {}); export async function setupRequest( context: APMRequestHandlerContext, request: KibanaRequest ): Promise> { - const { config } = context; + const { config, logger } = context; const { query } = context.params; const [indices, includeFrozen] = await Promise.all([ @@ -85,7 +75,7 @@ export async function setupRequest( context.core.uiSettings.client.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN), ]); - const uiFiltersES = decodeUiFilters(query.uiFilters); + const uiFilters = decodeUiFilters(logger, query.uiFilters); const coreSetupRequest = { indices, @@ -108,12 +98,13 @@ export async function setupRequest( ) : undefined, config, + uiFilters, + esFilter: getEsFilter(uiFilters), }; return { ...('start' in query ? { start: moment.utc(query.start).valueOf() } : {}), ...('end' in query ? { end: moment.utc(query.end).valueOf() } : {}), - ...('uiFilters' in query ? { uiFiltersES } : {}), ...coreSetupRequest, } as InferSetup; } @@ -129,3 +120,15 @@ function getMlSetup( modules: ml.modulesProvider(request, savedObjectsClient), }; } + +function decodeUiFilters(logger: Logger, uiFiltersEncoded?: string): UIFilters { + if (!uiFiltersEncoded) { + return {}; + } + try { + return JSON.parse(uiFiltersEncoded); + } catch (error) { + logger.error(error); + return {}; + } +} diff --git a/x-pack/plugins/apm/server/lib/metrics/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/metrics/__snapshots__/queries.test.ts.snap index 2868dcfda97b6e..961a1eee61d1d5 100644 --- a/x-pack/plugins/apm/server/lib/metrics/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/metrics/__snapshots__/queries.test.ts.snap @@ -87,7 +87,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -175,7 +175,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -206,7 +206,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -231,7 +231,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -258,7 +258,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -283,7 +283,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -338,7 +338,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -431,7 +431,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -514,7 +514,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -623,7 +623,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -717,7 +717,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -748,7 +748,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -773,7 +773,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -800,7 +800,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -825,7 +825,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -886,7 +886,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -985,7 +985,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -1074,7 +1074,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -1172,7 +1172,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -1255,7 +1255,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -1286,7 +1286,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -1311,7 +1311,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -1338,7 +1338,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -1363,7 +1363,7 @@ Object { "lang": "painless", "source": " /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -1413,7 +1413,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -1501,7 +1501,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -1579,7 +1579,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts index 6ee507d7b9bb16..fbcbc9f12791fa 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts @@ -4,16 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { getCPUChartData } from './shared/cpu'; import { getMemoryChartData } from './shared/memory'; export async function getDefaultMetricsCharts( - setup: Setup & SetupTimeRange & SetupUIFilters, + setup: Setup & SetupTimeRange, serviceName: string ) { const charts = await Promise.all([ diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts index d7e64bdcacd12b..2ed11480a75857 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts @@ -11,11 +11,7 @@ import { sum, round } from 'lodash'; import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../../helpers/setup_request'; import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; import { ChartBase } from '../../../types'; import { getMetricsProjection } from '../../../../../projections/metrics'; @@ -36,7 +32,7 @@ export async function fetchAndTransformGcMetrics({ chartBase, fieldName, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName: string; serviceNodeName?: string; chartBase: ChartBase; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_rate_chart.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_rate_chart.ts index 6e562b9a8ee870..7cedeb828e3b73 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_rate_chart.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_rate_chart.ts @@ -7,11 +7,7 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import { METRIC_JAVA_GC_COUNT } from '../../../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../../helpers/setup_request'; import { fetchAndTransformGcMetrics } from './fetch_and_transform_gc_metrics'; import { ChartBase } from '../../../types'; @@ -35,7 +31,7 @@ const chartBase: ChartBase = { }; const getGcRateChart = ( - setup: Setup & SetupTimeRange & SetupUIFilters, + setup: Setup & SetupTimeRange, serviceName: string, serviceNodeName?: string ) => { diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_time_chart.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_time_chart.ts index 0b9d6240fc1c9b..f21d3d8e7c0565 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_time_chart.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_time_chart.ts @@ -7,11 +7,7 @@ import theme from '@elastic/eui/dist/eui_theme_light.json'; import { i18n } from '@kbn/i18n'; import { METRIC_JAVA_GC_TIME } from '../../../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../../helpers/setup_request'; import { fetchAndTransformGcMetrics } from './fetch_and_transform_gc_metrics'; import { ChartBase } from '../../../types'; @@ -35,7 +31,7 @@ const chartBase: ChartBase = { }; const getGcTimeChart = ( - setup: Setup & SetupTimeRange & SetupUIFilters, + setup: Setup & SetupTimeRange, serviceName: string, serviceNodeName?: string ) => { diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts index ba3183c0fa7d7a..eb79897f9f0558 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts @@ -12,11 +12,7 @@ import { METRIC_JAVA_HEAP_MEMORY_USED, AGENT_NAME, } from '../../../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../../helpers/setup_request'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; import { ChartBase } from '../../../types'; @@ -55,7 +51,7 @@ const chartBase: ChartBase = { }; export async function getHeapMemoryChart( - setup: Setup & SetupTimeRange & SetupUIFilters, + setup: Setup & SetupTimeRange, serviceName: string, serviceNodeName?: string ) { diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts index 21caab6590fc46..d4084701f0f49a 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts @@ -5,11 +5,7 @@ */ import { getHeapMemoryChart } from './heap_memory'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../helpers/setup_request'; import { getNonHeapMemoryChart } from './non_heap_memory'; import { getThreadCountChart } from './thread_count'; import { getCPUChartData } from '../shared/cpu'; @@ -18,7 +14,7 @@ import { getGcRateChart } from './gc/get_gc_rate_chart'; import { getGcTimeChart } from './gc/get_gc_time_chart'; export async function getJavaMetricsCharts( - setup: Setup & SetupTimeRange & SetupUIFilters, + setup: Setup & SetupTimeRange, serviceName: string, serviceNodeName?: string ) { diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts index 1a2d5bd0b0e68a..50cc449da3c159 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts @@ -12,11 +12,7 @@ import { METRIC_JAVA_NON_HEAP_MEMORY_USED, AGENT_NAME, } from '../../../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../../helpers/setup_request'; import { ChartBase } from '../../../types'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; @@ -52,7 +48,7 @@ const chartBase: ChartBase = { }; export async function getNonHeapMemoryChart( - setup: Setup & SetupUIFilters & SetupTimeRange, + setup: Setup & SetupTimeRange, serviceName: string, serviceNodeName?: string ) { diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts index 01cc6d84952446..0062f0a423970c 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts @@ -10,11 +10,7 @@ import { METRIC_JAVA_THREAD_COUNT, AGENT_NAME, } from '../../../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../../helpers/setup_request'; import { ChartBase } from '../../../types'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; @@ -44,7 +40,7 @@ const chartBase: ChartBase = { }; export async function getThreadCountChart( - setup: Setup & SetupTimeRange & SetupUIFilters, + setup: Setup & SetupTimeRange, serviceName: string, serviceNodeName?: string ) { diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts index 066ef40b4ab6ce..ca642aa12fff1d 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts @@ -10,11 +10,7 @@ import { METRIC_SYSTEM_CPU_PERCENT, METRIC_PROCESS_CPU_PERCENT, } from '../../../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../../helpers/setup_request'; import { ChartBase } from '../../../types'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; @@ -56,7 +52,7 @@ const chartBase: ChartBase = { }; export async function getCPUChartData( - setup: Setup & SetupTimeRange & SetupUIFilters, + setup: Setup & SetupTimeRange, serviceName: string, serviceNodeName?: string ) { diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts index a60576ca0c175e..e6ee47cc815efd 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts @@ -11,11 +11,7 @@ import { METRIC_SYSTEM_FREE_MEMORY, METRIC_SYSTEM_TOTAL_MEMORY, } from '../../../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../../helpers/setup_request'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; import { ChartBase } from '../../../types'; @@ -54,7 +50,7 @@ export const percentCgroupMemoryUsedScript = { lang: 'painless', source: ` /* - When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. + When no limit is specified in the container, docker allows the app as much memory / swap memory as it wants. This number represents the max possible value for the limit field. */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; @@ -73,7 +69,7 @@ export const percentCgroupMemoryUsedScript = { }; export async function getMemoryChartData( - setup: Setup & SetupTimeRange & SetupUIFilters, + setup: Setup & SetupTimeRange, serviceName: string, serviceNodeName?: string ) { diff --git a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts index a42a10d6518a01..3ccba8c7586dcf 100644 --- a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts +++ b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts @@ -5,11 +5,7 @@ */ import { Unionize, Overwrite } from 'utility-types'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getMetricsDateHistogramParams } from '../helpers/metrics'; import { ChartBase } from './types'; import { transformDataToMetricsChart } from './transform_metrics_chart'; @@ -58,7 +54,7 @@ export async function fetchAndTransformMetrics({ aggs, additionalFilters = [], }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName: string; serviceNodeName?: string; chartBase: ChartBase; diff --git a/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts b/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts index 059e1ce48c83df..72cd65deebff63 100644 --- a/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts +++ b/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts @@ -3,11 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getJavaMetricsCharts } from './by_agent/java'; import { getDefaultMetricsCharts } from './by_agent/default'; import { GenericMetricsChart } from './transform_metrics_chart'; @@ -22,7 +18,7 @@ export async function getMetricsChartDataByAgent({ serviceNodeName, agentName, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName: string; serviceNodeName?: string; agentName: string; diff --git a/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap index dcafe092211646..1fafa080824439 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap @@ -61,7 +61,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -151,7 +151,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -230,7 +230,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -500,7 +500,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -552,7 +552,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -667,7 +667,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -723,7 +723,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts b/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts index 6566ea4f5e29bf..6d596246d6af92 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts @@ -7,11 +7,7 @@ import { TRANSACTION_DURATION } from '../../../common/elasticsearch_fieldnames'; import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { TRANSACTION_DOM_INTERACTIVE, TRANSACTION_TIME_TO_FIRST_BYTE, @@ -22,7 +18,7 @@ export async function getClientMetrics({ urlQuery, percentile = 50, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; urlQuery?: string; percentile?: number; }) { diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts b/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts index 0540ea4bf09dd8..a8a4e2714c86e0 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts @@ -5,11 +5,7 @@ */ import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getRumErrorsProjection } from '../../projections/rum_page_load_transactions'; import { ERROR_EXC_MESSAGE, @@ -23,7 +19,7 @@ export async function getJSErrors({ pageSize, pageIndex, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; pageSize: number; pageIndex: number; }) { diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_long_task_metrics.ts b/x-pack/plugins/apm/server/lib/rum_client/get_long_task_metrics.ts index c2c86ae05d57c6..dfb31de8f10f78 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_long_task_metrics.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_long_task_metrics.ts @@ -6,11 +6,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; const LONG_TASK_SUM_FIELD = 'transaction.experience.longtask.sum'; const LONG_TASK_COUNT_FIELD = 'transaction.experience.longtask.count'; @@ -21,7 +17,7 @@ export async function getLongTaskMetrics({ urlQuery, percentile = 50, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; urlQuery?: string; percentile?: number; }) { diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_page_load_distribution.ts b/x-pack/plugins/apm/server/lib/rum_client/get_page_load_distribution.ts index 5f666feb8a18f2..225afff2818abb 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_page_load_distribution.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_page_load_distribution.ts @@ -7,11 +7,7 @@ import { TRANSACTION_DURATION } from '../../../common/elasticsearch_fieldnames'; import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; export const MICRO_TO_SEC = 1000000; @@ -56,7 +52,7 @@ export async function getPageLoadDistribution({ maxPercentile, urlQuery, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; minPercentile?: string; maxPercentile?: string; urlQuery?: string; @@ -168,7 +164,7 @@ const getPercentilesDistribution = async ({ minDuration, maxDuration, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; minDuration: number; maxDuration: number; }) => { diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts b/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts index 40f8a8bc58a546..c1a602c33feae1 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts @@ -5,11 +5,7 @@ */ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { BreakdownItem } from '../../../typings/ui_filters'; export async function getPageViewTrends({ @@ -17,7 +13,7 @@ export async function getPageViewTrends({ breakdowns, urlQuery, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; breakdowns?: string; urlQuery?: string; }) { diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_pl_dist_breakdown.ts b/x-pack/plugins/apm/server/lib/rum_client/get_pl_dist_breakdown.ts index bebf9c0bc99c92..e2ec59d232b211 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_pl_dist_breakdown.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_pl_dist_breakdown.ts @@ -7,11 +7,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { ProcessorEvent } from '../../../common/processor_event'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { CLIENT_GEO_COUNTRY_ISO_CODE, USER_AGENT_DEVICE, @@ -46,7 +42,7 @@ export const getPageLoadDistBreakdown = async ({ breakdown, urlQuery, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; minPercentile: number; maxPercentile: number; breakdown: string; diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_rum_services.ts b/x-pack/plugins/apm/server/lib/rum_client/get_rum_services.ts index 3adad0868ed4b5..e9bd203e354cb7 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_rum_services.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_rum_services.ts @@ -5,18 +5,14 @@ */ import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; export async function getRumServices({ setup, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { const projection = getRumPageLoadTransactionsProjection({ setup, diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_url_search.ts b/x-pack/plugins/apm/server/lib/rum_client/get_url_search.ts index 6aa39c7ef961fc..febfd66897e182 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_url_search.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_url_search.ts @@ -5,11 +5,7 @@ */ import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { TRANSACTION_DURATION, @@ -21,7 +17,7 @@ export async function getUrlSearch({ urlQuery, percentile, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; urlQuery?: string; percentile: number; }) { diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts b/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts index 52d089e4e29c99..6350bc2c070160 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts @@ -6,11 +6,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { USER_AGENT_NAME, USER_AGENT_OS, @@ -20,7 +16,7 @@ export async function getVisitorBreakdown({ setup, urlQuery, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; urlQuery?: string; }) { const projection = getRumPageLoadTransactionsProjection({ diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts b/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts index 676b3506397a71..c5baf0b529eb42 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts @@ -6,11 +6,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { CLS_FIELD, FCP_FIELD, @@ -25,7 +21,7 @@ export async function getWebCoreVitals({ urlQuery, percentile = 50, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; urlQuery?: string; percentile?: number; }) { diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts index 75acebe7ed56ce..330bb936c9e889 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts @@ -82,7 +82,7 @@ async function getServicesData(options: IEnvOptions) { const { setup, searchAggregatedTransactions } = options; const projection = getServicesProjection({ - setup: { ...setup, uiFiltersES: [] }, + setup: { ...setup, esFilter: [] }, searchAggregatedTransactions, }); diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts index 7af1607697ef39..eb2ddbf38b2746 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts @@ -19,11 +19,10 @@ describe('getServiceMapServiceNodeInfo', () => { }), }, indices: {}, + uiFilters: { environment: 'test environment' }, } as unknown) as Setup & SetupTimeRange; - const environment = 'test environment'; const serviceName = 'test service name'; const result = await getServiceMapServiceNodeInfo({ - uiFilters: { environment }, setup, serviceName, searchAggregatedTransactions: false, @@ -67,11 +66,10 @@ describe('getServiceMapServiceNodeInfo', () => { config: { 'xpack.apm.metricsInterval': 30, }, + uiFilters: { environment: 'test environment' }, } as unknown) as Setup & SetupTimeRange; - const environment = 'test environment'; const serviceName = 'test service name'; const result = await getServiceMapServiceNodeInfo({ - uiFilters: { environment }, setup, serviceName, searchAggregatedTransactions: false, diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts index 7c2137ce65d839..37b34641435fbc 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts @@ -8,7 +8,6 @@ import { TRANSACTION_REQUEST, TRANSACTION_PAGE_LOAD, } from '../../../common/transaction_types'; -import { UIFilters } from '../../../typings/ui_filters'; import { SERVICE_NAME, METRIC_SYSTEM_CPU_PERCENT, @@ -53,9 +52,8 @@ export async function getServiceMapServiceNodeInfo({ serviceName, setup, searchAggregatedTransactions, - uiFilters, -}: Options & { serviceName: string; uiFilters: UIFilters }) { - const { start, end } = setup; +}: Options & { serviceName: string }) { + const { start, end, uiFilters } = setup; const filter: ESFilter[] = [ { range: rangeFilter(start, end) }, @@ -105,7 +103,8 @@ async function getErrorStats({ }) { const setupWithBlankUiFilters = { ...setup, - uiFiltersES: getEnvironmentUiFilterES(environment), + uiFilters: { environment }, + esFilter: getEnvironmentUiFilterES(environment), }; const { noHits, average } = await getErrorRate({ setup: setupWithBlankUiFilters, diff --git a/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_grouped.json b/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_grouped.json index e7bba585de1807..94c508fe90230d 100644 --- a/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_grouped.json +++ b/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_grouped.json @@ -3,7 +3,7 @@ { "data": { "id": "opbeans-rum", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-rum", "agent.name": "rum-js" } @@ -18,7 +18,7 @@ { "data": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" } diff --git a/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_pregrouped.json b/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_pregrouped.json index 22c5c50de74727..58469f607ac130 100644 --- a/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_pregrouped.json +++ b/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_pregrouped.json @@ -3,7 +3,7 @@ { "data": { "id": "opbeans-rum", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-rum", "agent.name": "rum-js" } @@ -18,7 +18,7 @@ { "data": { "id": "opbeans-node", - "service.environment": "testing", + "service.environment": "test", "service.name": "opbeans-node", "agent.name": "nodejs" } diff --git a/x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap index 87aca0d0569091..d83e558775be40 100644 --- a/x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap @@ -51,7 +51,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -119,7 +119,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -188,7 +188,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], diff --git a/x-pack/plugins/apm/server/lib/service_nodes/index.ts b/x-pack/plugins/apm/server/lib/service_nodes/index.ts index a83aba192dba93..d5e29532e3d7b9 100644 --- a/x-pack/plugins/apm/server/lib/service_nodes/index.ts +++ b/x-pack/plugins/apm/server/lib/service_nodes/index.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getServiceNodesProjection } from '../../projections/service_nodes'; import { mergeProjection } from '../../projections/util/merge_projection'; import { SERVICE_NODE_NAME_MISSING } from '../../../common/service_nodes'; @@ -23,7 +19,7 @@ const getServiceNodes = async ({ setup, serviceName, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName: string; }) => { const { apmEventClient } = setup; diff --git a/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap index 431f11066aaff0..3a38f80c87b35e 100644 --- a/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap @@ -144,7 +144,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -194,7 +194,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -257,7 +257,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -334,7 +334,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -389,7 +389,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], diff --git a/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts b/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts index fca472b0ce8c22..d6ba9f5447ba50 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { HOST_NAME, CONTAINER_ID, @@ -24,7 +20,7 @@ export async function getServiceNodeMetadata({ }: { serviceName: string; serviceNodeName: string; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { const { apmEventClient } = setup; diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts b/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts index c09be7aacc784f..092485c46fb083 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts @@ -5,11 +5,7 @@ */ import { joinByKey } from '../../../../common/utils/join_by_key'; import { PromiseReturnType } from '../../../../typings/common'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { getServicesProjection } from '../../../projections/services'; import { getTransactionDurationAverages, @@ -21,17 +17,15 @@ import { } from './get_services_items_stats'; export type ServiceListAPIResponse = PromiseReturnType; -export type ServicesItemsSetup = Setup & SetupTimeRange & SetupUIFilters; +export type ServicesItemsSetup = Setup & SetupTimeRange; export type ServicesItemsProjection = ReturnType; export async function getServicesItems({ setup, searchAggregatedTransactions, - mlAnomaliesEnvironment, }: { setup: ServicesItemsSetup; searchAggregatedTransactions: boolean; - mlAnomaliesEnvironment?: string; }) { const params = { projection: getServicesProjection({ @@ -55,7 +49,7 @@ export async function getServicesItems({ getTransactionRates(params), getTransactionErrorRates(params), getEnvironments(params), - getHealthStatuses(params, mlAnomaliesEnvironment), + getHealthStatuses(params, setup.uiFilters.environment), ]); const allMetrics = [ diff --git a/x-pack/plugins/apm/server/lib/services/get_services/index.ts b/x-pack/plugins/apm/server/lib/services/get_services/index.ts index 351457b2a815ee..04744a9c791bb1 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/index.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services/index.ts @@ -6,11 +6,7 @@ import { isEmpty } from 'lodash'; import { PromiseReturnType } from '../../../../typings/common'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { hasHistoricalAgentData } from './has_historical_agent_data'; import { getLegacyDataStatus } from './get_legacy_data_status'; import { getServicesItems } from './get_services_items'; @@ -20,17 +16,14 @@ export type ServiceListAPIResponse = PromiseReturnType; export async function getServices({ setup, searchAggregatedTransactions, - mlAnomaliesEnvironment, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; - mlAnomaliesEnvironment?: string; }) { const [items, hasLegacyData] = await Promise.all([ getServicesItems({ setup, searchAggregatedTransactions, - mlAnomaliesEnvironment, }), getLegacyDataStatus(setup), ]); diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/transaction_groups/__snapshots__/queries.test.ts.snap index bd6cefa793467f..c678e7db711b65 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/transaction_groups/__snapshots__/queries.test.ts.snap @@ -61,7 +61,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -128,7 +128,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -195,7 +195,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -270,7 +270,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -325,7 +325,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -380,7 +380,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -441,7 +441,7 @@ Array [ }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts index 5d581149db6678..0a4d9748f25977 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts @@ -15,11 +15,7 @@ import { getTransactionGroupsProjection } from '../../projections/transaction_gr import { mergeProjection } from '../../projections/util/merge_projection'; import { PromiseReturnType } from '../../../../observability/typings/common'; import { AggregationOptionsByType } from '../../../typings/elasticsearch/aggregations'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getAverages, getSums, @@ -57,7 +53,7 @@ export type TransactionGroupRequestBase = ReturnType< }; }; -export type TransactionGroupSetup = Setup & SetupTimeRange & SetupUIFilters; +export type TransactionGroupSetup = Setup & SetupTimeRange; function getItemsWithRelativeImpact( setup: TransactionGroupSetup, diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts index 3dc126c45d328a..d5289430b2698d 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts @@ -12,11 +12,7 @@ import { EVENT_OUTCOME, } from '../../../common/elasticsearch_fieldnames'; import { rangeFilter } from '../../../common/utils/range_filter'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getBucketSize } from '../helpers/get_bucket_size'; import { getProcessorEventForAggregatedTransactions, @@ -33,10 +29,10 @@ export async function getErrorRate({ serviceName: string; transactionType?: string; transactionName?: string; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; }) { - const { start, end, uiFiltersES, apmEventClient } = setup; + const { start, end, esFilter, apmEventClient } = setup; const transactionNamefilter = transactionName ? [{ term: { [TRANSACTION_NAME]: transactionName } }] @@ -53,7 +49,7 @@ export async function getErrorRate({ }, ...transactionNamefilter, ...transactionTypefilter, - ...uiFiltersES, + ...esFilter, ]; const params = { diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_sample_for_group.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_sample_for_group.ts index 6c9b23b3dc0793..7e1aad075fb161 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_sample_for_group.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_sample_for_group.ts @@ -12,11 +12,7 @@ import { } from '../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../common/processor_event'; import { rangeFilter } from '../../../common/utils/range_filter'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; export async function getTransactionSampleForGroup({ serviceName, @@ -25,9 +21,9 @@ export async function getTransactionSampleForGroup({ }: { serviceName: string; transactionName: string; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { - const { apmEventClient, start, end, uiFiltersES } = setup; + const { apmEventClient, start, end, esFilter } = setup; const filter = [ { @@ -43,7 +39,7 @@ export async function getTransactionSampleForGroup({ [TRANSACTION_NAME]: transactionName, }, }, - ...uiFiltersES, + ...esFilter, ]; const getSampledTransaction = async () => { diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/index.ts b/x-pack/plugins/apm/server/lib/transaction_groups/index.ts index 6e0d619268d444..3796511029243a 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/index.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/index.ts @@ -4,16 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { transactionGroupsFetcher, Options } from './fetcher'; export async function getTransactionGroupList( options: Options, - setup: Setup & SetupTimeRange & SetupUIFilters + setup: Setup & SetupTimeRange ) { const bucketSize = setup.config['xpack.apm.ui.transactionGroupBucketSize']; return await transactionGroupsFetcher(options, setup, bucketSize); diff --git a/x-pack/plugins/apm/server/lib/transactions/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/transactions/__snapshots__/queries.test.ts.snap index c63dfcc0c0ec70..3e0a7317afd706 100644 --- a/x-pack/plugins/apm/server/lib/transactions/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/transactions/__snapshots__/queries.test.ts.snap @@ -161,7 +161,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -295,7 +295,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -401,7 +401,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], @@ -502,7 +502,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -608,7 +608,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, Object { @@ -673,7 +673,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], diff --git a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts b/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts index 34863c64f98041..8bbcaebe06513d 100644 --- a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts +++ b/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts @@ -36,7 +36,8 @@ function getMockSetup(esResponse: any) { get: () => 'myIndex', } ) as APMConfig, - uiFiltersES: [], + uiFilters: {}, + esFilter: [], indices: mockIndices, dynamicIndexPattern: null as any, }; diff --git a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts b/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts index 9730ddbbf38d7c..8febdc898ab97f 100644 --- a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts @@ -16,11 +16,7 @@ import { TRANSACTION_NAME, TRANSACTION_BREAKDOWN_COUNT, } from '../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { rangeFilter } from '../../../../common/utils/range_filter'; import { getMetricsDateHistogramParams } from '../../helpers/metrics'; import { MAX_KPIS } from './constants'; @@ -32,12 +28,12 @@ export async function getTransactionBreakdown({ transactionName, transactionType, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName: string; transactionName?: string; transactionType: string; }) { - const { uiFiltersES, apmEventClient, start, end, config } = setup; + const { esFilter, apmEventClient, start, end, config } = setup; const subAggs = { sum_all_self_times: { @@ -84,7 +80,7 @@ export async function getTransactionBreakdown({ { term: { [SERVICE_NAME]: serviceName } }, { term: { [TRANSACTION_TYPE]: transactionType } }, { range: rangeFilter(start, end) }, - ...uiFiltersES, + ...esFilter, ]; if (transactionName) { diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts index 3cf9a54e3fe9be..287c7bc2c47f9f 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts @@ -5,6 +5,7 @@ */ import { Logger } from 'kibana/server'; +import { ESSearchResponse } from '../../../../../typings/elasticsearch'; import { PromiseReturnType } from '../../../../../../observability/typings/common'; import { Setup, SetupTimeRange } from '../../../helpers/setup_request'; @@ -47,7 +48,7 @@ export async function anomalySeriesFetcher({ filter: [ { term: { job_id: jobId } }, { exists: { field: 'bucket_span' } }, - { term: { result_type: 'model_plot' } }, + { terms: { result_type: ['model_plot', 'record'] } }, { term: { partition_field_value: serviceName } }, { term: { by_field_value: transactionType } }, { @@ -67,7 +68,7 @@ export async function anomalySeriesFetcher({ extended_bounds: { min: newStart, max: end }, }, aggs: { - anomaly_score: { max: { field: 'anomaly_score' } }, + anomaly_score: { max: { field: 'record_score' } }, lower: { min: { field: 'model_lower' } }, upper: { max: { field: 'model_upper' } }, }, @@ -77,7 +78,11 @@ export async function anomalySeriesFetcher({ }; try { - const response = await ml.mlSystem.mlAnomalySearch(params); + const response: ESSearchResponse< + unknown, + typeof params + > = (await ml.mlSystem.mlAnomalySearch(params)) as any; + return response; } catch (err) { const isHttpError = 'statusCode' in err; diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.ts index d8865f0049d357..f11623eaa2daea 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.ts @@ -5,17 +5,13 @@ */ import { Logger } from 'kibana/server'; import { isNumber } from 'lodash'; +import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; import { getBucketSize } from '../../../helpers/get_bucket_size'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../helpers/setup_request'; import { anomalySeriesFetcher } from './fetcher'; import { getMlBucketSize } from './get_ml_bucket_size'; import { anomalySeriesTransform } from './transform'; import { getMLJobIds } from '../../../service_map/get_service_anomalies'; -import { UIFilters } from '../../../../../typings/ui_filters'; export async function getAnomalySeries({ serviceName, @@ -24,15 +20,13 @@ export async function getAnomalySeries({ timeSeriesDates, setup, logger, - uiFilters, }: { serviceName: string; transactionType: string | undefined; transactionName: string | undefined; timeSeriesDates: number[]; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; logger: Logger; - uiFilters: UIFilters; }) { // don't fetch anomalies for transaction details page if (transactionName) { @@ -44,12 +38,22 @@ export async function getAnomalySeries({ return; } + const { uiFilters, start, end } = setup; + const { environment } = uiFilters; + + // don't fetch anomalies when no specific environment is selected + if (environment === ENVIRONMENT_ALL.value) { + return; + } + // don't fetch anomalies if unknown uiFilters are applied const knownFilters = ['environment', 'serviceName']; - const uiFilterNames = Object.keys(uiFilters); - if ( - uiFilterNames.some((uiFilterName) => !knownFilters.includes(uiFilterName)) - ) { + const hasUnknownFiltersApplied = Object.entries(setup.uiFilters) + .filter(([key, value]) => !!value) + .map(([key]) => key) + .some((uiFilterName) => !knownFilters.includes(uiFilterName)); + + if (hasUnknownFiltersApplied) { return; } @@ -64,15 +68,8 @@ export async function getAnomalySeries({ return; } - const mlJobIds = await getMLJobIds( - setup.ml.anomalyDetectors, - uiFilters.environment - ); + const mlJobIds = await getMLJobIds(setup.ml.anomalyDetectors, environment); - // don't fetch anomalies if there are isn't exaclty 1 ML job match for the given environment - if (mlJobIds.length !== 1) { - return; - } const jobId = mlJobIds[0]; const mlBucketSize = await getMlBucketSize({ setup, jobId, logger }); @@ -80,7 +77,6 @@ export async function getAnomalySeries({ return; } - const { start, end } = setup; const { intervalString, bucketSize } = getBucketSize(start, end); const esResponse = await anomalySeriesFetcher({ diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts index fdbd99bf274d6d..75dfae3e7375f3 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts @@ -29,7 +29,10 @@ describe('timeseriesFetcher', () => { get: () => 'myIndex', } ) as APMConfig, - uiFiltersES: [ + uiFilters: { + environment: 'test', + }, + esFilter: [ { term: { 'service.environment': 'test' }, }, diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts index 5a3948f5774306..e2edbbec63d475 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts @@ -14,11 +14,7 @@ import { import { PromiseReturnType } from '../../../../../../observability/typings/common'; import { getBucketSize } from '../../../helpers/get_bucket_size'; import { rangeFilter } from '../../../../../common/utils/range_filter'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../helpers/setup_request'; import { getProcessorEventForAggregatedTransactions, getTransactionDurationFieldForAggregatedTransactions, @@ -36,10 +32,10 @@ export function timeseriesFetcher({ serviceName: string; transactionType: string | undefined; transactionName: string | undefined; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; }) { - const { start, end, uiFiltersES, apmEventClient } = setup; + const { start, end, apmEventClient } = setup; const { intervalString } = getBucketSize(start, end); const filter: ESFilter[] = [ @@ -48,7 +44,7 @@ export function timeseriesFetcher({ ...getDocumentTypeFilterForAggregatedTransactions( searchAggregatedTransactions ), - ...uiFiltersES, + ...setup.esFilter, ]; if (transactionName) { diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/index.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/index.ts index 81dca447f16cab..c0421005dd06eb 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/index.ts @@ -5,11 +5,7 @@ */ import { getBucketSize } from '../../../helpers/get_bucket_size'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../helpers/setup_request'; import { timeseriesFetcher } from './fetcher'; import { timeseriesTransformer } from './transform'; @@ -17,7 +13,7 @@ export async function getApmTimeseriesData(options: { serviceName: string; transactionType: string | undefined; transactionName: string | undefined; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; }) { const { start, end } = options.setup; diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/index.ts b/x-pack/plugins/apm/server/lib/transactions/charts/index.ts index 43abf0b1a1d33d..d8593612c05828 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/index.ts @@ -6,15 +6,10 @@ import { Logger } from 'kibana/server'; import { PromiseReturnType } from '../../../../../observability/typings/common'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { getAnomalySeries } from './get_anomaly_data'; import { getApmTimeseriesData } from './get_timeseries_data'; import { ApmTimeSeriesResponse } from './get_timeseries_data/transform'; -import { UIFilters } from '../../../../typings/ui_filters'; function getDates(apmTimeseries: ApmTimeSeriesResponse) { return apmTimeseries.responseTimes.avg.map((p) => p.x); @@ -27,10 +22,9 @@ export async function getTransactionCharts(options: { serviceName: string; transactionType: string | undefined; transactionName: string | undefined; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; logger: Logger; - uiFilters: UIFilters; }) { const apmTimeseries = await getApmTimeseriesData(options); const anomalyTimeseries = await getAnomalySeries({ diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/index.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/index.ts index 6e2fe34a5f5ef5..34d01627a2869d 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/index.ts @@ -17,11 +17,7 @@ import { TRANSACTION_TYPE, } from '../../../../../common/elasticsearch_fieldnames'; import { rangeFilter } from '../../../../../common/utils/range_filter'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../../helpers/setup_request'; import { getDocumentTypeFilterForAggregatedTransactions, getProcessorEventForAggregatedTransactions, @@ -66,17 +62,17 @@ export async function getBuckets({ traceId: string; distributionMax: number; bucketSize: number; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; }) { - const { start, end, uiFiltersES, apmEventClient } = setup; + const { start, end, esFilter, apmEventClient } = setup; const commonFilters = [ { term: { [SERVICE_NAME]: serviceName } }, { term: { [TRANSACTION_TYPE]: transactionType } }, { term: { [TRANSACTION_NAME]: transactionName } }, { range: rangeFilter(start, end) }, - ...uiFiltersES, + ...esFilter, ]; async function getSamplesForDistributionBuckets() { diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts index 24ca2a4a07b68c..249b1c4fbb20a5 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts @@ -9,11 +9,7 @@ import { TRANSACTION_NAME, TRANSACTION_TYPE, } from '../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { getProcessorEventForAggregatedTransactions, getTransactionDurationFieldForAggregatedTransactions, @@ -29,10 +25,10 @@ export async function getDistributionMax({ serviceName: string; transactionName: string; transactionType: string; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; }) { - const { start, end, uiFiltersES, apmEventClient } = setup; + const { start, end, esFilter, apmEventClient } = setup; const params = { apm: { @@ -59,7 +55,7 @@ export async function getDistributionMax({ }, }, }, - ...uiFiltersES, + ...esFilter, ], }, }, diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/index.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/index.ts index b9ab36fb08d422..deafc37ee42e20 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/index.ts @@ -5,11 +5,7 @@ */ import { PromiseReturnType } from '../../../../../observability/typings/common'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { getBuckets } from './get_buckets'; import { getDistributionMax } from './get_distribution_max'; import { roundToNearestFiveOrTen } from '../../helpers/round_to_nearest_five_or_ten'; @@ -39,7 +35,7 @@ export async function getTransactionDistribution({ transactionType: string; transactionId: string; traceId: string; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; }) { const distributionMax = await getDistributionMax({ diff --git a/x-pack/plugins/apm/server/lib/transactions/get_transaction/index.ts b/x-pack/plugins/apm/server/lib/transactions/get_transaction/index.ts index 9aa1a8f4de87fc..8958be0819613d 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_transaction/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_transaction/index.ts @@ -9,11 +9,7 @@ import { TRANSACTION_ID, } from '../../../../common/elasticsearch_fieldnames'; import { rangeFilter } from '../../../../common/utils/range_filter'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { ProcessorEvent } from '../../../../common/processor_event'; export async function getTransaction({ @@ -23,7 +19,7 @@ export async function getTransaction({ }: { transactionId: string; traceId: string; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { const { start, end, apmEventClient } = setup; diff --git a/x-pack/plugins/apm/server/lib/transactions/queries.test.ts b/x-pack/plugins/apm/server/lib/transactions/queries.test.ts index 87b8bc7c4ae90f..eff9451c9e1cd4 100644 --- a/x-pack/plugins/apm/server/lib/transactions/queries.test.ts +++ b/x-pack/plugins/apm/server/lib/transactions/queries.test.ts @@ -56,7 +56,6 @@ describe('transaction queries', () => { setup, searchAggregatedTransactions: false, logger: loggerMock.create(), - uiFilters: {}, }) ); expect(mock.params).toMatchSnapshot(); @@ -71,7 +70,6 @@ describe('transaction queries', () => { setup, searchAggregatedTransactions: false, logger: loggerMock.create(), - uiFilters: {}, }) ); expect(mock.params).toMatchSnapshot(); @@ -86,7 +84,6 @@ describe('transaction queries', () => { setup, searchAggregatedTransactions: false, logger: loggerMock.create(), - uiFilters: {}, }) ); diff --git a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/__snapshots__/queries.test.ts.snap index 5f384327192800..e7ca65eb740b6a 100644 --- a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/__snapshots__/queries.test.ts.snap @@ -46,7 +46,7 @@ Object { }, Object { "term": Object { - "my.custom.ui.filter": "foo-bar", + "service.environment": "test", }, }, ], diff --git a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/get_local_filter_query.ts b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/get_local_filter_query.ts index 10f6e93c1cfc13..9fbdba679b6675 100644 --- a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/get_local_filter_query.ts +++ b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/get_local_filter_query.ts @@ -8,7 +8,7 @@ import { omit } from 'lodash'; import { mergeProjection } from '../../../projections/util/merge_projection'; import { Projection } from '../../../projections/typings'; import { UIFilters } from '../../../../typings/ui_filters'; -import { getUiFiltersES } from '../../helpers/convert_ui_filters/get_ui_filters_es'; +import { getEsFilter } from '../../helpers/convert_ui_filters/get_es_filter'; import { localUIFilters } from './config'; import { LocalUIFilterName } from '../../../../common/ui_filter'; @@ -22,7 +22,7 @@ export const getLocalFilterQuery = ({ localUIFilterName: LocalUIFilterName; }) => { const field = localUIFilters[localUIFilterName]; - const filter = getUiFiltersES(omit(uiFilters, field.name)); + const filter = getEsFilter(omit(uiFilters, field.name)); const bucketCountAggregation = projection.body.aggs ? { diff --git a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/queries.test.ts b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/queries.test.ts index 22fa20e255f6ed..f4e8aafc1bcf5f 100644 --- a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/queries.test.ts +++ b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/queries.test.ts @@ -15,7 +15,7 @@ describe('local ui filter queries', () => { let mock: SearchParamsMock; beforeEach(() => { - jest.mock('../../helpers/convert_ui_filters/get_ui_filters_es', () => { + jest.mock('../../helpers/convert_ui_filters/get_es_filter', () => { return []; }); }); diff --git a/x-pack/plugins/apm/server/projections/errors.ts b/x-pack/plugins/apm/server/projections/errors.ts index 49a0e9f479d263..173dc94a0840cd 100644 --- a/x-pack/plugins/apm/server/projections/errors.ts +++ b/x-pack/plugins/apm/server/projections/errors.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../server/lib/helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../server/lib/helpers/setup_request'; import { SERVICE_NAME, ERROR_GROUP_ID, @@ -20,10 +16,10 @@ export function getErrorGroupsProjection({ setup, serviceName, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName: string; }) { - const { start, end, uiFiltersES } = setup; + const { start, end, esFilter } = setup; return { apm: { @@ -35,7 +31,7 @@ export function getErrorGroupsProjection({ filter: [ { term: { [SERVICE_NAME]: serviceName } }, { range: rangeFilter(start, end) }, - ...uiFiltersES, + ...esFilter, ], }, }, diff --git a/x-pack/plugins/apm/server/projections/metrics.ts b/x-pack/plugins/apm/server/projections/metrics.ts index eb80a6bc73248d..c3b5db5be6af88 100644 --- a/x-pack/plugins/apm/server/projections/metrics.ts +++ b/x-pack/plugins/apm/server/projections/metrics.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../server/lib/helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../server/lib/helpers/setup_request'; import { SERVICE_NAME, SERVICE_NODE_NAME, @@ -34,17 +30,17 @@ export function getMetricsProjection({ serviceName, serviceNodeName, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName: string; serviceNodeName?: string; }) { - const { start, end, uiFiltersES } = setup; + const { start, end, esFilter } = setup; const filter = [ { term: { [SERVICE_NAME]: serviceName } }, { range: rangeFilter(start, end) }, ...getServiceNodeNameFilters(serviceNodeName), - ...uiFiltersES, + ...esFilter, ]; return { diff --git a/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts b/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts index c27314923f6bd6..96ee26c6e65f58 100644 --- a/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts +++ b/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../server/lib/helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../server/lib/helpers/setup_request'; import { AGENT_NAME, TRANSACTION_TYPE, @@ -22,10 +18,10 @@ export function getRumPageLoadTransactionsProjection({ setup, urlQuery, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; urlQuery?: string; }) { - const { start, end, uiFiltersES } = setup; + const { start, end, esFilter } = setup; const bool = { filter: [ @@ -49,7 +45,7 @@ export function getRumPageLoadTransactionsProjection({ }, ] : []), - ...uiFiltersES, + ...esFilter, ], }; @@ -68,9 +64,9 @@ export function getRumPageLoadTransactionsProjection({ export function getRumErrorsProjection({ setup, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { - const { start, end, uiFiltersES } = setup; + const { start, end, esFilter: esFilter } = setup; const bool = { filter: [ @@ -82,7 +78,7 @@ export function getRumErrorsProjection({ [SERVICE_LANGUAGE_NAME]: 'javascript', }, }, - ...uiFiltersES, + ...esFilter, ], }; diff --git a/x-pack/plugins/apm/server/projections/service_nodes.ts b/x-pack/plugins/apm/server/projections/service_nodes.ts index 87fe815a12d0de..ed8d4c7409eda0 100644 --- a/x-pack/plugins/apm/server/projections/service_nodes.ts +++ b/x-pack/plugins/apm/server/projections/service_nodes.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../server/lib/helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../server/lib/helpers/setup_request'; import { SERVICE_NODE_NAME } from '../../common/elasticsearch_fieldnames'; import { mergeProjection } from './util/merge_projection'; import { getMetricsProjection } from './metrics'; @@ -18,7 +14,7 @@ export function getServiceNodesProjection({ serviceName, serviceNodeName, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName: string; serviceNodeName?: string; }) { diff --git a/x-pack/plugins/apm/server/projections/services.ts b/x-pack/plugins/apm/server/projections/services.ts index ba61f72519a237..d912a95546515e 100644 --- a/x-pack/plugins/apm/server/projections/services.ts +++ b/x-pack/plugins/apm/server/projections/services.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupUIFilters, - SetupTimeRange, -} from '../../server/lib/helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../server/lib/helpers/setup_request'; import { SERVICE_NAME } from '../../common/elasticsearch_fieldnames'; import { rangeFilter } from '../../common/utils/range_filter'; import { ProcessorEvent } from '../../common/processor_event'; @@ -18,10 +14,10 @@ export function getServicesProjection({ setup, searchAggregatedTransactions, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; searchAggregatedTransactions: boolean; }) { - const { start, end, uiFiltersES } = setup; + const { start, end, esFilter } = setup; return { apm: { @@ -37,7 +33,7 @@ export function getServicesProjection({ size: 0, query: { bool: { - filter: [{ range: rangeFilter(start, end) }, ...uiFiltersES], + filter: [{ range: rangeFilter(start, end) }, ...esFilter], }, }, aggs: { diff --git a/x-pack/plugins/apm/server/projections/transaction_groups.ts b/x-pack/plugins/apm/server/projections/transaction_groups.ts index 0cc3a7a35d2143..2ce720eb121672 100644 --- a/x-pack/plugins/apm/server/projections/transaction_groups.ts +++ b/x-pack/plugins/apm/server/projections/transaction_groups.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { omit } from 'lodash'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../server/lib/helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../server/lib/helpers/setup_request'; import { TRANSACTION_NAME, PARENT_ID, @@ -22,7 +18,7 @@ export function getTransactionGroupsProjection({ setup, options, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; options: Options; }) { const transactionsProjection = getTransactionsProjection({ diff --git a/x-pack/plugins/apm/server/projections/transactions.ts b/x-pack/plugins/apm/server/projections/transactions.ts index 8e9bb3bf321f62..548e77b5d2cd99 100644 --- a/x-pack/plugins/apm/server/projections/transactions.ts +++ b/x-pack/plugins/apm/server/projections/transactions.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../server/lib/helpers/setup_request'; +import { Setup, SetupTimeRange } from '../../server/lib/helpers/setup_request'; import { SERVICE_NAME, TRANSACTION_TYPE, @@ -27,13 +23,13 @@ export function getTransactionsProjection({ transactionType, searchAggregatedTransactions, }: { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName?: string; transactionName?: string; transactionType?: string; searchAggregatedTransactions: boolean; }) { - const { start, end, uiFiltersES } = setup; + const { start, end, esFilter } = setup; const transactionNameFilter = transactionName ? [{ term: { [TRANSACTION_NAME]: transactionName } }] @@ -51,7 +47,7 @@ export function getTransactionsProjection({ ...transactionNameFilter, ...transactionTypeFilter, ...serviceNameFilter, - ...uiFiltersES, + ...esFilter, ...getDocumentTypeFilterForAggregatedTransactions( searchAggregatedTransactions ), diff --git a/x-pack/plugins/apm/server/routes/service_map.ts b/x-pack/plugins/apm/server/routes/service_map.ts index 1996d4d4a262dc..6e86ececd1bfe4 100644 --- a/x-pack/plugins/apm/server/routes/service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map.ts @@ -17,7 +17,6 @@ import { createRoute } from './create_route'; import { rangeRt, uiFiltersRt } from './default_api_types'; import { notifyFeatureUsage } from '../feature'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; -import { getParsedUiFilters } from '../lib/helpers/convert_ui_filters/get_parsed_ui_filters'; export const serviceMapRoute = createRoute(() => ({ path: '/api/apm/service-map', @@ -77,24 +76,20 @@ export const serviceMapServiceNodeRoute = createRoute(() => ({ if (!isActivePlatinumLicense(context.licensing.license)) { throw Boom.forbidden(invalidLicenseMessage); } - const logger = context.logger; const setup = await setupRequest(context, request); const { - query: { uiFilters: uiFiltersJson }, path: { serviceName }, } = context.params; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); - const uiFilters = getParsedUiFilters({ uiFilters: uiFiltersJson, logger }); return getServiceMapServiceNodeInfo({ setup, serviceName, searchAggregatedTransactions, - uiFilters, }); }, })); diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index 4bb10f31ba6a1a..538ba3926c792d 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -17,7 +17,6 @@ import { uiFiltersRt, rangeRt } from './default_api_types'; import { getServiceAnnotations } from '../lib/services/annotations'; import { dateAsStringRt } from '../../common/runtime_types/date_as_string_rt'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; -import { getParsedUiFilters } from '../lib/helpers/convert_ui_filters/get_parsed_ui_filters'; export const servicesRoute = createRoute(() => ({ path: '/api/apm/services', @@ -25,22 +24,13 @@ export const servicesRoute = createRoute(() => ({ query: t.intersection([uiFiltersRt, rangeRt]), }, handler: async ({ context, request }) => { - const { environment } = getParsedUiFilters({ - uiFilters: context.params.query.uiFilters, - logger: context.logger, - }); - const setup = await setupRequest(context, request); const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); - const services = await getServices({ - setup, - searchAggregatedTransactions, - mlAnomaliesEnvironment: environment, - }); + const services = await getServices({ setup, searchAggregatedTransactions }); return services; }, diff --git a/x-pack/plugins/apm/server/routes/transaction_groups.ts b/x-pack/plugins/apm/server/routes/transaction_groups.ts index dd1335fb2c2a19..18fc73b468cd4d 100644 --- a/x-pack/plugins/apm/server/routes/transaction_groups.ts +++ b/x-pack/plugins/apm/server/routes/transaction_groups.ts @@ -5,6 +5,7 @@ */ import * as t from 'io-ts'; +import Boom from 'boom'; import { setupRequest } from '../lib/helpers/setup_request'; import { getTransactionCharts } from '../lib/transactions/charts'; import { getTransactionDistribution } from '../lib/transactions/distribution'; @@ -15,7 +16,6 @@ import { uiFiltersRt, rangeRt } from './default_api_types'; import { getTransactionSampleForGroup } from '../lib/transaction_groups/get_transaction_sample_for_group'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; import { getErrorRate } from '../lib/transaction_groups/get_error_rate'; -import { getParsedUiFilters } from '../lib/helpers/convert_ui_filters/get_parsed_ui_filters'; export const transactionGroupsRoute = createRoute(() => ({ path: '/api/apm/services/{serviceName}/transaction_groups', @@ -71,27 +71,28 @@ export const transactionGroupsChartsRoute = createRoute(() => ({ const setup = await setupRequest(context, request); const logger = context.logger; const { serviceName } = context.params.path; - const { - transactionType, - transactionName, - uiFilters: uiFiltersJson, - } = context.params.query; + const { transactionType, transactionName } = context.params.query; - const uiFilters = getParsedUiFilters({ uiFilters: uiFiltersJson, logger }); + if (!setup.uiFilters.environment) { + throw Boom.badRequest( + `environment is a required property of the ?uiFilters JSON for transaction_groups/charts.` + ); + } const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); - return getTransactionCharts({ + const options = { serviceName, transactionType, transactionName, setup, searchAggregatedTransactions, logger, - uiFilters, - }); + }; + + return getTransactionCharts(options); }, })); diff --git a/x-pack/plugins/apm/server/routes/ui_filters.ts b/x-pack/plugins/apm/server/routes/ui_filters.ts index 936d460102dcec..26fe0118c02ed9 100644 --- a/x-pack/plugins/apm/server/routes/ui_filters.ts +++ b/x-pack/plugins/apm/server/routes/ui_filters.ts @@ -9,13 +9,12 @@ import { omit } from 'lodash'; import { setupRequest, Setup, - SetupUIFilters, SetupTimeRange, } from '../lib/helpers/setup_request'; import { getEnvironments } from '../lib/ui_filters/get_environments'; import { Projection } from '../projections/typings'; import { localUIFilterNames } from '../lib/ui_filters/local_ui_filters/config'; -import { getUiFiltersES } from '../lib/helpers/convert_ui_filters/get_ui_filters_es'; +import { getEsFilter } from '../lib/helpers/convert_ui_filters/get_es_filter'; import { getLocalUIFilters } from '../lib/ui_filters/local_ui_filters'; import { getServicesProjection } from '../projections/services'; import { getTransactionGroupsProjection } from '../projections/transaction_groups'; @@ -97,23 +96,23 @@ function createLocalFiltersRoute< }, handler: async ({ context, request }) => { const setup = await setupRequest(context, request); + const { uiFilters } = setup; const { query } = context.params; - const { uiFilters, filterNames } = query; - const parsedUiFilters = JSON.parse(uiFilters); + const { filterNames } = query; const projection = await getProjection({ query, context, setup: { ...setup, - uiFiltersES: getUiFiltersES(omit(parsedUiFilters, filterNames)), + esFilter: getEsFilter(omit(uiFilters, filterNames)), }, }); return getLocalUIFilters({ projection, setup, - uiFilters: parsedUiFilters, + uiFilters, localFilterNames: filterNames, }); }, @@ -271,6 +270,6 @@ type GetProjection< context, }: { query: t.TypeOf; - setup: Setup & SetupUIFilters & SetupTimeRange; + setup: Setup & SetupTimeRange; context: APMRequestHandlerContext; }) => Promise | TProjection; diff --git a/x-pack/plugins/apm/server/utils/test_helpers.tsx b/x-pack/plugins/apm/server/utils/test_helpers.tsx index 98c1436b2b9b8f..18b990b35b5a58 100644 --- a/x-pack/plugins/apm/server/utils/test_helpers.tsx +++ b/x-pack/plugins/apm/server/utils/test_helpers.tsx @@ -9,6 +9,7 @@ import { ESSearchRequest, } from '../../typings/elasticsearch'; import { PromiseReturnType } from '../../typings/common'; +import { UIFilters } from '../../typings/ui_filters'; import { APMConfig } from '..'; interface Options { @@ -23,7 +24,8 @@ interface MockSetup { apmEventClient: any; internalClient: any; config: APMConfig; - uiFiltersES: ESFilter[]; + uiFilters: UIFilters; + esFilter: ESFilter[]; indices: { /* eslint-disable @typescript-eslint/naming-convention */ 'apm_oss.sourcemapIndices': string; @@ -78,7 +80,8 @@ export async function inspectSearchParams( }, } ) as APMConfig, - uiFiltersES: [{ term: { 'my.custom.ui.filter': 'foo-bar' } }], + uiFilters: { environment: 'test' }, + esFilter: [{ term: { 'service.environment': 'test' } }], indices: { /* eslint-disable @typescript-eslint/naming-convention */ 'apm_oss.sourcemapIndices': 'myIndex', diff --git a/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts index e0e13b7b7fb98d..a2223e55602888 100644 --- a/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts +++ b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts @@ -107,21 +107,21 @@ export default function featureControlsTests({ getService }: FtrProviderContext) }, { req: { - url: `/api/apm/services/foo/transaction_groups/charts?start=${start}&end=${end}&transactionType=bar&uiFilters=%7B%7D`, + url: `/api/apm/services/foo/transaction_groups/charts?start=${start}&end=${end}&transactionType=bar&uiFilters=%7B%22environment%22%3A%22testing%22%7D`, }, expectForbidden: expect404, expectResponse: expect200, }, { req: { - url: `/api/apm/services/foo/transaction_groups/charts?start=${start}&end=${end}&uiFilters=%7B%7D`, + url: `/api/apm/services/foo/transaction_groups/charts?start=${start}&end=${end}&uiFilters=%7B%22environment%22%3A%22testing%22%7D`, }, expectForbidden: expect404, expectResponse: expect200, }, { req: { - url: `/api/apm/services/foo/transaction_groups/charts?start=${start}&end=${end}&transactionType=bar&transactionName=baz&uiFilters=%7B%7D`, + url: `/api/apm/services/foo/transaction_groups/charts?start=${start}&end=${end}&transactionType=bar&transactionName=baz&uiFilters=%7B%22environment%22%3A%22testing%22%7D`, }, expectForbidden: expect404, expectResponse: expect200, diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts index c9581079b99520..d7d6d613281ef7 100644 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts +++ b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/transaction_charts.ts @@ -19,7 +19,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { // url parameters const start = encodeURIComponent(metadata.start); const end = encodeURIComponent(metadata.end); - const uiFilters = encodeURIComponent(JSON.stringify({})); + const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'testing' })); describe('Transaction charts', () => { describe('when data is not loaded ', () => { diff --git a/x-pack/test/apm_api_integration/trial/tests/index.ts b/x-pack/test/apm_api_integration/trial/tests/index.ts index a6a031def34ea4..e609279366390f 100644 --- a/x-pack/test/apm_api_integration/trial/tests/index.ts +++ b/x-pack/test/apm_api_integration/trial/tests/index.ts @@ -16,6 +16,7 @@ export default function observabilityApiIntegrationTests({ loadTestFile }: FtrPr describe('Services', function () { loadTestFile(require.resolve('./services/annotations')); loadTestFile(require.resolve('./services/top_services.ts')); + loadTestFile(require.resolve('./services/transaction_groups_charts')); }); describe('Settings', function () { diff --git a/x-pack/test/apm_api_integration/trial/tests/services/__snapshots__/transaction_groups_charts.snap b/x-pack/test/apm_api_integration/trial/tests/services/__snapshots__/transaction_groups_charts.snap new file mode 100644 index 00000000000000..8169e73202fbc7 --- /dev/null +++ b/x-pack/test/apm_api_integration/trial/tests/services/__snapshots__/transaction_groups_charts.snap @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`APM Transaction Overview when data is loaded and fetching transaction groups charts with uiFilters when not defined environments selected should return the correct anomaly boundaries 1`] = `Array []`; + +exports[`APM Transaction Overview when data is loaded and fetching transaction groups charts with uiFilters with environment selected and empty kuery filter should return a non-empty anomaly series 1`] = ` +Array [ + Object { + "x": 1601389800000, + "y": 1206111.33487531, + "y0": 10555.1290143587, + }, + Object { + "x": 1601390700000, + "y": 1223987.49321778, + "y0": 10177.4677901726, + }, + Object { + "x": 1601391600000, + "y": 1223987.49321778, + "y0": 10177.4677901726, + }, +] +`; + +exports[`APM Transaction Overview when data is loaded and fetching transaction groups charts with uiFilters with environment selected in uiFilters should return a non-empty anomaly series 1`] = ` +Array [ + Object { + "x": 1601389800000, + "y": 1206111.33487531, + "y0": 10555.1290143587, + }, + Object { + "x": 1601390700000, + "y": 1223987.49321778, + "y0": 10177.4677901726, + }, + Object { + "x": 1601391600000, + "y": 1223987.49321778, + "y0": 10177.4677901726, + }, +] +`; diff --git a/x-pack/test/apm_api_integration/trial/tests/services/transaction_groups_charts.ts b/x-pack/test/apm_api_integration/trial/tests/services/transaction_groups_charts.ts new file mode 100644 index 00000000000000..c35dfcc3817a42 --- /dev/null +++ b/x-pack/test/apm_api_integration/trial/tests/services/transaction_groups_charts.ts @@ -0,0 +1,161 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { expectSnapshot } from '../../../common/match_snapshot'; +import { PromiseReturnType } from '../../../../../plugins/apm/typings/common'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import archives_metadata from '../../../common/archives_metadata'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + const archiveName = 'apm_8.0.0'; + + const range = archives_metadata[archiveName]; + + // url parameters + const start = encodeURIComponent(range.start); + const end = encodeURIComponent(range.end); + const transactionType = 'request'; + + describe('APM Transaction Overview', () => { + describe('when data is loaded', () => { + before(() => esArchiver.load(archiveName)); + after(() => esArchiver.unload(archiveName)); + + describe('and fetching transaction groups charts with uiFilters', () => { + const serviceName = 'opbeans-java'; + let response: PromiseReturnType; + + describe('without environment', () => { + const uiFilters = encodeURIComponent(JSON.stringify({})); + before(async () => { + response = await supertest.get( + `/api/apm/services/${serviceName}/transaction_groups/charts?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}` + ); + }); + it('should return an error response', () => { + expect(response.status).to.eql(400); + }); + }); + + describe('without uiFilters', () => { + before(async () => { + response = await supertest.get( + `/api/apm/services/${serviceName}/transaction_groups/charts?start=${start}&end=${end}&transactionType=${transactionType}` + ); + }); + it('should return an error response', () => { + expect(response.status).to.eql(400); + }); + }); + + describe('with environment selected in uiFilters', () => { + const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'production' })); + before(async () => { + response = await supertest.get( + `/api/apm/services/${serviceName}/transaction_groups/charts?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}` + ); + }); + + it('should have a successful response', () => { + expect(response.status).to.eql(200); + }); + + it('should return the ML job id for anomalies of the selected environment', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries).to.have.property('jobId'); + expectSnapshot(response.body.anomalyTimeseries.jobId).toMatchInline( + `"apm-production-229a-high_mean_transaction_duration"` + ); + }); + + it('should return a non-empty anomaly series', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries.anomalyBoundaries?.length).to.be.greaterThan(0); + expectSnapshot(response.body.anomalyTimeseries.anomalyBoundaries).toMatch(); + }); + }); + + describe('when not defined environments selected', () => { + const uiFilters = encodeURIComponent( + JSON.stringify({ environment: 'ENVIRONMENT_NOT_DEFINED' }) + ); + before(async () => { + response = await supertest.get( + `/api/apm/services/${serviceName}/transaction_groups/charts?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}` + ); + }); + + it('should have a successful response', () => { + expect(response.status).to.eql(200); + }); + + it('should return the ML job id for anomalies with no defined environment', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries).to.have.property('jobId'); + expectSnapshot(response.body.anomalyTimeseries.jobId).toMatchInline( + `"apm-environment_not_defined-7ed6-high_mean_transaction_duration"` + ); + }); + + it('should return the correct anomaly boundaries', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expectSnapshot(response.body.anomalyTimeseries.anomalyBoundaries).toMatch(); + }); + }); + + describe('with all environments selected', () => { + const uiFilters = encodeURIComponent(JSON.stringify({ environment: 'ENVIRONMENT_ALL' })); + before(async () => { + response = await supertest.get( + `/api/apm/services/${serviceName}/transaction_groups/charts?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}` + ); + }); + + it('should have a successful response', () => { + expect(response.status).to.eql(200); + }); + + it('should not return anomaly timeseries data', () => { + expect(response.body).to.not.have.property('anomalyTimeseries'); + }); + }); + + describe('with environment selected and empty kuery filter', () => { + const uiFilters = encodeURIComponent( + JSON.stringify({ kuery: '', environment: 'production' }) + ); + before(async () => { + response = await supertest.get( + `/api/apm/services/${serviceName}/transaction_groups/charts?start=${start}&end=${end}&transactionType=${transactionType}&uiFilters=${uiFilters}` + ); + }); + + it('should have a successful response', () => { + expect(response.status).to.eql(200); + }); + + it('should return the ML job id for anomalies of the selected environment', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries).to.have.property('jobId'); + expectSnapshot(response.body.anomalyTimeseries.jobId).toMatchInline( + `"apm-production-229a-high_mean_transaction_duration"` + ); + }); + + it('should return a non-empty anomaly series', () => { + expect(response.body).to.have.property('anomalyTimeseries'); + expect(response.body.anomalyTimeseries.anomalyBoundaries?.length).to.be.greaterThan(0); + expectSnapshot(response.body.anomalyTimeseries.anomalyBoundaries).toMatch(); + }); + }); + }); + }); + }); +} From bd9a9a7a2bf65c465dd805815a2b1a6eea03bc9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?= Date: Fri, 2 Oct 2020 10:45:53 +0200 Subject: [PATCH 06/21] [Security Solution] Refactor react-beautiful-dnd render props (#78128) --- .../timeline/events/all/index.ts | 7 +- .../common/search_strategy/timeline/index.ts | 18 +- .../add_filter_to_global_search_bar/index.tsx | 56 +- .../drag_drop_context_wrapper.tsx | 13 +- .../drag_and_drop/draggable_wrapper.tsx | 131 +- .../drag_and_drop/droppable_wrapper.tsx | 33 +- .../common/components/draggables/index.tsx | 2 +- .../events_viewer/events_viewer.tsx | 28 +- .../common/components/events_viewer/mock.ts | 2 +- .../common/components/ml/entity_draggable.tsx | 67 +- .../components/ml/score/draggable_score.tsx | 76 +- .../recent_timelines/recent_timelines.tsx | 160 +- .../components/flyout/button/index.tsx | 34 +- .../components/formatted_ip/index.tsx | 157 +- .../__snapshots__/timeline.test.tsx.snap | 34 +- .../timeline/auto_save_warning/index.tsx | 121 +- .../body/column_headers/actions/index.tsx | 29 +- .../body/column_headers/column_header.tsx | 43 +- .../timeline/body/column_headers/index.tsx | 29 +- .../body/events/event_column_view.tsx | 18 +- .../timeline/body/events/stateful_event.tsx | 228 +- .../renderers/suricata/suricata_signature.tsx | 82 +- .../body/renderers/zeek/zeek_signature.tsx | 76 +- .../data_providers.test.tsx.snap | 5 - .../__snapshots__/providers.test.tsx.snap | 2243 +++++++++++++---- .../data_providers/data_providers.test.tsx | 27 +- .../timeline/data_providers/index.tsx | 80 +- .../data_providers/provider_badge.tsx | 4 +- .../data_providers/provider_item_badge.tsx | 47 +- .../data_providers/providers.test.tsx | 264 +- .../timeline/data_providers/providers.tsx | 460 ++-- .../timelines/components/timeline/events.ts | 32 +- .../footer/__snapshots__/index.test.tsx.snap | 2 +- .../components/timeline/footer/index.test.tsx | 39 +- .../components/timeline/footer/index.tsx | 90 +- .../header/__snapshots__/index.test.tsx.snap | 5 - .../components/timeline/header/index.tsx | 27 - .../timelines/components/timeline/index.tsx | 78 +- .../timeline/properties/helpers.tsx | 42 +- .../components/timeline/timeline.test.tsx | 210 -- .../components/timeline/timeline.tsx | 26 +- .../public/timelines/containers/index.tsx | 20 +- .../timeline/epic_local_storage.test.tsx | 5 - .../timelines/store/timeline/helpers.ts | 15 +- .../timeline/factory/events/all/index.ts | 9 +- 45 files changed, 3039 insertions(+), 2135 deletions(-) diff --git a/x-pack/plugins/security_solution/common/search_strategy/timeline/events/all/index.ts b/x-pack/plugins/security_solution/common/search_strategy/timeline/events/all/index.ts index 0503a9c327467e..f673fca290a292 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/timeline/events/all/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/timeline/events/all/index.ts @@ -6,7 +6,7 @@ import { IEsSearchResponse } from '../../../../../../../../src/plugins/data/common'; import { Ecs } from '../../../../ecs'; -import { CursorType, Inspect, Maybe } from '../../../common'; +import { CursorType, Inspect, Maybe, PageInfoPaginated } from '../../../common'; import { TimelineRequestOptionsPaginated } from '../..'; export interface TimelineEdges { @@ -29,10 +29,7 @@ export interface TimelineNonEcsData { export interface TimelineEventsAllStrategyResponse extends IEsSearchResponse { edges: TimelineEdges[]; totalCount: number; - pageInfo: { - activePage: number; - totalPages: number; - }; + pageInfo: PageInfoPaginated; inspect?: Maybe; } diff --git a/x-pack/plugins/security_solution/common/search_strategy/timeline/index.ts b/x-pack/plugins/security_solution/common/search_strategy/timeline/index.ts index 773ee608558866..6b96783adc25a3 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/timeline/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/timeline/index.ts @@ -14,7 +14,13 @@ import { TimelineEventsLastEventTimeRequestOptions, TimelineEventsLastEventTimeStrategyResponse, } from './events'; -import { DocValueFields, TimerangeInput, SortField } from '../common'; +import { + DocValueFields, + PaginationInput, + PaginationInputPaginated, + TimerangeInput, + SortField, +} from '../common'; export * from './events'; @@ -29,19 +35,13 @@ export interface TimelineRequestBasicOptions extends IEsSearchRequest { } export interface TimelineRequestOptions extends TimelineRequestBasicOptions { - pagination: { - activePage: number; - querySize: number; - }; + pagination: PaginationInput; sort: SortField; } export interface TimelineRequestOptionsPaginated extends TimelineRequestBasicOptions { - pagination: { - activePage: number; - querySize: number; - }; + pagination: PaginationInputPaginated; sort: SortField; } diff --git a/x-pack/plugins/security_solution/public/common/components/add_filter_to_global_search_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/add_filter_to_global_search_bar/index.tsx index 8a294ec1b71fdd..9f273b4f293bac 100644 --- a/x-pack/plugins/security_solution/public/common/components/add_filter_to_global_search_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/add_filter_to_global_search_bar/index.tsx @@ -5,7 +5,7 @@ */ import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { Filter } from '../../../../../../../src/plugins/data/public'; import { WithHoverActions } from '../with_hover_actions'; @@ -47,34 +47,36 @@ export const AddFilterToGlobalSearchBar = React.memo( } }, [filterManager, filter, onFilterAdded]); - return ( - - - - + const HoverContent = useMemo( + () => ( +
+ + + - - - -
- } - render={() => children} - /> + + + + + ), + [filterForValue, filterOutValue] ); + + const render = useCallback(() => children, [children]); + + return ; } ); diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/drag_drop_context_wrapper.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/drag_drop_context_wrapper.tsx index 74efe2d34fcca7..4efb662a4aab60 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/drag_drop_context_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/drag_drop_context_wrapper.tsx @@ -9,6 +9,7 @@ import React, { useCallback } from 'react'; import { DropResult, DragDropContext } from 'react-beautiful-dnd'; import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; +import deepEqual from 'fast-deep-equal'; import { BeforeCapture } from './drag_drop_context'; import { BrowserFields } from '../../containers/source'; @@ -134,13 +135,11 @@ export const DragDropContextWrapperComponent = React.memo ); }, - (prevProps, nextProps) => { - return ( - prevProps.children === nextProps.children && - prevProps.dataProviders === nextProps.dataProviders && - prevProps.activeTimelineDataProviders === nextProps.activeTimelineDataProviders - ); // prevent re-renders when data providers are added or removed, but all other props are the same - } + // prevent re-renders when data providers are added or removed, but all other props are the same + (prevProps, nextProps) => + prevProps.children === nextProps.children && + deepEqual(prevProps.dataProviders, nextProps.dataProviders) && + prevProps.activeTimelineDataProviders === nextProps.activeTimelineDataProviders ); DragDropContextWrapperComponent.displayName = 'DragDropContextWrapperComponent'; diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx index 64f6699d21dacc..bd22811612a672 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx @@ -196,76 +196,93 @@ const DraggableWrapperComponent: React.FC = ({ ] ); - const renderContent = useCallback( + const RenderClone = useCallback( + (provided, snapshot) => ( + +
+ + {render(dataProvider, provided, snapshot)} + +
+
+ ), + [dataProvider, registerProvider, render] + ); + + const DraggableContent = useCallback( + (provided, snapshot) => ( + { + provided.innerRef(e); + draggableRef.current = e; + }} + data-test-subj="providerContainer" + isDragging={snapshot.isDragging} + registerProvider={registerProvider} + > + {truncate && !snapshot.isDragging ? ( + + {render(dataProvider, provided, snapshot)} + + ) : ( + + {render(dataProvider, provided, snapshot)} + + )} + + ), + [dataProvider, registerProvider, render, truncate] + ); + + const DroppableContent = useCallback( + (droppableProvided) => ( +
+ + {DraggableContent} + + {droppableProvided.placeholder} +
+ ), + [DraggableContent, dataProvider.id, isDisabled] + ); + + const content = useMemo( () => ( ( - -
- - {render(dataProvider, provided, snapshot)} - -
-
- )} + renderClone={RenderClone} > - {(droppableProvided) => ( -
- - {(provided, snapshot) => ( - { - provided.innerRef(e); - draggableRef.current = e; - }} - data-test-subj="providerContainer" - isDragging={snapshot.isDragging} - registerProvider={registerProvider} - > - {truncate && !snapshot.isDragging ? ( - - {render(dataProvider, provided, snapshot)} - - ) : ( - - {render(dataProvider, provided, snapshot)} - - )} - - )} - - {droppableProvided.placeholder} -
- )} + {DroppableContent}
), - [dataProvider, registerProvider, render, isDisabled, truncate] + [DroppableContent, RenderClone, dataProvider.id, isDisabled] ); - if (isDisabled) return <>{renderContent()}; + const renderContent = useCallback(() => content, [content]); + + if (isDisabled) return <>{content}; return ( ( type, render = null, renderClone, - }) => ( - - {(provided, snapshot) => ( + }) => { + const DroppableContent = useCallback( + (provided, snapshot) => ( ( {render == null ? children : render({ isDraggingOver: snapshot.isDraggingOver })} {provided.placeholder} - )} - - ) + ), + [children, height, render] + ); + + return ( + + {DroppableContent} + + ); + } ); DroppableWrapper.displayName = 'DroppableWrapper'; diff --git a/x-pack/plugins/security_solution/public/common/components/draggables/index.tsx b/x-pack/plugins/security_solution/public/common/components/draggables/index.tsx index 4dc3c6fcbe440c..d37de2cd3ec3da 100644 --- a/x-pack/plugins/security_solution/public/common/components/draggables/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/draggables/index.tsx @@ -135,7 +135,7 @@ DefaultDraggable.displayName = 'DefaultDraggable'; export const Badge = styled(EuiBadge)` vertical-align: top; -` as any; // eslint-disable-line @typescript-eslint/no-explicit-any +`; Badge.displayName = 'Badge'; diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx index 2c8c8136a47332..7859f5584b0e54 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx @@ -5,7 +5,7 @@ */ import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; -import { getOr, isEmpty, union } from 'lodash/fp'; +import { isEmpty, union } from 'lodash/fp'; import React, { useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import deepEqual from 'fast-deep-equal'; @@ -239,6 +239,19 @@ const EventsViewerComponent: React.FC = ({ events, ]); + const HeaderSectionContent = useMemo( + () => + headerFilterGroup && ( + + {headerFilterGroup} + + ), + [graphEventId, headerFilterGroup] + ); + useEffect(() => { setIsQueryLoading(loading); }, [loading]); @@ -257,14 +270,7 @@ const EventsViewerComponent: React.FC = ({ subtitle={utilityBar ? undefined : subtitle} title={inspect ? justTitle : titleWithExitFullScreen} > - {headerFilterGroup && ( - - {headerFilterGroup} - - )} + {HeaderSectionContent} {utilityBar && !resolverIsShowing(graphEventId) && ( {utilityBar?.(refetch, totalCountMinusDeleted)} @@ -293,7 +299,7 @@ const EventsViewerComponent: React.FC = ({ /** Hide the footer if Resolver is showing. */ !graphEventId && (