[ML] Explain Log Rate Spikes: Fix loading state for grouping. (#141770)

Fix loading state messages for grouping:
- Fixes the progress bar messages to include the grouping step.
- If progress stalls, it might look to the user like the analysis got stuck when there are steps like the grouping that take a longer time. This updates the progress bar to show an animated background as long as the analysis is running. When the analysis finishes or gets canceled the animated background gets disabled and shows a static background.
This commit is contained in:
Walter Rafelsberger 2022-10-03 10:25:39 +02:00 committed by GitHub
parent f8a90275d5
commit 5203f1bcc8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 108 additions and 17 deletions

View file

@ -55,6 +55,8 @@ RUNTIME_DEPS = [
"@npm//react",
"@npm//@elastic/charts",
"@npm//@elastic/eui",
"@npm//@emotion/react",
"@npm//@emotion/css",
"//packages/kbn-i18n-react",
"//x-pack/packages/ml/aiops_utils",
]
@ -78,6 +80,8 @@ TYPES_DEPS = [
"@npm//@types/react",
"@npm//@elastic/charts",
"@npm//@elastic/eui",
"@npm//@emotion/react",
"@npm//@emotion/css",
"//packages/kbn-i18n-react:npm_module_types",
"//x-pack/packages/ml/aiops_utils:npm_module_types",
]

View file

@ -5,7 +5,10 @@
* 2.0.
*/
import React from 'react';
import {
useEuiTheme,
EuiButton,
EuiFlexGroup,
EuiFlexItem,
@ -13,9 +16,11 @@ import {
EuiProgress,
EuiText,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import React from 'react';
import { useAnimatedProgressBarBackground } from './use_animated_progress_bar_background';
// TODO Consolidate with duplicate component `CorrelationsProgressControls` in
// `x-pack/plugins/apm/public/components/app/correlations/progress_controls.tsx`
@ -37,6 +42,9 @@ export function ProgressControls({
isRunning,
shouldRerunAnalysis,
}: ProgressControlProps) {
const { euiTheme } = useEuiTheme();
const runningProgressBarStyles = useAnimatedProgressBarBackground(euiTheme.colors.success);
return (
<EuiFlexGroup>
<EuiFlexItem>
@ -51,7 +59,7 @@ export function ProgressControls({
/>
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexItem css={isRunning ? runningProgressBarStyles : undefined}>
<EuiProgress
aria-label={i18n.translate('xpack.aiops.progressAriaLabel', {
defaultMessage: 'Progress',

View file

@ -0,0 +1,53 @@
/*
* 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 { useMemo } from 'react';
import { css } from '@emotion/react';
export const useAnimatedProgressBarBackground = (color: string) => {
return useMemo(() => {
const progressBackground = {
background: `repeating-linear-gradient(
-45deg,
transparent 0 6px,
rgba(0, 0, 0, 0.1) 6px 12px
),
${color}`,
// 0.707 = cos(45deg)
backgroundSize: 'calc(12px / 0.707) 100%, 100% 800%',
backgroundPosition: 'inherit',
};
return css({
'progress[value]': {
animation: 'aiopsAnimatedProgress 4s infinite linear',
'::-webkit-progress-inner-element': {
overflow: 'hidden',
backgroundPosition: 'inherit',
},
'::-webkit-progress-bar': {
backgroundColor: 'transparent',
backgroundPosition: 'inherit',
},
'::-webkit-progress-value': progressBackground,
'::-moz-progress-bar': progressBackground,
'@keyframes aiopsAnimatedProgress': {
'0%': {
backgroundPosition: '0 0',
},
'100%': {
backgroundPosition: 'calc(10 * (12px / 0.707)) 100%',
},
},
},
});
}, [color]);
};

View file

@ -12,7 +12,8 @@
"@types/d3-transition",
"jest",
"node",
"react"
"react",
"@emotion/react/types/css-prop"
]
},
"include": [

View file

@ -52,8 +52,10 @@ import {
// Overall progress is a float from 0 to 1.
const LOADED_FIELD_CANDIDATES = 0.2;
const PROGRESS_STEP_P_VALUES = 0.6;
const PROGRESS_STEP_HISTOGRAMS = 0.2;
const PROGRESS_STEP_P_VALUES = 0.5;
const PROGRESS_STEP_GROUPING = 0.1;
const PROGRESS_STEP_HISTOGRAMS = 0.1;
const PROGRESS_STEP_HISTOGRAMS_GROUPS = 0.1;
export const defineExplainLogRateSpikesRoute = (
router: IRouter<DataRequestHandlerContext>,
@ -233,7 +235,35 @@ export const defineExplainLogRateSpikesRoute = (
undefined
)) as [NumericChartData];
function pushHistogramDataLoadingState() {
push(
updateLoadingStateAction({
ccsWarning: false,
loaded,
loadingState: i18n.translate(
'xpack.aiops.explainLogRateSpikes.loadingState.loadingHistogramData',
{
defaultMessage: 'Loading histogram data.',
}
),
})
);
}
if (groupingEnabled) {
push(
updateLoadingStateAction({
ccsWarning: false,
loaded,
loadingState: i18n.translate(
'xpack.aiops.explainLogRateSpikes.loadingState.groupingResults',
{
defaultMessage: 'Transforming significant field/value pairs into groups.',
}
),
})
);
// To optimize the `frequent_items` query, we identify duplicate change points by count attributes.
// Note this is a compromise and not 100% accurate because there could be change points that
// have the exact same counts but still don't co-occur.
@ -389,6 +419,10 @@ export const defineExplainLogRateSpikesRoute = (
push(addChangePointsGroupAction(changePointGroups));
}
loaded += PROGRESS_STEP_GROUPING;
pushHistogramDataLoadingState();
if (changePointGroups) {
await asyncForEach(changePointGroups, async (cpg, index) => {
const histogramQuery = {
@ -445,6 +479,8 @@ export const defineExplainLogRateSpikesRoute = (
}
}
loaded += PROGRESS_STEP_HISTOGRAMS_GROUPS;
// time series filtered by fields
if (changePoints) {
await asyncForEach(changePoints, async (cp, index) => {
@ -496,18 +532,7 @@ export const defineExplainLogRateSpikesRoute = (
const { fieldName, fieldValue } = cp;
loaded += (1 / changePoints.length) * PROGRESS_STEP_HISTOGRAMS;
push(
updateLoadingStateAction({
ccsWarning: false,
loaded,
loadingState: i18n.translate(
'xpack.aiops.explainLogRateSpikes.loadingState.loadingHistogramData',
{
defaultMessage: 'Loading histogram data.',
}
),
})
);
pushHistogramDataLoadingState();
push(
addChangePointsHistogramAction([
{