From f8ba95f1fea3ae47702ddff08734d35a07624d00 Mon Sep 17 00:00:00 2001 From: Zacqary Adam Xeper Date: Wed, 29 Jul 2020 13:05:19 -0500 Subject: [PATCH] [Metrics UI] Fix evaluating rate-aggregated alerts when there's no normalized value (#73545) Co-authored-by: Elastic Machine --- .../metric_threshold/lib/evaluate_alert.ts | 11 ++++--- .../metric_threshold_executor.test.ts | 29 ++++++++++++++++++- .../alerting/metric_threshold/test_mocks.ts | 13 +++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts index d862f70c47ca..ca46f6cc1654 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts @@ -67,10 +67,13 @@ export const evaluateAlert = ( currentValue: Array.isArray(points) ? last(points)?.value : NaN, timestamp: Array.isArray(points) ? last(points)?.key : NaN, shouldFire: Array.isArray(points) - ? points.map((point) => comparisonFunction(point.value, threshold)) + ? points.map( + (point) => + typeof point.value === 'number' && comparisonFunction(point.value, threshold) + ) : [false], - isNoData: points === null, - isError: isNaN(points), + isNoData: (Array.isArray(points) ? last(points)?.value : points) === null, + isError: isNaN(Array.isArray(points) ? last(points)?.value : points), }; }); }) @@ -172,7 +175,7 @@ const getValuesFromAggregations = ( } return buckets.map((bucket) => ({ key: bucket.key_as_string, - value: bucket.aggregatedValue.value, + value: bucket.aggregatedValue?.value ?? null, })); } catch (e) { return NaN; // Error state diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts index 9a46925a5176..fa705798baf7 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts @@ -318,6 +318,31 @@ describe('The metric threshold alert type', () => { }); }); + describe("querying a rate-aggregated metric that hasn't reported data", () => { + const instanceID = '*'; + const execute = () => + executor({ + services, + params: { + criteria: [ + { + ...baseCriterion, + comparator: Comparator.GT, + threshold: 1, + metric: 'test.metric.3', + aggType: 'rate', + }, + ], + alertOnNoData: true, + }, + }); + test('sends a No Data alert', async () => { + await execute(); + expect(mostRecentAction(instanceID).id).toBe(FIRED_ACTIONS.id); + expect(getState(instanceID).alertState).toBe(AlertStates.NO_DATA); + }); + }); + // describe('querying a metric that later recovers', () => { // const instanceID = '*'; // const execute = (threshold: number[]) => @@ -401,7 +426,9 @@ services.callCluster.mockImplementation(async (_: string, { body, index }: any) if (metric === 'test.metric.2') { return mocks.alternateMetricResponse; } else if (metric === 'test.metric.3') { - return mocks.emptyMetricResponse; + return body.aggs.aggregatedIntervals.aggregations.aggregatedValue_max + ? mocks.emptyRateResponse + : mocks.emptyMetricResponse; } return mocks.basicMetricResponse; }); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/test_mocks.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/test_mocks.ts index c7e53eb2008f..5c2f76cea87c 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/test_mocks.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/test_mocks.ts @@ -62,6 +62,19 @@ export const emptyMetricResponse = { }, }; +export const emptyRateResponse = { + aggregations: { + aggregatedIntervals: { + buckets: [ + { + doc_count: 2, + aggregatedValue_max: { value: null }, + }, + ], + }, + }, +}; + export const basicCompositeResponse = { aggregations: { groupings: {