From 46cccc69cfd22b267a916e44b3cedf09572c8623 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 3 Aug 2023 18:34:47 +0200 Subject: [PATCH 01/16] auto-detect if spike or dip selection --- .../document_count_chart.tsx | 40 ++++++++++++++--- x-pack/packages/ml/aiops_utils/index.ts | 8 +++- .../aiops_utils/src/log_rate_analysis_type.ts | 21 +++++++++ x-pack/plugins/aiops/common/constants.ts | 14 ------ x-pack/plugins/aiops/common/index.ts | 2 - .../document_count_content.tsx | 8 +++- .../log_rate_analysis_content.tsx | 23 ++++++---- .../log_rate_analysis_content_wrapper.tsx | 5 --- .../log_rate_analysis_results.tsx | 45 ++++++++++++++++++- x-pack/plugins/aiops/public/index.ts | 2 - .../components/log_rate_analysis.tsx | 41 ++++++----------- 11 files changed, 140 insertions(+), 69 deletions(-) create mode 100644 x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx index f20c5311d183a..dc75c302eaf4e 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { median } from 'd3-array'; import React, { type FC, useCallback, useEffect, useMemo, useState } from 'react'; import moment from 'moment'; @@ -27,8 +28,13 @@ import { import { i18n } from '@kbn/i18n'; import { IUiSettingsClient } from '@kbn/core/public'; -import { getSnappedWindowParameters, getWindowParameters } from '@kbn/aiops-utils'; -import type { WindowParameters } from '@kbn/aiops-utils'; +import { + getSnappedWindowParameters, + getWindowParameters, + LOG_RATE_ANALYSIS_TYPE, + type LogRateAnalysisType, + type WindowParameters, +} from '@kbn/aiops-utils'; import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; @@ -95,7 +101,11 @@ export interface DocumentCountChartProps { uiSettings: IUiSettingsClient; }; /** Optional callback function which gets called the brush selection has changed */ - brushSelectionUpdateHandler?: (windowParameters: WindowParameters, force: boolean) => void; + brushSelectionUpdateHandler?: ( + logRateAnalysisType: LogRateAnalysisType, + windowParameters: WindowParameters, + force: boolean + ) => void; /** Optional width */ width?: number; /** Data chart points */ @@ -159,6 +169,21 @@ function getBaselineBadgeOverflow( : 0; } +function getLogRateAnalysisType( + chartPoints: DocumentCountChartPoint[], + { baselineMin, baselineMax, deviationMin, deviationMax }: WindowParameters +): LogRateAnalysisType { + const baselineItems = chartPoints.filter((d) => d.time >= baselineMin && d.time < baselineMax); + const baselineMedian = median(baselineItems.map((d) => d.value)) ?? 0; + + const deviationItems = chartPoints.filter((d) => d.time >= deviationMin && d.time < deviationMax); + const deviationMedian = median(deviationItems.map((d) => d.value)) ?? 0; + + return deviationMedian >= baselineMedian + ? LOG_RATE_ANALYSIS_TYPE.SPIKE + : LOG_RATE_ANALYSIS_TYPE.DIP; +} + /** * Document count chart with draggable brushes to select time ranges * by default use `Baseline` and `Deviation` for the badge names @@ -333,8 +358,13 @@ export const DocumentCountChart: FC = ({ const wpSnap = getSnappedWindowParameters(wp, snapTimestamps); setOriginalWindowParameters(wpSnap); setWindowParameters(wpSnap); + if (brushSelectionUpdateHandler !== undefined) { - brushSelectionUpdateHandler(wpSnap, true); + brushSelectionUpdateHandler( + getLogRateAnalysisType(adjustedChartPoints, wpSnap), + wpSnap, + true + ); } } } @@ -385,7 +415,7 @@ export const DocumentCountChart: FC = ({ } setWindowParameters(wp); setWindowParametersAsPixels(wpPx); - brushSelectionUpdateHandler(wp, false); + brushSelectionUpdateHandler(getLogRateAnalysisType(adjustedChartPoints, wp), wp, false); } const [mlBrushWidth, setMlBrushWidth] = useState(); diff --git a/x-pack/packages/ml/aiops_utils/index.ts b/x-pack/packages/ml/aiops_utils/index.ts index f2c343f2500ac..61ad548870f10 100644 --- a/x-pack/packages/ml/aiops_utils/index.ts +++ b/x-pack/packages/ml/aiops_utils/index.ts @@ -5,5 +5,9 @@ * 2.0. */ -export { getSnappedWindowParameters, getWindowParameters } from './src/get_window_parameters'; -export type { WindowParameters } from './src/get_window_parameters'; +export { + getSnappedWindowParameters, + getWindowParameters, + type WindowParameters, +} from './src/get_window_parameters'; +export { LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType } from './src/log_rate_analysis_type'; diff --git a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts new file mode 100644 index 0000000000000..ba8f370029782 --- /dev/null +++ b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts @@ -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. + */ + +/** + * The type of log rate analysis (spike or dip) will affect how parameters are + * passed to the analysis API endpoint. + */ +export const LOG_RATE_ANALYSIS_TYPE = { + SPIKE: 'spike', + DIP: 'dip', +} as const; + +/** + * Union type of log rate analysis types. + */ +export type LogRateAnalysisType = + typeof LOG_RATE_ANALYSIS_TYPE[keyof typeof LOG_RATE_ANALYSIS_TYPE]; diff --git a/x-pack/plugins/aiops/common/constants.ts b/x-pack/plugins/aiops/common/constants.ts index b6ab2d3e6e34b..4f461016aa0e4 100644 --- a/x-pack/plugins/aiops/common/constants.ts +++ b/x-pack/plugins/aiops/common/constants.ts @@ -10,20 +10,6 @@ */ export const LOG_RATE_ANALYSIS_P_VALUE_THRESHOLD = 0.02; -/** - * The type of log rate analysis (spike or dip) will affect how parameters are - * passed to the analysis API endpoint. - */ -export const LOG_RATE_ANALYSIS_TYPE = { - SPIKE: 'spike', - DIP: 'dip', -} as const; -/** - * Union type of log rate analysis types. - */ -export type LogRateAnalysisType = - typeof LOG_RATE_ANALYSIS_TYPE[keyof typeof LOG_RATE_ANALYSIS_TYPE]; - /** * For the technical preview of Log Rate Analysis we use a hard coded seed. * In future versions we might use a user specific seed or let the user customise it. diff --git a/x-pack/plugins/aiops/common/index.ts b/x-pack/plugins/aiops/common/index.ts index 2d41737dbc45e..d9d9b9cb4d385 100755 --- a/x-pack/plugins/aiops/common/index.ts +++ b/x-pack/plugins/aiops/common/index.ts @@ -5,8 +5,6 @@ * 2.0. */ -export type { LogRateAnalysisType } from './constants'; - /** * PLUGIN_ID is used as a unique identifier for the aiops plugin */ diff --git a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx index abb7668384ca9..11be8af45ccc7 100644 --- a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx +++ b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx @@ -13,7 +13,7 @@ import { RectAnnotationSpec, } from '@elastic/charts/dist/chart_types/xy_chart/utils/specs'; -import type { WindowParameters } from '@kbn/aiops-utils'; +import type { LogRateAnalysisType, WindowParameters } from '@kbn/aiops-utils'; import { DocumentCountChart, type DocumentCountChartPoint } from '@kbn/aiops-components'; import { useAiopsAppContext } from '../../../hooks/use_aiops_app_context'; @@ -22,7 +22,11 @@ import { DocumentCountStats } from '../../../get_document_stats'; import { TotalCountHeader } from '../total_count_header'; export interface DocumentCountContentProps { - brushSelectionUpdateHandler: (d: WindowParameters, force: boolean) => void; + brushSelectionUpdateHandler: ( + logRateAnalysisType: LogRateAnalysisType, + d: WindowParameters, + force: boolean + ) => void; documentCountStats?: DocumentCountStats; documentCountStatsSplit?: DocumentCountStats; documentCountStatsSplitLabel?: string; diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx index 33180584256df..cc43e53e01dd2 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx @@ -15,11 +15,13 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { Dictionary } from '@kbn/ml-url-state'; -import type { WindowParameters } from '@kbn/aiops-utils'; +import { + LOG_RATE_ANALYSIS_TYPE, + type LogRateAnalysisType, + type WindowParameters, +} from '@kbn/aiops-utils'; import type { SignificantTerm } from '@kbn/ml-agg-utils'; -import { LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType } from '../../../../common/constants'; - import { useData } from '../../../hooks/use_data'; import { DocumentCountContent } from '../../document_count_content/document_count_content'; @@ -48,8 +50,6 @@ export function getDocumentCountStatsSplitLabel( export interface LogRateAnalysisContentProps { /** The data view to analyze. */ dataView: DataView; - /** The type of analysis, whether it's a spike or dip */ - analysisType?: LogRateAnalysisType; setGlobalState?: (params: Dictionary) => void; /** Timestamp for the start of the range for initial analysis */ initialAnalysisStart?: number | WindowParameters; @@ -68,7 +68,6 @@ export interface LogRateAnalysisContentProps { export const LogRateAnalysisContent: FC = ({ dataView, - analysisType = LOG_RATE_ANALYSIS_TYPE.SPIKE, setGlobalState, initialAnalysisStart: incomingInitialAnalysisStart, timeRange, @@ -83,6 +82,9 @@ export const LogRateAnalysisContent: FC = ({ number | WindowParameters | undefined >(incomingInitialAnalysisStart); const [isBrushCleared, setIsBrushCleared] = useState(true); + const [logRateAnalysisType, setLogRateAnalysisType] = useState( + LOG_RATE_ANALYSIS_TYPE.SPIKE + ); useEffect(() => { setIsBrushCleared(windowParameters === undefined); @@ -111,13 +113,18 @@ export const LogRateAnalysisContent: FC = ({ const { sampleProbability, totalCount, documentCountStats, documentCountStatsCompare } = documentStats; - function brushSelectionUpdate(d: WindowParameters, force: boolean) { + function brushSelectionUpdate( + logRateAnalysisTypeUpdate: LogRateAnalysisType, + d: WindowParameters, + force: boolean + ) { if (!isBrushCleared || force) { setWindowParameters(d); } if (force) { setIsBrushCleared(false); } + setLogRateAnalysisType(logRateAnalysisTypeUpdate); } function clearSelection() { @@ -153,7 +160,7 @@ export const LogRateAnalysisContent: FC = ({ {earliest !== undefined && latest !== undefined && windowParameters !== undefined && ( = ({ dataView, - analysisType = LOG_RATE_ANALYSIS_TYPE.SPIKE, appDependencies, setGlobalState, initialAnalysisStart, @@ -100,7 +96,6 @@ export const LogRateAnalysisContentWrapper: FC = ({ const { clearAllRowState } = useLogRateAnalysisResultsTableRowContext(); + const [currentAnalysisType, setCurrentAnalysisType] = useState(); const [currentAnalysisWindowParameters, setCurrentAnalysisWindowParameters] = useState< WindowParameters | undefined >(); @@ -215,6 +221,7 @@ export const LogRateAnalysisResults: FC = ({ setOverrides(undefined); if (onAnalysisCompleted) { onAnalysisCompleted({ + analysisType, significantTerms: data.significantTerms, significantTermsGroups: data.significantTermsGroups, }); @@ -241,6 +248,7 @@ export const LogRateAnalysisResults: FC = ({ clearAllRowState(); } + setCurrentAnalysisType(analysisType); setCurrentAnalysisWindowParameters(windowParameters); // We trigger hooks updates above so we cannot directly call `start()` here @@ -257,6 +265,7 @@ export const LogRateAnalysisResults: FC = ({ }, [shouldStart]); useEffect(() => { + setCurrentAnalysisType(analysisType); setCurrentAnalysisWindowParameters(windowParameters); start(); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -341,6 +350,38 @@ export const LogRateAnalysisResults: FC = ({ /> + {showLogRateAnalysisResultsTable && ( + <> + + + + {currentAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE + ? i18n.translate('xpack.aiops.analysis.analysisTypeSpikeCallOutContent', { + defaultMessage: + 'The median log rate in the selected deviation time range is higher than the baseline. Therefore, the results shows statistically significant items within the deviation time range that are contributors to the spike. The "doc count" column refers to the amount of documents in the deviation time range.', + }) + : i18n.translate('xpack.aiops.analysis.analysisTypeDipCallOutContent', { + defaultMessage: + 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less present or missing within the deviation time range. The "doc count" column refers to the amount of documents in baseline time range.', + })} + + + + + )} {errors.length > 0 ? ( <> diff --git a/x-pack/plugins/aiops/public/index.ts b/x-pack/plugins/aiops/public/index.ts index 4c7ec4e9fc100..3e6ea42afe55c 100755 --- a/x-pack/plugins/aiops/public/index.ts +++ b/x-pack/plugins/aiops/public/index.ts @@ -13,8 +13,6 @@ export function plugin() { return new AiopsPlugin(); } -export { LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType } from '../common/constants'; - export type { AiopsAppDependencies } from './hooks/use_aiops_app_context'; export type { LogRateAnalysisAppStateProps } from './components/log_rate_analysis'; export type { LogRateAnalysisContentWrapperProps } from './components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content_wrapper'; diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx index 66d26dc836cf1..d4e1d228f03f6 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx @@ -13,12 +13,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DataView } from '@kbn/data-views-plugin/common'; -import { - LogRateAnalysisContent, - LOG_RATE_ANALYSIS_TYPE, - type LogRateAnalysisResultsData, - type LogRateAnalysisType, -} from '@kbn/aiops-plugin/public'; +import type { LogRateAnalysisType } from '@kbn/aiops-utils'; +import { LogRateAnalysisContent, type LogRateAnalysisResultsData } from '@kbn/aiops-plugin/public'; import { Rule } from '@kbn/alerting-plugin/common'; import { TopAlert } from '@kbn/observability-plugin/public'; import { @@ -33,7 +29,6 @@ import { ALERT_END } from '@kbn/rule-data-utils'; import { Color, colorTransformer } from '../../../../../../common/color_palette'; import { useKibanaContextForPlugin } from '../../../../../hooks/use_kibana'; import { - Comparator, CountRuleParams, isRatioRuleParams, PartialRuleParams, @@ -60,11 +55,9 @@ export const LogRateAnalysis: FC = ({ r const [dataView, setDataView] = useState(); const [esSearchQuery, setEsSearchQuery] = useState(); const [logRateAnalysisParams, setLogRateAnalysisParams] = useState< - { significantFieldValues: SignificantFieldValue[] } | undefined + | { logRateAnalysisType: LogRateAnalysisType; significantFieldValues: SignificantFieldValue[] } + | undefined >(); - const [logRateAnalysisType, setLogRateAnalysisType] = useState( - undefined - ); const validatedParams = useMemo(() => decodeOrThrow(ruleParamsRT)(rule.params), [rule]); @@ -95,19 +88,6 @@ export const LogRateAnalysis: FC = ({ r if (!isRatioRuleParams(validatedParams)) { getDataView(); - - switch (validatedParams.count.comparator) { - case Comparator.GT: - case Comparator.GT_OR_EQ: - setLogRateAnalysisType(LOG_RATE_ANALYSIS_TYPE.SPIKE); - break; - case Comparator.LT: - case Comparator.LT_OR_EQ: - setLogRateAnalysisType(LOG_RATE_ANALYSIS_TYPE.DIP); - break; - default: - setLogRateAnalysisType(undefined); - } } }, [validatedParams, alert, dataViews, logsShared]); @@ -188,7 +168,13 @@ export const LogRateAnalysis: FC = ({ r ['pValue', 'docCount'], ['asc', 'asc'] ).slice(0, 50); - setLogRateAnalysisParams(significantFieldValues ? { significantFieldValues } : undefined); + + const logRateAnalysisType = analysisResults?.analysisType; + setLogRateAnalysisParams( + significantFieldValues && logRateAnalysisType + ? { logRateAnalysisType, significantFieldValues } + : undefined + ); }; const aiAssistant = useObservabilityAIAssistant(); @@ -201,6 +187,8 @@ export const LogRateAnalysis: FC = ({ r return undefined; } + const { logRateAnalysisType } = logRateAnalysisParams; + const header = 'Field name,Field value,Doc count,p-value'; const rows = logRateAnalysisParams.significantFieldValues .map((item) => Object.values(item).join(',')) @@ -251,7 +239,7 @@ export const LogRateAnalysis: FC = ({ r }, }, ]; - }, [logRateAnalysisParams, logRateAnalysisType]); + }, [logRateAnalysisParams]); if (!dataView || !esSearchQuery) return null; @@ -271,7 +259,6 @@ export const LogRateAnalysis: FC = ({ r Date: Thu, 3 Aug 2023 19:58:33 +0200 Subject: [PATCH 02/16] fix types --- .../document_count_chart/document_count_chart.tsx | 12 ++++++------ .../src/progress_controls/progress_controls.tsx | 2 +- .../document_count_content.tsx | 6 +++--- .../log_rate_analysis_content.tsx | 8 ++++---- .../document_count_with_dual_brush.tsx | 2 +- x-pack/plugins/infra/tsconfig.json | 1 + 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx index dc75c302eaf4e..23c8a971ee00b 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx @@ -102,9 +102,9 @@ export interface DocumentCountChartProps { }; /** Optional callback function which gets called the brush selection has changed */ brushSelectionUpdateHandler?: ( - logRateAnalysisType: LogRateAnalysisType, windowParameters: WindowParameters, - force: boolean + force: boolean, + logRateAnalysisType: LogRateAnalysisType ) => void; /** Optional width */ width?: number; @@ -188,7 +188,7 @@ function getLogRateAnalysisType( * Document count chart with draggable brushes to select time ranges * by default use `Baseline` and `Deviation` for the badge names * @param dependencies - List of Kibana services that are required as dependencies - * @param brushSelectionUpdateHandler - Optional callback function which gets called the brush selection has changed + * @param brushSelectionUpdateHandler - Optional callback function which gets called when the brush selection has changed * @param width - Optional width * @param chartPoints - Data chart points * @param chartPointsSplit - Data chart points split @@ -361,9 +361,9 @@ export const DocumentCountChart: FC = ({ if (brushSelectionUpdateHandler !== undefined) { brushSelectionUpdateHandler( - getLogRateAnalysisType(adjustedChartPoints, wpSnap), wpSnap, - true + true, + getLogRateAnalysisType(adjustedChartPoints, wpSnap) ); } } @@ -415,7 +415,7 @@ export const DocumentCountChart: FC = ({ } setWindowParameters(wp); setWindowParametersAsPixels(wpPx); - brushSelectionUpdateHandler(getLogRateAnalysisType(adjustedChartPoints, wp), wp, false); + brushSelectionUpdateHandler(wp, false, getLogRateAnalysisType(adjustedChartPoints, wp)); } const [mlBrushWidth, setMlBrushWidth] = useState(); 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 7083282d3609f..fb0dc0d2713a9 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 @@ -47,7 +47,7 @@ interface ProgressControlProps { * by default use `Baseline` and `Deviation` for the badge name * @type {FC} * @param children - List of Kibana services that are required as dependencies - * @param brushSelectionUpdateHandler - Optional callback function which gets called the brush selection has changed + * @param brushSelectionUpdateHandler - Optional callback function which gets called when the brush selection has changed * @param width - Optional width * @param chartPoints - Data chart points * @param chartPointsSplit - Data chart points split diff --git a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx index 11be8af45ccc7..228b278a2cc14 100644 --- a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx +++ b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx @@ -23,9 +23,9 @@ import { TotalCountHeader } from '../total_count_header'; export interface DocumentCountContentProps { brushSelectionUpdateHandler: ( - logRateAnalysisType: LogRateAnalysisType, - d: WindowParameters, - force: boolean + windowParameters: WindowParameters, + force: boolean, + logRateAnalysisType: LogRateAnalysisType ) => void; documentCountStats?: DocumentCountStats; documentCountStatsSplit?: DocumentCountStats; diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx index cc43e53e01dd2..e27d3af3aefa7 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_content/log_rate_analysis_content.tsx @@ -114,12 +114,12 @@ export const LogRateAnalysisContent: FC = ({ documentStats; function brushSelectionUpdate( - logRateAnalysisTypeUpdate: LogRateAnalysisType, - d: WindowParameters, - force: boolean + windowParametersUpdate: WindowParameters, + force: boolean, + logRateAnalysisTypeUpdate: LogRateAnalysisType ) { if (!isBrushCleared || force) { - setWindowParameters(d); + setWindowParameters(windowParametersUpdate); } if (force) { setIsBrushCleared(false); diff --git a/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx b/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx index cc4267be0087b..47da063329d03 100644 --- a/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx +++ b/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx @@ -26,7 +26,7 @@ export interface DocumentCountContentProps | 'interval' | 'chartPointsSplitLabel' > { - brushSelectionUpdateHandler: (d: WindowParameters, force: boolean) => void; + brushSelectionUpdateHandler: (windowParameters: WindowParameters, force: boolean) => void; documentCountStats?: DocumentCountStats; documentCountStatsSplit?: DocumentCountStats; documentCountStatsSplitLabel?: string; diff --git a/x-pack/plugins/infra/tsconfig.json b/x-pack/plugins/infra/tsconfig.json index 7978b6f3b0901..c0cc1cbf1b3c9 100644 --- a/x-pack/plugins/infra/tsconfig.json +++ b/x-pack/plugins/infra/tsconfig.json @@ -68,6 +68,7 @@ "@kbn/core-http-server", "@kbn/logs-shared-plugin", "@kbn/licensing-plugin", + "@kbn/aiops-utils", ], "exclude": ["target/**/*"] } From fdb93e5a0ecc2c43291f42901120df561d0baa11 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 3 Aug 2023 20:15:33 +0200 Subject: [PATCH 03/16] break out getLogRateAnalysisType into own file and add unit tests --- .../document_count_chart.tsx | 18 +----- x-pack/packages/ml/aiops_utils/index.ts | 8 ++- .../src/log_rate_analysis_type.test.ts | 58 +++++++++++++++++++ .../aiops_utils/src/log_rate_analysis_type.ts | 33 +++++++++++ ...dow_parameters.ts => window_parameters.ts} | 0 5 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts rename x-pack/packages/ml/aiops_utils/src/{get_window_parameters.ts => window_parameters.ts} (100%) diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx index 23c8a971ee00b..8d11e1b6f9832 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import { median } from 'd3-array'; import React, { type FC, useCallback, useEffect, useMemo, useState } from 'react'; import moment from 'moment'; @@ -29,9 +28,9 @@ import { import { i18n } from '@kbn/i18n'; import { IUiSettingsClient } from '@kbn/core/public'; import { + getLogRateAnalysisType, getSnappedWindowParameters, getWindowParameters, - LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType, type WindowParameters, } from '@kbn/aiops-utils'; @@ -169,21 +168,6 @@ function getBaselineBadgeOverflow( : 0; } -function getLogRateAnalysisType( - chartPoints: DocumentCountChartPoint[], - { baselineMin, baselineMax, deviationMin, deviationMax }: WindowParameters -): LogRateAnalysisType { - const baselineItems = chartPoints.filter((d) => d.time >= baselineMin && d.time < baselineMax); - const baselineMedian = median(baselineItems.map((d) => d.value)) ?? 0; - - const deviationItems = chartPoints.filter((d) => d.time >= deviationMin && d.time < deviationMax); - const deviationMedian = median(deviationItems.map((d) => d.value)) ?? 0; - - return deviationMedian >= baselineMedian - ? LOG_RATE_ANALYSIS_TYPE.SPIKE - : LOG_RATE_ANALYSIS_TYPE.DIP; -} - /** * Document count chart with draggable brushes to select time ranges * by default use `Baseline` and `Deviation` for the badge names diff --git a/x-pack/packages/ml/aiops_utils/index.ts b/x-pack/packages/ml/aiops_utils/index.ts index 61ad548870f10..9d63b0587c1c1 100644 --- a/x-pack/packages/ml/aiops_utils/index.ts +++ b/x-pack/packages/ml/aiops_utils/index.ts @@ -9,5 +9,9 @@ export { getSnappedWindowParameters, getWindowParameters, type WindowParameters, -} from './src/get_window_parameters'; -export { LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType } from './src/log_rate_analysis_type'; +} from './src/window_parameters'; +export { + getLogRateAnalysisType, + LOG_RATE_ANALYSIS_TYPE, + type LogRateAnalysisType, +} from './src/log_rate_analysis_type'; diff --git a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts new file mode 100644 index 0000000000000..cb22663e35c35 --- /dev/null +++ b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts @@ -0,0 +1,58 @@ +/* + * 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 type { DocumentCountChartPoint } from '@kbn/aiops-components'; + +import { getLogRateAnalysisType } from './log_rate_analysis_type'; + +describe('getLogRateAnalysisType', () => { + const documentCountChartPointsMock: DocumentCountChartPoint[] = [ + { time: 0, value: 10 }, + { time: 1, value: 10 }, + { time: 2, value: 10 }, + { time: 3, value: 5 }, + { time: 4, value: 10 }, + { time: 5, value: 10 }, + { time: 6, value: 10 }, + { time: 7, value: 20 }, + { time: 8, value: 10 }, + { time: 9, value: 10 }, + ]; + + test('returns "spike" for the given parameters', () => { + expect( + getLogRateAnalysisType(documentCountChartPointsMock, { + baselineMin: 4, + baselineMax: 6, + deviationMin: 7, + deviationMax: 8, + }) + ).toBe('spike'); + }); + + test('returns "dip" for the given parameters', () => { + expect( + getLogRateAnalysisType(documentCountChartPointsMock, { + baselineMin: 0, + baselineMax: 2, + deviationMin: 3, + deviationMax: 4, + }) + ).toBe('dip'); + }); + + test('falls back to "spike" if both time range have the same median', () => { + expect( + getLogRateAnalysisType(documentCountChartPointsMock, { + baselineMin: 0, + baselineMax: 2, + deviationMin: 4, + deviationMax: 6, + }) + ).toBe('spike'); + }); +}); diff --git a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts index ba8f370029782..572556fdb1bbc 100644 --- a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts +++ b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts @@ -5,6 +5,12 @@ * 2.0. */ +import { median } from 'd3-array'; + +import type { DocumentCountChartPoint } from '@kbn/aiops-components'; + +import type { WindowParameters } from './window_parameters'; + /** * The type of log rate analysis (spike or dip) will affect how parameters are * passed to the analysis API endpoint. @@ -19,3 +25,30 @@ export const LOG_RATE_ANALYSIS_TYPE = { */ export type LogRateAnalysisType = typeof LOG_RATE_ANALYSIS_TYPE[keyof typeof LOG_RATE_ANALYSIS_TYPE]; + +/** + * Identify the log rate analysis type based on the baseline/deviation + * time ranges on a given log rate histogram. + * + * @param documentCountChartPoints The log rate histogram. + * @param windowParameters The window parameters with baseline and deviation time range. + * @returns The log rate analysis type. + */ +export function getLogRateAnalysisType( + documentCountChartPoints: DocumentCountChartPoint[], + { baselineMin, baselineMax, deviationMin, deviationMax }: WindowParameters +): LogRateAnalysisType { + const baselineItems = documentCountChartPoints.filter( + (d) => d.time >= baselineMin && d.time < baselineMax + ); + const baselineMedian = median(baselineItems.map((d) => d.value)) ?? 0; + + const deviationItems = documentCountChartPoints.filter( + (d) => d.time >= deviationMin && d.time < deviationMax + ); + const deviationMedian = median(deviationItems.map((d) => d.value)) ?? 0; + + return deviationMedian >= baselineMedian + ? LOG_RATE_ANALYSIS_TYPE.SPIKE + : LOG_RATE_ANALYSIS_TYPE.DIP; +} diff --git a/x-pack/packages/ml/aiops_utils/src/get_window_parameters.ts b/x-pack/packages/ml/aiops_utils/src/window_parameters.ts similarity index 100% rename from x-pack/packages/ml/aiops_utils/src/get_window_parameters.ts rename to x-pack/packages/ml/aiops_utils/src/window_parameters.ts From e2b4ab781edc1b58db4a39db4dac32b955c9af5f Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 3 Aug 2023 21:03:40 +0200 Subject: [PATCH 04/16] adds functional test with artificial logs dataset with dip --- .../test/functional/apps/aiops/test_data.ts | 13 ++++++----- .../aiops/log_rate_analysis_data_generator.ts | 23 +++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/x-pack/test/functional/apps/aiops/test_data.ts b/x-pack/test/functional/apps/aiops/test_data.ts index 4f2573c362933..e4e950e3f5fca 100644 --- a/x-pack/test/functional/apps/aiops/test_data.ts +++ b/x-pack/test/functional/apps/aiops/test_data.ts @@ -171,11 +171,11 @@ const DAY_MS = 86400000; const DEVIATION_TS = REFERENCE_TS - DAY_MS * 2; const BASELINE_TS = DEVIATION_TS - DAY_MS * 1; -export const artificialLogDataViewTestData: TestData = { - suiteTitle: 'artificial logs with spike', - dataGenerator: 'artificial_logs_with_spike', +const getArtificialLogDataViewTestData = (analysisType: 'spike' | 'dip'): TestData => ({ + suiteTitle: `artificial logs with ${analysisType}`, + dataGenerator: `artificial_logs_with_${analysisType}`, isSavedSearch: false, - sourceIndexOrSavedSearch: 'artificial_logs_with_spike', + sourceIndexOrSavedSearch: `artificial_logs_with_${analysisType}`, brushBaselineTargetTimestamp: BASELINE_TS + DAY_MS / 2, brushDeviationTargetTimestamp: DEVIATION_TS + DAY_MS / 2, brushIntervalFactor: 10, @@ -224,11 +224,12 @@ export const artificialLogDataViewTestData: TestData = { ], fieldSelectorPopover: ['response_code', 'url', 'user'], }, -}; +}); export const logRateAnalysisTestData: TestData[] = [ kibanaLogsDataViewTestData, farequoteDataViewTestData, farequoteDataViewTestDataWithQuery, - artificialLogDataViewTestData, + getArtificialLogDataViewTestData('spike'), + getArtificialLogDataViewTestData('dip'), ]; diff --git a/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts b/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts index 0993850db55c1..43c687182d7d2 100644 --- a/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts +++ b/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts @@ -24,7 +24,7 @@ const DAY_MS = 86400000; const DEVIATION_TS = REFERENCE_TS - DAY_MS * 2; const BASELINE_TS = DEVIATION_TS - DAY_MS * 1; -function getArtificialLogsWithSpike(index: string) { +function getArtificialLogsWithDeviation(index: string, deviationType: string) { const bulkBody: estypes.BulkRequest['body'] = []; const action = { index: { _index: index } }; let tsOffset = 0; @@ -81,7 +81,7 @@ function getArtificialLogsWithSpike(index: string) { response_code: responseCode, url, version: 'v1.0.0', - '@timestamp': DEVIATION_TS + tsOffset, + '@timestamp': (deviationType === 'spike' ? DEVIATION_TS : BASELINE_TS) + tsOffset, should_ignore_this_field: 'should_ignore_this_field', }); }); @@ -104,7 +104,7 @@ function getArtificialLogsWithSpike(index: string) { response_code: '500', url, version: 'v1.0.0', - '@timestamp': DEVIATION_TS + tsOffset, + '@timestamp': (deviationType === 'spike' ? DEVIATION_TS : BASELINE_TS) + tsOffset, should_ignore_this_field: 'should_ignore_this_field', }); }); @@ -159,17 +159,18 @@ export function LogRateAnalysisDataGeneratorProvider({ getService }: FtrProvider break; case 'artificial_logs_with_spike': + case 'artificial_logs_with_dip': try { await es.indices.delete({ - index: 'artificial_logs_with_spike', + index: dataGenerator, }); } catch (e) { - log.info(`Could not delete index 'artificial_logs_with_spike' in before() callback`); + log.info(`Could not delete index '${dataGenerator}' in before() callback`); } // Create index with mapping await es.indices.create({ - index: 'artificial_logs_with_spike', + index: dataGenerator, mappings: { properties: { user: { type: 'keyword' }, @@ -184,7 +185,10 @@ export function LogRateAnalysisDataGeneratorProvider({ getService }: FtrProvider await es.bulk({ refresh: 'wait_for', - body: getArtificialLogsWithSpike('artificial_logs_with_spike'), + body: getArtificialLogsWithDeviation( + dataGenerator, + dataGenerator.split('_').pop() ?? 'spike' + ), }); break; @@ -204,12 +208,13 @@ export function LogRateAnalysisDataGeneratorProvider({ getService }: FtrProvider break; case 'artificial_logs_with_spike': + case 'artificial_logs_with_dip': try { await es.indices.delete({ - index: 'artificial_logs_with_spike', + index: dataGenerator, }); } catch (e) { - log.error(`Error deleting index 'artificial_logs_with_spike' in after() callback`); + log.error(`Error deleting index '${dataGenerator}' in after() callback`); } break; From df6002a9556d6aca92696eec492393f6c6866f45 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 3 Aug 2023 21:12:44 +0200 Subject: [PATCH 05/16] replace plain string --- .../components/log_rate_analysis.tsx | 8 ++++---- x-pack/test/functional/apps/aiops/test_data.ts | 12 +++++++++--- x-pack/test/functional/apps/aiops/types.ts | 2 ++ .../aiops/log_rate_analysis_data_generator.ts | 12 +++++++++--- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx index d4e1d228f03f6..35c029f41ee35 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx @@ -13,7 +13,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DataView } from '@kbn/data-views-plugin/common'; -import type { LogRateAnalysisType } from '@kbn/aiops-utils'; +import { LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType } from '@kbn/aiops-utils'; import { LogRateAnalysisContent, type LogRateAnalysisResultsData } from '@kbn/aiops-plugin/public'; import { Rule } from '@kbn/alerting-plugin/common'; import { TopAlert } from '@kbn/observability-plugin/public'; @@ -198,7 +198,7 @@ export const LogRateAnalysis: FC = ({ r "Log Rate Analysis" is an AIOps feature that uses advanced statistical methods to identify reasons for increases and decreases in log rates. It makes it easy to find and investigate causes of unusual spikes or dips by using the analysis workflow view. You are using "Log Rate Analysis" and ran the statistical analysis on the log messages which occured during the alert. You received the following analysis results from "Log Rate Analysis" which list statistically significant co-occuring field/value combinations sorted from most significant (lower p-values) to least significant (higher p-values) that ${ - logRateAnalysisType === 'spike' + logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? 'contribute to the log rate spike' : 'are less or not present in the log rate dip' }: @@ -209,12 +209,12 @@ export const LogRateAnalysis: FC = ({ r Based on the above analysis results and your observability expert knowledge, output the following: Analyse the type of these logs and explain their usual purpose (1 paragraph). ${ - logRateAnalysisType === 'spike' + logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? 'Based on the type of these logs do a root cause analysis on why the field and value combinations from the analysis results are causing this log rate spike (2 parapraphs)' : 'Based on the type of these logs do a concise analysis why the statistically significant field and value combinations are less present or missing from the log rate dip with concrete examples based on the analysis results data. Do not guess, just output what you are sure of (2 paragraphs)' }. ${ - logRateAnalysisType === 'spike' + logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? 'Recommend concrete remediations to resolve the root cause (3 bullet points).' : '' } diff --git a/x-pack/test/functional/apps/aiops/test_data.ts b/x-pack/test/functional/apps/aiops/test_data.ts index e4e950e3f5fca..d0b9035c69ced 100644 --- a/x-pack/test/functional/apps/aiops/test_data.ts +++ b/x-pack/test/functional/apps/aiops/test_data.ts @@ -5,10 +5,13 @@ * 2.0. */ +import { LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType } from '@kbn/aiops-utils'; + import type { TestData } from './types'; export const kibanaLogsDataViewTestData: TestData = { suiteTitle: 'kibana sample data logs', + analysisType: LOG_RATE_ANALYSIS_TYPE.SPIKE, dataGenerator: 'kibana_sample_data_logs', isSavedSearch: false, sourceIndexOrSavedSearch: 'kibana_sample_data_logs', @@ -114,6 +117,7 @@ export const kibanaLogsDataViewTestData: TestData = { export const farequoteDataViewTestData: TestData = { suiteTitle: 'farequote with spike', + analysisType: LOG_RATE_ANALYSIS_TYPE.SPIKE, dataGenerator: 'farequote_with_spike', isSavedSearch: false, sourceIndexOrSavedSearch: 'ft_farequote', @@ -131,6 +135,7 @@ export const farequoteDataViewTestData: TestData = { export const farequoteDataViewTestDataWithQuery: TestData = { suiteTitle: 'farequote with spike', + analysisType: LOG_RATE_ANALYSIS_TYPE.SPIKE, dataGenerator: 'farequote_with_spike', isSavedSearch: false, sourceIndexOrSavedSearch: 'ft_farequote', @@ -171,8 +176,9 @@ const DAY_MS = 86400000; const DEVIATION_TS = REFERENCE_TS - DAY_MS * 2; const BASELINE_TS = DEVIATION_TS - DAY_MS * 1; -const getArtificialLogDataViewTestData = (analysisType: 'spike' | 'dip'): TestData => ({ +const getArtificialLogDataViewTestData = (analysisType: LogRateAnalysisType): TestData => ({ suiteTitle: `artificial logs with ${analysisType}`, + analysisType, dataGenerator: `artificial_logs_with_${analysisType}`, isSavedSearch: false, sourceIndexOrSavedSearch: `artificial_logs_with_${analysisType}`, @@ -230,6 +236,6 @@ export const logRateAnalysisTestData: TestData[] = [ kibanaLogsDataViewTestData, farequoteDataViewTestData, farequoteDataViewTestDataWithQuery, - getArtificialLogDataViewTestData('spike'), - getArtificialLogDataViewTestData('dip'), + getArtificialLogDataViewTestData(LOG_RATE_ANALYSIS_TYPE.SPIKE), + getArtificialLogDataViewTestData(LOG_RATE_ANALYSIS_TYPE.DIP), ]; diff --git a/x-pack/test/functional/apps/aiops/types.ts b/x-pack/test/functional/apps/aiops/types.ts index 58fe28eb5fe00..0832d9d921615 100644 --- a/x-pack/test/functional/apps/aiops/types.ts +++ b/x-pack/test/functional/apps/aiops/types.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type { LogRateAnalysisType } from '@kbn/aiops-utils'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; interface TestDataTableActionLogPatternAnalysis { @@ -44,6 +45,7 @@ interface TestDataExpectedWithoutSampleProbability { export interface TestData { suiteTitle: string; + analysisType: LogRateAnalysisType; dataGenerator: string; isSavedSearch?: boolean; sourceIndexOrSavedSearch: string; diff --git a/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts b/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts index 43c687182d7d2..e87c49ac16941 100644 --- a/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts +++ b/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts @@ -7,6 +7,8 @@ import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { LOG_RATE_ANALYSIS_TYPE } from '@kbn/aiops-utils'; + import { FtrProviderContext } from '../../ftr_provider_context'; export interface GeneratedDoc { @@ -81,7 +83,9 @@ function getArtificialLogsWithDeviation(index: string, deviationType: string) { response_code: responseCode, url, version: 'v1.0.0', - '@timestamp': (deviationType === 'spike' ? DEVIATION_TS : BASELINE_TS) + tsOffset, + '@timestamp': + (deviationType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? DEVIATION_TS : BASELINE_TS) + + tsOffset, should_ignore_this_field: 'should_ignore_this_field', }); }); @@ -104,7 +108,9 @@ function getArtificialLogsWithDeviation(index: string, deviationType: string) { response_code: '500', url, version: 'v1.0.0', - '@timestamp': (deviationType === 'spike' ? DEVIATION_TS : BASELINE_TS) + tsOffset, + '@timestamp': + (deviationType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? DEVIATION_TS : BASELINE_TS) + + tsOffset, should_ignore_this_field: 'should_ignore_this_field', }); }); @@ -187,7 +193,7 @@ export function LogRateAnalysisDataGeneratorProvider({ getService }: FtrProvider refresh: 'wait_for', body: getArtificialLogsWithDeviation( dataGenerator, - dataGenerator.split('_').pop() ?? 'spike' + dataGenerator.split('_').pop() ?? LOG_RATE_ANALYSIS_TYPE.SPIKE ), }); break; From 53f0ef42d9f9d879c6fb5c0f8eca72f3930ea106 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 3 Aug 2023 21:33:03 +0200 Subject: [PATCH 06/16] assert the analysis type once the analysis completes --- .../log_rate_analysis_results.tsx | 18 ++++++++++-------- .../functional/apps/aiops/log_rate_analysis.ts | 2 +- .../services/aiops/log_rate_analysis_page.ts | 10 +++++++++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_results.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_results.tsx index 6bc385c07c5df..f7b70ea6adfc9 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_results.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_results.tsx @@ -355,13 +355,15 @@ export const LogRateAnalysisResults: FC = ({ + {currentAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE + ? i18n.translate('xpack.aiops.analysis.analysisTypeSpikeCallOutTitle', { + defaultMessage: 'Analysis type: Log rate spike', + }) + : i18n.translate('xpack.aiops.analysis.analysisTypeDipCallOutTitle', { + defaultMessage: 'Analysis type: Log rate dip', + })} + } color="primary" iconType="pin" @@ -375,7 +377,7 @@ export const LogRateAnalysisResults: FC = ({ }) : i18n.translate('xpack.aiops.analysis.analysisTypeDipCallOutContent', { defaultMessage: - 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less present or missing within the deviation time range. The "doc count" column refers to the amount of documents in baseline time range.', + 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less present or missing within the deviation time range. The "doc count" column refers to the amount of documents in the baseline time range.', })} diff --git a/x-pack/test/functional/apps/aiops/log_rate_analysis.ts b/x-pack/test/functional/apps/aiops/log_rate_analysis.ts index 512e1914ccffe..72323d4fef37c 100644 --- a/x-pack/test/functional/apps/aiops/log_rate_analysis.ts +++ b/x-pack/test/functional/apps/aiops/log_rate_analysis.ts @@ -147,7 +147,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await aiops.logRateAnalysisPage.clickRerunAnalysisButton(true); } - await aiops.logRateAnalysisPage.assertAnalysisComplete(); + await aiops.logRateAnalysisPage.assertAnalysisComplete(testData.analysisType); // The group switch should be disabled by default await aiops.logRateAnalysisPage.assertLogRateAnalysisResultsGroupSwitchExists(false); diff --git a/x-pack/test/functional/services/aiops/log_rate_analysis_page.ts b/x-pack/test/functional/services/aiops/log_rate_analysis_page.ts index 6a1d34e419984..510a056ca5c42 100644 --- a/x-pack/test/functional/services/aiops/log_rate_analysis_page.ts +++ b/x-pack/test/functional/services/aiops/log_rate_analysis_page.ts @@ -7,6 +7,8 @@ import expect from '@kbn/expect'; +import type { LogRateAnalysisType } from '@kbn/aiops-utils'; + import type { FtrProviderContext } from '../../ftr_provider_context'; export function LogRateAnalysisPageProvider({ getService, getPageObject }: FtrProviderContext) { @@ -239,11 +241,17 @@ export function LogRateAnalysisPageProvider({ getService, getPageObject }: FtrPr }); }, - async assertAnalysisComplete() { + async assertAnalysisComplete(analisysType: LogRateAnalysisType) { await retry.tryForTime(30 * 1000, async () => { await testSubjects.existOrFail('aiopsAnalysisComplete'); const currentProgressTitle = await testSubjects.getVisibleText('aiopsAnalysisComplete'); expect(currentProgressTitle).to.be('Analysis complete'); + + await testSubjects.existOrFail('aiopsAnalysisTypeCalloutTitle'); + const currentAnalysisTypeCalloutTitle = await testSubjects.getVisibleText( + 'aiopsAnalysisTypeCalloutTitle' + ); + expect(currentAnalysisTypeCalloutTitle).to.be(`Analysis type: Log rate ${analisysType}`); }); }, From 883f1979db6dc05b7462c0e9888781779f31de17 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 3 Aug 2023 22:03:35 +0200 Subject: [PATCH 07/16] fix missing comments/exports --- x-pack/packages/ml/aiops_components/index.ts | 2 +- .../document_count_chart.tsx | 66 +++++++++---------- .../src/document_count_chart/index.ts | 6 +- .../src/dual_brush/dual_brush.tsx | 45 +++---------- .../src/dual_brush/dual_brush_annotation.tsx | 9 +-- .../progress_controls/progress_controls.tsx | 49 +++++--------- 6 files changed, 69 insertions(+), 108 deletions(-) diff --git a/x-pack/packages/ml/aiops_components/index.ts b/x-pack/packages/ml/aiops_components/index.ts index bfe84e260decd..5cd95f003b515 100644 --- a/x-pack/packages/ml/aiops_components/index.ts +++ b/x-pack/packages/ml/aiops_components/index.ts @@ -7,5 +7,5 @@ export { DualBrush, DualBrushAnnotation } from './src/dual_brush'; export { ProgressControls } from './src/progress_controls'; -export { DocumentCountChart } from './src/document_count_chart'; +export { DocumentCountChart, type BrushSettings } from './src/document_count_chart'; export type { DocumentCountChartPoint, DocumentCountChartProps } from './src/document_count_chart'; diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx index 8d11e1b6f9832..5f9e4efcb07c7 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx @@ -99,7 +99,13 @@ export interface DocumentCountChartProps { fieldFormats: FieldFormatsStart; uiSettings: IUiSettingsClient; }; - /** Optional callback function which gets called the brush selection has changed */ + /** + * Optional callback function which gets called the brush selection has changed + * + * @param windowParameters Baseline and deviation time ranges. + * @param force Force update + * @param logRateAnalysisType `spike` or `dip` based on median log rate bucket size + */ brushSelectionUpdateHandler?: ( windowParameters: WindowParameters, force: boolean, @@ -171,42 +177,30 @@ function getBaselineBadgeOverflow( /** * Document count chart with draggable brushes to select time ranges * by default use `Baseline` and `Deviation` for the badge names - * @param dependencies - List of Kibana services that are required as dependencies - * @param brushSelectionUpdateHandler - Optional callback function which gets called when the brush selection has changed - * @param width - Optional width - * @param chartPoints - Data chart points - * @param chartPointsSplit - Data chart points split - * @param timeRangeEarliest - Start time range for the chart - * @param timeRangeLatest - Ending time range for the chart - * @param interval - Time interval for the document count buckets - * @param chartPointsSplitLabel - Label to name the adjustedChartPointsSplit histogram - * @param isBrushCleared - Whether or not brush has been reset - * @param autoAnalysisStart - Timestamp for start of initial analysis - * @param barColorOverride - Optional color override for the default bar color for charts - * @param barStyleAccessor - Optional style to override bar chart - * @param barHighlightColorOverride - Optional color override for the highlighted bar color for charts - * @param deviationBrush - Optional settings override for the 'deviation' brush - * @param baselineBrush - Optional settings override for the 'baseline' brush - * @constructor + * + * @param props DocumentCountChart component props + * @returns The DocumentCountChart component. */ -export const DocumentCountChart: FC = ({ - dependencies, - brushSelectionUpdateHandler, - width, - chartPoints, - chartPointsSplit, - timeRangeEarliest, - timeRangeLatest, - interval, - chartPointsSplitLabel, - isBrushCleared, - autoAnalysisStart, - barColorOverride, - barStyleAccessor, - barHighlightColorOverride, - deviationBrush = {}, - baselineBrush = {}, -}) => { +export const DocumentCountChart: FC = (props) => { + const { + dependencies, + brushSelectionUpdateHandler, + width, + chartPoints, + chartPointsSplit, + timeRangeEarliest, + timeRangeLatest, + interval, + chartPointsSplitLabel, + isBrushCleared, + autoAnalysisStart, + barColorOverride, + barStyleAccessor, + barHighlightColorOverride, + deviationBrush = {}, + baselineBrush = {}, + } = props; + const { data, uiSettings, fieldFormats, charts } = dependencies; const chartTheme = charts.theme.useChartsTheme(); diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts b/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts index 808496f810782..0bb6cb37fd54b 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts @@ -6,4 +6,8 @@ */ export { DocumentCountChart } from './document_count_chart'; -export type { DocumentCountChartPoint, DocumentCountChartProps } from './document_count_chart'; +export type { + BrushSettings, + DocumentCountChartPoint, + DocumentCountChartProps, +} from './document_count_chart'; diff --git a/x-pack/packages/ml/aiops_components/src/dual_brush/dual_brush.tsx b/x-pack/packages/ml/aiops_components/src/dual_brush/dual_brush.tsx index 05635405e39d9..7288b120aa613 100644 --- a/x-pack/packages/ml/aiops_components/src/dual_brush/dual_brush.tsx +++ b/x-pack/packages/ml/aiops_components/src/dual_brush/dual_brush.tsx @@ -6,7 +6,7 @@ */ import { isEqual } from 'lodash'; -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useRef, type FC } from 'react'; import * as d3Brush from 'd3-brush'; import * as d3Scale from 'd3-scale'; @@ -54,6 +54,9 @@ const BRUSH_MARGIN = 4; const BRUSH_HANDLE_SIZE = 4; const BRUSH_HANDLE_ROUNDED_CORNER = 2; +/** + * Props for the DualBrush React Component + */ interface DualBrushProps { /** * Min and max numeric timestamps for the two brushes @@ -88,40 +91,12 @@ interface DualBrushProps { /** * DualBrush React Component * Dual brush component that overlays the document count chart - * @type {FC} - * @param props - `DualBrushProps` component props - * @returns {React.ReactElement} The DualBrush component. + * + * @param props DualBrushProps component props + * @returns The DualBrush component. */ -export function DualBrush({ - /** - * Min and max numeric timestamps for the two brushes - */ - windowParameters, - /** - * Min timestamp for x domain - */ - min, - /** - * Max timestamp for x domain - */ - max, - /** - * Callback function whenever the brush changes - */ - onChange, - /** - * Margin left - */ - marginLeft, - /** - * Nearest timestamps to snap to the brushes to - */ - snapTimestamps, - /** - * Width - */ - width, -}: DualBrushProps) { +export const DualBrush: FC = (props) => { + const { windowParameters, min, max, onChange, marginLeft, snapTimestamps, width } = props; const d3BrushContainer = useRef(null); const brushes = useRef([]); @@ -383,4 +358,4 @@ export function DualBrush({ )} ); -} +}; diff --git a/x-pack/packages/ml/aiops_components/src/dual_brush/dual_brush_annotation.tsx b/x-pack/packages/ml/aiops_components/src/dual_brush/dual_brush_annotation.tsx index f78bfc78f3cce..5970aea37f5f6 100644 --- a/x-pack/packages/ml/aiops_components/src/dual_brush/dual_brush_annotation.tsx +++ b/x-pack/packages/ml/aiops_components/src/dual_brush/dual_brush_annotation.tsx @@ -21,11 +21,12 @@ interface BrushAnnotationProps { /** * DualBrushAnnotation React Component * Dual brush annotation component that overlays the document count chart - * @type {FC} - * @param props - `BrushAnnotationProps` component props - * @returns {React.ReactElement} The DualBrushAnnotation component. + * + * @param props BrushAnnotationProps component props + * @returns The DualBrushAnnotation component. */ -export const DualBrushAnnotation: FC = ({ id, min, max, style }) => { +export const DualBrushAnnotation: FC = (props) => { + const { id, min, max, style } = props; const { euiTheme } = useEuiTheme(); const { colors } = euiTheme; 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 fb0dc0d2713a9..4a2e38a4f3acf 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 @@ -44,38 +44,25 @@ interface ProgressControlProps { /** * ProgressControls React Component * Component with ability to Run & cancel analysis - * by default use `Baseline` and `Deviation` for the badge name - * @type {FC} - * @param children - List of Kibana services that are required as dependencies - * @param brushSelectionUpdateHandler - Optional callback function which gets called when the brush selection has changed - * @param width - Optional width - * @param chartPoints - Data chart points - * @param chartPointsSplit - Data chart points split - * @param timeRangeEarliest - Start time range for the chart - * @param timeRangeLatest - Ending time range for the chart - * @param interval - Time interval for the document count buckets - * @param chartPointsSplitLabel - Label to name the adjustedChartPointsSplit histogram - * @param isBrushCleared - Whether or not brush has been reset - * @param autoAnalysisStart - Timestamp for start of initial analysis - * @param barColorOverride - Optional color override for the default bar color for charts - * @param barStyleAccessor - Optional style to override bar chart - * @param barHighlightColorOverride - Optional color override for the highlighted bar color for charts - * @param deviationBrush - Optional settings override for the 'deviation' brush - * @param baselineBrush - Optional settings override for the 'baseline' brush - * @returns {React.ReactElement} The ProgressControls component. + * by default uses `Baseline` and `Deviation` for the badge name + * + * @param props ProgressControls component props + * @returns The ProgressControls component. */ -export const ProgressControls: FC = ({ - children, - isBrushCleared, - progress, - progressMessage, - onRefresh, - onCancel, - onReset, - isRunning, - shouldRerunAnalysis, - runAnalysisDisabled = false, -}) => { +export const ProgressControls: FC = (props) => { + const { + children, + isBrushCleared, + progress, + progressMessage, + onRefresh, + onCancel, + onReset, + isRunning, + shouldRerunAnalysis, + runAnalysisDisabled = false, + } = props; + const { euiTheme } = useEuiTheme(); const runningProgressBarStyles = useAnimatedProgressBarBackground(euiTheme.colors.success); const analysisCompleteStyle = { display: 'none' }; From 226af34415209cf308a11a2f4d10d462afebedb3 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 3 Aug 2023 22:15:13 +0200 Subject: [PATCH 08/16] linting scripts --- x-pack/packages/ml/aiops_utils/tsconfig.json | 1 + x-pack/test/tsconfig.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/packages/ml/aiops_utils/tsconfig.json b/x-pack/packages/ml/aiops_utils/tsconfig.json index 806b5b07e847e..ed22df919879e 100644 --- a/x-pack/packages/ml/aiops_utils/tsconfig.json +++ b/x-pack/packages/ml/aiops_utils/tsconfig.json @@ -15,6 +15,7 @@ ], "kbn_references": [ "@kbn/ml-is-populated-object", + "@kbn/aiops-components", ], "exclude": [ "target/**/*", diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index f5f0fb6bc31f8..437ff50201b88 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -137,6 +137,7 @@ "@kbn/uptime-plugin", "@kbn/ml-category-validator", "@kbn/observability-ai-assistant-plugin", - "@kbn/stack-connectors-plugin" + "@kbn/stack-connectors-plugin", + "@kbn/aiops-utils" ] } From 2223676d7c909a8ba3e9c37c8d204690b14386c3 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 3 Aug 2023 22:34:34 +0200 Subject: [PATCH 09/16] fix circular dependency --- x-pack/packages/ml/aiops_components/index.ts | 2 +- .../document_count_chart.tsx | 19 +++------------- .../src/document_count_chart/index.ts | 6 +---- x-pack/packages/ml/aiops_utils/index.ts | 1 + .../src/log_rate_analysis_type.test.ts | 12 +++++----- .../aiops_utils/src/log_rate_analysis_type.ts | 22 ++++++++++++++----- x-pack/packages/ml/aiops_utils/tsconfig.json | 1 - .../document_count_content.tsx | 8 +++---- .../document_count_chart.tsx | 9 +++----- .../document_count_chart/index.ts | 1 - .../document_count_content.tsx | 4 ++-- .../document_count_with_dual_brush.tsx | 8 +++---- 12 files changed, 41 insertions(+), 52 deletions(-) diff --git a/x-pack/packages/ml/aiops_components/index.ts b/x-pack/packages/ml/aiops_components/index.ts index 5cd95f003b515..5968a19a813c9 100644 --- a/x-pack/packages/ml/aiops_components/index.ts +++ b/x-pack/packages/ml/aiops_components/index.ts @@ -8,4 +8,4 @@ export { DualBrush, DualBrushAnnotation } from './src/dual_brush'; export { ProgressControls } from './src/progress_controls'; export { DocumentCountChart, type BrushSettings } from './src/document_count_chart'; -export type { DocumentCountChartPoint, DocumentCountChartProps } from './src/document_count_chart'; +export type { DocumentCountChartProps } from './src/document_count_chart'; diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx index 5f9e4efcb07c7..c52db9c95ffcf 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx @@ -32,6 +32,7 @@ import { getSnappedWindowParameters, getWindowParameters, type LogRateAnalysisType, + type LogRateHistogramItem, type WindowParameters, } from '@kbn/aiops-utils'; import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; @@ -56,20 +57,6 @@ interface TimeFilterRange { to: number; } -/** - * Datum for the bar chart - */ -export interface DocumentCountChartPoint { - /** - * Time of bucket - */ - time: number | string; - /** - * Number of doc count for that time bucket - */ - value: number; -} - /** * Brush settings */ @@ -114,9 +101,9 @@ export interface DocumentCountChartProps { /** Optional width */ width?: number; /** Data chart points */ - chartPoints: DocumentCountChartPoint[]; + chartPoints: LogRateHistogramItem[]; /** Data chart points split */ - chartPointsSplit?: DocumentCountChartPoint[]; + chartPointsSplit?: LogRateHistogramItem[]; /** Start time range for the chart */ timeRangeEarliest: number; /** Ending time range for the chart */ diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts b/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts index 0bb6cb37fd54b..bc5e1f165580d 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts @@ -6,8 +6,4 @@ */ export { DocumentCountChart } from './document_count_chart'; -export type { - BrushSettings, - DocumentCountChartPoint, - DocumentCountChartProps, -} from './document_count_chart'; +export type { BrushSettings, DocumentCountChartProps } from './document_count_chart'; diff --git a/x-pack/packages/ml/aiops_utils/index.ts b/x-pack/packages/ml/aiops_utils/index.ts index 9d63b0587c1c1..75c6e64f43636 100644 --- a/x-pack/packages/ml/aiops_utils/index.ts +++ b/x-pack/packages/ml/aiops_utils/index.ts @@ -14,4 +14,5 @@ export { getLogRateAnalysisType, LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType, + type LogRateHistogramItem, } from './src/log_rate_analysis_type'; diff --git a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts index cb22663e35c35..f0b6bdd73aaaf 100644 --- a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts +++ b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts @@ -5,12 +5,10 @@ * 2.0. */ -import type { DocumentCountChartPoint } from '@kbn/aiops-components'; - -import { getLogRateAnalysisType } from './log_rate_analysis_type'; +import { getLogRateAnalysisType, type LogRateHistogramItem } from './log_rate_analysis_type'; describe('getLogRateAnalysisType', () => { - const documentCountChartPointsMock: DocumentCountChartPoint[] = [ + const LogRateHistogramMock: LogRateHistogramItem[] = [ { time: 0, value: 10 }, { time: 1, value: 10 }, { time: 2, value: 10 }, @@ -25,7 +23,7 @@ describe('getLogRateAnalysisType', () => { test('returns "spike" for the given parameters', () => { expect( - getLogRateAnalysisType(documentCountChartPointsMock, { + getLogRateAnalysisType(LogRateHistogramMock, { baselineMin: 4, baselineMax: 6, deviationMin: 7, @@ -36,7 +34,7 @@ describe('getLogRateAnalysisType', () => { test('returns "dip" for the given parameters', () => { expect( - getLogRateAnalysisType(documentCountChartPointsMock, { + getLogRateAnalysisType(LogRateHistogramMock, { baselineMin: 0, baselineMax: 2, deviationMin: 3, @@ -47,7 +45,7 @@ describe('getLogRateAnalysisType', () => { test('falls back to "spike" if both time range have the same median', () => { expect( - getLogRateAnalysisType(documentCountChartPointsMock, { + getLogRateAnalysisType(LogRateHistogramMock, { baselineMin: 0, baselineMax: 2, deviationMin: 4, diff --git a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts index 572556fdb1bbc..c36e1a536e6aa 100644 --- a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts +++ b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts @@ -7,8 +7,6 @@ import { median } from 'd3-array'; -import type { DocumentCountChartPoint } from '@kbn/aiops-components'; - import type { WindowParameters } from './window_parameters'; /** @@ -26,6 +24,20 @@ export const LOG_RATE_ANALYSIS_TYPE = { export type LogRateAnalysisType = typeof LOG_RATE_ANALYSIS_TYPE[keyof typeof LOG_RATE_ANALYSIS_TYPE]; +/** + * Log rate histogram item + */ +export interface LogRateHistogramItem { + /** + * Time of bucket + */ + time: number | string; + /** + * Number of doc count for that time bucket + */ + value: number; +} + /** * Identify the log rate analysis type based on the baseline/deviation * time ranges on a given log rate histogram. @@ -35,15 +47,15 @@ export type LogRateAnalysisType = * @returns The log rate analysis type. */ export function getLogRateAnalysisType( - documentCountChartPoints: DocumentCountChartPoint[], + logRateHistogram: LogRateHistogramItem[], { baselineMin, baselineMax, deviationMin, deviationMax }: WindowParameters ): LogRateAnalysisType { - const baselineItems = documentCountChartPoints.filter( + const baselineItems = logRateHistogram.filter( (d) => d.time >= baselineMin && d.time < baselineMax ); const baselineMedian = median(baselineItems.map((d) => d.value)) ?? 0; - const deviationItems = documentCountChartPoints.filter( + const deviationItems = logRateHistogram.filter( (d) => d.time >= deviationMin && d.time < deviationMax ); const deviationMedian = median(deviationItems.map((d) => d.value)) ?? 0; diff --git a/x-pack/packages/ml/aiops_utils/tsconfig.json b/x-pack/packages/ml/aiops_utils/tsconfig.json index ed22df919879e..806b5b07e847e 100644 --- a/x-pack/packages/ml/aiops_utils/tsconfig.json +++ b/x-pack/packages/ml/aiops_utils/tsconfig.json @@ -15,7 +15,6 @@ ], "kbn_references": [ "@kbn/ml-is-populated-object", - "@kbn/aiops-components", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx index 228b278a2cc14..8a34a59dfa1e2 100644 --- a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx +++ b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx @@ -13,8 +13,8 @@ import { RectAnnotationSpec, } from '@elastic/charts/dist/chart_types/xy_chart/utils/specs'; -import type { LogRateAnalysisType, WindowParameters } from '@kbn/aiops-utils'; -import { DocumentCountChart, type DocumentCountChartPoint } from '@kbn/aiops-components'; +import type { LogRateAnalysisType, LogRateHistogramItem, WindowParameters } from '@kbn/aiops-utils'; +import { DocumentCountChart } from '@kbn/aiops-components'; import { useAiopsAppContext } from '../../../hooks/use_aiops_app_context'; import { DocumentCountStats } from '../../../get_document_stats'; @@ -82,14 +82,14 @@ export const DocumentCountContent: FC = ({ ) : null; } - const chartPoints: DocumentCountChartPoint[] = Object.entries(documentCountStats.buckets).map( + const chartPoints: LogRateHistogramItem[] = Object.entries(documentCountStats.buckets).map( ([time, value]) => ({ time: +time, value, }) ); - let chartPointsSplit: DocumentCountChartPoint[] | undefined; + let chartPointsSplit: LogRateHistogramItem[] | undefined; if (documentCountStatsSplit?.buckets !== undefined) { chartPointsSplit = Object.entries(documentCountStatsSplit?.buckets).map(([time, value]) => ({ time: +time, diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/document_count_chart.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/document_count_chart.tsx index 9e71561f051a3..31e18d155b72d 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/document_count_chart.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/document_count_chart.tsx @@ -22,17 +22,14 @@ import { import moment from 'moment'; import { IUiSettingsClient } from '@kbn/core/public'; import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; +import type { LogRateHistogramItem } from '@kbn/aiops-utils'; + import { EuiFlexGroup, EuiLoadingSpinner, EuiFlexItem } from '@elastic/eui'; import { useDataVisualizerKibana } from '../../../../kibana_context'; -export interface DocumentCountChartPoint { - time: number | string; - value: number; -} - interface Props { width?: number; - chartPoints: DocumentCountChartPoint[]; + chartPoints: LogRateHistogramItem[]; timeRangeEarliest: number; timeRangeLatest: number; interval?: number; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/index.ts b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/index.ts index 1b69f9b825165..870cb010d2038 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/index.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_chart/index.ts @@ -5,5 +5,4 @@ * 2.0. */ -export type { DocumentCountChartPoint } from './document_count_chart'; export { DocumentCountChart } from './document_count_chart'; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx index 911a6ba9ea731..3d1268140df17 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { DocumentCountChartPoint } from './document_count_chart'; +import type { LogRateHistogramItem } from '@kbn/aiops-utils'; import { RandomSamplerOption, RANDOM_SAMPLER_SELECT_OPTIONS, @@ -108,7 +108,7 @@ export const DocumentCountContent: FC = ({ if (timeRangeEarliest === undefined || timeRangeLatest === undefined) return ; - let chartPoints: DocumentCountChartPoint[] = []; + let chartPoints: LogRateHistogramItem[] = []; if (documentCountStats.buckets !== undefined) { const buckets: Record = documentCountStats?.buckets; chartPoints = Object.entries(buckets).map(([time, value]) => ({ time: +time, value })); diff --git a/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx b/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx index 47da063329d03..744b18fbc6d4c 100644 --- a/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx +++ b/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx @@ -5,9 +5,9 @@ * 2.0. */ -import { WindowParameters } from '@kbn/aiops-utils'; +import type { WindowParameters, LogRateHistogramItem } from '@kbn/aiops-utils'; import React, { FC } from 'react'; -import { DocumentCountChart, type DocumentCountChartPoint } from '@kbn/aiops-components'; +import { DocumentCountChart } from '@kbn/aiops-components'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import type { DocumentCountChartProps } from '@kbn/aiops-components'; import { RandomSampler } from '@kbn/ml-random-sampler-utils'; @@ -83,14 +83,14 @@ export const DocumentCountWithDualBrush: FC = ({ return totalCount !== undefined ? : null; } - const chartPoints: DocumentCountChartPoint[] = Object.entries(documentCountStats.buckets).map( + const chartPoints: LogRateHistogramItem[] = Object.entries(documentCountStats.buckets).map( ([time, value]) => ({ time: +time, value, }) ); - let chartPointsSplit: DocumentCountChartPoint[] | undefined; + let chartPointsSplit: LogRateHistogramItem[] | undefined; if (documentCountStatsSplit?.buckets !== undefined) { chartPointsSplit = Object.entries(documentCountStatsSplit?.buckets).map(([time, value]) => ({ time: +time, From 71aa5d01061d071f2220b71fe909e15abd1251bd Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Fri, 4 Aug 2023 13:37:28 +0200 Subject: [PATCH 10/16] fix jsdoc --- x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts index c36e1a536e6aa..a1f2203ad1a21 100644 --- a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts +++ b/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts @@ -42,14 +42,15 @@ export interface LogRateHistogramItem { * Identify the log rate analysis type based on the baseline/deviation * time ranges on a given log rate histogram. * - * @param documentCountChartPoints The log rate histogram. + * @param logRateHistogram The log rate histogram. * @param windowParameters The window parameters with baseline and deviation time range. * @returns The log rate analysis type. */ export function getLogRateAnalysisType( logRateHistogram: LogRateHistogramItem[], - { baselineMin, baselineMax, deviationMin, deviationMax }: WindowParameters + windowParameters: WindowParameters ): LogRateAnalysisType { + const { baselineMin, baselineMax, deviationMin, deviationMax } = windowParameters; const baselineItems = logRateHistogram.filter( (d) => d.time >= baselineMin && d.time < baselineMax ); From eaa2330d908d7db1e6b88fbd2c29742d460ebe5a Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Fri, 4 Aug 2023 13:42:28 +0200 Subject: [PATCH 11/16] switch to deep import --- x-pack/packages/ml/aiops_utils/index.ts | 4 ++-- .../ml/aiops_utils/{src => }/log_rate_analysis_type.test.ts | 0 .../ml/aiops_utils/{src => }/log_rate_analysis_type.ts | 0 .../packages/ml/aiops_utils/{src => }/window_parameters.ts | 0 .../components/log_rate_analysis.tsx | 5 ++++- 5 files changed, 6 insertions(+), 3 deletions(-) rename x-pack/packages/ml/aiops_utils/{src => }/log_rate_analysis_type.test.ts (100%) rename x-pack/packages/ml/aiops_utils/{src => }/log_rate_analysis_type.ts (100%) rename x-pack/packages/ml/aiops_utils/{src => }/window_parameters.ts (100%) diff --git a/x-pack/packages/ml/aiops_utils/index.ts b/x-pack/packages/ml/aiops_utils/index.ts index 75c6e64f43636..53acf06857c29 100644 --- a/x-pack/packages/ml/aiops_utils/index.ts +++ b/x-pack/packages/ml/aiops_utils/index.ts @@ -9,10 +9,10 @@ export { getSnappedWindowParameters, getWindowParameters, type WindowParameters, -} from './src/window_parameters'; +} from './window_parameters'; export { getLogRateAnalysisType, LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType, type LogRateHistogramItem, -} from './src/log_rate_analysis_type'; +} from './log_rate_analysis_type'; diff --git a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts b/x-pack/packages/ml/aiops_utils/log_rate_analysis_type.test.ts similarity index 100% rename from x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.test.ts rename to x-pack/packages/ml/aiops_utils/log_rate_analysis_type.test.ts diff --git a/x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts b/x-pack/packages/ml/aiops_utils/log_rate_analysis_type.ts similarity index 100% rename from x-pack/packages/ml/aiops_utils/src/log_rate_analysis_type.ts rename to x-pack/packages/ml/aiops_utils/log_rate_analysis_type.ts diff --git a/x-pack/packages/ml/aiops_utils/src/window_parameters.ts b/x-pack/packages/ml/aiops_utils/window_parameters.ts similarity index 100% rename from x-pack/packages/ml/aiops_utils/src/window_parameters.ts rename to x-pack/packages/ml/aiops_utils/window_parameters.ts diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx index 35c029f41ee35..2cb58b2be08bb 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx @@ -13,7 +13,10 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DataView } from '@kbn/data-views-plugin/common'; -import { LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType } from '@kbn/aiops-utils'; +import { + LOG_RATE_ANALYSIS_TYPE, + type LogRateAnalysisType, +} from '@kbn/aiops-utils/log_rate_analysis_type'; import { LogRateAnalysisContent, type LogRateAnalysisResultsData } from '@kbn/aiops-plugin/public'; import { Rule } from '@kbn/alerting-plugin/common'; import { TopAlert } from '@kbn/observability-plugin/public'; From 543661acbf80a4c757498f24928476add73751f8 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Fri, 4 Aug 2023 15:00:09 +0200 Subject: [PATCH 12/16] more granular code org to avoid bundle bloat --- ....ts => get_log_rate_analysis_type.test.ts} | 3 +- .../aiops_utils/get_log_rate_analysis_type.ts | 40 ++++++++++++++++ x-pack/packages/ml/aiops_utils/index.ts | 9 ++-- .../ml/aiops_utils/log_rate_analysis_type.ts | 46 ------------------- .../ml/aiops_utils/log_rate_histogram_item.ts | 20 ++++++++ 5 files changed, 65 insertions(+), 53 deletions(-) rename x-pack/packages/ml/aiops_utils/{log_rate_analysis_type.test.ts => get_log_rate_analysis_type.test.ts} (91%) create mode 100644 x-pack/packages/ml/aiops_utils/get_log_rate_analysis_type.ts create mode 100644 x-pack/packages/ml/aiops_utils/log_rate_histogram_item.ts diff --git a/x-pack/packages/ml/aiops_utils/log_rate_analysis_type.test.ts b/x-pack/packages/ml/aiops_utils/get_log_rate_analysis_type.test.ts similarity index 91% rename from x-pack/packages/ml/aiops_utils/log_rate_analysis_type.test.ts rename to x-pack/packages/ml/aiops_utils/get_log_rate_analysis_type.test.ts index f0b6bdd73aaaf..84f9275128552 100644 --- a/x-pack/packages/ml/aiops_utils/log_rate_analysis_type.test.ts +++ b/x-pack/packages/ml/aiops_utils/get_log_rate_analysis_type.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { getLogRateAnalysisType, type LogRateHistogramItem } from './log_rate_analysis_type'; +import type { LogRateHistogramItem } from './log_rate_histogram_item'; +import { getLogRateAnalysisType } from './get_log_rate_analysis_type'; describe('getLogRateAnalysisType', () => { const LogRateHistogramMock: LogRateHistogramItem[] = [ diff --git a/x-pack/packages/ml/aiops_utils/get_log_rate_analysis_type.ts b/x-pack/packages/ml/aiops_utils/get_log_rate_analysis_type.ts new file mode 100644 index 0000000000000..0303d903da05b --- /dev/null +++ b/x-pack/packages/ml/aiops_utils/get_log_rate_analysis_type.ts @@ -0,0 +1,40 @@ +/* + * 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 { median } from 'd3-array'; + +import { LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType } from './log_rate_analysis_type'; +import type { LogRateHistogramItem } from './log_rate_histogram_item'; +import type { WindowParameters } from './window_parameters'; + +/** + * Identify the log rate analysis type based on the baseline/deviation + * time ranges on a given log rate histogram. + * + * @param logRateHistogram The log rate histogram. + * @param windowParameters The window parameters with baseline and deviation time range. + * @returns The log rate analysis type. + */ +export function getLogRateAnalysisType( + logRateHistogram: LogRateHistogramItem[], + windowParameters: WindowParameters +): LogRateAnalysisType { + const { baselineMin, baselineMax, deviationMin, deviationMax } = windowParameters; + const baselineItems = logRateHistogram.filter( + (d) => d.time >= baselineMin && d.time < baselineMax + ); + const baselineMedian = median(baselineItems.map((d) => d.value)) ?? 0; + + const deviationItems = logRateHistogram.filter( + (d) => d.time >= deviationMin && d.time < deviationMax + ); + const deviationMedian = median(deviationItems.map((d) => d.value)) ?? 0; + + return deviationMedian >= baselineMedian + ? LOG_RATE_ANALYSIS_TYPE.SPIKE + : LOG_RATE_ANALYSIS_TYPE.DIP; +} diff --git a/x-pack/packages/ml/aiops_utils/index.ts b/x-pack/packages/ml/aiops_utils/index.ts index 53acf06857c29..6d22ce5849ec6 100644 --- a/x-pack/packages/ml/aiops_utils/index.ts +++ b/x-pack/packages/ml/aiops_utils/index.ts @@ -5,14 +5,11 @@ * 2.0. */ +export { getLogRateAnalysisType } from './get_log_rate_analysis_type'; +export { LOG_RATE_ANALYSIS_TYPE, type LogRateAnalysisType } from './log_rate_analysis_type'; +export { type LogRateHistogramItem } from './log_rate_histogram_item'; export { getSnappedWindowParameters, getWindowParameters, type WindowParameters, } from './window_parameters'; -export { - getLogRateAnalysisType, - LOG_RATE_ANALYSIS_TYPE, - type LogRateAnalysisType, - type LogRateHistogramItem, -} from './log_rate_analysis_type'; diff --git a/x-pack/packages/ml/aiops_utils/log_rate_analysis_type.ts b/x-pack/packages/ml/aiops_utils/log_rate_analysis_type.ts index a1f2203ad1a21..ba8f370029782 100644 --- a/x-pack/packages/ml/aiops_utils/log_rate_analysis_type.ts +++ b/x-pack/packages/ml/aiops_utils/log_rate_analysis_type.ts @@ -5,10 +5,6 @@ * 2.0. */ -import { median } from 'd3-array'; - -import type { WindowParameters } from './window_parameters'; - /** * The type of log rate analysis (spike or dip) will affect how parameters are * passed to the analysis API endpoint. @@ -23,45 +19,3 @@ export const LOG_RATE_ANALYSIS_TYPE = { */ export type LogRateAnalysisType = typeof LOG_RATE_ANALYSIS_TYPE[keyof typeof LOG_RATE_ANALYSIS_TYPE]; - -/** - * Log rate histogram item - */ -export interface LogRateHistogramItem { - /** - * Time of bucket - */ - time: number | string; - /** - * Number of doc count for that time bucket - */ - value: number; -} - -/** - * Identify the log rate analysis type based on the baseline/deviation - * time ranges on a given log rate histogram. - * - * @param logRateHistogram The log rate histogram. - * @param windowParameters The window parameters with baseline and deviation time range. - * @returns The log rate analysis type. - */ -export function getLogRateAnalysisType( - logRateHistogram: LogRateHistogramItem[], - windowParameters: WindowParameters -): LogRateAnalysisType { - const { baselineMin, baselineMax, deviationMin, deviationMax } = windowParameters; - const baselineItems = logRateHistogram.filter( - (d) => d.time >= baselineMin && d.time < baselineMax - ); - const baselineMedian = median(baselineItems.map((d) => d.value)) ?? 0; - - const deviationItems = logRateHistogram.filter( - (d) => d.time >= deviationMin && d.time < deviationMax - ); - const deviationMedian = median(deviationItems.map((d) => d.value)) ?? 0; - - return deviationMedian >= baselineMedian - ? LOG_RATE_ANALYSIS_TYPE.SPIKE - : LOG_RATE_ANALYSIS_TYPE.DIP; -} diff --git a/x-pack/packages/ml/aiops_utils/log_rate_histogram_item.ts b/x-pack/packages/ml/aiops_utils/log_rate_histogram_item.ts new file mode 100644 index 0000000000000..86368346ddde0 --- /dev/null +++ b/x-pack/packages/ml/aiops_utils/log_rate_histogram_item.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/** + * Log rate histogram item + */ +export interface LogRateHistogramItem { + /** + * Time of bucket + */ + time: number | string; + /** + * Number of doc count for that time bucket + */ + value: number; +} From 4e314f7e2e62f6a84bb6ace5b5d45d51356003d9 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Fri, 4 Aug 2023 15:58:05 +0200 Subject: [PATCH 13/16] update ai assistant prompt for spike/dip --- .../components/log_rate_analysis.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx index 2cb58b2be08bb..d17103ce7b0ac 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx @@ -206,6 +206,12 @@ export const LogRateAnalysis: FC = ({ r : 'are less or not present in the log rate dip' }: + ${ + logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE + ? 'The median log rate in the selected deviation time range is higher than the baseline. Therefore, the results shows statistically significant items within the deviation time range that are contributors to the spike. The "doc count" column refers to the amount of documents in the deviation time range.' + : 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less present or missing within the deviation time range. The "doc count" column refers to the amount of documents in the baseline time range.' + } + ${header} ${rows} @@ -214,14 +220,15 @@ export const LogRateAnalysis: FC = ({ r ${ logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? 'Based on the type of these logs do a root cause analysis on why the field and value combinations from the analysis results are causing this log rate spike (2 parapraphs)' - : 'Based on the type of these logs do a concise analysis why the statistically significant field and value combinations are less present or missing from the log rate dip with concrete examples based on the analysis results data. Do not guess, just output what you are sure of (2 paragraphs)' + : 'Based on the type of these logs explain why the statistically significant field and value combinations are less present or missing from the log rate dip with concrete examples based on the analysis results data which contains items that are present in the baseline time range and are missing or less present in the deviation time range (2 paragraphs)' }. ${ logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? 'Recommend concrete remediations to resolve the root cause (3 bullet points).' : '' } - Do not repeat the given instructions in your output.`; + + Do not mention indidivual p-values from the analysis results. Do not guess, just say what you are sure of. Do not repeat the given instructions in your output.`; const now = new Date().toString(); From f6380024d41f2aa9bf41c89b0199d3a031936959 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 7 Aug 2023 20:37:25 +0200 Subject: [PATCH 14/16] BrushSelectionUpdateHandler --- x-pack/packages/ml/aiops_components/index.ts | 6 +++- .../document_count_chart.tsx | 30 +++++++++++-------- .../src/document_count_chart/index.ts | 6 +++- .../document_count_content.tsx | 10 ++----- .../document_count_with_dual_brush.tsx | 4 +-- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/x-pack/packages/ml/aiops_components/index.ts b/x-pack/packages/ml/aiops_components/index.ts index 5968a19a813c9..c9ca50ad0daff 100644 --- a/x-pack/packages/ml/aiops_components/index.ts +++ b/x-pack/packages/ml/aiops_components/index.ts @@ -7,5 +7,9 @@ export { DualBrush, DualBrushAnnotation } from './src/dual_brush'; export { ProgressControls } from './src/progress_controls'; -export { DocumentCountChart, type BrushSettings } from './src/document_count_chart'; +export { + DocumentCountChart, + type BrushSettings, + type BrushSelectionUpdateHandler, +} from './src/document_count_chart'; export type { DocumentCountChartProps } from './src/document_count_chart'; diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx index c52db9c95ffcf..967821db0e0db 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx @@ -36,11 +36,12 @@ import { type WindowParameters, } from '@kbn/aiops-utils'; import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; - import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; + import { DualBrush, DualBrushAnnotation } from '../..'; + import { BrushBadge } from './brush_badge'; declare global { @@ -75,6 +76,19 @@ export interface BrushSettings { badgeWidth?: number; } +/** + * Callback function which gets called when the brush selection has changed + * + * @param windowParameters Baseline and deviation time ranges. + * @param force Force update + * @param logRateAnalysisType `spike` or `dip` based on median log rate bucket size + */ +export type BrushSelectionUpdateHandler = ( + windowParameters: WindowParameters, + force: boolean, + logRateAnalysisType: LogRateAnalysisType +) => void; + /** * Props for document count chart */ @@ -86,18 +100,8 @@ export interface DocumentCountChartProps { fieldFormats: FieldFormatsStart; uiSettings: IUiSettingsClient; }; - /** - * Optional callback function which gets called the brush selection has changed - * - * @param windowParameters Baseline and deviation time ranges. - * @param force Force update - * @param logRateAnalysisType `spike` or `dip` based on median log rate bucket size - */ - brushSelectionUpdateHandler?: ( - windowParameters: WindowParameters, - force: boolean, - logRateAnalysisType: LogRateAnalysisType - ) => void; + /** Optional callback for handling brush selection updates */ + brushSelectionUpdateHandler?: BrushSelectionUpdateHandler; /** Optional width */ width?: number; /** Data chart points */ diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts b/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts index bc5e1f165580d..5b64acedbf5f6 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/index.ts @@ -6,4 +6,8 @@ */ export { DocumentCountChart } from './document_count_chart'; -export type { BrushSettings, DocumentCountChartProps } from './document_count_chart'; +export type { + BrushSelectionUpdateHandler, + BrushSettings, + DocumentCountChartProps, +} from './document_count_chart'; diff --git a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx index 8a34a59dfa1e2..23149aeb7c58d 100644 --- a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx +++ b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx @@ -13,8 +13,8 @@ import { RectAnnotationSpec, } from '@elastic/charts/dist/chart_types/xy_chart/utils/specs'; -import type { LogRateAnalysisType, LogRateHistogramItem, WindowParameters } from '@kbn/aiops-utils'; -import { DocumentCountChart } from '@kbn/aiops-components'; +import type { LogRateHistogramItem, WindowParameters } from '@kbn/aiops-utils'; +import { DocumentCountChart, type BrushSelectionUpdateHandler } from '@kbn/aiops-components'; import { useAiopsAppContext } from '../../../hooks/use_aiops_app_context'; import { DocumentCountStats } from '../../../get_document_stats'; @@ -22,11 +22,7 @@ import { DocumentCountStats } from '../../../get_document_stats'; import { TotalCountHeader } from '../total_count_header'; export interface DocumentCountContentProps { - brushSelectionUpdateHandler: ( - windowParameters: WindowParameters, - force: boolean, - logRateAnalysisType: LogRateAnalysisType - ) => void; + brushSelectionUpdateHandler: BrushSelectionUpdateHandler; documentCountStats?: DocumentCountStats; documentCountStatsSplit?: DocumentCountStats; documentCountStatsSplitLabel?: string; diff --git a/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx b/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx index 744b18fbc6d4c..159a1a52597ca 100644 --- a/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx +++ b/x-pack/plugins/data_visualizer/public/application/data_comparison/document_count_with_dual_brush.tsx @@ -9,7 +9,7 @@ import type { WindowParameters, LogRateHistogramItem } from '@kbn/aiops-utils'; import React, { FC } from 'react'; import { DocumentCountChart } from '@kbn/aiops-components'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import type { DocumentCountChartProps } from '@kbn/aiops-components'; +import type { BrushSelectionUpdateHandler, DocumentCountChartProps } from '@kbn/aiops-components'; import { RandomSampler } from '@kbn/ml-random-sampler-utils'; import { useDataVisualizerKibana } from '../kibana_context'; import { DocumentCountStats } from '../../../common/types/field_stats'; @@ -26,7 +26,7 @@ export interface DocumentCountContentProps | 'interval' | 'chartPointsSplitLabel' > { - brushSelectionUpdateHandler: (windowParameters: WindowParameters, force: boolean) => void; + brushSelectionUpdateHandler: BrushSelectionUpdateHandler; documentCountStats?: DocumentCountStats; documentCountStatsSplit?: DocumentCountStats; documentCountStatsSplitLabel?: string; From 4f8c71ac387ff36f80bc9b758acd74f45ee37cf9 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 7 Aug 2023 20:38:06 +0200 Subject: [PATCH 15/16] text tweaks --- .../log_rate_analysis/log_rate_analysis_results.tsx | 4 ++-- .../components/log_rate_analysis.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_results.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_results.tsx index f7b70ea6adfc9..f1b1a6d38de12 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_results.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis/log_rate_analysis_results.tsx @@ -373,11 +373,11 @@ export const LogRateAnalysisResults: FC = ({ {currentAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? i18n.translate('xpack.aiops.analysis.analysisTypeSpikeCallOutContent', { defaultMessage: - 'The median log rate in the selected deviation time range is higher than the baseline. Therefore, the results shows statistically significant items within the deviation time range that are contributors to the spike. The "doc count" column refers to the amount of documents in the deviation time range.', + 'The median log rate in the selected deviation time range is higher than the baseline. Therefore, the analysis results table shows statistically significant items within the deviation time range that are contributors to the spike. The "doc count" column refers to the amount of documents in the deviation time range.', }) : i18n.translate('xpack.aiops.analysis.analysisTypeDipCallOutContent', { defaultMessage: - 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less present or missing within the deviation time range. The "doc count" column refers to the amount of documents in the baseline time range.', + 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less in number or missing within the deviation time range. The "doc count" column refers to the amount of documents in the baseline time range.', })} diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx index d17103ce7b0ac..be1a753edb5fa 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/alert_details_app_section/components/log_rate_analysis.tsx @@ -209,7 +209,7 @@ export const LogRateAnalysis: FC = ({ r ${ logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? 'The median log rate in the selected deviation time range is higher than the baseline. Therefore, the results shows statistically significant items within the deviation time range that are contributors to the spike. The "doc count" column refers to the amount of documents in the deviation time range.' - : 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less present or missing within the deviation time range. The "doc count" column refers to the amount of documents in the baseline time range.' + : 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less in number or missing within the deviation time range. The "doc count" column refers to the amount of documents in the baseline time range.' } ${header} @@ -220,7 +220,7 @@ export const LogRateAnalysis: FC = ({ r ${ logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE ? 'Based on the type of these logs do a root cause analysis on why the field and value combinations from the analysis results are causing this log rate spike (2 parapraphs)' - : 'Based on the type of these logs explain why the statistically significant field and value combinations are less present or missing from the log rate dip with concrete examples based on the analysis results data which contains items that are present in the baseline time range and are missing or less present in the deviation time range (2 paragraphs)' + : 'Based on the type of these logs explain why the statistically significant field and value combinations are less in number or missing from the log rate dip with concrete examples based on the analysis results data which contains items that are present in the baseline time range and are missing or less in number in the deviation time range (2 paragraphs)' }. ${ logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE From f289fc846aeca31765ba0a5d038c525c5d4444d4 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 8 Aug 2023 15:31:52 +0200 Subject: [PATCH 16/16] fix timestamp creation for artificial datasets --- .../services/aiops/log_rate_analysis_data_generator.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts b/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts index e87c49ac16941..a628c730fdf76 100644 --- a/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts +++ b/x-pack/test/functional/services/aiops/log_rate_analysis_data_generator.ts @@ -46,7 +46,7 @@ function getArtificialLogsWithDeviation(index: string, deviationType: string) { ) { tsOffset = 0; [...Array(100)].forEach(() => { - tsOffset += DAY_MS / 100; + tsOffset += Math.round(DAY_MS / 100); const doc: GeneratedDoc = { user, response_code: responseCode, @@ -76,7 +76,7 @@ function getArtificialLogsWithDeviation(index: string, deviationType: string) { ['login.php', 'user.php', 'home.php'].forEach((url) => { tsOffset = 0; [...Array(docsPerUrl1[url])].forEach(() => { - tsOffset += DAY_MS / docsPerUrl1[url]; + tsOffset += Math.round(DAY_MS / docsPerUrl1[url]); bulkBody.push(action); bulkBody.push({ user: 'Peter', @@ -101,7 +101,7 @@ function getArtificialLogsWithDeviation(index: string, deviationType: string) { ['login.php', 'home.php'].forEach((url) => { tsOffset = 0; [...Array(docsPerUrl2[url] + userIndex)].forEach(() => { - tsOffset += DAY_MS / docsPerUrl2[url]; + tsOffset += Math.round(DAY_MS / docsPerUrl2[url]); bulkBody.push(action); bulkBody.push({ user,