Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions x-pack/plugins/ml/public/util/__tests__/ml_time_buckets.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
import ngMock from 'ng_mock';
import expect from 'expect.js';
import moment from 'moment';
import { IntervalHelperProvider, getBoundsRoundedToInterval } from '../ml_time_buckets';
import {
IntervalHelperProvider,
getBoundsRoundedToInterval,
calcEsInterval } from '../ml_time_buckets';

describe('ML - time buckets', () => {

Expand Down Expand Up @@ -125,7 +128,7 @@ describe('ML - time buckets', () => {

});

describe('getBoundsRoundedToInterval ', () => {
describe('getBoundsRoundedToInterval', () => {
// Must include timezone when creating moments for this test to ensure
// checks are correct when running tests in different timezones.
const testBounds = { min: moment('2017-01-05T10:11:12.000+00:00'), max: moment('2017-10-26T09:08:07.000+00:00') };
Expand Down Expand Up @@ -156,4 +159,24 @@ describe('ML - time buckets', () => {

});

describe('calcEsInterval', () => {
it('returns correct interval for various durations', () => {
expect(calcEsInterval(moment.duration(500, 'ms'))).to.eql({ value: 500, unit: 'ms', expression: '500ms' });
expect(calcEsInterval(moment.duration(1000, 'ms'))).to.eql({ value: 1, unit: 's', expression: '1s' });
expect(calcEsInterval(moment.duration(15, 's'))).to.eql({ value: 15, unit: 's', expression: '15s' });
expect(calcEsInterval(moment.duration(60, 's'))).to.eql({ value: 1, unit: 'm', expression: '1m' });
expect(calcEsInterval(moment.duration(1, 'm'))).to.eql({ value: 1, unit: 'm', expression: '1m' });
expect(calcEsInterval(moment.duration(60, 'm'))).to.eql({ value: 1, unit: 'h', expression: '1h' });
expect(calcEsInterval(moment.duration(3, 'h'))).to.eql({ value: 3, unit: 'h', expression: '3h' });
expect(calcEsInterval(moment.duration(24, 'h'))).to.eql({ value: 1, unit: 'd', expression: '1d' });
expect(calcEsInterval(moment.duration(3, 'd'))).to.eql({ value: 3, unit: 'd', expression: '3d' });
expect(calcEsInterval(moment.duration(7, 'd'))).to.eql({ value: 1, unit: 'w', expression: '1w' });
expect(calcEsInterval(moment.duration(1, 'w'))).to.eql({ value: 1, unit: 'w', expression: '1w' });
expect(calcEsInterval(moment.duration(4, 'w'))).to.eql({ value: 28, unit: 'd', expression: '28d' });
expect(calcEsInterval(moment.duration(1, 'M'))).to.eql({ value: 1, unit: 'M', expression: '1M' });
expect(calcEsInterval(moment.duration(12, 'M'))).to.eql({ value: 1, unit: 'y', expression: '1y' });
expect(calcEsInterval(moment.duration(1, 'y'))).to.eql({ value: 1, unit: 'y', expression: '1y' });
});
});

});
42 changes: 40 additions & 2 deletions x-pack/plugins/ml/public/util/ml_time_buckets.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@



// custom TimeBuckets which inherits from the standrd kibana TimeBuckets
// custom TimeBuckets which inherits from the standard kibana TimeBuckets
// this adds the ability to override the barTarget and maxBars settings
// allowing for a more granular visualization interval without having to
// modify the global settings stored in the kibana config

import _ from 'lodash';
import moment from 'moment';
import dateMath from '@kbn/datemath';

import { TimeBucketsCalcAutoIntervalProvider } from 'plugins/ml/util/ml_calc_auto_interval';
import { inherits } from 'plugins/ml/util/inherits';
import { calcEsInterval } from 'ui/time_buckets/calc_es_interval';

const unitsDesc = dateMath.unitsDesc;
const largeMax = unitsDesc.indexOf('w'); // Multiple units of week or longer converted to days for ES intervals.

import { TimeBuckets as KibanaTimeBuckets } from 'ui/time_buckets';
export function IntervalHelperProvider(Private, timefilter, config) {
Expand Down Expand Up @@ -149,3 +152,38 @@ export function getBoundsRoundedToInterval(bounds, interval, inclusiveEnd = fals
return { min: moment(adjustedMinMs), max: moment(adjustedMaxMs) };
}

export function calcEsInterval(duration) {
// Converts a moment.duration into an Elasticsearch compatible interval expression,
// and provides associated metadata.

// Note this is a copy of Kibana's ui/time_buckets/calc_es_interval,
// but with the definition of a 'large' unit changed from 'M' to 'w',
// bringing it into line with the time units supported by Elasticsearch
for (let i = 0; i < unitsDesc.length; i++) {
const unit = unitsDesc[i];
const val = duration.as(unit);
// find a unit that rounds neatly
if (val >= 1 && Math.floor(val) === val) {

// if the unit is "large", like years, but isn't set to 1, ES will throw an error.
// So keep going until we get out of the "large" units.
if (i <= largeMax && val !== 1) {
continue;
}

return {
value: val,
unit: unit,
expression: val + unit
};
}
}

const ms = duration.as('ms');
return {
value: ms,
unit: 'ms',
expression: ms + 'ms'
};
}