diff --git a/src/core_plugins/metrics/common/interval_regexp.js b/src/core_plugins/metrics/common/interval_regexp.js
new file mode 100644
index 0000000000000..011c173b63b46
--- /dev/null
+++ b/src/core_plugins/metrics/common/interval_regexp.js
@@ -0,0 +1,4 @@
+import dateMath from '@elastic/datemath';
+export const GTE_INTERVAL_RE = new RegExp(`^>=([\\d\\.]*\\s*(${dateMath.units.join('|')}))$`);
+export const INTERVAL_STRING_RE = new RegExp('^([0-9\\.]*)\\s*(' + dateMath.units.join('|') + ')$');
+
diff --git a/src/core_plugins/metrics/public/components/index_pattern.js b/src/core_plugins/metrics/public/components/index_pattern.js
index 5625de853e367..f036ce440b485 100644
--- a/src/core_plugins/metrics/public/components/index_pattern.js
+++ b/src/core_plugins/metrics/public/components/index_pattern.js
@@ -51,7 +51,7 @@ export const IndexPattern = props => {
/>
{
const panel = vis.params;
if (panel && panel.id) {
diff --git a/src/core_plugins/metrics/public/lib/validate_interval.js b/src/core_plugins/metrics/public/lib/validate_interval.js
index ea397b9f14eed..6a342a8bace19 100644
--- a/src/core_plugins/metrics/public/lib/validate_interval.js
+++ b/src/core_plugins/metrics/public/lib/validate_interval.js
@@ -1,16 +1,19 @@
import { parseInterval } from 'ui/utils/parse_interval';
+import { GTE_INTERVAL_RE } from '../../common/interval_regexp';
export function validateInterval(timefilter, panel, maxBuckets) {
const { interval } = panel;
const { min, max } = timefilter.getBounds();
// No need to check auto it will return around 100
+ if (!interval) return;
if (interval === 'auto') return;
+ const greaterThanMatch = interval.match(GTE_INTERVAL_RE);
+ if (greaterThanMatch) return;
const duration = parseInterval(interval);
- if (!duration) {
- throw new Error(`Invalid interval: ${interval} is not a valid interval`);
- }
- const span = max.valueOf() - min.valueOf();
- const buckets = Math.floor(span / duration.asMilliseconds());
- if (buckets > maxBuckets) {
- throw new Error(`Max buckets exceeded: ${buckets} is greater than ${maxBuckets}, try a larger time interval in the panel options.`);
+ if (duration) {
+ const span = max.valueOf() - min.valueOf();
+ const buckets = Math.floor(span / duration.asMilliseconds());
+ if (buckets > maxBuckets) {
+ throw new Error(`Max buckets exceeded: ${buckets} is greater than ${maxBuckets}, try a larger time interval in the panel options.`);
+ }
}
}
diff --git a/src/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/get_bucket_size.js b/src/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/get_bucket_size.js
index c22c744b1b213..60de2065bff7d 100644
--- a/src/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/get_bucket_size.js
+++ b/src/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/get_bucket_size.js
@@ -35,4 +35,16 @@ describe('getBucketSize', () => {
expect(result).to.have.property('intervalString', '1d');
});
+ it('returns overriden buckets (>=2d)', () => {
+ const result = getBucketSize(req, '>=2d');
+ expect(result).to.have.property('bucketSize', 86400 * 2);
+ expect(result).to.have.property('intervalString', '2d');
+ });
+
+ it('returns overriden buckets (>=10s)', () => {
+ const result = getBucketSize(req, '>=10s');
+ expect(result).to.have.property('bucketSize', 30);
+ expect(result).to.have.property('intervalString', '30s');
+ });
+
});
diff --git a/src/core_plugins/metrics/server/lib/vis_data/helpers/get_bucket_size.js b/src/core_plugins/metrics/server/lib/vis_data/helpers/get_bucket_size.js
index d5d19f6a10278..dea0cd44aaacd 100644
--- a/src/core_plugins/metrics/server/lib/vis_data/helpers/get_bucket_size.js
+++ b/src/core_plugins/metrics/server/lib/vis_data/helpers/get_bucket_size.js
@@ -1,6 +1,10 @@
import calculateAuto from './calculate_auto';
import moment from 'moment';
import unitToSeconds from './unit_to_seconds';
+import {
+ INTERVAL_STRING_RE,
+ GTE_INTERVAL_RE
+} from '../../../../common/interval_regexp';
export default (req, interval) => {
const from = moment.utc(req.payload.timerange.min);
const to = moment.utc(req.payload.timerange.max);
@@ -9,7 +13,19 @@ export default (req, interval) => {
if (bucketSize < 1) bucketSize = 1; // don't go too small
let intervalString = `${bucketSize}s`;
- const matches = interval && interval.match(/^([\d]+)([shmdwMy]|ms)$/);
+ const gteAutoMatch = interval && interval.match(GTE_INTERVAL_RE);
+ if (gteAutoMatch) {
+ const intervalStringMatch = gteAutoMatch[1].match(INTERVAL_STRING_RE);
+ const gteBucketSize = Number(intervalStringMatch[1]) * unitToSeconds(intervalStringMatch[2]);
+ if (gteBucketSize >= bucketSize) {
+ return {
+ bucketSize: gteBucketSize,
+ intervalString: gteAutoMatch[1]
+ };
+ }
+ }
+
+ const matches = interval && interval.match(INTERVAL_STRING_RE);
if (matches) {
bucketSize = Number(matches[1]) * unitToSeconds(matches[2]);
intervalString = interval;