Skip to content

Commit 7178b38

Browse files
committed
[TSVB] Greater Than or Equal to Interval Pattern (#13872)
* Create new interval pattern for specifying greater than or equal to a bucket size * Updating label to add >=1m example * Adding test case for gteAutoMatch
1 parent 60ee437 commit 7178b38

File tree

6 files changed

+44
-10
lines changed

6 files changed

+44
-10
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import dateMath from '@elastic/datemath';
2+
export const GTE_INTERVAL_RE = new RegExp(`^>=([\\d\\.]*\\s*(${dateMath.units.join('|')}))$`);
3+
export const INTERVAL_STRING_RE = new RegExp('^([0-9\\.]*)\\s*(' + dateMath.units.join('|') + ')$');
4+

src/core_plugins/metrics/public/components/index_pattern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const IndexPattern = props => {
5151
/>
5252
</div>
5353
<label className="vis_editor__label" htmlFor={htmlId('interval')}>
54-
Interval (auto, 1m, 1d, 1w, 1y)
54+
Interval (auto, 1m, 1d, 1w, 1y, &gt;=1m)
5555
</label>
5656
<input
5757
id={htmlId('interval')}

src/core_plugins/metrics/public/kbn_vis_types/request_handler.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const MetricsRequestHandlerProvider = function (Private, Notifier, config, timef
1010
name: 'metrics',
1111
handler: function (vis /*, appState, uiState, queryFilter*/) {
1212
const timezone = Private(timezoneProvider)();
13-
1413
return new Promise((resolve) => {
1514
const panel = vis.params;
1615
if (panel && panel.id) {
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import { parseInterval } from 'ui/utils/parse_interval';
2+
import { GTE_INTERVAL_RE } from '../../common/interval_regexp';
23
export function validateInterval(timefilter, panel, maxBuckets) {
34
const { interval } = panel;
45
const { min, max } = timefilter.getBounds();
56
// No need to check auto it will return around 100
7+
if (!interval) return;
68
if (interval === 'auto') return;
9+
const greaterThanMatch = interval.match(GTE_INTERVAL_RE);
10+
if (greaterThanMatch) return;
711
const duration = parseInterval(interval);
8-
if (!duration) {
9-
throw new Error(`Invalid interval: ${interval} is not a valid interval`);
10-
}
11-
const span = max.valueOf() - min.valueOf();
12-
const buckets = Math.floor(span / duration.asMilliseconds());
13-
if (buckets > maxBuckets) {
14-
throw new Error(`Max buckets exceeded: ${buckets} is greater than ${maxBuckets}, try a larger time interval in the panel options.`);
12+
if (duration) {
13+
const span = max.valueOf() - min.valueOf();
14+
const buckets = Math.floor(span / duration.asMilliseconds());
15+
if (buckets > maxBuckets) {
16+
throw new Error(`Max buckets exceeded: ${buckets} is greater than ${maxBuckets}, try a larger time interval in the panel options.`);
17+
}
1518
}
1619
}

src/core_plugins/metrics/server/lib/vis_data/__tests__/helpers/get_bucket_size.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,16 @@ describe('getBucketSize', () => {
3535
expect(result).to.have.property('intervalString', '1d');
3636
});
3737

38+
it('returns overriden buckets (>=2d)', () => {
39+
const result = getBucketSize(req, '>=2d');
40+
expect(result).to.have.property('bucketSize', 86400 * 2);
41+
expect(result).to.have.property('intervalString', '2d');
42+
});
43+
44+
it('returns overriden buckets (>=10s)', () => {
45+
const result = getBucketSize(req, '>=10s');
46+
expect(result).to.have.property('bucketSize', 30);
47+
expect(result).to.have.property('intervalString', '30s');
48+
});
49+
3850
});

src/core_plugins/metrics/server/lib/vis_data/helpers/get_bucket_size.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import calculateAuto from './calculate_auto';
22
import moment from 'moment';
33
import unitToSeconds from './unit_to_seconds';
4+
import {
5+
INTERVAL_STRING_RE,
6+
GTE_INTERVAL_RE
7+
} from '../../../../common/interval_regexp';
48
export default (req, interval) => {
59
const from = moment.utc(req.payload.timerange.min);
610
const to = moment.utc(req.payload.timerange.max);
@@ -9,7 +13,19 @@ export default (req, interval) => {
913
if (bucketSize < 1) bucketSize = 1; // don't go too small
1014
let intervalString = `${bucketSize}s`;
1115

12-
const matches = interval && interval.match(/^([\d]+)([shmdwMy]|ms)$/);
16+
const gteAutoMatch = interval && interval.match(GTE_INTERVAL_RE);
17+
if (gteAutoMatch) {
18+
const intervalStringMatch = gteAutoMatch[1].match(INTERVAL_STRING_RE);
19+
const gteBucketSize = Number(intervalStringMatch[1]) * unitToSeconds(intervalStringMatch[2]);
20+
if (gteBucketSize >= bucketSize) {
21+
return {
22+
bucketSize: gteBucketSize,
23+
intervalString: gteAutoMatch[1]
24+
};
25+
}
26+
}
27+
28+
const matches = interval && interval.match(INTERVAL_STRING_RE);
1329
if (matches) {
1430
bucketSize = Number(matches[1]) * unitToSeconds(matches[2]);
1531
intervalString = interval;

0 commit comments

Comments
 (0)