[8.6] [Uptime] Ping histogram fix using local timezone or configured (#145412) (#145853)

# Backport

This will backport the following commits from `main` to `8.6`:
- [[Uptime] Ping histogram fix using local timezone or configured
(#145412)](https://github.com/elastic/kibana/pull/145412)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"Shahzad","email":"shahzad.muhammad@elastic.co"},"sourceCommit":{"committedDate":"2022-11-21T12:43:39Z","message":"[Uptime]
Ping histogram fix using local timezone or configured (#145412)\n\nFixes
https://github.com/elastic/kibana/issues/144054","sha":"082e4aa71372f8120928d68b6acbdcf329f67b54","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:uptime","release_note:skip","v8.6.0","v8.7.0"],"number":145412,"url":"https://github.com/elastic/kibana/pull/145412","mergeCommit":{"message":"[Uptime]
Ping histogram fix using local timezone or configured (#145412)\n\nFixes
https://github.com/elastic/kibana/issues/144054","sha":"082e4aa71372f8120928d68b6acbdcf329f67b54"}},"sourceBranch":"main","suggestedTargetBranches":["8.6"],"targetPullRequestStates":[{"branch":"8.6","label":"v8.6.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/145412","number":145412,"mergeCommit":{"message":"[Uptime]
Ping histogram fix using local timezone or configured (#145412)\n\nFixes
https://github.com/elastic/kibana/issues/144054","sha":"082e4aa71372f8120928d68b6acbdcf329f67b54"}}]}]
BACKPORT-->

Co-authored-by: Shahzad <shahzad.muhammad@elastic.co>
This commit is contained in:
Kibana Machine 2022-11-21 08:48:51 -05:00 committed by GitHub
parent 0cf8fa18f8
commit c2871d07b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 99 additions and 8 deletions

View file

@ -22,6 +22,7 @@ import moment from 'moment';
import React, { useContext } from 'react';
import { useHistory } from 'react-router-dom';
import { ThemeContext } from 'styled-components';
import { useTimeZone } from '../../../../hooks/use_time_zone';
import { SectionContainer } from '..';
import { getDataHandler } from '../../../../data_handler';
import { useChartTheme } from '../../../../hooks/use_chart_theme';
@ -46,19 +47,31 @@ export function UptimeSection({ bucketSize }: Props) {
const { relativeStart, relativeEnd, absoluteStart, absoluteEnd, lastUpdated } =
useDatePickerContext();
const timeZone = useTimeZone();
const { data, status } = useFetcher(
() => {
if (bucketSize && absoluteStart && absoluteEnd) {
return getDataHandler('synthetics')?.fetchData({
absoluteTime: { start: absoluteStart, end: absoluteEnd },
relativeTime: { start: relativeStart, end: relativeEnd },
timeZone,
...bucketSize,
});
}
},
// `forceUpdate` and `lastUpdated` should trigger a reload
// eslint-disable-next-line react-hooks/exhaustive-deps
[bucketSize, relativeStart, relativeEnd, absoluteStart, absoluteEnd, forceUpdate, lastUpdated]
[
bucketSize,
relativeStart,
relativeEnd,
absoluteStart,
absoluteEnd,
forceUpdate,
lastUpdated,
timeZone,
]
);
if (!hasDataMap.synthetics?.hasData) {

View file

@ -0,0 +1,21 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { useUiSetting } from '@kbn/kibana-react-plugin/public';
import moment from 'moment-timezone';
export const useTimeZone = () => {
const timeZone = useUiSetting<string | undefined>('dateFormat:tz');
const localTZ = moment.tz.guess();
if (!timeZone || timeZone === 'Browser') {
return localTZ;
}
return timeZone;
};

View file

@ -80,6 +80,7 @@ export * from './typings';
export { useChartTheme } from './hooks/use_chart_theme';
export { useBreadcrumbs } from './hooks/use_breadcrumbs';
export { useTheme } from './hooks/use_theme';
export { useTimeZone } from './hooks/use_time_zone';
export { createUseRulesLink } from './hooks/create_use_rules_link';
export { useLinkProps, shouldHandleLinkEvent } from './hooks/use_link_props';
export type { LinkDescriptor } from './hooks/use_link_props';

View file

@ -31,6 +31,7 @@ export interface FetchDataParams {
bucketSize: number;
// Bucket size in seconds (string)
intervalString: string;
timeZone?: string;
}
export interface HasDataParams {

View file

@ -24,6 +24,7 @@ export interface GetPingHistogramParams {
monitorId?: string;
bucketSize?: string;
query?: string;
timeZone: string;
}
export interface HistogramResult {

View file

@ -7,6 +7,7 @@
import { CoreStart } from '@kbn/core/public';
import { UptimeFetchDataResponse, FetchDataParams } from '@kbn/observability-plugin/public';
import moment from 'moment-timezone';
import { fetchIndexStatus, fetchPingHistogram, fetchSnapshotCount } from '../state/api';
import { kibanaService } from '../state/kibana_service';
@ -14,6 +15,7 @@ async function fetchUptimeOverviewData({
absoluteTime,
relativeTime,
intervalString,
timeZone,
}: FetchDataParams) {
const start = new Date(absoluteTime.start).toISOString();
const end = new Date(absoluteTime.end).toISOString();
@ -26,6 +28,7 @@ async function fetchUptimeOverviewData({
dateStart: start,
dateEnd: end,
bucketSize: intervalString,
timeZone: timeZone ?? moment.tz.guess(),
});
const response: UptimeFetchDataResponse = {

View file

@ -28,6 +28,7 @@ describe('PingHistogram component', () => {
const props: PingHistogramComponentProps = {
absoluteStartDate: 1548697920000,
absoluteEndDate: 1548700920000,
timeZone: 'UTC',
data: {
histogram: [
{ x: 1581068329000, downCount: 6, upCount: 33, y: 1 },

View file

@ -54,6 +54,8 @@ export interface PingHistogramComponentProps {
data: HistogramResult | null;
loading?: boolean;
timeZone: string;
}
interface BarPoint {
@ -68,6 +70,7 @@ export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
data,
loading = false,
height,
timeZone,
}) => {
const {
colors: { danger, gray },
@ -181,7 +184,7 @@ export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
})}
stackAccessors={['x']}
splitSeriesAccessors={['type']}
timeZone="local"
timeZone={timeZone}
xAccessor="x"
xScaleType={ScaleType.Time}
yAccessors={['y']}

View file

@ -7,6 +7,7 @@
import React, { useContext, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useTimeZone } from '@kbn/observability-plugin/public';
import { PingHistogramComponent } from '../../common/charts';
import { getPingHistogram } from '../../../state/actions';
import { esKuerySelector, selectPingHistogram } from '../../../state/selectors';
@ -39,16 +40,36 @@ const Container: React.FC<Props & ResponsiveWrapperProps> = ({ height }) => {
const { loading, pingHistogram: data } = useSelector(selectPingHistogram);
const timeZone = useTimeZone();
useEffect(() => {
if (monitorId) {
// we don't need filter check on monitor details page, where we have monitorId defined
dispatch(getPingHistogram.get({ monitorId, dateStart, dateEnd, query, filters: esKuery }));
dispatch(
getPingHistogram.get({
monitorId,
dateStart,
dateEnd,
query,
filters: esKuery,
timeZone,
})
);
} else {
filterCheck(() =>
dispatch(getPingHistogram.get({ monitorId, dateStart, dateEnd, query, filters: esKuery }))
dispatch(
getPingHistogram.get({
monitorId,
dateStart,
dateEnd,
query,
filters: esKuery,
timeZone,
})
)
);
}
}, [filterCheck, dateStart, dateEnd, monitorId, lastRefresh, esKuery, dispatch, query]);
}, [filterCheck, dateStart, dateEnd, monitorId, lastRefresh, esKuery, dispatch, query, timeZone]);
return (
<PingHistogramComponent
data={data}
@ -56,6 +77,7 @@ const Container: React.FC<Props & ResponsiveWrapperProps> = ({ height }) => {
absoluteEndDate={absoluteDateRangeEnd}
height={height}
loading={loading}
timeZone={timeZone}
/>
);
};

View file

@ -28,6 +28,7 @@ export const fetchPingHistogram: APIFn<GetPingHistogramParams, HistogramResult>
filters,
bucketSize,
query,
timeZone,
}) => {
const queryParams = {
dateStart,
@ -36,6 +37,7 @@ export const fetchPingHistogram: APIFn<GetPingHistogramParams, HistogramResult>
filters,
bucketSize,
query,
timeZone,
};
return await apiService.get(API_URLS.PING_HISTOGRAM, queryParams);

View file

@ -70,6 +70,7 @@ describe('getPingHistogram', () => {
uptimeEsClient,
dateStart: 'now-15m',
dateEnd: 'now',
timeZone: 'UTC',
});
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
@ -92,6 +93,7 @@ describe('getPingHistogram', () => {
dateStart: 'now-15m',
dateEnd: 'now',
filters: '',
timeZone: 'UTC',
});
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
@ -157,6 +159,7 @@ describe('getPingHistogram', () => {
dateEnd: 'now',
filters: JSON.stringify(searchFilter),
monitorId: undefined,
timeZone: 'UTC',
});
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
@ -212,6 +215,7 @@ describe('getPingHistogram', () => {
dateStart: 'now-15m',
dateEnd: 'now',
filters,
timeZone: 'UTC',
});
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
@ -232,7 +236,12 @@ describe('getPingHistogram', () => {
},
} as any);
const result = await getPingHistogram({ uptimeEsClient, dateStart: 'now-15m', dateEnd: 'now' });
const result = await getPingHistogram({
uptimeEsClient,
dateStart: 'now-15m',
dateEnd: 'now',
timeZone: 'UTC',
});
expect(result.histogram).toEqual([]);
});
@ -251,7 +260,12 @@ describe('getPingHistogram', () => {
},
} as any);
const result = await getPingHistogram({ uptimeEsClient, dateStart: 'now-15m', dateEnd: 'now' });
const result = await getPingHistogram({
uptimeEsClient,
dateStart: 'now-15m',
dateEnd: 'now',
timeZone: 'UTC',
});
expect(result.histogram).toEqual([]);
});

View file

@ -24,6 +24,7 @@ export const getPingHistogram: UMElasticsearchQueryFn<
monitorId,
bucketSize,
query,
timeZone,
}) => {
const boolFilters = filters ? JSON.parse(filters) : null;
const additionalFilters = [];
@ -73,6 +74,7 @@ export const getPingHistogram: UMElasticsearchQueryFn<
field: '@timestamp',
fixed_interval: bucketSize || minInterval + 'ms',
missing: '0',
time_zone: timeZone,
},
aggs: {
down: {

View file

@ -21,10 +21,11 @@ export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServe
filters: schema.maybe(schema.string()),
bucketSize: schema.maybe(schema.string()),
query: schema.maybe(schema.string()),
timeZone: schema.string(),
}),
},
handler: async ({ uptimeEsClient, request }): Promise<any> => {
const { dateStart, dateEnd, monitorId, filters, bucketSize, query } = request.query;
const { dateStart, dateEnd, monitorId, filters, bucketSize, query, timeZone } = request.query;
return await libs.requests.getPingHistogram({
uptimeEsClient,
@ -34,6 +35,7 @@ export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServe
filters,
bucketSize,
query,
timeZone,
});
},
});

View file

@ -13,6 +13,8 @@ export default function ({ getService }: FtrProviderContext) {
describe('pingHistogram', () => {
const supertest = getService('supertest');
const timeZone = 'UTC';
it('will fetch histogram data for all monitors', async () => {
const dateStart = '2019-09-11T03:31:04.380Z';
const dateEnd = '2019-09-11T03:40:34.410Z';
@ -20,6 +22,7 @@ export default function ({ getService }: FtrProviderContext) {
const apiResponse = await supertest.get(API_URLS.PING_HISTOGRAM).query({
dateStart,
dateEnd,
timeZone,
});
const data = apiResponse.body;
@ -35,6 +38,7 @@ export default function ({ getService }: FtrProviderContext) {
monitorId,
dateStart,
dateEnd,
timeZone,
});
const data = apiResponse.body;
@ -51,6 +55,7 @@ export default function ({ getService }: FtrProviderContext) {
dateStart,
dateEnd,
filters,
timeZone,
});
const data = apiResponse.body;