kibana/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts
Cauê Marcondes ffc1caa2d2
[APM] Add default message to alerts. (#78930)
* adding default message

* addressing pr comments

* addressing pr comments

* addressing pr comments

* addressing pr comments

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
2020-10-06 09:18:15 +02:00

161 lines
5.2 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { schema } from '@kbn/config-schema';
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { getDurationFormatter } from '../../../common/utils/formatters';
import { ProcessorEvent } from '../../../common/processor_event';
import { AlertType, ALERT_TYPES_CONFIG } from '../../../common/alert_types';
import { ESSearchResponse } from '../../../typings/elasticsearch';
import {
PROCESSOR_EVENT,
SERVICE_NAME,
TRANSACTION_TYPE,
TRANSACTION_DURATION,
SERVICE_ENVIRONMENT,
} from '../../../common/elasticsearch_fieldnames';
import { AlertingPlugin } from '../../../../alerts/server';
import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
import { APMConfig } from '../..';
import { getEnvironmentUiFilterES } from '../helpers/convert_ui_filters/get_environment_ui_filter_es';
import { apmActionVariables } from './action_variables';
interface RegisterAlertParams {
alerts: AlertingPlugin['setup'];
config$: Observable<APMConfig>;
}
const paramsSchema = schema.object({
serviceName: schema.string(),
transactionType: schema.string(),
windowSize: schema.number(),
windowUnit: schema.string(),
threshold: schema.number(),
aggregationType: schema.oneOf([
schema.literal('avg'),
schema.literal('95th'),
schema.literal('99th'),
]),
environment: schema.string(),
});
const alertTypeConfig = ALERT_TYPES_CONFIG[AlertType.TransactionDuration];
export function registerTransactionDurationAlertType({
alerts,
config$,
}: RegisterAlertParams) {
alerts.registerType({
id: AlertType.TransactionDuration,
name: alertTypeConfig.name,
actionGroups: alertTypeConfig.actionGroups,
defaultActionGroupId: alertTypeConfig.defaultActionGroupId,
validate: {
params: paramsSchema,
},
actionVariables: {
context: [
apmActionVariables.serviceName,
apmActionVariables.transactionType,
apmActionVariables.environment,
apmActionVariables.threshold,
apmActionVariables.triggerValue,
apmActionVariables.interval,
],
},
producer: 'apm',
executor: async ({ services, params }) => {
const config = await config$.pipe(take(1)).toPromise();
const alertParams = params;
const indices = await getApmIndices({
config,
savedObjectsClient: services.savedObjectsClient,
});
const searchParams = {
index: indices['apm_oss.transactionIndices'],
size: 0,
body: {
query: {
bool: {
filter: [
{
range: {
'@timestamp': {
gte: `now-${alertParams.windowSize}${alertParams.windowUnit}`,
},
},
},
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
{ term: { [SERVICE_NAME]: alertParams.serviceName } },
{ term: { [TRANSACTION_TYPE]: alertParams.transactionType } },
...getEnvironmentUiFilterES(alertParams.environment),
],
},
},
aggs: {
agg:
alertParams.aggregationType === 'avg'
? { avg: { field: TRANSACTION_DURATION } }
: {
percentiles: {
field: TRANSACTION_DURATION,
percents: [
alertParams.aggregationType === '95th' ? 95 : 99,
],
},
},
environments: {
terms: {
field: SERVICE_ENVIRONMENT,
},
},
},
},
};
const response: ESSearchResponse<
unknown,
typeof searchParams
> = await services.callCluster('search', searchParams);
if (!response.aggregations) {
return;
}
const { agg, environments } = response.aggregations;
const transactionDuration =
'values' in agg ? Object.values(agg.values)[0] : agg?.value;
const threshold = alertParams.threshold * 1000;
if (transactionDuration && transactionDuration > threshold) {
const durationFormatter = getDurationFormatter(transactionDuration);
const transactionDurationFormatted = durationFormatter(
transactionDuration
).formatted;
environments.buckets.map((bucket) => {
const environment = bucket.key;
const alertInstance = services.alertInstanceFactory(
`${AlertType.TransactionDuration}_${environment}`
);
alertInstance.scheduleActions(alertTypeConfig.defaultActionGroupId, {
transactionType: alertParams.transactionType,
serviceName: alertParams.serviceName,
environment,
threshold,
triggerValue: transactionDurationFormatted,
interval: `${alertParams.windowSize}${alertParams.windowUnit}`,
});
});
}
},
});
}