Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TSVB] add "minimum time interval" option #13880

Closed
wants to merge 1 commit into from
Closed
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
12 changes: 12 additions & 0 deletions src/core_plugins/metrics/public/components/index_pattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ export const IndexPattern = props => {
const timeFieldName = `${prefix}time_field`;
const indexPatternName = `${prefix}index_pattern`;
const intervalName = `${prefix}interval`;
const minIntervalName = `${prefix}min_interval`;
const dropBucketName = `${prefix}drop_last_bucket`;

const defaults = {
[indexPatternName]: '*',
[intervalName]: 'auto',
[minIntervalName]: '1ms',
[dropBucketName]: 1
};

Expand Down Expand Up @@ -60,6 +62,16 @@ export const IndexPattern = props => {
onChange={handleTextChange(intervalName, 'auto')}
value={model[intervalName]}
/>
<label className="vis_editor__label" htmlFor={htmlId('minInterval')}>
Min Interval
</label>
<input
id={htmlId('minInterval')}
className="vis_editor__input"
disabled={props.disabled}
onChange={handleTextChange(minIntervalName, '1ms')}
value={model[minIntervalName]}
/>
<div className="vis_editor__label">Drop Last Bucket</div>
<YesNo
value={model[dropBucketName]}
Expand Down
1 change: 1 addition & 0 deletions src/core_plugins/metrics/public/kbn_vis_types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export default function MetricsVisProvider(Private) {
time_field: '@timestamp',
index_pattern: '*',
interval: 'auto',
min_interval: '1ms',
axis_position: 'left',
axis_formatter: 'number',
show_legend:1,
Expand Down
1 change: 1 addition & 0 deletions src/core_plugins/metrics/public/lib/create_new_panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default () => {
time_field: '@timestamp',
index_pattern: '*',
interval: 'auto',
min_interval: '1ms',
axis_position: 'left',
axis_formatter: 'number',
show_legend: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,23 @@ import getIntervalAndTimefield from '../get_interval_and_timefield';

describe('getIntervalAndTimefield(panel, series)', () => {

it('returns the panel interval and timefield', () => {
const panel = { time_field: '@timestamp', interval: 'auto' };
it('returns the panel interval, minInterval and timefield', () => {
const panel = { time_field: '@timestamp', interval: 'auto', min_interval: '1ms' };
const series = {};
expect(getIntervalAndTimefield(panel, series)).to.eql({
timeField: '@timestamp',
interval: 'auto'
interval: 'auto',
minInterval: '1ms'
});
});

it('returns the series interval and timefield', () => {
it('returns the series interval, minInterval and timefield', () => {
const panel = { time_field: '@timestamp', interval: 'auto' };
const series = { override_index_pattern: true, series_interval: '1m', series_time_field: 'time' };
const series = { override_index_pattern: true, series_interval: '1m', series_time_field: 'time', series_min_interval: '1ms' };
expect(getIntervalAndTimefield(panel, series)).to.eql({
timeField: 'time',
interval: '1m'
interval: '1m',
minInterval: '1ms'
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default function getIntervalAndTimefield(panel, series) {
const timeField = series.override_index_pattern && series.series_time_field || panel.time_field;
const interval = series.override_index_pattern && series.series_interval || panel.interval;
return { timeField, interval };
const minInterval = series.override_index_pattern && series.series_min_interval || panel.min_interval;
return { timeField, interval, minInterval };
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
import calculateAuto from './calculate_auto';
import moment from 'moment';
import unitToSeconds from './unit_to_seconds';
export default (req, interval) => {
export default (req, interval, minInterval) => {
const from = moment.utc(req.payload.timerange.min);
const to = moment.utc(req.payload.timerange.max);
const duration = moment.duration(to.valueOf() - from.valueOf(), 'ms');
let bucketSize = calculateAuto.near(100, duration).asSeconds();
if (bucketSize < 1) bucketSize = 1; // don't go too small
let intervalString = `${bucketSize}s`;
let intervalString = `${bucketSize}s`; // set auto interval

// set manual interval if defined
const matches = interval && interval.match(/^([\d]+)([shmdwMy]|ms)$/);
if (matches) {
bucketSize = Number(matches[1]) * unitToSeconds(matches[2]);
intervalString = interval;
} else {
// if auto interval, make sure we're above the minimum
const minBucketMatches = minInterval && minInterval.match(/^([\d]+)([shmdwMy]|ms)$/);
if (minBucketMatches) {
const minBucketSize = Number(minBucketMatches[1]) * unitToSeconds(minBucketMatches[2]);
if (minBucketSize > bucketSize) {
bucketSize = minBucketSize;
intervalString = minInterval;
}
}
}

return { bucketSize, intervalString };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ describe('dateHistogram(req, panel, series)', () => {
panel = {
index_pattern: '*',
time_field: '@timestamp',
interval: '10s'
interval: '10s',
min_interval: '1ms'
};
series = { id: 'test' };
});
Expand Down Expand Up @@ -82,6 +83,59 @@ describe('dateHistogram(req, panel, series)', () => {
});
});

it('returns valid date histogram (minimum interval 1h)', () => {
panel.interval = 'auto';
panel.min_interval = '1h';
const next = doc => doc;
const doc = dateHistogram(req, panel, series)(next)({});
expect(doc).to.eql({
aggs: {
test: {
aggs: {
timeseries: {
date_histogram: {
field: '@timestamp',
interval: '1h',
min_doc_count: 0,
time_zone: 'UTC',
extended_bounds: {
min: 1483228800000,
max: 1483232400000
}
}
}
}
}
}
});
});

it('returns valid date histogram (minimum interval 1h - not auto)', () => {
panel.min_interval = '1h';
const next = doc => doc;
const doc = dateHistogram(req, panel, series)(next)({});
expect(doc).to.eql({
aggs: {
test: {
aggs: {
timeseries: {
date_histogram: {
field: '@timestamp',
interval: '10s',
min_doc_count: 0,
time_zone: 'UTC',
extended_bounds: {
min: 1483228800000,
max: 1483232400000
}
}
}
}
}
}
});
});

it('returns valid date histogram with overriden index pattern', () => {
series.override_index_pattern = 1;
series.series_index_pattern = '*';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import getIntervalAndTimefield from '../../get_interval_and_timefield';
import { set } from 'lodash';
export default function dateHistogram(req, panel, series) {
return next => doc => {
const { timeField, interval } = getIntervalAndTimefield(panel, series);
const { intervalString } = getBucketSize(req, interval);
const { timeField, interval, minInterval } = getIntervalAndTimefield(panel, series);
const { intervalString } = getBucketSize(req, interval, minInterval);
const { from, to } = offsetTime(req, series.offset_time);
const { timezone:time_zone } = req.payload.timerange;

Expand Down