[8.8] [ML] AIOps: Change point detection fixes (#156481) (#156591)

# Backport

This will backport the following commits from `main` to `8.8`:
- [[ML] AIOps: Change point detection fixes
(#156481)](https://github.com/elastic/kibana/pull/156481)

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

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

<!--BACKPORT [{"author":{"name":"Dima
Arnautov","email":"dmitrii.arnautov@elastic.co"},"sourceCommit":{"committedDate":"2023-05-03T16:31:03Z","message":"[ML]
AIOps: Change point detection fixes
(#156481)","sha":"a3fad62c3491bd12c9cc8a62a126e21081422253","branchLabelMapping":{"^v8.9.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":[":ml","release_note:skip","Team:ML","v8.8.0","v8.9.0"],"number":156481,"url":"https://github.com/elastic/kibana/pull/156481","mergeCommit":{"message":"[ML]
AIOps: Change point detection fixes
(#156481)","sha":"a3fad62c3491bd12c9cc8a62a126e21081422253"}},"sourceBranch":"main","suggestedTargetBranches":["8.8"],"targetPullRequestStates":[{"branch":"8.8","label":"v8.8.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.9.0","labelRegex":"^v8.9.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/156481","number":156481,"mergeCommit":{"message":"[ML]
AIOps: Change point detection fixes
(#156481)","sha":"a3fad62c3491bd12c9cc8a62a126e21081422253"}}]}]
BACKPORT-->

Co-authored-by: Dima Arnautov <dmitrii.arnautov@elastic.co>
This commit is contained in:
Kibana Machine 2023-05-03 13:44:23 -04:00 committed by GitHub
parent 5b3d015ad6
commit ec997b3ced
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 14 deletions

View file

@ -11,13 +11,13 @@ import React from 'react';
import { EuiSuperDatePicker } from '@elastic/eui';
import { useUrlState } from '@kbn/ml-url-state';
import type { UI_SETTINGS } from '@kbn/data-plugin/common';
import { useDatePickerContext } from '../hooks/use_date_picker_context';
import { mlTimefilterRefresh$ } from '../services/timefilter_refresh_service';
import { DatePickerWrapper } from './date_picker_wrapper';
import { useRefreshIntervalUpdates } from '../..';
jest.mock('@elastic/eui', () => {
const EuiButtonMock = jest.fn(() => {
@ -51,7 +51,12 @@ jest.mock('@kbn/ml-url-state', () => {
});
jest.mock('../hooks/use_timefilter', () => ({
useRefreshIntervalUpdates: jest.fn(),
useRefreshIntervalUpdates: jest.fn(() => {
return {
pause: false,
};
}),
useTimefilter: () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { of } = require('rxjs');
@ -152,7 +157,7 @@ describe('<DatePickerWrapper />', () => {
test('should set interval to default of 5s when pause is disabled and refresh interval is 0', () => {
// arrange
(useUrlState as jest.Mock).mockReturnValue([{ refreshInterval: { pause: false, value: 0 } }]);
(useRefreshIntervalUpdates as jest.Mock).mockReturnValue({ pause: false, value: 0 });
const displayWarningSpy = jest.fn(() => {});
@ -171,7 +176,7 @@ describe('<DatePickerWrapper />', () => {
test('should show a warning when configured interval is too short', () => {
// arrange
(useUrlState as jest.Mock).mockReturnValue([{ refreshInterval: { pause: false, value: 10 } }]);
(useRefreshIntervalUpdates as jest.Mock).mockReturnValue({ pause: false, value: 10 });
const displayWarningSpy = jest.fn(() => {});

View file

@ -121,7 +121,7 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
const time = useTimeRangeUpdates();
useEffect(
function syncTimRangeFromUrlState() {
function syncTimeRangeFromUrlState() {
if (globalState?.time !== undefined) {
timefilter.setTime({
from: globalState.time.from,
@ -162,11 +162,7 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
timefilter.isTimeRangeSelectorEnabled()
);
const refreshInterval = useMemo(
(): RefreshInterval => globalState?.refreshInterval ?? timeFilterRefreshInterval,
// eslint-disable-next-line react-hooks/exhaustive-deps
[JSON.stringify(globalState?.refreshInterval), timeFilterRefreshInterval]
);
const refreshInterval = timeFilterRefreshInterval;
useEffect(
function warnAboutShortRefreshInterval() {

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { type FC, useMemo, useState } from 'react';
import React, { type FC, useMemo, useState, useEffect, useRef } from 'react';
import {
EuiBadge,
EuiDescriptionList,
@ -21,7 +21,9 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { SelectedChangePoint } from './change_point_detection_context';
import { useTimefilter } from '@kbn/ml-date-picker';
import { type RefreshInterval } from '@kbn/data-plugin/common';
import { type SelectedChangePoint } from './change_point_detection_context';
import { ChartComponent } from './chart_component';
const CHARTS_PER_PAGE = 6;
@ -31,6 +33,28 @@ interface ChartsGridProps {
}
export const ChartsGrid: FC<ChartsGridProps> = ({ changePoints: changePointsDict }) => {
const timefilter = useTimefilter();
const initialRefreshSetting = useRef<RefreshInterval>();
useEffect(
function pauseRefreshOnMount() {
initialRefreshSetting.current = timefilter.getRefreshInterval();
timefilter.setRefreshInterval({
...initialRefreshSetting.current,
pause: true,
});
return () => {
if (initialRefreshSetting.current) {
// reset initial settings
timefilter.setRefreshInterval(initialRefreshSetting.current);
}
};
},
[timefilter]
);
const changePoints = useMemo(() => {
return Object.values(changePointsDict).flat();
}, [changePointsDict]);

View file

@ -5,7 +5,8 @@
* 2.0.
*/
import { FilterStateStore } from '@kbn/es-query';
import moment from 'moment';
import { FilterStateStore, type TimeRange } from '@kbn/es-query';
import { type TypedLensByValueInput } from '@kbn/lens-plugin/public';
import { useTimeRangeUpdates } from '@kbn/ml-date-picker';
import { useMemo } from 'react';
@ -33,6 +34,17 @@ export const useCommonChartProps = ({
const { dataView } = useDataSource();
const { bucketInterval, resultQuery, resultFilters } = useChangePointDetectionContext();
/**
* In order to correctly render annotations for change points at the edges,
* we need to adjust time bound based on the change point timestamp.
*/
const chartTimeRange = useMemo<TimeRange>(() => {
return {
from: moment.min(moment(timeRange.from), moment(annotation.timestamp)).toISOString(),
to: moment.max(moment(timeRange.to), moment(annotation.timestamp)).toISOString(),
};
}, [timeRange, annotation.timestamp]);
const filters = useMemo(() => {
return [
...resultFilters,
@ -214,7 +226,7 @@ export const useCommonChartProps = ({
]);
return {
timeRange,
timeRange: chartTimeRange,
filters,
query: resultQuery,
attributes,