diff --git a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/types.ts b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/types.ts index 2633da58c20339..38b7e6d90061c7 100644 --- a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/types.ts +++ b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/types.ts @@ -60,6 +60,7 @@ export enum AlertStates { // Types for the executor export interface CustomThresholdSearchSourceFields extends SerializedSearchSourceFields { query?: Query; + filter?: Array>; } export interface ThresholdParams { diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx index b169f83739881e..41127b2880233d 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx @@ -125,12 +125,18 @@ export default function Expressions(props: Props) { const createdSearchSource = await data.search.searchSource.create( initialSearchConfiguration ); - setRuleParams('searchConfiguration', { - ...initialSearchConfiguration, - ...(ruleParams.searchConfiguration?.query && { - query: ruleParams.searchConfiguration.query, - }), - }); + setRuleParams( + 'searchConfiguration', + getSearchConfiguration( + { + ...initialSearchConfiguration, + ...(ruleParams.searchConfiguration?.query && { + query: ruleParams.searchConfiguration.query, + }), + }, + setParamsWarning + ) + ); setSearchSource(createdSearchSource); setDataView(createdSearchSource.getField('index')); @@ -232,7 +238,10 @@ export default function Expressions(props: Props) { const onFilterChange = useCallback( ({ query }: { query?: Query }) => { setParamsWarning(undefined); - setRuleParams('searchConfiguration', { ...ruleParams.searchConfiguration, query }); + setRuleParams( + 'searchConfiguration', + getSearchConfiguration({ ...ruleParams.searchConfiguration, query }, setParamsWarning) + ); }, [setRuleParams, ruleParams.searchConfiguration] ); @@ -442,13 +451,16 @@ export default function Expressions(props: Props) { query={ruleParams.searchConfiguration?.query} filters={ruleParams.searchConfiguration?.filter} onFiltersUpdated={(filter) => { - // Since rule params will be sent to the API as is, and we only need meta and query parameters to be - // saved in the rule's saved object, we filter extra fields here (such as $state). - const filters = filter.map(({ meta, query }) => ({ meta, query })); - setRuleParams('searchConfiguration', { - ...ruleParams.searchConfiguration, - filter: filters, - }); + setRuleParams( + 'searchConfiguration', + getSearchConfiguration( + { + ...ruleParams.searchConfiguration, + filter, + }, + setParamsWarning + ) + ); }} /> {errors.filterQuery && ( diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/helpers/get_search_configuration.test.ts b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/helpers/get_search_configuration.test.ts index 734a31c7b87446..243f4ce197a667 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/helpers/get_search_configuration.test.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/helpers/get_search_configuration.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { FilterStateStore } from '@kbn/es-query'; import { defaultQuery, getSearchConfiguration } from './get_search_configuration'; describe('getSearchConfiguration()', () => { @@ -37,4 +38,72 @@ describe('getSearchConfiguration()', () => { expect(getSearchConfiguration({ query }, onWarning)).toEqual({ query: defaultQuery }); expect(onWarning).toHaveBeenCalledTimes(1); }); + + it('should return filter without $state field WITHOUT query', () => { + const filter = [ + { + meta: { + alias: null, + disabled: false, + field: 'service.name', + index: 'dataset-logs-*-*', + key: 'service.name', + negate: false, + params: { + query: 'synth-node-0', + }, + type: 'phrase', + }, + query: { + match_phrase: { + 'service.name': 'synth-node-0', + }, + }, + $state: { + store: FilterStateStore.APP_STATE, + }, + }, + ]; + + expect(getSearchConfiguration({ filter }, onWarning)).toEqual({ + filter: filter.map((aFilter) => ({ meta: aFilter.meta, query: aFilter.query })), + }); + expect(onWarning).toHaveBeenCalledTimes(0); + }); + + it('should return filter without $state field WITH esql query', () => { + const filter = [ + { + meta: { + alias: null, + disabled: false, + field: 'service.name', + index: 'dataset-logs-*-*', + key: 'service.name', + negate: false, + params: { + query: 'synth-node-0', + }, + type: 'phrase', + }, + query: { + match_phrase: { + 'service.name': 'synth-node-0', + }, + }, + $state: { + store: FilterStateStore.APP_STATE, + }, + }, + ]; + const query = { + esql: 'random esql', + }; + + expect(getSearchConfiguration({ filter, query }, onWarning)).toEqual({ + filter: filter.map((aFilter) => ({ meta: aFilter.meta, query: aFilter.query })), + query: defaultQuery, + }); + expect(onWarning).toHaveBeenCalledTimes(1); + }); }); diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/helpers/get_search_configuration.ts b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/helpers/get_search_configuration.ts index 9bdcd74a978040..ed1b3ae4db7d90 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/helpers/get_search_configuration.ts +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/helpers/get_search_configuration.ts @@ -29,13 +29,27 @@ export const getSearchConfiguration = ( ): CustomThresholdSearchSourceFields => { if (fields.query && !isOfQueryType(fields.query)) { onWarning(searchConfigQueryWarning); - return { + return adjustSearchConfigurationFilter({ ...fields, query: defaultQuery, - }; + }); } - return { + return adjustSearchConfigurationFilter({ ...fields, query: fields.query, + }); +}; + +const adjustSearchConfigurationFilter = ( + searchConfiguration: CustomThresholdSearchSourceFields +): CustomThresholdSearchSourceFields => { + // Only meta and query fields are saved in the rule params, so we ignore other fields such as $state + const filter = searchConfiguration.filter + ? searchConfiguration.filter.map(({ meta, query }) => ({ meta, query })) + : undefined; + + return { + ...searchConfiguration, + filter, }; };