[Custom threshold rule] Add last value aggregation (#187082)

Closes https://github.com/elastic/observability-dev/issues/3627

Adds last value aggregation in Custom threshold rule

<img width="608" alt="Screenshot 2024-07-02 at 11 45 59"
src="6b9a4fbf-565f-4485-9fd0-e419ce919401">
This commit is contained in:
Bena Kansara 2024-07-24 18:47:56 +02:00 committed by GitHub
parent 49a985625b
commit fabaf02e2f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 3582 additions and 1781 deletions

View file

@ -32,6 +32,7 @@ export enum Aggregators {
RATE = 'rate',
P95 = 'p95',
P99 = 'p99',
LAST_VALUE = 'last_value',
}
export const aggType = fromEnum('Aggregators', Aggregators);
export type AggType = rt.TypeOf<typeof aggType>;

View file

@ -313,4 +313,13 @@ export const aggregationType: { [key: string]: AggregationType } = {
value: Aggregators.RATE,
validNormalizedTypes: ['number'],
},
last_value: {
text: i18n.translate(
'xpack.observability..customThreshold.rule.alertFlyout.aggregationText.last_value',
{ defaultMessage: 'Last value' }
),
fieldRequired: false,
value: Aggregators.LAST_VALUE,
validNormalizedTypes: ['number'],
},
};

View file

@ -11,6 +11,10 @@ import {
Aggregators,
CustomThresholdExpressionMetric,
} from '../../../../../common/custom_threshold_rule/types';
import {
createLastValueAggBucket,
createLastValueAggBucketScript,
} from './create_last_value_aggregation';
import { createRateAggsBuckets, createRateAggsBucketScript } from './create_rate_aggregation';
export const createCustomMetricsAggregations = (
@ -23,7 +27,7 @@ export const createCustomMetricsAggregations = (
const bucketsPath: { [id: string]: string } = {};
const metricAggregations = customMetrics.reduce((acc, metric) => {
const key = `${id}_${metric.name}`;
const aggregation = metric.aggType;
const aggregation: Aggregators = metric.aggType;
if (aggregation === 'count') {
bucketsPath[metric.name] = `${key}>_count`;
@ -59,6 +63,19 @@ export const createCustomMetricsAggregations = (
};
}
if (aggregation === Aggregators.LAST_VALUE) {
bucketsPath[metric.name] = key;
return metric.field
? {
...acc,
...createLastValueAggBucket(key, timeFieldName, metric.field),
...createLastValueAggBucketScript(key, metric.field),
}
: {
...acc,
};
}
if (aggregation && metric.field) {
bucketsPath[metric.name] = key;
return {

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
export const createLastValueAggBucketScript = (key: string, field?: string) => {
return {
[key]: {
bucket_script: {
buckets_path: {
last_value: `_${key}>last_value[${field}]`,
},
script: `params.last_value`,
},
},
};
};
export const createLastValueAggBucket = (key: string, timeFieldName: string, field?: string) => {
return {
[`_${key}`]: {
filter: {
bool: {
must: [
{
exists: {
field,
},
},
],
},
},
aggs: {
last_value: {
top_metrics: {
metrics: { field },
sort: { [timeFieldName]: 'desc' },
},
},
},
},
};
};

View file

@ -14,6 +14,7 @@ import {
CARDINALITY_I18N,
CUSTOM_EQUATION_I18N,
DOCUMENT_COUNT_I18N,
LAST_VALUE_I18N,
MAX_I18N,
MIN_I18N,
PERCENTILE_95_I18N,
@ -49,6 +50,8 @@ export const getLabel = (criterion: Evaluation) => {
return CARDINALITY_I18N(criterion.metrics[0].field!);
case Aggregators.SUM:
return SUM_I18N(criterion.metrics[0].field!);
case Aggregators.LAST_VALUE:
return LAST_VALUE_I18N(criterion.metrics[0].field!);
}
}
return criterion.label || CUSTOM_EQUATION_I18N;

View file

@ -78,6 +78,14 @@ export const SUM_I18N = (metric: string) =>
},
});
export const LAST_VALUE_I18N = (metric: string) =>
i18n.translate('xpack.observability.customThreshold.rule.aggregators.last_value', {
defaultMessage: 'Last value of {metric}',
values: {
metric,
},
});
export const CUSTOM_EQUATION_I18N = i18n.translate(
'xpack.observability.customThreshold.rule.aggregators.customEquation',
{