mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Add filter field to index threshold rule type (#142255)
* Add filter field to index threshold rule type
This commit is contained in:
parent
f2bbc534f5
commit
660a24e94f
15 changed files with 303 additions and 78 deletions
|
@ -121,6 +121,7 @@ describe('IndexThresholdAlertTypeExpression', () => {
|
|||
expect(wrapper.find('[data-test-subj="forLastExpression"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="visualizationPlaceholder"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="thresholdVisualization"]').exists()).toBeFalsy();
|
||||
expect(wrapper.find('[data-test-subj="filterKuery"]').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
test(`should render IndexThresholdAlertTypeExpression with expected components when aggType does require field`, async () => {
|
||||
|
@ -133,6 +134,7 @@ describe('IndexThresholdAlertTypeExpression', () => {
|
|||
expect(wrapper.find('[data-test-subj="forLastExpression"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="visualizationPlaceholder"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="thresholdVisualization"]').exists()).toBeFalsy();
|
||||
expect(wrapper.find('[data-test-subj="filterKuery"]').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
test(`should render IndexThresholdAlertTypeExpression with visualization when there are no expression errors`, async () => {
|
||||
|
@ -175,6 +177,7 @@ describe('IndexThresholdAlertTypeExpression', () => {
|
|||
expect(
|
||||
wrapper.find('EuiEmptyPrompt[data-test-subj="visualizationPlaceholder"]').text()
|
||||
).toEqual(`Complete the expression to generate a preview.`);
|
||||
expect(wrapper.find('input[data-test-subj="filterKuery"]').text()).toEqual('');
|
||||
});
|
||||
|
||||
test(`should use alert params when params are defined`, async () => {
|
||||
|
@ -186,6 +189,7 @@ describe('IndexThresholdAlertTypeExpression', () => {
|
|||
const groupBy = 'top';
|
||||
const termSize = '27';
|
||||
const termField = 'host.name';
|
||||
|
||||
const wrapper = await setup(
|
||||
getAlertParams({
|
||||
aggType,
|
||||
|
|
|
@ -5,10 +5,18 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState, Fragment, useEffect } from 'react';
|
||||
import React, { useState, Fragment, useEffect, useCallback, ChangeEvent } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiSpacer, EuiCallOut, EuiEmptyPrompt, EuiText, EuiTitle } from '@elastic/eui';
|
||||
import {
|
||||
EuiSpacer,
|
||||
EuiCallOut,
|
||||
EuiEmptyPrompt,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
EuiFieldSearch,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
import { HttpSetup } from '@kbn/core/public';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import {
|
||||
|
@ -78,6 +86,7 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<
|
|||
threshold,
|
||||
timeWindowSize,
|
||||
timeWindowUnit,
|
||||
filterKuery,
|
||||
} = ruleParams;
|
||||
|
||||
const indexArray = indexParamToArray(index);
|
||||
|
@ -133,6 +142,13 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<
|
|||
setEsFields(currentEsFields);
|
||||
};
|
||||
|
||||
const handleFilterChange = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
setRuleParams('filterKuery', e.target.value || undefined);
|
||||
},
|
||||
[setRuleParams]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setDefaultExpressionValues();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
@ -261,6 +277,33 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<
|
|||
}
|
||||
/>
|
||||
<EuiSpacer />
|
||||
<EuiTitle size="xs">
|
||||
<h5>
|
||||
<FormattedMessage
|
||||
id="xpack.stackAlerts.threshold.ui.filterTitle"
|
||||
defaultMessage="Filter (Optional)"
|
||||
/>
|
||||
</h5>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFormRow
|
||||
helpText={i18n.translate('xpack.stackAlerts.threshold.ui.filterKQLHelpText', {
|
||||
defaultMessage: 'Use a KQL expression to limit the scope of your alert trigger.',
|
||||
})}
|
||||
fullWidth
|
||||
display="rowCompressed"
|
||||
isInvalid={errors.filterKuery.length > 0}
|
||||
error={errors.filterKuery}
|
||||
>
|
||||
<EuiFieldSearch
|
||||
data-test-subj="filterKuery"
|
||||
onChange={handleFilterChange}
|
||||
value={filterKuery}
|
||||
fullWidth
|
||||
isInvalid={errors.filterKuery.length > 0}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiSpacer />
|
||||
<div className="actAlertVisualization__chart">
|
||||
{cannotShowVisualization ? (
|
||||
<Fragment>
|
||||
|
|
|
@ -36,6 +36,7 @@ export async function getThresholdAlertVisualizationData({
|
|||
termSize: model.termSize,
|
||||
timeWindowSize: model.timeWindowSize,
|
||||
timeWindowUnit: model.timeWindowUnit,
|
||||
filterKuery: model.filterKuery,
|
||||
dateStart: new Date(visualizeOptions.rangeFrom).toISOString(),
|
||||
dateEnd: new Date(visualizeOptions.rangeTo).toISOString(),
|
||||
interval: visualizeOptions.interval,
|
||||
|
|
|
@ -39,4 +39,5 @@ export interface IndexThresholdAlertParams extends RuleTypeParams {
|
|||
threshold: number[];
|
||||
timeWindowSize: number;
|
||||
timeWindowUnit: string;
|
||||
filterKuery?: string;
|
||||
}
|
||||
|
|
|
@ -94,4 +94,21 @@ describe('expression params validation', () => {
|
|||
expect(validateExpression(initialParams).errors.threshold1.length).toBeGreaterThan(0);
|
||||
expect(validateExpression(initialParams).errors.threshold1[0]).toBe('Threshold1 is required.');
|
||||
});
|
||||
|
||||
test('if filterKuery is invalid should return proper error message', () => {
|
||||
const initialParams: IndexThresholdAlertParams = {
|
||||
index: ['test'],
|
||||
aggType: 'count',
|
||||
groupBy: 'top',
|
||||
threshold: [1],
|
||||
timeWindowSize: 1,
|
||||
timeWindowUnit: 's',
|
||||
thresholdComparator: 'between',
|
||||
filterKuery: 'group:',
|
||||
};
|
||||
expect(validateExpression(initialParams).errors.filterKuery.length).toBeGreaterThan(0);
|
||||
expect(validateExpression(initialParams).errors.filterKuery[0]).toBe(
|
||||
'Filter query is invalid.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
ValidationResult,
|
||||
|
@ -26,6 +27,7 @@ export const validateExpression = (alertParams: IndexThresholdAlertParams): Vali
|
|||
threshold,
|
||||
timeWindowSize,
|
||||
thresholdComparator,
|
||||
filterKuery,
|
||||
} = alertParams;
|
||||
const validationResult = { errors: {} };
|
||||
const errors = {
|
||||
|
@ -37,8 +39,22 @@ export const validateExpression = (alertParams: IndexThresholdAlertParams): Vali
|
|||
threshold1: new Array<string>(),
|
||||
index: new Array<string>(),
|
||||
timeField: new Array<string>(),
|
||||
filterKuery: new Array<string>(),
|
||||
};
|
||||
validationResult.errors = errors;
|
||||
|
||||
if (!!filterKuery) {
|
||||
try {
|
||||
toElasticsearchQuery(fromKueryExpression(filterKuery as string));
|
||||
} catch (e) {
|
||||
errors.filterKuery.push(
|
||||
i18n.translate('xpack.stackAlerts.threshold.ui.validation.error.invalidKql', {
|
||||
defaultMessage: 'Filter query is invalid.',
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!index || index.length === 0) {
|
||||
errors.index.push(
|
||||
i18n.translate('xpack.stackAlerts.threshold.ui.validation.error.requiredIndexText', {
|
||||
|
|
|
@ -104,6 +104,10 @@ describe('ruleType', () => {
|
|||
"description": "termField",
|
||||
"name": "termField",
|
||||
},
|
||||
Object {
|
||||
"description": "filterKuery",
|
||||
"name": "filterKuery",
|
||||
},
|
||||
Object {
|
||||
"description": "termSize",
|
||||
"name": "termSize",
|
||||
|
|
|
@ -169,6 +169,7 @@ export function getRuleType(
|
|||
timeWindowSize: params.timeWindowSize,
|
||||
timeWindowUnit: params.timeWindowUnit,
|
||||
interval: undefined,
|
||||
filterKuery: params.filterKuery,
|
||||
};
|
||||
// console.log(`index_threshold: query: ${JSON.stringify(queryParams, null, 4)}`);
|
||||
const result = await (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue