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 144ee6505c5931..943f5728d5daba 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 @@ -180,6 +180,7 @@ const getValuesFromAggregations = ( try { const { buckets } = aggregations.aggregatedIntervals; if (!buckets.length) return null; // No Data state + if (aggType === Aggregators.COUNT) { return buckets.map((bucket) => ({ key: bucket.to_as_string, diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts index 79aa94f98d2ada..32208d029b8376 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts @@ -58,26 +58,4 @@ describe("The Metric Threshold Alert's getElasticsearchMetricQuery", () => { ); }); }); - - describe('handles time', () => { - const end = new Date('2020-07-08T22:07:27.235Z').valueOf(); - const timerange = { - end, - start: end - 5 * 60 * 1000, - }; - const searchBody = getElasticsearchMetricQuery( - expressionParams, - timefield, - undefined, - undefined, - timerange - ); - test('by rounding timestamps to the nearest timeUnit', () => { - const rangeFilter = searchBody.query.bool.filter.find((filter) => - filter.hasOwnProperty('range') - )?.range[timefield]; - expect(rangeFilter?.lte).toBe(1594246020000); - expect(rangeFilter?.gte).toBe(1594245720000); - }); - }); }); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts index 0e495c08cc9fd7..a596ad9f7c2383 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import moment from 'moment'; import { networkTraffic } from '../../../../../common/inventory_models/shared/metrics/snapshot/network_traffic'; import { MetricExpressionParams, Aggregators } from '../types'; import { getIntervalInSeconds } from '../../../../utils/get_interval_in_seconds'; @@ -39,7 +39,11 @@ export const getElasticsearchMetricQuery = ( const intervalAsSeconds = getIntervalInSeconds(interval); const intervalAsMS = intervalAsSeconds * 1000; - const to = roundTimestamp(timeframe ? timeframe.end : Date.now(), timeUnit); + const to = moment(timeframe ? timeframe.end : Date.now()) + .add(1, timeUnit) + .startOf(timeUnit) + .valueOf(); + // We need enough data for 5 buckets worth of data. We also need // to convert the intervalAsSeconds to milliseconds. const minimumFrom = to - intervalAsMS * MINIMUM_BUCKETS; @@ -49,8 +53,7 @@ export const getElasticsearchMetricQuery = ( timeUnit ); - const offset = calculateDateHistogramOffset({ from, to, interval, field: timefield }); - const offsetInMS = parseInt(offset, 10) * 1000; + const deliveryDelay = 60 * 1000; // INFO: This allows us to account for any delay ES has in indexing the most recent data. const aggregations = aggType === Aggregators.COUNT @@ -74,7 +77,7 @@ export const getElasticsearchMetricQuery = ( date_histogram: { field: timefield, fixed_interval: interval, - offset, + offset: calculateDateHistogramOffset({ from, to, interval, field: timefield }), extended_bounds: { min: from, max: to, @@ -87,10 +90,12 @@ export const getElasticsearchMetricQuery = ( aggregatedIntervals: { date_range: { field: timefield, - ranges: Array.from(Array(Math.floor((to - from) / intervalAsMS)), (_, i) => ({ - from: from + intervalAsMS * i + offsetInMS, - to: from + intervalAsMS * (i + 1) + offsetInMS, - })), + ranges: [ + { + from: to - intervalAsMS - deliveryDelay, + to: to - deliveryDelay, + }, + ], }, aggregations, }, 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 e5cad99dcb4ed4..04e5a3df5822ad 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 @@ -204,7 +204,7 @@ describe('The metric threshold alert type', () => { }); test('sends no alert when some, but not all, criteria cross the threshold', async () => { const instanceID = '*'; - await execute(Comparator.LT_OR_EQ, [1.0], [3.0]); + await execute(Comparator.LT_OR_EQ, [1.0], [2.5]); expect(mostRecentAction(instanceID)).toBe(undefined); }); test('alerts only on groups that meet all criteria when querying with a groupBy parameter', async () => { @@ -223,7 +223,7 @@ describe('The metric threshold alert type', () => { expect(reasons[0]).toContain('test.metric.1'); expect(reasons[1]).toContain('test.metric.2'); expect(reasons[0]).toContain('current value is 1'); - expect(reasons[1]).toContain('current value is 3.5'); + expect(reasons[1]).toContain('current value is 3'); expect(reasons[0]).toContain('threshold of 1'); expect(reasons[1]).toContain('threshold of 3'); }); @@ -247,9 +247,9 @@ describe('The metric threshold alert type', () => { }, }); test('alerts based on the doc_count value instead of the aggregatedValue', async () => { - await execute(Comparator.GT, [2]); + await execute(Comparator.GT, [0.9]); expect(mostRecentAction(instanceID).id).toBe(FIRED_ACTIONS.id); - await execute(Comparator.LT, [1.5]); + await execute(Comparator.LT, [0.5]); expect(mostRecentAction(instanceID)).toBe(undefined); }); });