Skip to content

Commit

Permalink
[TSVB] Handle ignore daylight time correctly and fix shift problem (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
flash1293 authored Jan 24, 2022
1 parent fd340b9 commit 3eded8e
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ class TimeseriesVisualization extends Component {
legend={Boolean(model.show_legend)}
legendPosition={model.legend_position}
truncateLegend={Boolean(model.truncate_legend)}
ignoreDaylightTime={Boolean(model.ignore_daylight_time)}
maxLegendLines={model.max_lines_legend}
tooltipMode={model.tooltip_mode}
xAxisFormatter={this.xAxisFormatter(interval)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import React from 'react';
import { shallow } from 'enzyme';
import { TimeSeries } from '../../../visualizations/views/timeseries';
import TimeseriesVisualization from './vis';
import { setFieldFormats } from '../../../../services';
import { setFieldFormats, setCharts, setUISettings } from '../../../../services';
import { createFieldFormatter } from '../../lib/create_field_formatter';
import { FORMATS_UI_SETTINGS } from '../../../../../../../field_formats/common';
import { METRIC_TYPES } from '../../../../../../../data/common';
import { getFieldFormatsRegistry } from '../../../../../../../data/public/test_utils';
import { MULTILAYER_TIME_AXIS_STYLE } from '../../../../../../../charts/public';

jest.mock('../../../../../../../data/public/services', () => ({
getUiSettings: () => ({ get: jest.fn() }),
Expand All @@ -35,12 +36,47 @@ describe('TimeseriesVisualization', () => {
})
);

const setupTimeSeriesProps = (formatters, valueTemplates) => {
setCharts({
theme: {
useChartsTheme: () => ({
axes: {
tickLabel: {
padding: {
inner: 0,
},
},
},
}),
useChartsBaseTheme: () => ({
axes: {
tickLabel: {
padding: {
inner: 0,
},
},
},
}),
},
activeCursor: {},
});

setUISettings({
get: () => ({}),
isDefault: () => true,
});

const renderShallow = (formatters, valueTemplates, modelOverwrites) => {
const series = formatters.map((formatter, index) => ({
id: id + index,
label: '',
formatter,
value_template: valueTemplates?.[index],
data: [],
lines: {
show: true,
},
points: {},
color: '#000000',
metrics: [
{
type: METRIC_TYPES.AVG,
Expand All @@ -63,6 +99,7 @@ describe('TimeseriesVisualization', () => {
id,
series,
use_kibana_indexes: true,
...modelOverwrites,
}}
visData={{
[id]: {
Expand All @@ -75,9 +112,26 @@ describe('TimeseriesVisualization', () => {
/>
);

return timeSeriesVisualization.find(TimeSeries).props();
return timeSeriesVisualization;
};

const setupTimeSeriesProps = (formatters, valueTemplates) => {
return renderShallow(formatters, valueTemplates).find(TimeSeries).props();
};

test('should enable new time axis if ignore daylight time setting is switched off', () => {
const component = renderShallow(['byte'], undefined, { ignore_daylight_time: false });
console.log(component.find('TimeSeries').dive().debug());
const xAxis = component.find('TimeSeries').dive().find('[id="bottom"]');
expect(xAxis.prop('style')).toEqual(MULTILAYER_TIME_AXIS_STYLE);
});

test('should disable new time axis for ignore daylight time setting', () => {
const component = renderShallow(['byte'], undefined, { ignore_daylight_time: true });
const xAxis = component.find('TimeSeries').dive().find('[id="bottom"]');
expect(xAxis.prop('style')).toBeUndefined();
});

test('should return byte formatted value from yAxis formatter for single byte series', () => {
const timeSeriesProps = setupTimeSeriesProps(['byte']);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export const TimeSeries = ({
interval,
isLastBucketDropped,
useLegacyTimeAxis,
ignoreDaylightTime,
}) => {
// If the color isn't configured by the user, use the color mapping service
// to assign a color from the Kibana palette. Colors will be shared across the
Expand Down Expand Up @@ -152,7 +153,9 @@ export const TimeSeries = ({
const shouldUseNewTimeAxis =
series.every(
({ stack, bars, lines }) => (bars?.show && stack !== STACKED_OPTIONS.NONE) || lines?.show
) && !useLegacyTimeAxis;
) &&
!useLegacyTimeAxis &&
!ignoreDaylightTime;

return (
<Chart ref={chartRef} renderer="canvas" className={classes}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@
*/

import { startsWith } from 'lodash';
import moment from 'moment';
import moment from 'moment-timezone';

export function timeShift(resp, panel, series) {
export function timeShift(
resp,
panel,
series,
meta,
extractFields,
fieldFormatService,
cachedIndexPatternFetcher,
timezone
) {
return (next) => (results) => {
if (/^([+-]?[\d]+)([shmdwMy]|ms)$/.test(series.offset_time)) {
const matches = series.offset_time.match(/^([+-]?[\d]+)([shmdwMy]|ms)$/);
Expand All @@ -18,14 +27,29 @@ export function timeShift(resp, panel, series) {
const offsetValue = matches[1];
const offsetUnit = matches[2];

let defaultTimezone;
if (!panel.ignore_daylight_time) {
// the datemath plugin always parses dates by using the current default moment time zone.
// to use the configured time zone, we are switching just for the bounds calculation.
defaultTimezone = moment().zoneName();
moment.tz.setDefault(timezone);
}

results.forEach((item) => {
if (startsWith(item.id, series.id)) {
item.data = item.data.map((row) => [
moment.utc(row[0]).add(offsetValue, offsetUnit).valueOf(),
(panel.ignore_daylight_time ? moment.utc : moment)(row[0])
.add(offsetValue, offsetUnit)
.valueOf(),
row[1],
]);
}
});

if (!panel.ignore_daylight_time) {
// reset default moment timezone
moment.tz.setDefault(defaultTimezone);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,59 @@ describe('timeShift(resp, panel, series)', () => {
[1483225210000 + 3600000, 2],
]);
});

test('shifts in right timezone', async () => {
series.offset_time = '1d';
const dateBeforeDST = new Date('2022-03-26T12:00:00.000Z').valueOf();
const dateAfterDST = new Date('2022-03-28T12:00:00.000Z').valueOf();
resp.aggregations.test.timeseries.buckets[0].key = dateBeforeDST;
resp.aggregations.test.timeseries.buckets[1].key = dateAfterDST;
const next = await timeShift(
resp,
panel,
series,
{},
undefined,
undefined,
undefined,
'Europe/Berlin'
)((results) => results);
const results = await stdMetric(resp, panel, series, {})(next)([]);

expect(results).toHaveLength(1);
expect(results[0].data).toEqual([
// only 23h in a day because it goes over the DST switch
[dateBeforeDST + 1000 * 60 * 60 * 23, 1],
// regular 24h in a day
[dateAfterDST + 1000 * 60 * 60 * 24, 2],
]);
});

test('shifts in utc if ignore daylight time is set', async () => {
series.offset_time = '1d';
panel.ignore_daylight_time = 1;
const dateBeforeDST = new Date('2022-03-26T12:00:00.000Z').valueOf();
const dateAfterDST = new Date('2022-03-28T12:00:00.000Z').valueOf();
resp.aggregations.test.timeseries.buckets[0].key = dateBeforeDST;
resp.aggregations.test.timeseries.buckets[1].key = dateAfterDST;
const next = await timeShift(
resp,
panel,
series,
{},
undefined,
undefined,
undefined,
'Europe/Berlin'
)((results) => results);
const results = await stdMetric(resp, panel, series, {})(next)([]);

expect(results).toHaveLength(1);
expect(results[0].data).toEqual([
// still 24h shift because DST is ignored
[dateBeforeDST + 1000 * 60 * 60 * 24, 1],
// regular 24h in a day
[dateAfterDST + 1000 * 60 * 60 * 24, 2],
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ export function handleResponseBody(
meta,
extractFields,
fieldFormatService,
services.cachedIndexPatternFetcher
services.cachedIndexPatternFetcher,
req.body.timerange.timezone
);

return await processor([]);
Expand Down

0 comments on commit 3eded8e

Please sign in to comment.