mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 10:23:14 -04:00
[AO] Add integration test for the Threshold Rule (#160633)
## Summary It fixes #160510 by: - Adding integration tests for the Threshold Rule. - Update the consumer value. - Update the action group.
This commit is contained in:
parent
73d1ed4ef8
commit
2b45cf628f
11 changed files with 439 additions and 15 deletions
|
@ -8,9 +8,9 @@
|
||||||
import * as rt from 'io-ts';
|
import * as rt from 'io-ts';
|
||||||
import { ML_ANOMALY_THRESHOLD } from '@kbn/ml-anomaly-utils/anomaly_threshold';
|
import { ML_ANOMALY_THRESHOLD } from '@kbn/ml-anomaly-utils/anomaly_threshold';
|
||||||
import { values } from 'lodash';
|
import { values } from 'lodash';
|
||||||
|
import { SerializedSearchSourceFields } from '@kbn/data-plugin/common';
|
||||||
import { Color } from './color_palette';
|
import { Color } from './color_palette';
|
||||||
import { metricsExplorerMetricRT } from './metrics_explorer';
|
import { metricsExplorerMetricRT } from './metrics_explorer';
|
||||||
|
|
||||||
import { TimeUnitChar } from '../utils/formatters/duration';
|
import { TimeUnitChar } from '../utils/formatters/duration';
|
||||||
import { SNAPSHOT_CUSTOM_AGGREGATIONS } from './constants';
|
import { SNAPSHOT_CUSTOM_AGGREGATIONS } from './constants';
|
||||||
|
|
||||||
|
@ -201,13 +201,14 @@ export interface MetricAnomalyParams {
|
||||||
|
|
||||||
// Types for the executor
|
// Types for the executor
|
||||||
|
|
||||||
export interface MetricThresholdParams {
|
export interface ThresholdParams {
|
||||||
criteria: MetricExpressionParams[];
|
criteria: MetricExpressionParams[];
|
||||||
filterQuery?: string;
|
filterQuery?: string;
|
||||||
filterQueryText?: string;
|
filterQueryText?: string;
|
||||||
sourceId?: string;
|
sourceId?: string;
|
||||||
alertOnNoData?: boolean;
|
alertOnNoData?: boolean;
|
||||||
alertOnGroupDisappear?: boolean;
|
alertOnGroupDisappear?: boolean;
|
||||||
|
searchConfiguration: SerializedSearchSourceFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BaseMetricExpressionParams {
|
interface BaseMetricExpressionParams {
|
||||||
|
|
|
@ -28,7 +28,7 @@ export function AlertFlyout(props: Props) {
|
||||||
() =>
|
() =>
|
||||||
triggersActionsUI &&
|
triggersActionsUI &&
|
||||||
triggersActionsUI.getAddRuleFlyout({
|
triggersActionsUI.getAddRuleFlyout({
|
||||||
consumer: 'infrastructure',
|
consumer: 'alerts',
|
||||||
onClose: onCloseFlyout,
|
onClose: onCloseFlyout,
|
||||||
canChangeTrigger: false,
|
canChangeTrigger: false,
|
||||||
ruleTypeId: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
|
ruleTypeId: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
|
||||||
|
|
|
@ -71,8 +71,8 @@ export type MetricThresholdAlertContext = {
|
||||||
value?: Record<string, unknown> | null;
|
value?: Record<string, unknown> | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FIRED_ACTIONS_ID = 'metrics.threshold.fired';
|
export const FIRED_ACTIONS_ID = 'threshold.fired';
|
||||||
export const NO_DATA_ACTIONS_ID = 'metrics.threshold.nodata';
|
export const NO_DATA_ACTIONS_ID = 'threshold.nodata';
|
||||||
|
|
||||||
type MetricThresholdActionGroup =
|
type MetricThresholdActionGroup =
|
||||||
| typeof FIRED_ACTIONS_ID
|
| typeof FIRED_ACTIONS_ID
|
||||||
|
@ -408,14 +408,14 @@ export const createMetricThresholdExecutor = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FIRED_ACTIONS = {
|
export const FIRED_ACTIONS = {
|
||||||
id: 'metrics.threshold.fired',
|
id: 'threshold.fired',
|
||||||
name: i18n.translate('xpack.observability.threshold.rule.alerting.threshold.fired', {
|
name: i18n.translate('xpack.observability.threshold.rule.alerting.threshold.fired', {
|
||||||
defaultMessage: 'Alert',
|
defaultMessage: 'Alert',
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NO_DATA_ACTIONS = {
|
export const NO_DATA_ACTIONS = {
|
||||||
id: 'metrics.threshold.nodata',
|
id: 'threshold.nodata',
|
||||||
name: i18n.translate('xpack.observability.threshold.rule.alerting.threshold.nodata', {
|
name: i18n.translate('xpack.observability.threshold.rule.alerting.threshold.nodata', {
|
||||||
defaultMessage: 'No Data',
|
defaultMessage: 'No Data',
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -185,6 +185,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions)
|
||||||
'--xpack.alerting.healthCheck.interval="1s"',
|
'--xpack.alerting.healthCheck.interval="1s"',
|
||||||
'--xpack.alerting.rules.minimumScheduleInterval.value="1s"',
|
'--xpack.alerting.rules.minimumScheduleInterval.value="1s"',
|
||||||
'--xpack.alerting.rules.run.alerts.max=20',
|
'--xpack.alerting.rules.run.alerts.max=20',
|
||||||
|
'--xpack.observability.unsafe.thresholdRule.enabled=true',
|
||||||
`--xpack.alerting.rules.run.actions.connectorTypeOverrides=${JSON.stringify([
|
`--xpack.alerting.rules.run.actions.connectorTypeOverrides=${JSON.stringify([
|
||||||
{ id: 'test.capped', max: '1' },
|
{ id: 'test.capped', max: '1' },
|
||||||
])}`,
|
])}`,
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { InfraRuleType, InfraRuleTypeParams } from '@kbn/infra-plugin/common/alerting/metrics';
|
import { MetricThresholdParams } from '@kbn/infra-plugin/common/alerting/metrics';
|
||||||
|
import { ThresholdParams } from '@kbn/observability-plugin/common/threshold_rule/types';
|
||||||
import type { SuperTest, Test } from 'supertest';
|
import type { SuperTest, Test } from 'supertest';
|
||||||
|
|
||||||
export async function createIndexConnector({
|
export async function createIndexConnector({
|
||||||
|
@ -31,31 +32,35 @@ export async function createIndexConnector({
|
||||||
return body.id as string;
|
return body.id as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createMetricThresholdRule<T extends InfraRuleType>({
|
export async function createRule({
|
||||||
supertest,
|
supertest,
|
||||||
name,
|
name,
|
||||||
ruleTypeId,
|
ruleTypeId,
|
||||||
params,
|
params,
|
||||||
actions = [],
|
actions = [],
|
||||||
|
tags = [],
|
||||||
schedule,
|
schedule,
|
||||||
|
consumer,
|
||||||
}: {
|
}: {
|
||||||
supertest: SuperTest<Test>;
|
supertest: SuperTest<Test>;
|
||||||
ruleTypeId: T;
|
ruleTypeId: string;
|
||||||
name: string;
|
name: string;
|
||||||
params: InfraRuleTypeParams[T];
|
params: MetricThresholdParams | ThresholdParams;
|
||||||
actions?: any[];
|
actions?: any[];
|
||||||
|
tags?: any[];
|
||||||
schedule?: { interval: string };
|
schedule?: { interval: string };
|
||||||
|
consumer: string;
|
||||||
}) {
|
}) {
|
||||||
const { body } = await supertest
|
const { body } = await supertest
|
||||||
.post(`/api/alerting/rule`)
|
.post(`/api/alerting/rule`)
|
||||||
.set('kbn-xsrf', 'foo')
|
.set('kbn-xsrf', 'foo')
|
||||||
.send({
|
.send({
|
||||||
params,
|
params,
|
||||||
consumer: 'infrastructure',
|
consumer,
|
||||||
schedule: schedule || {
|
schedule: schedule || {
|
||||||
interval: '5m',
|
interval: '5m',
|
||||||
},
|
},
|
||||||
tags: ['infrastructure'],
|
tags,
|
||||||
name,
|
name,
|
||||||
rule_type_id: ruleTypeId,
|
rule_type_id: ruleTypeId,
|
||||||
actions,
|
actions,
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
|
* 2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { SuperTest, Test } from 'supertest';
|
||||||
|
|
||||||
|
export const createDataView = async ({
|
||||||
|
supertest,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
}: {
|
||||||
|
supertest: SuperTest<Test>;
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
title: string;
|
||||||
|
}) => {
|
||||||
|
const { body } = await supertest
|
||||||
|
.post(`/api/content_management/rpc/create`)
|
||||||
|
.set('kbn-xsrf', 'foo')
|
||||||
|
.send({
|
||||||
|
contentTypeId: 'index-pattern',
|
||||||
|
data: {
|
||||||
|
fieldAttrs: '{}',
|
||||||
|
title,
|
||||||
|
timeFieldName: '@timestamp',
|
||||||
|
sourceFilters: '[]',
|
||||||
|
fields: '[]',
|
||||||
|
fieldFormatMap: '{}',
|
||||||
|
typeMeta: '{}',
|
||||||
|
runtimeFieldMap: '{}',
|
||||||
|
name,
|
||||||
|
},
|
||||||
|
options: { id },
|
||||||
|
version: 1,
|
||||||
|
});
|
||||||
|
return body;
|
||||||
|
};
|
||||||
|
export const deleteDataView = async ({
|
||||||
|
supertest,
|
||||||
|
id,
|
||||||
|
}: {
|
||||||
|
supertest: SuperTest<Test>;
|
||||||
|
id: string;
|
||||||
|
}) => {
|
||||||
|
const { body } = await supertest
|
||||||
|
.delete(`/api/content_management/rpc/create`)
|
||||||
|
.set('kbn-xsrf', 'foo')
|
||||||
|
.send({
|
||||||
|
contentTypeId: 'index-pattern',
|
||||||
|
id,
|
||||||
|
options: { force: true },
|
||||||
|
version: 1,
|
||||||
|
});
|
||||||
|
return body;
|
||||||
|
};
|
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
|
* 2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Client } from '@elastic/elasticsearch';
|
||||||
|
import {
|
||||||
|
ApmSynthtraceEsClient,
|
||||||
|
ApmSynthtraceKibanaClient,
|
||||||
|
createLogger,
|
||||||
|
LogLevel,
|
||||||
|
} from '@kbn/apm-synthtrace';
|
||||||
|
import { apm, timerange } from '@kbn/apm-synthtrace-client';
|
||||||
|
|
||||||
|
export const getSyntraceClient = async ({
|
||||||
|
kibanaUrl,
|
||||||
|
esClient,
|
||||||
|
}: {
|
||||||
|
kibanaUrl: string;
|
||||||
|
esClient: Client;
|
||||||
|
}) => {
|
||||||
|
const kibanaClient = new ApmSynthtraceKibanaClient({
|
||||||
|
logger: createLogger(LogLevel.info),
|
||||||
|
target: kibanaUrl,
|
||||||
|
});
|
||||||
|
const packageVersion = await kibanaClient.fetchLatestApmPackageVersion();
|
||||||
|
return new ApmSynthtraceEsClient({
|
||||||
|
client: esClient,
|
||||||
|
logger: createLogger(LogLevel.info),
|
||||||
|
refreshAfterIndex: true,
|
||||||
|
version: packageVersion,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dataConfig = {
|
||||||
|
rate: 10,
|
||||||
|
transaction: {
|
||||||
|
name: 'GET /data',
|
||||||
|
duration: 1000,
|
||||||
|
},
|
||||||
|
service: {
|
||||||
|
name: 'lambda-python-dev-hello',
|
||||||
|
version: '$LATEST',
|
||||||
|
runtime: {
|
||||||
|
name: 'AWS_Lambda_python3.8',
|
||||||
|
version: '3.8.11',
|
||||||
|
},
|
||||||
|
framework: 'AWS Lambda',
|
||||||
|
agent: {
|
||||||
|
name: 'python',
|
||||||
|
version: '6.6.0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
containerOs: 'linux',
|
||||||
|
serverless: {
|
||||||
|
firstFunctionName: 'my-function-1',
|
||||||
|
secondFunctionName: 'my-function-2',
|
||||||
|
faasTriggerType: 'other',
|
||||||
|
},
|
||||||
|
cloud: {
|
||||||
|
provider: 'aws',
|
||||||
|
availabilityZone: 'us-central1-c',
|
||||||
|
region: 'us-east-1',
|
||||||
|
machineType: 'e2-standard-4',
|
||||||
|
projectName: 'elastic-observability',
|
||||||
|
serviceName: 'lambda',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function generateData({
|
||||||
|
synthtraceEsClient,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
}: {
|
||||||
|
synthtraceEsClient: ApmSynthtraceEsClient;
|
||||||
|
start: number;
|
||||||
|
end: number;
|
||||||
|
}) {
|
||||||
|
const { rate, service, containerOs, serverless, cloud, transaction } = dataConfig;
|
||||||
|
const {
|
||||||
|
provider,
|
||||||
|
availabilityZone,
|
||||||
|
region,
|
||||||
|
machineType,
|
||||||
|
projectName,
|
||||||
|
serviceName: cloudServiceName,
|
||||||
|
} = cloud;
|
||||||
|
const { faasTriggerType, firstFunctionName, secondFunctionName } = serverless;
|
||||||
|
const { version, runtime, framework, agent, name: serviceName } = service;
|
||||||
|
const { name: serviceRunTimeName, version: serviceRunTimeVersion } = runtime;
|
||||||
|
const { name: agentName, version: agentVersion } = agent;
|
||||||
|
|
||||||
|
const instance = apm
|
||||||
|
.service({ name: serviceName, environment: 'production', agentName })
|
||||||
|
.instance('instance-a');
|
||||||
|
|
||||||
|
const traceEvents = [
|
||||||
|
timerange(start, end)
|
||||||
|
.interval('30s')
|
||||||
|
.rate(rate)
|
||||||
|
.generator((timestamp) =>
|
||||||
|
instance
|
||||||
|
.containerId('instance-a')
|
||||||
|
.transaction({ transactionName: transaction.name })
|
||||||
|
.timestamp(timestamp)
|
||||||
|
.defaults({
|
||||||
|
'cloud.provider': provider,
|
||||||
|
'cloud.project.name': projectName,
|
||||||
|
'cloud.service.name': cloudServiceName,
|
||||||
|
'cloud.availability_zone': availabilityZone,
|
||||||
|
'cloud.machine.type': machineType,
|
||||||
|
'cloud.region': region,
|
||||||
|
'faas.id': `arn:aws:lambda:us-west-2:123456789012:function:${firstFunctionName}`,
|
||||||
|
'faas.trigger.type': faasTriggerType,
|
||||||
|
'host.os.platform': containerOs,
|
||||||
|
'kubernetes.pod.uid': '48f4c5a5-0625-4bea-9d94-77ee94a17e70',
|
||||||
|
'service.version': version,
|
||||||
|
'service.runtime.name': serviceRunTimeName,
|
||||||
|
'service.runtime.version': serviceRunTimeVersion,
|
||||||
|
'service.framework.name': framework,
|
||||||
|
'agent.version': agentVersion,
|
||||||
|
})
|
||||||
|
.duration(transaction.duration)
|
||||||
|
.success()
|
||||||
|
),
|
||||||
|
|
||||||
|
timerange(start, end)
|
||||||
|
.interval('30s')
|
||||||
|
.rate(rate)
|
||||||
|
.generator((timestamp) =>
|
||||||
|
instance
|
||||||
|
.transaction({ transactionName: transaction.name })
|
||||||
|
.timestamp(timestamp)
|
||||||
|
.defaults({
|
||||||
|
'cloud.provider': provider,
|
||||||
|
'cloud.project.name': projectName,
|
||||||
|
'cloud.service.name': cloudServiceName,
|
||||||
|
'cloud.availability_zone': availabilityZone,
|
||||||
|
'cloud.machine.type': machineType,
|
||||||
|
'cloud.region': region,
|
||||||
|
'faas.id': `arn:aws:lambda:us-west-2:123456789012:function:${secondFunctionName}`,
|
||||||
|
'faas.trigger.type': faasTriggerType,
|
||||||
|
'host.os.platform': containerOs,
|
||||||
|
'kubernetes.pod.uid': '48f4c5a5-0625-4bea-9d94-77ee94a17e70',
|
||||||
|
'service.version': version,
|
||||||
|
'service.runtime.name': serviceRunTimeName,
|
||||||
|
'service.runtime.version': serviceRunTimeVersion,
|
||||||
|
'service.framework.name': framework,
|
||||||
|
'agent.version': agentVersion,
|
||||||
|
})
|
||||||
|
.duration(transaction.duration)
|
||||||
|
.success()
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
await synthtraceEsClient.index(traceEvents);
|
||||||
|
}
|
|
@ -9,5 +9,6 @@
|
||||||
export default function ({ loadTestFile }: any) {
|
export default function ({ loadTestFile }: any) {
|
||||||
describe('MetricsUI Endpoints', () => {
|
describe('MetricsUI Endpoints', () => {
|
||||||
loadTestFile(require.resolve('./metric_threshold_rule'));
|
loadTestFile(require.resolve('./metric_threshold_rule'));
|
||||||
|
loadTestFile(require.resolve('./threshold_rule'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
waitForRuleStatus,
|
waitForRuleStatus,
|
||||||
} from './helpers/alerting_wait_for_helpers';
|
} from './helpers/alerting_wait_for_helpers';
|
||||||
import { FtrProviderContext } from '../common/ftr_provider_context';
|
import { FtrProviderContext } from '../common/ftr_provider_context';
|
||||||
import { createIndexConnector, createMetricThresholdRule } from './helpers/alerting_api_helper';
|
import { createIndexConnector, createRule } from './helpers/alerting_api_helper';
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-default-export
|
// eslint-disable-next-line import/no-default-export
|
||||||
export default function ({ getService }: FtrProviderContext) {
|
export default function ({ getService }: FtrProviderContext) {
|
||||||
|
@ -42,9 +42,11 @@ export default function ({ getService }: FtrProviderContext) {
|
||||||
name: 'Index Connector: Metric threshold API test',
|
name: 'Index Connector: Metric threshold API test',
|
||||||
indexName: ALERT_ACTION_INDEX,
|
indexName: ALERT_ACTION_INDEX,
|
||||||
});
|
});
|
||||||
const createdRule = await createMetricThresholdRule({
|
const createdRule = await createRule({
|
||||||
supertest,
|
supertest,
|
||||||
ruleTypeId: InfraRuleType.MetricThreshold,
|
ruleTypeId: InfraRuleType.MetricThreshold,
|
||||||
|
consumer: 'infrastructure',
|
||||||
|
tags: ['infrastructure'],
|
||||||
name: 'Metric threshold rule',
|
name: 'Metric threshold rule',
|
||||||
params: {
|
params: {
|
||||||
criteria: [
|
criteria: [
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
|
* 2.0.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
|
* 2.0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import moment from 'moment';
|
||||||
|
import { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace';
|
||||||
|
import { format } from 'url';
|
||||||
|
import { Aggregators, Comparator } from '@kbn/observability-plugin/common/threshold_rule/types';
|
||||||
|
import { FIRED_ACTIONS_ID } from '@kbn/observability-plugin/server/lib/rules/threshold/threshold_executor';
|
||||||
|
import expect from '@kbn/expect';
|
||||||
|
import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/observability-plugin/common/constants';
|
||||||
|
import { FtrProviderContext } from '../common/ftr_provider_context';
|
||||||
|
import { createIndexConnector, createRule } from './helpers/alerting_api_helper';
|
||||||
|
import { createDataView, deleteDataView } from './helpers/data_view';
|
||||||
|
import { getSyntraceClient, generateData } from './helpers/syntrace';
|
||||||
|
import { waitForAlertInIndex, waitForRuleStatus } from './helpers/alerting_wait_for_helpers';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
export default function ({ getService }: FtrProviderContext) {
|
||||||
|
const start = moment(Date.now()).subtract(10, 'minutes').valueOf();
|
||||||
|
const end = moment(Date.now()).valueOf();
|
||||||
|
const esClient = getService('es');
|
||||||
|
const config = getService('config');
|
||||||
|
const kibanaServerConfig = config.get('servers.kibana');
|
||||||
|
const kibanaUrl = format(kibanaServerConfig);
|
||||||
|
const supertest = getService('supertest');
|
||||||
|
|
||||||
|
describe('Threshold rule', () => {
|
||||||
|
const THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default';
|
||||||
|
const ALERT_ACTION_INDEX = 'alert-action-threshold';
|
||||||
|
const DATA_VIEW_ID = 'data-view-id';
|
||||||
|
|
||||||
|
let synthtraceEsClient: ApmSynthtraceEsClient;
|
||||||
|
let actionId: string;
|
||||||
|
let ruleId: string;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
synthtraceEsClient = await getSyntraceClient({ esClient, kibanaUrl });
|
||||||
|
await generateData({ synthtraceEsClient, start, end });
|
||||||
|
await createDataView({
|
||||||
|
supertest,
|
||||||
|
name: 'test-data-view',
|
||||||
|
id: DATA_VIEW_ID,
|
||||||
|
title: 'traces-apm*,metrics-apm*,logs-apm*',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await supertest.delete(`/api/alerting/rule/${ruleId}`).set('kbn-xsrf', 'foo');
|
||||||
|
await supertest.delete(`/api/actions/connector/${actionId}`).set('kbn-xsrf', 'foo');
|
||||||
|
await esClient.deleteByQuery({
|
||||||
|
index: THRESHOLD_RULE_ALERT_INDEX,
|
||||||
|
query: { term: { 'kibana.alert.rule.uuid': ruleId } },
|
||||||
|
});
|
||||||
|
await esClient.deleteByQuery({
|
||||||
|
index: '.kibana-event-log-*',
|
||||||
|
query: { term: { 'kibana.alert.rule.consumer': 'alerts' } },
|
||||||
|
});
|
||||||
|
await synthtraceEsClient.clean();
|
||||||
|
await deleteDataView({
|
||||||
|
supertest,
|
||||||
|
id: DATA_VIEW_ID,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Rule creation', () => {
|
||||||
|
it('creates rule successfully', async () => {
|
||||||
|
actionId = await createIndexConnector({
|
||||||
|
supertest,
|
||||||
|
name: 'Index Connector: Threshold API test',
|
||||||
|
indexName: ALERT_ACTION_INDEX,
|
||||||
|
});
|
||||||
|
|
||||||
|
const createdRule = await createRule({
|
||||||
|
supertest,
|
||||||
|
tags: ['observability'],
|
||||||
|
consumer: 'alerts',
|
||||||
|
name: 'Threshold rule',
|
||||||
|
ruleTypeId: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID,
|
||||||
|
params: {
|
||||||
|
criteria: [
|
||||||
|
{
|
||||||
|
aggType: Aggregators.CUSTOM,
|
||||||
|
comparator: Comparator.GT,
|
||||||
|
threshold: [7500000],
|
||||||
|
timeSize: 5,
|
||||||
|
timeUnit: 'm',
|
||||||
|
customMetrics: [
|
||||||
|
{ name: 'A', field: 'span.self_time.sum.us', aggType: Aggregators.AVERAGE },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
alertOnNoData: true,
|
||||||
|
alertOnGroupDisappear: true,
|
||||||
|
searchConfiguration: {
|
||||||
|
query: {
|
||||||
|
query: '',
|
||||||
|
language: 'kuery',
|
||||||
|
},
|
||||||
|
index: DATA_VIEW_ID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
group: FIRED_ACTIONS_ID,
|
||||||
|
id: actionId,
|
||||||
|
params: {
|
||||||
|
documents: [
|
||||||
|
{
|
||||||
|
ruleType: '{{rule.type}}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
frequency: {
|
||||||
|
notify_when: 'onActionGroupChange',
|
||||||
|
throttle: null,
|
||||||
|
summary: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
ruleId = createdRule.id;
|
||||||
|
expect(ruleId).not.to.be(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be active', async () => {
|
||||||
|
const executionStatus = await waitForRuleStatus({
|
||||||
|
id: ruleId,
|
||||||
|
expectedStatus: 'active',
|
||||||
|
supertest,
|
||||||
|
});
|
||||||
|
expect(executionStatus.status).to.be('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set correct information in the alert document', async () => {
|
||||||
|
const resp = await waitForAlertInIndex({
|
||||||
|
esClient,
|
||||||
|
indexName: THRESHOLD_RULE_ALERT_INDEX,
|
||||||
|
ruleId,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(resp.hits.hits[0]._source).property(
|
||||||
|
'kibana.alert.rule.category',
|
||||||
|
'Threshold (Technical Preview)'
|
||||||
|
);
|
||||||
|
expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'alerts');
|
||||||
|
expect(resp.hits.hits[0]._source).property('kibana.alert.rule.name', 'Threshold rule');
|
||||||
|
expect(resp.hits.hits[0]._source).property('kibana.alert.rule.producer', 'observability');
|
||||||
|
expect(resp.hits.hits[0]._source).property('kibana.alert.rule.revision', 0);
|
||||||
|
expect(resp.hits.hits[0]._source).property(
|
||||||
|
'kibana.alert.rule.rule_type_id',
|
||||||
|
'observability.rules.threshold'
|
||||||
|
);
|
||||||
|
expect(resp.hits.hits[0]._source).property('kibana.alert.rule.uuid', ruleId);
|
||||||
|
expect(resp.hits.hits[0]._source).property('kibana.space_ids').contain('default');
|
||||||
|
expect(resp.hits.hits[0]._source)
|
||||||
|
.property('kibana.alert.rule.tags')
|
||||||
|
.contain('observability');
|
||||||
|
expect(resp.hits.hits[0]._source).property('kibana.alert.action_group', 'threshold.fired');
|
||||||
|
expect(resp.hits.hits[0]._source).property('tags').contain('observability');
|
||||||
|
expect(resp.hits.hits[0]._source).property('kibana.alert.instance.id', '*');
|
||||||
|
expect(resp.hits.hits[0]._source).property('kibana.alert.workflow_status', 'open');
|
||||||
|
expect(resp.hits.hits[0]._source).property('event.kind', 'signal');
|
||||||
|
expect(resp.hits.hits[0]._source).property('event.action', 'open');
|
||||||
|
|
||||||
|
expect(resp.hits.hits[0]._source)
|
||||||
|
.property('kibana.alert.rule.parameters')
|
||||||
|
.eql({
|
||||||
|
criteria: [
|
||||||
|
{
|
||||||
|
aggType: 'custom',
|
||||||
|
comparator: '>',
|
||||||
|
threshold: [7500000],
|
||||||
|
timeSize: 5,
|
||||||
|
timeUnit: 'm',
|
||||||
|
customMetrics: [{ name: 'A', field: 'span.self_time.sum.us', aggType: 'avg' }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
alertOnNoData: true,
|
||||||
|
alertOnGroupDisappear: true,
|
||||||
|
searchConfiguration: { index: 'data-view-id', query: { query: '', language: 'kuery' } },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -63,6 +63,7 @@ export default function createRegisteredRuleTypeTests({ getService }: FtrProvide
|
||||||
'monitoring_alert_elasticsearch_version_mismatch',
|
'monitoring_alert_elasticsearch_version_mismatch',
|
||||||
'monitoring_ccr_read_exceptions',
|
'monitoring_ccr_read_exceptions',
|
||||||
'monitoring_shard_size',
|
'monitoring_shard_size',
|
||||||
|
'observability.rules.threshold',
|
||||||
'apm.transaction_duration',
|
'apm.transaction_duration',
|
||||||
'apm.anomaly',
|
'apm.anomaly',
|
||||||
'apm.error_rate',
|
'apm.error_rate',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue