[Metrics UI] Remove rounding from Metric Threshold start time (#111634)

* [Metrics UI] Remove rounding from Metric Threshold start time

* adding missed files
This commit is contained in:
Chris Cowan 2021-09-09 07:20:33 -06:00 committed by GitHub
parent cac4957ef2
commit 36cec00c6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 170 additions and 21 deletions

View file

@ -0,0 +1,132 @@
/*
* 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 { createTimerange } from './create_timerange';
import { Aggregators } from '../types';
import moment from 'moment';
describe('createTimerange(interval, aggType, timeframe)', () => {
describe('without timeframe', () => {
describe('Basic Metric Aggs', () => {
it('should return a second range for last 1 second', () => {
const subject = createTimerange(1000, Aggregators.COUNT);
expect(subject.end - subject.start).toEqual(1000);
});
it('should return a minute range for last 1 minute', () => {
const subject = createTimerange(60000, Aggregators.COUNT);
expect(subject.end - subject.start).toEqual(60000);
});
it('should return 5 minute range for last 5 minutes', () => {
const subject = createTimerange(300000, Aggregators.COUNT);
expect(subject.end - subject.start).toEqual(300000);
});
it('should return a hour range for last 1 hour', () => {
const subject = createTimerange(3600000, Aggregators.COUNT);
expect(subject.end - subject.start).toEqual(3600000);
});
it('should return a day range for last 1 day', () => {
const subject = createTimerange(86400000, Aggregators.COUNT);
expect(subject.end - subject.start).toEqual(86400000);
});
});
describe('Rate Aggs', () => {
it('should return a 20 second range for last 1 second', () => {
const subject = createTimerange(1000, Aggregators.RATE);
expect(subject.end - subject.start).toEqual(1000 * 5);
});
it('should return a 5 minute range for last 1 minute', () => {
const subject = createTimerange(60000, Aggregators.RATE);
expect(subject.end - subject.start).toEqual(60000 * 5);
});
it('should return 25 minute range for last 5 minutes', () => {
const subject = createTimerange(300000, Aggregators.RATE);
expect(subject.end - subject.start).toEqual(300000 * 5);
});
it('should return 5 hour range for last hour', () => {
const subject = createTimerange(3600000, Aggregators.RATE);
expect(subject.end - subject.start).toEqual(3600000 * 5);
});
it('should return a 5 day range for last day', () => {
const subject = createTimerange(86400000, Aggregators.RATE);
expect(subject.end - subject.start).toEqual(86400000 * 5);
});
});
});
describe('with full timeframe', () => {
describe('Basic Metric Aggs', () => {
it('should return 5 minute range when given 4 minute timeframe', () => {
const end = moment();
const timeframe = {
start: end.clone().subtract(4, 'minutes').valueOf(),
end: end.valueOf(),
};
const subject = createTimerange(300000, Aggregators.COUNT, timeframe);
expect(subject.end - subject.start).toEqual(300000);
});
it('should return 6 minute range when given 6 minute timeframe', () => {
const end = moment();
const timeframe = {
start: end.clone().subtract(6, 'minutes').valueOf(),
end: end.valueOf(),
};
const subject = createTimerange(300000, Aggregators.COUNT, timeframe);
expect(subject.end - subject.start).toEqual(360000);
});
});
describe('Rate Aggs', () => {
it('should return 25 minute range when given 4 minute timeframe', () => {
const end = moment();
const timeframe = {
start: end.clone().subtract(4, 'minutes').valueOf(),
end: end.valueOf(),
};
const subject = createTimerange(300000, Aggregators.RATE, timeframe);
expect(subject.end - subject.start).toEqual(300000 * 5);
});
it('should return 25 minute range when given 6 minute timeframe', () => {
const end = moment();
const timeframe = {
start: end.clone().subtract(6, 'minutes').valueOf(),
end: end.valueOf(),
};
const subject = createTimerange(300000, Aggregators.RATE, timeframe);
expect(subject.end - subject.start).toEqual(300000 * 5);
});
});
});
describe('with partial timeframe', () => {
describe('Basic Metric Aggs', () => {
it('should return 5 minute range for last 5 minutes', () => {
const end = moment();
const timeframe = {
end: end.valueOf(),
};
const subject = createTimerange(300000, Aggregators.AVERAGE, timeframe);
expect(subject).toEqual({
start: end.clone().subtract(5, 'minutes').valueOf(),
end: end.valueOf(),
});
});
});
describe('Rate Aggs', () => {
it('should return 25 minute range for last 5 minutes', () => {
const end = moment();
const timeframe = {
end: end.valueOf(),
};
const subject = createTimerange(300000, Aggregators.RATE, timeframe);
expect(subject).toEqual({
start: end
.clone()
.subtract(300 * 5, 'seconds')
.valueOf(),
end: end.valueOf(),
});
});
});
});
});

View file

@ -0,0 +1,31 @@
/*
* 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 { Aggregators } from '../types';
export const createTimerange = (
interval: number,
aggType: Aggregators,
timeframe?: { end: number; start?: number }
) => {
const to = moment(timeframe ? timeframe.end : Date.now()).valueOf();
// Rate aggregations need 5 buckets worth of data
const minimumBuckets = aggType === Aggregators.RATE ? 5 : 1;
const calculatedFrom = to - interval * minimumBuckets;
// Use either the timeframe.start when the start is less then calculatedFrom
// OR use the calculatedFrom
const from =
timeframe && timeframe.start && timeframe.start <= calculatedFrom
? timeframe.start
: calculatedFrom;
return { start: from, end: to };
};

View file

@ -13,7 +13,6 @@ import {
TOO_MANY_BUCKETS_PREVIEW_EXCEPTION,
} from '../../../../../common/alerting/metrics';
import { getIntervalInSeconds } from '../../../../utils/get_interval_in_seconds';
import { roundTimestamp } from '../../../../utils/round_timestamp';
import { InfraSource } from '../../../../../common/source_configuration/source_configuration';
import { InfraDatabaseSearchResponse } from '../../../adapters/framework/adapter_types';
import { createAfterKeyHandler } from '../../../../utils/create_afterkey_handler';
@ -22,6 +21,7 @@ import { DOCUMENT_COUNT_I18N } from '../../common/messages';
import { UNGROUPED_FACTORY_KEY } from '../../common/utils';
import { MetricExpressionParams, Comparator, Aggregators } from '../types';
import { getElasticsearchMetricQuery } from './metric_query';
import { createTimerange } from './create_timerange';
interface AggregationWithoutIntervals {
aggregatedValue: { value: number; values?: Array<{ key: number; value: number }> };
@ -135,23 +135,12 @@ const getMetric: (
const interval = `${timeSize}${timeUnit}`;
const intervalAsSeconds = getIntervalInSeconds(interval);
const intervalAsMS = intervalAsSeconds * 1000;
const to = moment(timeframe ? timeframe.end : Date.now()).valueOf();
// Rate aggregations need 5 buckets worth of data
const minimumBuckets = aggType === Aggregators.RATE ? 5 : 1;
const minimumFrom = to - intervalAsMS * minimumBuckets;
const from = roundTimestamp(
timeframe && timeframe.start && timeframe.start <= minimumFrom ? timeframe.start : minimumFrom,
timeUnit
);
const calculatedTimerange = createTimerange(intervalAsMS, aggType, timeframe);
const searchBody = getElasticsearchMetricQuery(
params,
timefield,
{ start: from, end: to },
calculatedTimerange,
hasGroupBy ? groupBy : undefined,
filterQuery
);
@ -160,8 +149,8 @@ const getMetric: (
// Rate aggs always drop partial buckets; guard against this boolean being passed as false
shouldDropPartialBuckets || aggType === Aggregators.RATE
? {
from,
to,
from: calculatedTimerange.start,
to: calculatedTimerange.end,
bucketSizeInMillis: intervalAsMS,
}
: null;
@ -191,10 +180,7 @@ const getMetric: (
bucket,
aggType,
dropPartialBucketsOptions,
{
start: from,
end: to,
},
calculatedTimerange,
bucket.doc_count
),
}),
@ -212,7 +198,7 @@ const getMetric: (
(result.aggregations! as unknown) as Aggregation,
aggType,
dropPartialBucketsOptions,
{ start: from, end: to },
calculatedTimerange,
isNumber(result.hits.total) ? result.hits.total : result.hits.total.value
),
};