mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Response Ops][Alerting] alert
-> rule
for stack alerts (#144613)
* Renaming folder * Renaming alertType to ruleType. Adding parameters to support group by * Renaming * Updating codeowners
This commit is contained in:
parent
f1f1b5789d
commit
a62635146e
105 changed files with 169 additions and 181 deletions
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
|
@ -227,8 +227,8 @@
|
|||
/x-pack/test/api_integration/apis/maps/ @elastic/kibana-gis
|
||||
/x-pack/test/functional/apps/maps/ @elastic/kibana-gis
|
||||
/x-pack/test/functional/es_archives/maps/ @elastic/kibana-gis
|
||||
/x-pack/plugins/stack_alerts/server/alert_types/geo_containment @elastic/kibana-gis
|
||||
/x-pack/plugins/stack_alerts/public/alert_types/geo_containment @elastic/kibana-gis
|
||||
/x-pack/plugins/stack_alerts/server/rule_types/geo_containment @elastic/kibana-gis
|
||||
/x-pack/plugins/stack_alerts/public/rule_types/geo_containment @elastic/kibana-gis
|
||||
#CC# /x-pack/plugins/file_upload @elastic/kibana-gis
|
||||
/x-pack/plugins/file_upload @elastic/kibana-gis
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { PluginInitializerContext } from '@kbn/core/public';
|
||||
import { StackAlertsPublicPlugin } from './plugin';
|
||||
|
||||
export const plugin = (ctx: PluginInitializerContext) => new StackAlertsPublicPlugin(ctx);
|
||||
export const plugin = () => new StackAlertsPublicPlugin();
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { CoreSetup, Plugin, PluginInitializerContext } from '@kbn/core/public';
|
||||
import { CoreSetup, Plugin } from '@kbn/core/public';
|
||||
import { TriggersAndActionsUIPublicPluginSetup } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/public';
|
||||
import { registerAlertTypes } from './alert_types';
|
||||
import { Config } from '../common';
|
||||
import { registerRuleTypes } from './rule_types';
|
||||
|
||||
export type Setup = void;
|
||||
export type Start = void;
|
||||
|
@ -20,16 +19,9 @@ export interface StackAlertsPublicSetupDeps {
|
|||
}
|
||||
|
||||
export class StackAlertsPublicPlugin implements Plugin<Setup, Start, StackAlertsPublicSetupDeps> {
|
||||
private initializerContext: PluginInitializerContext;
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.initializerContext = initializerContext;
|
||||
}
|
||||
|
||||
public setup(core: CoreSetup, { triggersActionsUi, alerting }: StackAlertsPublicSetupDeps) {
|
||||
registerAlertTypes({
|
||||
registerRuleTypes({
|
||||
ruleTypeRegistry: triggersActionsUi.ruleTypeRegistry,
|
||||
config: this.initializerContext.config.get<Config>(),
|
||||
alerting,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
ISearchStart,
|
||||
} from '@kbn/data-plugin/public';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { EsQueryAlertParams, SearchType } from '../types';
|
||||
import { EsQueryRuleParams, SearchType } from '../types';
|
||||
import { EsQueryExpression } from './es_query_expression';
|
||||
|
||||
jest.mock('@kbn/kibana-react-plugin/public', () => ({
|
||||
|
@ -106,7 +106,7 @@ const dataViewMock = dataViewPluginMocks.createStartContract();
|
|||
const unifiedSearchMock = unifiedSearchPluginMock.createStartContract();
|
||||
const chartsStartMock = chartPluginMock.createStartContract();
|
||||
|
||||
const defaultEsQueryExpressionParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const defaultEsQueryExpressionParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [0],
|
||||
|
@ -118,7 +118,7 @@ const defaultEsQueryExpressionParams: EsQueryAlertParams<SearchType.esQuery> = {
|
|||
excludeHitsFromPreviousRun: true,
|
||||
};
|
||||
|
||||
describe('EsQueryAlertTypeExpression', () => {
|
||||
describe('EsQueryRuleTypeExpression', () => {
|
||||
beforeAll(() => {
|
||||
(useKibana as jest.Mock).mockReturnValue({
|
||||
services: {
|
||||
|
@ -135,7 +135,7 @@ describe('EsQueryAlertTypeExpression', () => {
|
|||
});
|
||||
});
|
||||
|
||||
async function setup(alertParams: EsQueryAlertParams<SearchType.esQuery>) {
|
||||
async function setup(alertParams: EsQueryRuleParams<SearchType.esQuery>) {
|
||||
const errors = {
|
||||
index: [],
|
||||
esQuery: [],
|
||||
|
@ -172,7 +172,7 @@ describe('EsQueryAlertTypeExpression', () => {
|
|||
return wrapper;
|
||||
}
|
||||
|
||||
test('should render EsQueryAlertTypeExpression with expected components', async () => {
|
||||
test('should render EsQueryRuleTypeExpression with expected components', async () => {
|
||||
const wrapper = await setup(defaultEsQueryExpressionParams);
|
||||
expect(wrapper.find('[data-test-subj="indexSelectPopover"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="sizeValueExpression"]').exists()).toBeTruthy();
|
||||
|
@ -197,7 +197,7 @@ describe('EsQueryAlertTypeExpression', () => {
|
|||
const wrapper = await setup({
|
||||
...defaultEsQueryExpressionParams,
|
||||
timeField: null,
|
||||
} as unknown as EsQueryAlertParams<SearchType.esQuery>);
|
||||
} as unknown as EsQueryRuleParams<SearchType.esQuery>);
|
||||
const testQueryButton = wrapper.find('EuiButton[data-test-subj="testQuery"]');
|
||||
expect(testQueryButton.exists()).toBeTruthy();
|
||||
expect(testQueryButton.prop('disabled')).toBe(true);
|
|
@ -19,7 +19,7 @@ import { getFields, RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-
|
|||
import { parseDuration } from '@kbn/alerting-plugin/common';
|
||||
import { hasExpressionValidationErrors } from '../validation';
|
||||
import { buildSortedEventsQuery } from '../../../../common/build_sorted_events_query';
|
||||
import { EsQueryAlertParams, SearchType } from '../types';
|
||||
import { EsQueryRuleParams, SearchType } from '../types';
|
||||
import { IndexSelectPopover } from '../../components/index_select_popover';
|
||||
import { DEFAULT_VALUES } from '../constants';
|
||||
import { RuleCommonExpressions } from '../rule_common_expressions';
|
||||
|
@ -33,7 +33,7 @@ interface KibanaDeps {
|
|||
}
|
||||
|
||||
export const EsQueryExpression: React.FC<
|
||||
RuleTypeParamsExpressionProps<EsQueryAlertParams<SearchType.esQuery>>
|
||||
RuleTypeParamsExpressionProps<EsQueryRuleParams<SearchType.esQuery>>
|
||||
> = ({ ruleParams, setRuleParams, setRuleProperty, errors, data }) => {
|
||||
const {
|
||||
index,
|
||||
|
@ -47,19 +47,20 @@ export const EsQueryExpression: React.FC<
|
|||
excludeHitsFromPreviousRun,
|
||||
} = ruleParams;
|
||||
|
||||
const [currentRuleParams, setCurrentRuleParams] = useState<
|
||||
EsQueryAlertParams<SearchType.esQuery>
|
||||
>({
|
||||
...ruleParams,
|
||||
timeWindowSize: timeWindowSize ?? DEFAULT_VALUES.TIME_WINDOW_SIZE,
|
||||
timeWindowUnit: timeWindowUnit ?? DEFAULT_VALUES.TIME_WINDOW_UNIT,
|
||||
threshold: threshold ?? DEFAULT_VALUES.THRESHOLD,
|
||||
thresholdComparator: thresholdComparator ?? DEFAULT_VALUES.THRESHOLD_COMPARATOR,
|
||||
size: size ?? DEFAULT_VALUES.SIZE,
|
||||
esQuery: esQuery ?? DEFAULT_VALUES.QUERY,
|
||||
searchType: SearchType.esQuery,
|
||||
excludeHitsFromPreviousRun: excludeHitsFromPreviousRun ?? DEFAULT_VALUES.EXCLUDE_PREVIOUS_HITS,
|
||||
});
|
||||
const [currentRuleParams, setCurrentRuleParams] = useState<EsQueryRuleParams<SearchType.esQuery>>(
|
||||
{
|
||||
...ruleParams,
|
||||
timeWindowSize: timeWindowSize ?? DEFAULT_VALUES.TIME_WINDOW_SIZE,
|
||||
timeWindowUnit: timeWindowUnit ?? DEFAULT_VALUES.TIME_WINDOW_UNIT,
|
||||
threshold: threshold ?? DEFAULT_VALUES.THRESHOLD,
|
||||
thresholdComparator: thresholdComparator ?? DEFAULT_VALUES.THRESHOLD_COMPARATOR,
|
||||
size: size ?? DEFAULT_VALUES.SIZE,
|
||||
esQuery: esQuery ?? DEFAULT_VALUES.QUERY,
|
||||
searchType: SearchType.esQuery,
|
||||
excludeHitsFromPreviousRun:
|
||||
excludeHitsFromPreviousRun ?? DEFAULT_VALUES.EXCLUDE_PREVIOUS_HITS,
|
||||
}
|
||||
);
|
||||
|
||||
const setParam = useCallback(
|
||||
(paramField: string, paramValue: unknown) => {
|
||||
|
@ -178,7 +179,6 @@ export const EsQueryExpression: React.FC<
|
|||
}}
|
||||
onTimeFieldChange={(updatedTimeField: string) => setParam('timeField', updatedTimeField)}
|
||||
/>
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<EuiTitle size="xs">
|
|
@ -13,8 +13,8 @@ import { httpServiceMock } from '@kbn/core/public/mocks';
|
|||
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
|
||||
import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks';
|
||||
import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks';
|
||||
import { CommonAlertParams, EsQueryAlertParams, SearchType } from '../types';
|
||||
import { EsQueryAlertTypeExpression } from './expression';
|
||||
import { CommonRuleParams, EsQueryRuleParams, SearchType } from '../types';
|
||||
import { EsQueryRuleTypeExpression } from './expression';
|
||||
import { chartPluginMock } from '@kbn/charts-plugin/public/mocks';
|
||||
import { Subject } from 'rxjs';
|
||||
import { ISearchSource } from '@kbn/data-plugin/common';
|
||||
|
@ -42,7 +42,7 @@ jest.mock('@kbn/kibana-react-plugin/public', () => {
|
|||
};
|
||||
});
|
||||
|
||||
const defaultEsQueryRuleParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const defaultEsQueryRuleParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [0],
|
||||
|
@ -54,7 +54,7 @@ const defaultEsQueryRuleParams: EsQueryAlertParams<SearchType.esQuery> = {
|
|||
searchType: SearchType.esQuery,
|
||||
excludeHitsFromPreviousRun: true,
|
||||
};
|
||||
const defaultSearchSourceRuleParams: EsQueryAlertParams<SearchType.searchSource> = {
|
||||
const defaultSearchSourceRuleParams: EsQueryRuleParams<SearchType.searchSource> = {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [0],
|
||||
|
@ -136,9 +136,9 @@ dataMock.query.savedQueries.findSavedQueries = jest.fn(() =>
|
|||
(httpMock.post as jest.Mock).mockImplementation(() => Promise.resolve({ fields: [] }));
|
||||
|
||||
const Wrapper: React.FC<{
|
||||
ruleParams: EsQueryAlertParams<SearchType.searchSource> | EsQueryAlertParams<SearchType.esQuery>;
|
||||
ruleParams: EsQueryRuleParams<SearchType.searchSource> | EsQueryRuleParams<SearchType.esQuery>;
|
||||
}> = ({ ruleParams }) => {
|
||||
const [currentRuleParams, setCurrentRuleParams] = useState<CommonAlertParams>(ruleParams);
|
||||
const [currentRuleParams, setCurrentRuleParams] = useState<CommonRuleParams>(ruleParams);
|
||||
const errors = {
|
||||
index: [],
|
||||
esQuery: [],
|
||||
|
@ -150,7 +150,7 @@ const Wrapper: React.FC<{
|
|||
};
|
||||
|
||||
return (
|
||||
<EsQueryAlertTypeExpression
|
||||
<EsQueryRuleTypeExpression
|
||||
ruleInterval="1m"
|
||||
ruleThrottle="1m"
|
||||
alertNotifyWhen="onThrottleInterval"
|
||||
|
@ -160,7 +160,7 @@ const Wrapper: React.FC<{
|
|||
}}
|
||||
setRuleProperty={(name, params) => {
|
||||
if (name === 'params') {
|
||||
setCurrentRuleParams(params as CommonAlertParams);
|
||||
setCurrentRuleParams(params as CommonRuleParams);
|
||||
}
|
||||
}}
|
||||
errors={errors}
|
||||
|
@ -175,7 +175,7 @@ const Wrapper: React.FC<{
|
|||
};
|
||||
|
||||
const setup = (
|
||||
ruleParams: EsQueryAlertParams<SearchType.searchSource> | EsQueryAlertParams<SearchType.esQuery>
|
||||
ruleParams: EsQueryRuleParams<SearchType.searchSource> | EsQueryRuleParams<SearchType.esQuery>
|
||||
) => {
|
||||
return mountWithIntl(
|
||||
<KibanaContextProvider
|
||||
|
@ -191,9 +191,9 @@ const setup = (
|
|||
);
|
||||
};
|
||||
|
||||
describe('EsQueryAlertTypeExpression', () => {
|
||||
describe('EsQueryRuleTypeExpression', () => {
|
||||
test('should render options by default', async () => {
|
||||
const wrapper = setup({} as EsQueryAlertParams<SearchType.esQuery>);
|
||||
const wrapper = setup({} as EsQueryRuleParams<SearchType.esQuery>);
|
||||
expect(findTestSubject(wrapper, 'queryFormTypeChooserTitle').exists()).toBeTruthy();
|
||||
expect(findTestSubject(wrapper, 'queryFormType_searchSource').exists()).toBeTruthy();
|
||||
expect(findTestSubject(wrapper, 'queryFormType_esQuery').exists()).toBeTruthy();
|
||||
|
@ -201,7 +201,7 @@ describe('EsQueryAlertTypeExpression', () => {
|
|||
});
|
||||
|
||||
test('should switch to QueryDSL form type on selection and return back on cancel', async () => {
|
||||
let wrapper = setup({} as EsQueryAlertParams<SearchType.esQuery>);
|
||||
let wrapper = setup({} as EsQueryRuleParams<SearchType.esQuery>);
|
||||
await act(async () => {
|
||||
findTestSubject(wrapper, 'queryFormType_esQuery').simulate('click');
|
||||
});
|
||||
|
@ -220,7 +220,7 @@ describe('EsQueryAlertTypeExpression', () => {
|
|||
});
|
||||
|
||||
test('should switch to KQL or Lucene form type on selection and return back on cancel', async () => {
|
||||
let wrapper = setup({} as EsQueryAlertParams<SearchType.searchSource>);
|
||||
let wrapper = setup({} as EsQueryRuleParams<SearchType.searchSource>);
|
||||
await act(async () => {
|
||||
findTestSubject(wrapper, 'queryFormType_searchSource').simulate('click');
|
||||
});
|
|
@ -11,11 +11,11 @@ import 'brace/theme/github';
|
|||
import { EuiCallOut, EuiHorizontalRule, EuiSpacer } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { EsQueryAlertParams, SearchType } from '../types';
|
||||
import { EsQueryRuleParams, SearchType } from '../types';
|
||||
import { SearchSourceExpression, SearchSourceExpressionProps } from './search_source_expression';
|
||||
import { EsQueryExpression } from './es_query_expression';
|
||||
import { QueryFormTypeChooser } from './query_form_type_chooser';
|
||||
import { isSearchSourceAlert } from '../util';
|
||||
import { isSearchSourceRule } from '../util';
|
||||
import { EXPRESSION_ERROR_KEYS } from '../constants';
|
||||
|
||||
function areSearchSourceExpressionPropsEqual(
|
||||
|
@ -32,11 +32,11 @@ const SearchSourceExpressionMemoized = memo<SearchSourceExpressionProps>(
|
|||
areSearchSourceExpressionPropsEqual
|
||||
);
|
||||
|
||||
export const EsQueryAlertTypeExpression: React.FunctionComponent<
|
||||
RuleTypeParamsExpressionProps<EsQueryAlertParams>
|
||||
export const EsQueryRuleTypeExpression: React.FunctionComponent<
|
||||
RuleTypeParamsExpressionProps<EsQueryRuleParams>
|
||||
> = (props) => {
|
||||
const { ruleParams, errors, setRuleProperty, setRuleParams } = props;
|
||||
const isSearchSource = isSearchSourceAlert(ruleParams);
|
||||
const isSearchSource = isSearchSourceRule(ruleParams);
|
||||
const isManagementPage = useRef(!Object.keys(ruleParams).length).current;
|
||||
|
||||
const formTypeSelected = useCallback(
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EsQueryAlertTypeExpression } from './expression';
|
||||
import { EsQueryRuleTypeExpression } from './expression';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default EsQueryAlertTypeExpression;
|
||||
export default EsQueryRuleTypeExpression;
|
|
@ -10,7 +10,7 @@ import React from 'react';
|
|||
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
|
||||
import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks';
|
||||
import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks';
|
||||
import { EsQueryAlertParams, SearchType } from '../types';
|
||||
import { EsQueryRuleParams, SearchType } from '../types';
|
||||
import { SearchSourceExpression } from './search_source_expression';
|
||||
import { chartPluginMock } from '@kbn/charts-plugin/public/mocks';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
@ -38,7 +38,7 @@ export const uiSettingsMock = {
|
|||
get: jest.fn(),
|
||||
} as unknown as IUiSettingsClient;
|
||||
|
||||
const defaultSearchSourceExpressionParams: EsQueryAlertParams<SearchType.searchSource> = {
|
||||
const defaultSearchSourceExpressionParams: EsQueryRuleParams<SearchType.searchSource> = {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [0],
|
||||
|
@ -191,7 +191,7 @@ dataMock.query.savedQueries.findSavedQueries = jest.fn(() =>
|
|||
Promise.resolve({ total: 0, queries: [] })
|
||||
);
|
||||
|
||||
const setup = (alertParams: EsQueryAlertParams<SearchType.searchSource>) => {
|
||||
const setup = (alertParams: EsQueryRuleParams<SearchType.searchSource>) => {
|
||||
const errors = {
|
||||
size: [],
|
||||
timeField: [],
|
|
@ -11,13 +11,13 @@ import { EuiSpacer, EuiLoadingSpinner, EuiEmptyPrompt, EuiCallOut } from '@elast
|
|||
import { ISearchSource } from '@kbn/data-plugin/common';
|
||||
import { RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { SavedQuery } from '@kbn/data-plugin/public';
|
||||
import { EsQueryAlertParams, SearchType } from '../types';
|
||||
import { EsQueryRuleParams, SearchType } from '../types';
|
||||
import { useTriggersAndActionsUiDeps } from '../util';
|
||||
import { SearchSourceExpressionForm } from './search_source_expression_form';
|
||||
import { DEFAULT_VALUES } from '../constants';
|
||||
|
||||
export type SearchSourceExpressionProps = RuleTypeParamsExpressionProps<
|
||||
EsQueryAlertParams<SearchType.searchSource>
|
||||
EsQueryRuleParams<SearchType.searchSource>
|
||||
>;
|
||||
|
||||
export const SearchSourceExpression = ({
|
|
@ -16,7 +16,7 @@ import { IErrorObject } from '@kbn/triggers-actions-ui-plugin/public';
|
|||
import { SearchBar, SearchBarProps } from '@kbn/unified-search-plugin/public';
|
||||
import { mapAndFlattenFilters, SavedQuery, TimeHistory } from '@kbn/data-plugin/public';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { CommonAlertParams, EsQueryAlertParams, SearchType } from '../types';
|
||||
import { CommonRuleParams, EsQueryRuleParams, SearchType } from '../types';
|
||||
import { DEFAULT_VALUES } from '../constants';
|
||||
import { DataViewSelectPopover } from '../../components/data_view_select_popover';
|
||||
import { useTriggersAndActionsUiDeps } from '../util';
|
||||
|
@ -33,12 +33,12 @@ interface LocalState {
|
|||
index: DataView;
|
||||
filter: Filter[];
|
||||
query: Query;
|
||||
thresholdComparator: CommonAlertParams['thresholdComparator'];
|
||||
threshold: CommonAlertParams['threshold'];
|
||||
timeWindowSize: CommonAlertParams['timeWindowSize'];
|
||||
timeWindowUnit: CommonAlertParams['timeWindowUnit'];
|
||||
size: CommonAlertParams['size'];
|
||||
excludeHitsFromPreviousRun: CommonAlertParams['excludeHitsFromPreviousRun'];
|
||||
thresholdComparator: CommonRuleParams['thresholdComparator'];
|
||||
threshold: CommonRuleParams['threshold'];
|
||||
timeWindowSize: CommonRuleParams['timeWindowSize'];
|
||||
timeWindowUnit: CommonRuleParams['timeWindowUnit'];
|
||||
size: CommonRuleParams['size'];
|
||||
excludeHitsFromPreviousRun: CommonRuleParams['excludeHitsFromPreviousRun'];
|
||||
}
|
||||
|
||||
interface LocalStateAction {
|
||||
|
@ -64,7 +64,7 @@ interface SearchSourceParamsAction {
|
|||
|
||||
interface SearchSourceExpressionFormProps {
|
||||
searchSource: ISearchSource;
|
||||
ruleParams: EsQueryAlertParams<SearchType.searchSource>;
|
||||
ruleParams: EsQueryRuleParams<SearchType.searchSource>;
|
||||
errors: IErrorObject;
|
||||
initialSavedQuery?: SavedQuery;
|
||||
setParam: (paramField: string, paramValue: unknown) => void;
|
|
@ -10,13 +10,13 @@ import { i18n } from '@kbn/i18n';
|
|||
import { RuleTypeModel } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/public';
|
||||
import { SanitizedRule } from '@kbn/alerting-plugin/common';
|
||||
import { EsQueryAlertParams, SearchType } from './types';
|
||||
import { EsQueryRuleParams, SearchType } from './types';
|
||||
import { validateExpression } from './validation';
|
||||
|
||||
const PLUGIN_ID = 'discover';
|
||||
const ES_QUERY_ALERT_TYPE = '.es-query';
|
||||
|
||||
export function getAlertType(alerting: AlertingSetup): RuleTypeModel<EsQueryAlertParams> {
|
||||
export function getRuleType(alerting: AlertingSetup): RuleTypeModel<EsQueryRuleParams> {
|
||||
registerNavigation(alerting);
|
||||
|
||||
return {
|
||||
|
@ -47,7 +47,7 @@ function registerNavigation(alerting: AlertingSetup) {
|
|||
alerting.registerNavigation(
|
||||
PLUGIN_ID,
|
||||
ES_QUERY_ALERT_TYPE,
|
||||
(alert: SanitizedRule<EsQueryAlertParams<SearchType.searchSource>>) => {
|
||||
(alert: SanitizedRule<EsQueryRuleParams<SearchType.searchSource>>) => {
|
||||
return `#/viewAlert/${alert.id}`;
|
||||
}
|
||||
);
|
|
@ -23,18 +23,18 @@ import {
|
|||
ThresholdExpression,
|
||||
ValueExpression,
|
||||
} from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { CommonAlertParams } from '../types';
|
||||
import { CommonRuleParams } from '../types';
|
||||
import { DEFAULT_VALUES } from '../constants';
|
||||
import { TestQueryRow, TestQueryRowProps } from '../test_query_row';
|
||||
import { QueryThresholdHelpPopover } from './threshold_help_popover';
|
||||
|
||||
export interface RuleCommonExpressionsProps {
|
||||
thresholdComparator?: CommonAlertParams['thresholdComparator'];
|
||||
threshold?: CommonAlertParams['threshold'];
|
||||
timeWindowSize: CommonAlertParams['timeWindowSize'];
|
||||
timeWindowUnit: CommonAlertParams['timeWindowUnit'];
|
||||
size: CommonAlertParams['size'];
|
||||
excludeHitsFromPreviousRun: CommonAlertParams['excludeHitsFromPreviousRun'];
|
||||
thresholdComparator?: CommonRuleParams['thresholdComparator'];
|
||||
threshold?: CommonRuleParams['threshold'];
|
||||
timeWindowSize: CommonRuleParams['timeWindowSize'];
|
||||
timeWindowUnit: CommonRuleParams['timeWindowUnit'];
|
||||
size: CommonRuleParams['size'];
|
||||
excludeHitsFromPreviousRun: CommonRuleParams['excludeHitsFromPreviousRun'];
|
||||
errors: IErrorObject;
|
||||
hasValidationErrors: boolean;
|
||||
onChangeThreshold: Parameters<typeof ThresholdExpression>[0]['onChangeSelectedThreshold'];
|
|
@ -23,7 +23,7 @@ export enum SearchType {
|
|||
searchSource = 'searchSource',
|
||||
}
|
||||
|
||||
export interface CommonAlertParams extends RuleTypeParams {
|
||||
export interface CommonRuleParams extends RuleTypeParams {
|
||||
size: number;
|
||||
thresholdComparator?: string;
|
||||
threshold: number[];
|
||||
|
@ -32,17 +32,17 @@ export interface CommonAlertParams extends RuleTypeParams {
|
|||
excludeHitsFromPreviousRun: boolean;
|
||||
}
|
||||
|
||||
export type EsQueryAlertParams<T = SearchType> = T extends SearchType.searchSource
|
||||
? CommonAlertParams & OnlySearchSourceAlertParams
|
||||
: CommonAlertParams & OnlyEsQueryAlertParams;
|
||||
export type EsQueryRuleParams<T = SearchType> = T extends SearchType.searchSource
|
||||
? CommonRuleParams & OnlySearchSourceRuleParams
|
||||
: CommonRuleParams & OnlyEsQueryRuleParams;
|
||||
|
||||
export interface OnlyEsQueryAlertParams {
|
||||
export interface OnlyEsQueryRuleParams {
|
||||
esQuery: string;
|
||||
index: string[];
|
||||
timeField: string;
|
||||
}
|
||||
|
||||
export interface OnlySearchSourceAlertParams {
|
||||
export interface OnlySearchSourceRuleParams {
|
||||
searchType?: 'searchSource';
|
||||
searchConfiguration?: SerializedSearchSourceFields;
|
||||
savedQueryId?: string;
|
|
@ -6,11 +6,11 @@
|
|||
*/
|
||||
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { EsQueryAlertParams, SearchType, TriggersAndActionsUiDeps } from './types';
|
||||
import { EsQueryRuleParams, SearchType, TriggersAndActionsUiDeps } from './types';
|
||||
|
||||
export const isSearchSourceAlert = (
|
||||
ruleParams: EsQueryAlertParams
|
||||
): ruleParams is EsQueryAlertParams<SearchType.searchSource> => {
|
||||
export const isSearchSourceRule = (
|
||||
ruleParams: EsQueryRuleParams
|
||||
): ruleParams is EsQueryRuleParams<SearchType.searchSource> => {
|
||||
return ruleParams.searchType === 'searchSource';
|
||||
};
|
||||
|
|
@ -5,19 +5,19 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EsQueryAlertParams, SearchType } from './types';
|
||||
import { EsQueryRuleParams, SearchType } from './types';
|
||||
import { validateExpression, hasExpressionValidationErrors } from './validation';
|
||||
|
||||
describe('expression params validation', () => {
|
||||
test('if params are not set should return a proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> =
|
||||
{} as EsQueryAlertParams<SearchType.esQuery>;
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> =
|
||||
{} as EsQueryRuleParams<SearchType.esQuery>;
|
||||
expect(validateExpression(initialParams).errors.searchType.length).toBeGreaterThan(0);
|
||||
expect(validateExpression(initialParams).errors.searchType[0]).toBe('Query type is required.');
|
||||
});
|
||||
|
||||
test('if index property is invalid should return proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: [],
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`,
|
||||
size: 100,
|
||||
|
@ -32,7 +32,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if timeField property is not defined should return proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`,
|
||||
size: 100,
|
||||
|
@ -47,7 +47,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if esQuery property is invalid JSON should return proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n`,
|
||||
size: 100,
|
||||
|
@ -62,7 +62,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if esQuery property is invalid should return proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: `{\n \"aggs\":{\n \"match_all\" : {}\n }\n}`,
|
||||
size: 100,
|
||||
|
@ -84,7 +84,7 @@ describe('expression params validation', () => {
|
|||
timeWindowUnit: 's',
|
||||
threshold: [0],
|
||||
searchType: SearchType.searchSource,
|
||||
} as EsQueryAlertParams<SearchType.searchSource>;
|
||||
} as EsQueryRuleParams<SearchType.searchSource>;
|
||||
expect(validateExpression(initialParams).errors.searchConfiguration.length).toBeGreaterThan(0);
|
||||
expect(validateExpression(initialParams).errors.searchConfiguration[0]).toBe(
|
||||
`Search source configuration is required.`
|
||||
|
@ -92,7 +92,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if threshold0 property is not set should return proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`,
|
||||
size: 100,
|
||||
|
@ -108,7 +108,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if threshold1 property is needed by thresholdComparator but not set should return proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`,
|
||||
size: 100,
|
||||
|
@ -124,7 +124,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if threshold0 property greater than threshold1 property should return proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`,
|
||||
size: 100,
|
||||
|
@ -142,7 +142,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if size property is < 0 should return proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n`,
|
||||
size: -1,
|
||||
|
@ -159,7 +159,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if size property is 0 should not return error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n`,
|
||||
size: 0,
|
||||
|
@ -173,7 +173,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if size property is > 10000 should return proper error message', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n`,
|
||||
size: 25000,
|
||||
|
@ -190,7 +190,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('should not return error messages if all is correct', () => {
|
||||
const initialParams: EsQueryAlertParams<SearchType.esQuery> = {
|
||||
const initialParams: EsQueryRuleParams<SearchType.esQuery> = {
|
||||
index: ['test'],
|
||||
esQuery: '{"query":{"match_all":{}}}',
|
||||
size: 250,
|
|
@ -8,11 +8,11 @@
|
|||
import { defaultsDeep, isNil } from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ValidationResult, builtInComparators } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { EsQueryAlertParams, ExpressionErrors } from './types';
|
||||
import { isSearchSourceAlert } from './util';
|
||||
import { EsQueryRuleParams, ExpressionErrors } from './types';
|
||||
import { isSearchSourceRule } from './util';
|
||||
import { EXPRESSION_ERRORS } from './constants';
|
||||
|
||||
export const validateExpression = (ruleParams: EsQueryAlertParams): ValidationResult => {
|
||||
export const validateExpression = (ruleParams: EsQueryRuleParams): ValidationResult => {
|
||||
const { size, threshold, timeWindowSize, thresholdComparator } = ruleParams;
|
||||
const validationResult = { errors: {} };
|
||||
const errors: ExpressionErrors = defaultsDeep({}, EXPRESSION_ERRORS);
|
||||
|
@ -80,10 +80,10 @@ export const validateExpression = (ruleParams: EsQueryAlertParams): ValidationRe
|
|||
}
|
||||
|
||||
/**
|
||||
* Skip esQuery and index params check if it is search source alert,
|
||||
* Skip esQuery and index params check if it is search source rule,
|
||||
* since it should contain searchConfiguration instead of esQuery and index.
|
||||
*/
|
||||
const isSearchSource = isSearchSourceAlert(ruleParams);
|
||||
const isSearchSource = isSearchSourceRule(ruleParams);
|
||||
if (isSearchSource) {
|
||||
if (!ruleParams.searchConfiguration) {
|
||||
errors.searchConfiguration.push(
|
||||
|
@ -148,7 +148,7 @@ export const validateExpression = (ruleParams: EsQueryAlertParams): ValidationRe
|
|||
return validationResult;
|
||||
};
|
||||
|
||||
export const hasExpressionValidationErrors = (ruleParams: EsQueryAlertParams) => {
|
||||
export const hasExpressionValidationErrors = (ruleParams: EsQueryRuleParams) => {
|
||||
const { errors: validationErrors } = validateExpression(ruleParams);
|
||||
return Object.keys(validationErrors).some(
|
||||
(key) => validationErrors[key] && validationErrors[key].length
|
|
@ -11,7 +11,7 @@ import { RuleTypeModel } from '@kbn/triggers-actions-ui-plugin/public';
|
|||
import { validateExpression } from './validation';
|
||||
import { GeoContainmentAlertParams } from './types';
|
||||
|
||||
export function getAlertType(): RuleTypeModel<GeoContainmentAlertParams> {
|
||||
export function getRuleType(): RuleTypeModel<GeoContainmentAlertParams> {
|
||||
return {
|
||||
id: '.geo-containment',
|
||||
description: i18n.translate('xpack.stackAlerts.geoContainment.descriptionText', {
|
|
@ -7,21 +7,18 @@
|
|||
|
||||
import { TriggersAndActionsUIPublicPluginSetup } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/public';
|
||||
import { getAlertType as getGeoContainmentAlertType } from './geo_containment';
|
||||
import { getAlertType as getThresholdAlertType } from './threshold';
|
||||
import { getAlertType as getEsQueryAlertType } from './es_query';
|
||||
import { Config } from '../../common';
|
||||
import { getRuleType as getGeoContainmentRuleType } from './geo_containment';
|
||||
import { getRuleType as getThresholdRuleType } from './threshold';
|
||||
import { getRuleType as getEsQueryRuleType } from './es_query';
|
||||
|
||||
export function registerAlertTypes({
|
||||
export function registerRuleTypes({
|
||||
ruleTypeRegistry,
|
||||
config,
|
||||
alerting,
|
||||
}: {
|
||||
ruleTypeRegistry: TriggersAndActionsUIPublicPluginSetup['ruleTypeRegistry'];
|
||||
config: Config;
|
||||
alerting: AlertingSetup;
|
||||
}) {
|
||||
ruleTypeRegistry.register(getGeoContainmentAlertType());
|
||||
ruleTypeRegistry.register(getThresholdAlertType());
|
||||
ruleTypeRegistry.register(getEsQueryAlertType(alerting));
|
||||
ruleTypeRegistry.register(getGeoContainmentRuleType());
|
||||
ruleTypeRegistry.register(getThresholdRuleType());
|
||||
ruleTypeRegistry.register(getEsQueryRuleType(alerting));
|
||||
}
|
|
@ -8,11 +8,11 @@
|
|||
import React from 'react';
|
||||
import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import IndexThresholdAlertTypeExpression, { DEFAULT_VALUES } from './expression';
|
||||
import IndexThresholdRuleTypeExpression, { DEFAULT_VALUES } from './expression';
|
||||
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
|
||||
import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks';
|
||||
import { chartPluginMock } from '@kbn/charts-plugin/public/mocks';
|
||||
import { IndexThresholdAlertParams } from './types';
|
||||
import { IndexThresholdRuleParams } from './types';
|
||||
import { validateExpression } from './validation';
|
||||
import {
|
||||
builtInAggregationTypes,
|
||||
|
@ -72,7 +72,7 @@ const dataMock = dataPluginMock.createStartContract();
|
|||
const dataViewMock = dataViewPluginMocks.createStartContract();
|
||||
const chartsStartMock = chartPluginMock.createStartContract();
|
||||
|
||||
describe('IndexThresholdAlertTypeExpression', () => {
|
||||
describe('IndexThresholdRuleTypeExpression', () => {
|
||||
function getAlertParams(overrides = {}) {
|
||||
return {
|
||||
index: 'test-index',
|
||||
|
@ -84,11 +84,11 @@ describe('IndexThresholdAlertTypeExpression', () => {
|
|||
...overrides,
|
||||
};
|
||||
}
|
||||
async function setup(ruleParams: IndexThresholdAlertParams) {
|
||||
async function setup(ruleParams: IndexThresholdRuleParams) {
|
||||
const { errors } = validateExpression(ruleParams);
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
<IndexThresholdAlertTypeExpression
|
||||
<IndexThresholdRuleTypeExpression
|
||||
ruleInterval="1m"
|
||||
ruleThrottle="1m"
|
||||
alertNotifyWhen="onThrottleInterval"
|
||||
|
@ -111,7 +111,7 @@ describe('IndexThresholdAlertTypeExpression', () => {
|
|||
return wrapper;
|
||||
}
|
||||
|
||||
test(`should render IndexThresholdAlertTypeExpression with expected components when aggType doesn't require field`, async () => {
|
||||
test(`should render IndexThresholdRuleTypeExpression with expected components when aggType doesn't require field`, async () => {
|
||||
const wrapper = await setup(getAlertParams());
|
||||
expect(wrapper.find('[data-test-subj="indexSelectPopover"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="whenExpression"]').exists()).toBeTruthy();
|
||||
|
@ -124,7 +124,7 @@ describe('IndexThresholdAlertTypeExpression', () => {
|
|||
expect(wrapper.find('[data-test-subj="filterKuery"]').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
test(`should render IndexThresholdAlertTypeExpression with expected components when aggType does require field`, async () => {
|
||||
test(`should render IndexThresholdRuleTypeExpression with expected components when aggType does require field`, async () => {
|
||||
const wrapper = await setup(getAlertParams({ aggType: 'avg' }));
|
||||
expect(wrapper.find('[data-test-subj="indexSelectPopover"]').exists()).toBeTruthy();
|
||||
expect(wrapper.find('[data-test-subj="whenExpression"]').exists()).toBeTruthy();
|
||||
|
@ -137,7 +137,7 @@ describe('IndexThresholdAlertTypeExpression', () => {
|
|||
expect(wrapper.find('[data-test-subj="filterKuery"]').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
test(`should render IndexThresholdAlertTypeExpression with visualization when there are no expression errors`, async () => {
|
||||
test(`should render IndexThresholdRuleTypeExpression with visualization when there are no expression errors`, async () => {
|
||||
const wrapper = await setup(getAlertParams({ timeField: '@timestamp' }));
|
||||
expect(wrapper.find('[data-test-subj="visualizationPlaceholder"]').exists()).toBeFalsy();
|
||||
expect(wrapper.find('[data-test-subj="thresholdVisualization"]').exists()).toBeTruthy();
|
|
@ -32,7 +32,7 @@ import {
|
|||
RuleTypeParamsExpressionProps,
|
||||
} from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { ThresholdVisualization } from './visualization';
|
||||
import { IndexThresholdAlertParams } from './types';
|
||||
import { IndexThresholdRuleParams } from './types';
|
||||
import './expression.scss';
|
||||
import { IndexSelectPopover } from '../components/index_select_popover';
|
||||
|
||||
|
@ -71,8 +71,8 @@ function indexParamToArray(index: string | string[]): string[] {
|
|||
return isString(index) ? [index] : index;
|
||||
}
|
||||
|
||||
export const IndexThresholdAlertTypeExpression: React.FunctionComponent<
|
||||
Omit<RuleTypeParamsExpressionProps<IndexThresholdAlertParams>, 'unifiedSearch'>
|
||||
export const IndexThresholdRuleTypeExpression: React.FunctionComponent<
|
||||
Omit<RuleTypeParamsExpressionProps<IndexThresholdRuleParams>, 'unifiedSearch'>
|
||||
> = ({ ruleParams, ruleInterval, setRuleParams, setRuleProperty, errors, charts, data }) => {
|
||||
const {
|
||||
index,
|
||||
|
@ -106,7 +106,7 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<
|
|||
(errorKey) =>
|
||||
expressionFieldsWithValidation.includes(errorKey) &&
|
||||
errors[errorKey].length >= 1 &&
|
||||
ruleParams[errorKey as keyof IndexThresholdAlertParams] !== undefined
|
||||
ruleParams[errorKey as keyof IndexThresholdRuleParams] !== undefined
|
||||
);
|
||||
|
||||
const cannotShowVisualization = !!Object.keys(errors).find(
|
||||
|
@ -339,4 +339,4 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<
|
|||
};
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export { IndexThresholdAlertTypeExpression as default };
|
||||
export { IndexThresholdRuleTypeExpression as default };
|
|
@ -9,9 +9,9 @@ import { lazy } from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { RuleTypeModel } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { validateExpression } from './validation';
|
||||
import { IndexThresholdAlertParams } from './types';
|
||||
import { IndexThresholdRuleParams } from './types';
|
||||
|
||||
export function getAlertType(): RuleTypeModel<IndexThresholdAlertParams> {
|
||||
export function getRuleType(): RuleTypeModel<IndexThresholdRuleParams> {
|
||||
return {
|
||||
id: '.index-threshold',
|
||||
description: i18n.translate('xpack.stackAlerts.threshold.ui.alertType.descriptionText', {
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
import { HttpSetup } from '@kbn/core/public';
|
||||
import { TimeSeriesResult } from '@kbn/triggers-actions-ui-plugin/common';
|
||||
import { IndexThresholdAlertParams } from './types';
|
||||
import { IndexThresholdRuleParams } from './types';
|
||||
|
||||
const INDEX_THRESHOLD_DATA_API_ROOT = '/internal/triggers_actions_ui/data';
|
||||
|
||||
export interface GetThresholdAlertVisualizationDataParams {
|
||||
model: IndexThresholdAlertParams;
|
||||
export interface GetThresholdRuleVisualizationDataParams {
|
||||
model: IndexThresholdRuleParams;
|
||||
visualizeOptions: {
|
||||
rangeFrom: string;
|
||||
rangeTo: string;
|
||||
|
@ -21,11 +21,11 @@ export interface GetThresholdAlertVisualizationDataParams {
|
|||
http: HttpSetup;
|
||||
}
|
||||
|
||||
export async function getThresholdAlertVisualizationData({
|
||||
export async function getThresholdRuleVisualizationData({
|
||||
model,
|
||||
visualizeOptions,
|
||||
http,
|
||||
}: GetThresholdAlertVisualizationDataParams): Promise<TimeSeriesResult> {
|
||||
}: GetThresholdRuleVisualizationDataParams): Promise<TimeSeriesResult> {
|
||||
const timeSeriesQueryParams = {
|
||||
index: model.index,
|
||||
timeField: model.timeField,
|
|
@ -27,7 +27,7 @@ export interface GroupByType {
|
|||
validNormalizedTypes: string[];
|
||||
}
|
||||
|
||||
export interface IndexThresholdAlertParams extends RuleTypeParams {
|
||||
export interface IndexThresholdRuleParams extends RuleTypeParams {
|
||||
index: string | string[];
|
||||
timeField?: string;
|
||||
aggType: string;
|
|
@ -5,12 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { IndexThresholdAlertParams } from './types';
|
||||
import { IndexThresholdRuleParams } from './types';
|
||||
import { validateExpression } from './validation';
|
||||
|
||||
describe('expression params validation', () => {
|
||||
test('if index property is invalid should return proper error message', () => {
|
||||
const initialParams: IndexThresholdAlertParams = {
|
||||
const initialParams: IndexThresholdRuleParams = {
|
||||
index: [],
|
||||
aggType: 'count',
|
||||
threshold: [],
|
||||
|
@ -21,7 +21,7 @@ describe('expression params validation', () => {
|
|||
expect(validateExpression(initialParams).errors.index[0]).toBe('Index is required.');
|
||||
});
|
||||
test('if timeField property is not defined should return proper error message', () => {
|
||||
const initialParams: IndexThresholdAlertParams = {
|
||||
const initialParams: IndexThresholdRuleParams = {
|
||||
index: ['test'],
|
||||
aggType: 'count',
|
||||
threshold: [],
|
||||
|
@ -32,7 +32,7 @@ describe('expression params validation', () => {
|
|||
expect(validateExpression(initialParams).errors.timeField[0]).toBe('Time field is required.');
|
||||
});
|
||||
test('if aggField property is invalid should return proper error message', () => {
|
||||
const initialParams: IndexThresholdAlertParams = {
|
||||
const initialParams: IndexThresholdRuleParams = {
|
||||
index: 'test',
|
||||
aggType: 'avg',
|
||||
threshold: [],
|
||||
|
@ -45,7 +45,7 @@ describe('expression params validation', () => {
|
|||
);
|
||||
});
|
||||
test('if termSize property is not set should return proper error message', () => {
|
||||
const initialParams: IndexThresholdAlertParams = {
|
||||
const initialParams: IndexThresholdRuleParams = {
|
||||
index: ['test'],
|
||||
aggType: 'count',
|
||||
groupBy: 'top',
|
||||
|
@ -57,7 +57,7 @@ describe('expression params validation', () => {
|
|||
expect(validateExpression(initialParams).errors.termSize[0]).toBe('Term size is required.');
|
||||
});
|
||||
test('if termField property is not set should return proper error message', () => {
|
||||
const initialParams: IndexThresholdAlertParams = {
|
||||
const initialParams: IndexThresholdRuleParams = {
|
||||
index: ['test'],
|
||||
aggType: 'count',
|
||||
groupBy: 'top',
|
||||
|
@ -69,7 +69,7 @@ describe('expression params validation', () => {
|
|||
expect(validateExpression(initialParams).errors.termField[0]).toBe('Term field is required.');
|
||||
});
|
||||
test('if threshold0 property is not set should return proper error message', () => {
|
||||
const initialParams: IndexThresholdAlertParams = {
|
||||
const initialParams: IndexThresholdRuleParams = {
|
||||
index: ['test'],
|
||||
aggType: 'count',
|
||||
groupBy: 'top',
|
||||
|
@ -82,7 +82,7 @@ describe('expression params validation', () => {
|
|||
expect(validateExpression(initialParams).errors.threshold0[0]).toBe('Threshold0 is required.');
|
||||
});
|
||||
test('if threshold1 property is not set should return proper error message', () => {
|
||||
const initialParams: IndexThresholdAlertParams = {
|
||||
const initialParams: IndexThresholdRuleParams = {
|
||||
index: ['test'],
|
||||
aggType: 'count',
|
||||
groupBy: 'top',
|
||||
|
@ -96,7 +96,7 @@ describe('expression params validation', () => {
|
|||
});
|
||||
|
||||
test('if filterKuery is invalid should return proper error message', () => {
|
||||
const initialParams: IndexThresholdAlertParams = {
|
||||
const initialParams: IndexThresholdRuleParams = {
|
||||
index: ['test'],
|
||||
aggType: 'count',
|
||||
groupBy: 'top',
|
|
@ -13,9 +13,9 @@ import {
|
|||
builtInAggregationTypes,
|
||||
builtInComparators,
|
||||
} from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { IndexThresholdAlertParams } from './types';
|
||||
import { IndexThresholdRuleParams } from './types';
|
||||
|
||||
export const validateExpression = (alertParams: IndexThresholdAlertParams): ValidationResult => {
|
||||
export const validateExpression = (alertParams: IndexThresholdRuleParams): ValidationResult => {
|
||||
const {
|
||||
index,
|
||||
timeField,
|
|
@ -22,7 +22,7 @@ import { useKibana } from '@kbn/kibana-react-plugin/public';
|
|||
|
||||
jest.mock('@kbn/kibana-react-plugin/public');
|
||||
jest.mock('./index_threshold_api', () => ({
|
||||
getThresholdAlertVisualizationData: jest.fn(() =>
|
||||
getThresholdRuleVisualizationData: jest.fn(() =>
|
||||
Promise.resolve({
|
||||
results: [
|
||||
{ group: 'a', metrics: [['b', 2]] },
|
||||
|
@ -32,7 +32,7 @@ jest.mock('./index_threshold_api', () => ({
|
|||
),
|
||||
}));
|
||||
|
||||
const { getThresholdAlertVisualizationData } = jest.requireMock('./index_threshold_api');
|
||||
const { getThresholdRuleVisualizationData } = jest.requireMock('./index_threshold_api');
|
||||
|
||||
const dataMock = dataPluginMock.createStartContract();
|
||||
const chartsStartMock = chartPluginMock.createStartContract();
|
||||
|
@ -99,7 +99,7 @@ describe('ThresholdVisualization', () => {
|
|||
await nextTick();
|
||||
wrapper.update();
|
||||
});
|
||||
expect(getThresholdAlertVisualizationData).toHaveBeenCalledTimes(1);
|
||||
expect(getThresholdRuleVisualizationData).toHaveBeenCalledTimes(1);
|
||||
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
await act(async () => {
|
||||
|
@ -107,7 +107,7 @@ describe('ThresholdVisualization', () => {
|
|||
await nextTick();
|
||||
wrapper.update();
|
||||
});
|
||||
expect(getThresholdAlertVisualizationData).toHaveBeenCalledTimes(i + 1);
|
||||
expect(getThresholdRuleVisualizationData).toHaveBeenCalledTimes(i + 1);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -130,7 +130,7 @@ describe('ThresholdVisualization', () => {
|
|||
});
|
||||
|
||||
expect(wrapper.find('[data-test-subj="firstLoad"]').exists()).toBeFalsy();
|
||||
expect(getThresholdAlertVisualizationData).toHaveBeenCalled();
|
||||
expect(getThresholdRuleVisualizationData).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('renders chart when visualization results are available', async () => {
|
||||
|
@ -144,7 +144,7 @@ describe('ThresholdVisualization', () => {
|
|||
});
|
||||
|
||||
test('renders multiple line series chart when visualization results contain multiple groups', async () => {
|
||||
getThresholdAlertVisualizationData.mockImplementation(() =>
|
||||
getThresholdRuleVisualizationData.mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
results: [
|
||||
{ group: 'a', metrics: [['b', 2]] },
|
||||
|
@ -165,7 +165,7 @@ describe('ThresholdVisualization', () => {
|
|||
|
||||
test('renders error callout with message when getting visualization fails', async () => {
|
||||
const errorMessage = 'oh no';
|
||||
getThresholdAlertVisualizationData.mockImplementation(() =>
|
||||
getThresholdRuleVisualizationData.mockImplementation(() =>
|
||||
Promise.reject(new Error(errorMessage))
|
||||
);
|
||||
const wrapper = await setup();
|
||||
|
@ -182,7 +182,7 @@ describe('ThresholdVisualization', () => {
|
|||
});
|
||||
|
||||
test('renders error callout even when unable to get message from error', async () => {
|
||||
getThresholdAlertVisualizationData.mockImplementation(() =>
|
||||
getThresholdRuleVisualizationData.mockImplementation(() =>
|
||||
Promise.reject(new Error(undefined))
|
||||
);
|
||||
const wrapper = await setup();
|
||||
|
@ -199,7 +199,7 @@ describe('ThresholdVisualization', () => {
|
|||
});
|
||||
|
||||
test('renders no data message when visualization results are empty', async () => {
|
||||
getThresholdAlertVisualizationData.mockImplementation(() => Promise.resolve({ results: [] }));
|
||||
getThresholdRuleVisualizationData.mockImplementation(() => Promise.resolve({ results: [] }));
|
||||
const wrapper = await setup();
|
||||
|
||||
expect(wrapper.find('[data-test-subj="alertVisualizationChart"]').exists()).toBeTruthy();
|
|
@ -35,10 +35,10 @@ import { useKibana } from '@kbn/kibana-react-plugin/public';
|
|||
import { AggregationType, Comparator } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { parseDuration } from '@kbn/alerting-plugin/common/parse_duration';
|
||||
import {
|
||||
getThresholdAlertVisualizationData,
|
||||
GetThresholdAlertVisualizationDataParams,
|
||||
getThresholdRuleVisualizationData,
|
||||
GetThresholdRuleVisualizationDataParams,
|
||||
} from './index_threshold_api';
|
||||
import { IndexThresholdAlertParams } from './types';
|
||||
import { IndexThresholdRuleParams } from './types';
|
||||
|
||||
const customTheme = () => {
|
||||
return {
|
||||
|
@ -87,7 +87,7 @@ const getDomain = (alertInterval: string, startAt: Date) => {
|
|||
};
|
||||
|
||||
interface Props {
|
||||
ruleParams: IndexThresholdAlertParams;
|
||||
ruleParams: IndexThresholdRuleParams;
|
||||
alertInterval: string;
|
||||
aggregationTypes: { [key: string]: AggregationType };
|
||||
comparators: {
|
||||
|
@ -336,11 +336,11 @@ export const ThresholdVisualization: React.FunctionComponent<Props> = ({
|
|||
|
||||
// convert the data from the visualization API into something easier to digest with charts
|
||||
async function getVisualizationData(
|
||||
model: IndexThresholdAlertParams,
|
||||
visualizeOptions: GetThresholdAlertVisualizationDataParams['visualizeOptions'],
|
||||
model: IndexThresholdRuleParams,
|
||||
visualizeOptions: GetThresholdRuleVisualizationDataParams['visualizeOptions'],
|
||||
http: HttpSetup
|
||||
) {
|
||||
const vizData = await getThresholdAlertVisualizationData({
|
||||
const vizData = await getThresholdRuleVisualizationData({
|
||||
model,
|
||||
visualizeOptions,
|
||||
http,
|
|
@ -9,9 +9,9 @@ import { i18n } from '@kbn/i18n';
|
|||
import { KibanaFeatureConfig } from '@kbn/features-plugin/common';
|
||||
import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server';
|
||||
import { TRANSFORM_RULE_TYPE } from '@kbn/transform-plugin/common';
|
||||
import { ID as IndexThreshold } from './alert_types/index_threshold/rule_type';
|
||||
import { GEO_CONTAINMENT_ID as GeoContainment } from './alert_types/geo_containment/alert_type';
|
||||
import { ES_QUERY_ID as ElasticsearchQuery } from './alert_types/es_query/constants';
|
||||
import { ID as IndexThreshold } from './rule_types/index_threshold/rule_type';
|
||||
import { GEO_CONTAINMENT_ID as GeoContainment } from './rule_types/geo_containment/alert_type';
|
||||
import { ES_QUERY_ID as ElasticsearchQuery } from './rule_types/es_query/constants';
|
||||
import { STACK_ALERTS_FEATURE_ID } from '../common';
|
||||
|
||||
const TransformHealth = TRANSFORM_RULE_TYPE.TRANSFORM_HEALTH;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { get } from 'lodash';
|
|||
import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server';
|
||||
import { AlertingBuiltinsPlugin } from './plugin';
|
||||
import { configSchema, Config } from '../common/config';
|
||||
export { ID as INDEX_THRESHOLD_ID } from './alert_types/index_threshold/rule_type';
|
||||
export { ID as INDEX_THRESHOLD_ID } from './rule_types/index_threshold/rule_type';
|
||||
|
||||
export const config: PluginConfigDescriptor<Config> = {
|
||||
exposeToBrowser: {},
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { Plugin, Logger, CoreSetup, PluginInitializerContext } from '@kbn/core/server';
|
||||
|
||||
import { StackAlertsDeps, StackAlertsStartDeps } from './types';
|
||||
import { registerBuiltInAlertTypes } from './alert_types';
|
||||
import { registerBuiltInRuleTypes } from './rule_types';
|
||||
import { BUILT_IN_ALERTS_FEATURE } from './feature';
|
||||
|
||||
export class AlertingBuiltinsPlugin
|
||||
|
@ -23,7 +23,7 @@ export class AlertingBuiltinsPlugin
|
|||
public setup(core: CoreSetup<StackAlertsStartDeps>, { alerting, features }: StackAlertsDeps) {
|
||||
features.registerKibanaFeature(BUILT_IN_ALERTS_FEATURE);
|
||||
|
||||
registerBuiltInAlertTypes({
|
||||
registerBuiltInRuleTypes({
|
||||
logger: this.logger,
|
||||
data: core
|
||||
.getStartServices()
|
||||
|
|
|
@ -10,14 +10,14 @@ import { AlertingSetup, StackAlertsStartDeps } from '../types';
|
|||
import { register as registerIndexThreshold } from './index_threshold';
|
||||
import { register as registerGeoContainment } from './geo_containment';
|
||||
import { register as registerEsQuery } from './es_query';
|
||||
interface RegisterAlertTypesParams {
|
||||
interface RegisterRuleTypesParams {
|
||||
logger: Logger;
|
||||
data: Promise<StackAlertsStartDeps['triggersActionsUi']['data']>;
|
||||
alerting: AlertingSetup;
|
||||
core: CoreSetup;
|
||||
}
|
||||
|
||||
export function registerBuiltInAlertTypes(params: RegisterAlertTypesParams) {
|
||||
export function registerBuiltInRuleTypes(params: RegisterRuleTypesParams) {
|
||||
registerIndexThreshold(params);
|
||||
registerGeoContainment(params);
|
||||
registerEsQuery(params);
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue