diff --git a/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx b/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx index e527d47a..6dfe53e0 100644 --- a/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx +++ b/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, Dispatch } from 'react'; import { EuiFlexItem, EuiFlexGroup, @@ -23,6 +23,7 @@ import { EuiTitle, EuiCallOut, EuiStat, + EuiLoadingChart, } from '@elastic/eui'; import moment from 'moment'; import { @@ -45,6 +46,7 @@ import { Detector, AnomalyData } from '../../../models/interfaces'; import { getLiveAnomalyResults, prepareDataForLiveChart, + getQueryParamsForLiveAnomalyResults, } from '../../utils/anomalyResultUtils'; import { get } from 'lodash'; import { @@ -58,6 +60,7 @@ import { dateFormatter } from '../../utils/helpers'; import { darkModeEnabled } from '../../../utils/kibanaUtils'; import { EuiIcon } from '@elastic/eui'; import { formatAnomalyNumber } from '../../../../server/utils/helpers'; +import { getDetectorLiveResults } from '../../../redux/reducers/liveAnomalyResults'; interface AnomalyResultsLiveChartProps { detector: Detector; @@ -68,6 +71,7 @@ export const AnomalyResultsLiveChart = ( ) => { const dispatch = useDispatch(); + const [firstLoading, setFirstLoading] = useState(true); const [isFullScreen, setIsFullScreen] = useState(false); const isLoading = useSelector( (state: AppState) => state.liveAnomalyResults.requesting @@ -85,14 +89,16 @@ export const AnomalyResultsLiveChart = ( 'minutes' ); const endDateTime = moment(); - const anomalies = prepareDataForLiveChart( - liveAnomalyResults.liveAnomalies, - { - startDate: startDateTime.valueOf(), - endDate: endDateTime.valueOf(), - }, - get(props.detector, 'detectionInterval.period.interval', 1), - ); + const anomalies = !firstLoading + ? prepareDataForLiveChart( + liveAnomalyResults.liveAnomalies, + { + startDate: startDateTime.valueOf(), + endDate: endDateTime.valueOf(), + }, + get(props.detector, 'detectionInterval.period.interval', 1) + ) + : []; const annotations = liveAnomalyResults ? get(liveAnomalyResults, 'liveAnomalies', []) @@ -116,8 +122,30 @@ export const AnomalyResultsLiveChart = ( ]); useEffect(() => { + async function loadLiveAnomalyResults( + dispatch: Dispatch, + detectorId: string, + detectionInterval: number, + intervals: number + ) { + try { + const queryParams = getQueryParamsForLiveAnomalyResults( + detectionInterval, + intervals + ); + await dispatch(getDetectorLiveResults(detectorId, queryParams)); + } catch (err) { + console.error( + `Failed to get live anomaly result for detector ${detectorId}`, + err + ); + } finally { + setFirstLoading(false); + } + } + if (props.detector.curState === DETECTOR_STATE.RUNNING) { - getLiveAnomalyResults( + loadLiveAnomalyResults( dispatch, props.detector.id, detectionInterval, @@ -237,68 +265,80 @@ export const AnomalyResultsLiveChart = ( opacity: showLoader ? 0.2 : 1, }} > - - {get(liveAnomalyResults, 'liveAnomalies', []).length === 0 || - !latestAnomalyGrade ? ( - - ) : null} - - - - - - - - - + {firstLoading ? ( + + + + + + ) : ( + + {get(liveAnomalyResults, 'liveAnomalies', []).length === 0 || + !latestAnomalyGrade ? ( + + ) : null} + + + + + + + + + + )} + diff --git a/public/pages/utils/anomalyResultUtils.ts b/public/pages/utils/anomalyResultUtils.ts index 68700e1e..12ad923b 100644 --- a/public/pages/utils/anomalyResultUtils.ts +++ b/public/pages/utils/anomalyResultUtils.ts @@ -34,9 +34,7 @@ import { MAX_ANOMALIES } from '../../utils/constants'; import { minuteDateFormatter } from './helpers'; import { toFixedNumberForAnomaly } from '../../../server/utils/helpers'; -export const getLiveAnomalyResults = ( - dispatch: Dispatch, - detectorId: string, +export const getQueryParamsForLiveAnomalyResults = ( detectionInterval: number, intervals: number ) => { @@ -53,7 +51,20 @@ export const getLiveAnomalyResults = ( fieldName: AD_DOC_FIELDS.DATA_START_TIME, }, }; - dispatch(getDetectorLiveResults(detectorId, updatedParams)); + return updatedParams; +}; + +export const getLiveAnomalyResults = ( + dispatch: Dispatch, + detectorId: string, + detectionInterval: number, + intervals: number +) => { + const queryParams = getQueryParamsForLiveAnomalyResults( + detectionInterval, + intervals + ); + dispatch(getDetectorLiveResults(detectorId, queryParams)); }; export const getAnomalyResultsWithDateRange = (