From 5203f1bcc86e777656fa7e7f0036638d83883f51 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 3 Oct 2022 10:25:39 +0200 Subject: [PATCH] [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. --- .../packages/ml/aiops_components/BUILD.bazel | 4 ++ .../progress_controls/progress_controls.tsx | 12 ++++- .../use_animated_progress_bar_background.ts | 53 +++++++++++++++++++ .../ml/aiops_components/tsconfig.json | 3 +- .../server/routes/explain_log_rate_spikes.ts | 53 ++++++++++++++----- 5 files changed, 108 insertions(+), 17 deletions(-) create mode 100644 x-pack/packages/ml/aiops_components/src/progress_controls/use_animated_progress_bar_background.ts diff --git a/x-pack/packages/ml/aiops_components/BUILD.bazel b/x-pack/packages/ml/aiops_components/BUILD.bazel index 37ed6c171c4a0..08b49643adc2f 100644 --- a/x-pack/packages/ml/aiops_components/BUILD.bazel +++ b/x-pack/packages/ml/aiops_components/BUILD.bazel @@ -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", ] diff --git a/x-pack/packages/ml/aiops_components/src/progress_controls/progress_controls.tsx b/x-pack/packages/ml/aiops_components/src/progress_controls/progress_controls.tsx index 579c528d16dca..af8f0ec1ad315 100644 --- a/x-pack/packages/ml/aiops_components/src/progress_controls/progress_controls.tsx +++ b/x-pack/packages/ml/aiops_components/src/progress_controls/progress_controls.tsx @@ -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 ( @@ -51,7 +59,7 @@ export function ProgressControls({ /> - + { + 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]); +}; diff --git a/x-pack/packages/ml/aiops_components/tsconfig.json b/x-pack/packages/ml/aiops_components/tsconfig.json index 8bca748268ac2..cdb1c5d8d0007 100644 --- a/x-pack/packages/ml/aiops_components/tsconfig.json +++ b/x-pack/packages/ml/aiops_components/tsconfig.json @@ -12,7 +12,8 @@ "@types/d3-transition", "jest", "node", - "react" + "react", + "@emotion/react/types/css-prop" ] }, "include": [ diff --git a/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts b/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts index 48ea2dbddb1c3..8a8a7372f80e2 100644 --- a/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts +++ b/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts @@ -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, @@ -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([ {