Skip to content

Commit

Permalink
[Custom threshold][Logs Explorer] Fix an issue with saving prefilled …
Browse files Browse the repository at this point in the history
…filters in the custom threshold rule on the Logs Explorer page (elastic#183900)

Fixes elastic#183710

## Summary

This PR fixes the issue of saving prefilled filters in the custom
threshold rule by using `getSearchConfiguration` every time the
serachConfiguration is saved in rule parameters. Now,
`getSearchConfiguration` does two things:
1. Ensure the query has the correct type (`Qurey`), or it will be set as
the default query.
2. Adjust filters by removing `$state` and only keeping `meta` and
`query`

Also, I adjusted the related type to exclude `$state`.

### How to test



https://github.com/elastic/kibana/assets/12370520/9d69e601-d021-4ae3-8baf-88286d3716fe
  • Loading branch information
maryam-saeidi committed May 23, 2024
1 parent d0d6075 commit 4ccd47d
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export enum AlertStates {
// Types for the executor
export interface CustomThresholdSearchSourceFields extends SerializedSearchSourceFields {
query?: Query;
filter?: Array<Pick<Filter, 'meta' | 'query'>>;
}

export interface ThresholdParams {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'));

Expand Down Expand Up @@ -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]
);
Expand Down Expand Up @@ -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 && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { FilterStateStore } from '@kbn/es-query';
import { defaultQuery, getSearchConfiguration } from './get_search_configuration';

describe('getSearchConfiguration()', () => {
Expand Down Expand Up @@ -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);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
};

0 comments on commit 4ccd47d

Please sign in to comment.