From de33e9770debfa496c0c3c0e25f024d3f0ce9552 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 19 Oct 2020 18:52:51 +0200 Subject: [PATCH 1/7] [ML] Fix race condition when loading index data. Clean up legacy outlier influence code. --- .../components/data_grid/common.ts | 11 +----- .../data_frame_analytics/common/fields.ts | 20 ++--------- .../common/get_index_data.ts | 18 +++++----- .../components/outlier_exploration/common.ts | 7 ++-- .../outlier_exploration.tsx | 9 ++--- .../outlier_exploration/use_outlier_data.ts | 36 +++++++++---------- 6 files changed, 34 insertions(+), 67 deletions(-) diff --git a/x-pack/plugins/ml/public/application/components/data_grid/common.ts b/x-pack/plugins/ml/public/application/components/data_grid/common.ts index f88694a1952b2..642d0ae564b85 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/common.ts +++ b/x-pack/plugins/ml/public/application/components/data_grid/common.ts @@ -33,7 +33,6 @@ import { import { FEATURE_IMPORTANCE, - FEATURE_INFLUENCE, OUTLIER_SCORE, TOP_CLASSES, } from '../../data_frame_analytics/common/constants'; @@ -112,10 +111,7 @@ export const getDataGridSchemasFromFieldTypes = (fieldTypes: FieldTypes, results schema = NON_AGGREGATABLE; } - if ( - field === `${resultsField}.${OUTLIER_SCORE}` || - field.includes(`${resultsField}.${FEATURE_INFLUENCE}`) - ) { + if (field === `${resultsField}.${OUTLIER_SCORE}`) { schema = 'numeric'; } @@ -203,11 +199,6 @@ export const useRenderCellValue = ( } function getCellValue(cId: string) { - if (cId.includes(`.${FEATURE_INFLUENCE}.`) && resultsField !== undefined) { - const results = getNestedProperty(tableItems[adjustedRowIndex], resultsField, null); - return results[cId.replace(`${resultsField}.`, '')]; - } - if (tableItems.hasOwnProperty(adjustedRowIndex)) { const item = tableItems[adjustedRowIndex]; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts index e4581f0a87bdd..c606cbd1cc11a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts @@ -17,7 +17,7 @@ import { import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../../../../../../src/plugins/data/public'; import { newJobCapsService } from '../../services/new_job_capabilities_service'; -import { FEATURE_IMPORTANCE, FEATURE_INFLUENCE, OUTLIER_SCORE, TOP_CLASSES } from './constants'; +import { FEATURE_IMPORTANCE, OUTLIER_SCORE, TOP_CLASSES } from './constants'; import { DataFrameAnalyticsConfig } from '../../../../common/types/data_frame_analytics'; export type EsId = string; @@ -179,7 +179,6 @@ export const getDefaultFieldsFromJobCaps = ( const resultsField = jobConfig.dest.results_field; const featureImportanceFields = []; - const featureInfluenceFields = []; const topClassesFields = []; const allFields: any = []; let type: ES_FIELD_TYPES | undefined; @@ -193,16 +192,6 @@ export const getDefaultFieldsFromJobCaps = ( name: `${resultsField}.${OUTLIER_SCORE}`, type: KBN_FIELD_TYPES.NUMBER, }); - - featureInfluenceFields.push( - ...fields - .filter((d) => !jobConfig.analyzed_fields.excludes.includes(d.id)) - .map((d) => ({ - id: `${resultsField}.${FEATURE_INFLUENCE}.${d.id}`, - name: `${resultsField}.${FEATURE_INFLUENCE}.${d.name}`, - type: KBN_FIELD_TYPES.NUMBER, - })) - ); } } @@ -247,12 +236,7 @@ export const getDefaultFieldsFromJobCaps = ( } } - allFields.push( - ...fields, - ...featureImportanceFields, - ...featureInfluenceFields, - ...topClassesFields - ); + allFields.push(...fields, ...featureImportanceFields, ...topClassesFields); allFields.sort(({ name: a }: { name: string }, { name: b }: { name: string }) => sortExplorationResultsFields(a, b, jobConfig) ); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_index_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_index_data.ts index 667dea27de96e..8e50aab0914db 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_index_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_index_data.ts @@ -19,7 +19,8 @@ import { DataFrameAnalyticsConfig } from '../../../../common/types/data_frame_an export const getIndexData = async ( jobConfig: DataFrameAnalyticsConfig | undefined, dataGrid: UseDataGridReturnType, - searchQuery: SavedSearchQuery + searchQuery: SavedSearchQuery, + options: { didCancel: boolean } ) => { if (jobConfig !== undefined) { const { @@ -52,7 +53,7 @@ export const getIndexData = async ( index: jobConfig.dest.index, body: { fields: ['*'], - _source: jobConfig.dest.results_field, + _source: [], query: searchQuery, from: pageIndex * pageSize, size: pageSize, @@ -60,14 +61,11 @@ export const getIndexData = async ( }, }); - setRowCount(resp.hits.total.value); - const docs = resp.hits.hits.map((d) => ({ - ...getProcessedFields(d.fields), - [jobConfig.dest.results_field]: d._source[jobConfig.dest.results_field], - })); - - setTableItems(docs); - setStatus(INDEX_STATUS.LOADED); + if (!options.didCancel) { + setRowCount(resp.hits.total.value); + setTableItems(resp.hits.hits.map((d) => getProcessedFields(d.fields))); + setStatus(INDEX_STATUS.LOADED); + } } catch (e) { setErrorMessage(extractErrorMessage(e)); setStatus(INDEX_STATUS.ERROR); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/common.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/common.ts index d1889a8acb990..1ce3b3528e44b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/common.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/common.ts @@ -19,11 +19,8 @@ export const getFeatureCount = (resultsField: string, tableItems: DataGridItem[] const fullItem = tableItems[0]; - if ( - fullItem[resultsField] !== undefined && - Array.isArray(fullItem[resultsField][FEATURE_INFLUENCE]) - ) { - return fullItem[resultsField][FEATURE_INFLUENCE].length; + if (Array.isArray(fullItem[`${resultsField}.${FEATURE_INFLUENCE}.feature_name`])) { + return fullItem[`${resultsField}.${FEATURE_INFLUENCE}.feature_name`].length; } return 0; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx index 8fc2486599755..fa711316df003 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx @@ -36,11 +36,8 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = const { columnsWithCharts, tableItems } = outlierData; - const colorRange = useColorRange( - COLOR_RANGE.BLUE, - COLOR_RANGE_SCALE.INFLUENCER, - jobConfig !== undefined ? getFeatureCount(jobConfig.dest.results_field, tableItems) : 1 - ); + const featureCount = getFeatureCount(jobConfig?.dest?.results_field || '', tableItems); + const colorRange = useColorRange(COLOR_RANGE.BLUE, COLOR_RANGE_SCALE.INFLUENCER, featureCount); return ( <> @@ -59,7 +56,7 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = )} {typeof jobConfig?.id === 'string' && } 0 ? colorRange : undefined} indexData={outlierData} indexPattern={indexPattern} jobConfig={jobConfig} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts index 88aa06808e8a7..148ff6b13699f 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts @@ -39,11 +39,6 @@ import { import { getFeatureCount, getOutlierScoreFieldName } from './common'; -interface FeatureInfluence { - feature_name: string; - influence: number; -} - export const useOutlierData = ( indexPattern: IndexPattern | undefined, jobConfig: DataFrameAnalyticsConfig | undefined, @@ -88,8 +83,15 @@ export const useOutlierData = ( } }, [jobConfig && jobConfig.id]); + // The pattern using `didCancel` allows us to abort out of date remote request. + // We wrap `didCancel` in a object so we can mutate the value as it's being + // passed on to `getIndexData`. useEffect(() => { - getIndexData(jobConfig, dataGrid, searchQuery); + const options = { didCancel: false }; + getIndexData(jobConfig, dataGrid, searchQuery, options); + return () => { + options.didCancel = true; + }; // custom comparison }, [jobConfig && jobConfig.id, dataGrid.pagination, searchQuery, dataGrid.sortingColumns]); @@ -151,19 +153,17 @@ export const useOutlierData = ( const split = columnId.split('.'); let backgroundColor; + const featureNames = fullItem[`${resultsField}.${FEATURE_INFLUENCE}.feature_name`]; + // column with feature values get color coded by its corresponding influencer value - if ( - fullItem[resultsField] !== undefined && - fullItem[resultsField][FEATURE_INFLUENCE] !== undefined && - fullItem[resultsField][FEATURE_INFLUENCE].find( - (d: FeatureInfluence) => d.feature_name === columnId - ) !== undefined - ) { - backgroundColor = colorRange( - fullItem[resultsField][FEATURE_INFLUENCE].find( - (d: FeatureInfluence) => d.feature_name === columnId - ).influence - ); + if (Array.isArray(featureNames)) { + const featureIndex = featureNames.indexOf(columnId); + + if (featureIndex > -1) { + backgroundColor = colorRange( + fullItem[`${resultsField}.${FEATURE_INFLUENCE}.influence`][featureIndex] + ); + } } // column with influencer values get color coded by its own value From 0785fb72d1dcc2933e94ae77a8249bd1b2274dbc Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 20 Oct 2020 11:58:04 +0200 Subject: [PATCH 2/7] [ML] Add callout for legacy feature influence data. --- .../ml/common/types/data_frame_analytics.ts | 4 +- .../plugins/ml/common/util/analytics_utils.ts | 3 ++ .../outlier_exploration.tsx | 45 +++++++++++++++++-- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/ml/common/types/data_frame_analytics.ts b/x-pack/plugins/ml/common/types/data_frame_analytics.ts index 5d0ecf96fb6b5..cbf2acd152476 100644 --- a/x-pack/plugins/ml/common/types/data_frame_analytics.ts +++ b/x-pack/plugins/ml/common/types/data_frame_analytics.ts @@ -19,7 +19,9 @@ export type DataFrameAnalyticsId = string; export interface OutlierAnalysis { [key: string]: {}; - outlier_detection: {}; + outlier_detection: { + compute_feature_influence?: boolean; + }; } interface Regression { diff --git a/x-pack/plugins/ml/common/util/analytics_utils.ts b/x-pack/plugins/ml/common/util/analytics_utils.ts index d231ed4344389..94797efdfcfad 100644 --- a/x-pack/plugins/ml/common/util/analytics_utils.ts +++ b/x-pack/plugins/ml/common/util/analytics_utils.ts @@ -13,16 +13,19 @@ import { import { ANALYSIS_CONFIG_TYPE } from '../../common/constants/data_frame_analytics'; export const isOutlierAnalysis = (arg: any): arg is OutlierAnalysis => { + if (typeof arg !== 'object' || arg === null) return false; const keys = Object.keys(arg); return keys.length === 1 && keys[0] === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION; }; export const isRegressionAnalysis = (arg: any): arg is RegressionAnalysis => { + if (typeof arg !== 'object' || arg === null) return false; const keys = Object.keys(arg); return keys.length === 1 && keys[0] === ANALYSIS_CONFIG_TYPE.REGRESSION; }; export const isClassificationAnalysis = (arg: any): arg is ClassificationAnalysis => { + if (typeof arg !== 'object' || arg === null) return false; const keys = Object.keys(arg); return keys.length === 1 && keys[0] === ANALYSIS_CONFIG_TYPE.CLASSIFICATION; }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx index fa711316df003..734b5170d26a1 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx @@ -6,7 +6,9 @@ import React, { useState, FC } from 'react'; -import { EuiSpacer, EuiText } from '@elastic/eui'; +import { EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; import { useColorRange, @@ -15,7 +17,8 @@ import { } from '../../../../../components/color_range_legend'; import { SavedSearchQuery } from '../../../../../contexts/ml'; -import { defaultSearchQuery, useResultsViewConfig } from '../../../../common'; +import { defaultSearchQuery, isOutlierAnalysis, useResultsViewConfig } from '../../../../common'; +import { FEATURE_INFLUENCE } from '../../../../common/constants'; import { ExpandableSectionAnalytics, ExpandableSectionResults } from '../expandable_section'; import { ExplorationQueryBar } from '../exploration_query_bar'; @@ -39,6 +42,24 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = const featureCount = getFeatureCount(jobConfig?.dest?.results_field || '', tableItems); const colorRange = useColorRange(COLOR_RANGE.BLUE, COLOR_RANGE_SCALE.INFLUENCER, featureCount); + // Show the color range only if feature influence is enabled and there's more than 0 features. + const showColorRange = + featureCount > 0 && + isOutlierAnalysis(jobConfig?.analysis) && + jobConfig?.analysis.outlier_detection.compute_feature_influence === true; + + const resultsField = jobConfig?.dest.results_field ?? ''; + + // Identify if the results index has a legacy feature influence format. + // If feature influence was enabled for the legacy job we'll show a callout + // with some additional information for a workaround. + const showLegacyFeatureInfluenceFormatCallout = + isOutlierAnalysis(jobConfig?.analysis) && + jobConfig?.analysis.outlier_detection.compute_feature_influence === true && + columnsWithCharts.findIndex( + (d) => d.id === `${resultsField}.${FEATURE_INFLUENCE}.feature_name` + ) === -1; + return ( <> {typeof jobConfig?.description !== 'undefined' && ( @@ -55,8 +76,26 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = )} {typeof jobConfig?.id === 'string' && } + {showLegacyFeatureInfluenceFormatCallout && ( + <> + + + + )} 0 ? colorRange : undefined} + colorRange={ + showColorRange && !showLegacyFeatureInfluenceFormatCallout ? colorRange : undefined + } indexData={outlierData} indexPattern={indexPattern} jobConfig={jobConfig} From 2768a72c241e7ea8d878a1299d24dbf78ac0e4b7 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 20 Oct 2020 13:54:51 +0200 Subject: [PATCH 3/7] [ML] Fix cancelling regression/classification results. --- .../exploration_results_table/use_exploration_results.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts index a56345017258e..8398e1d7dd4a2 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts @@ -73,8 +73,15 @@ export const useExplorationResults = ( dataGrid.resetPagination(); }, [JSON.stringify(searchQuery)]); + // The pattern using `didCancel` allows us to abort out of date remote request. + // We wrap `didCancel` in a object so we can mutate the value as it's being + // passed on to `getIndexData`. useEffect(() => { - getIndexData(jobConfig, dataGrid, searchQuery); + const options = { didCancel: false }; + getIndexData(jobConfig, dataGrid, searchQuery, options); + return () => { + options.didCancel = true; + }; // custom comparison }, [jobConfig && jobConfig.id, dataGrid.pagination, searchQuery, dataGrid.sortingColumns]); From 6a6255c4255a482202e319b4e767ac47ac79b559 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 20 Oct 2020 14:01:03 +0200 Subject: [PATCH 4/7] [ML] Tweak legacy callout text. --- .../components/outlier_exploration/outlier_exploration.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx index 734b5170d26a1..5d1d4c5f131a2 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx @@ -84,7 +84,7 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = 'xpack.ml.dataframe.analytics.outlierExploration.legacyFeatureInfluenceFormatCalloutTitle', { defaultMessage: - 'Color coded table cells based on feature influence are not available, because this results index uses an unsupported legacy format. Please clone an rerun the job to enable support for color coding.', + 'Color coded table cells based on feature influence are not available because the results index uses an unsupported legacy format. Please clone and rerun the job.', } )} iconType="pin" From 625dc09c84842c0bc34c5eb9b99994cdfe452537 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 20 Oct 2020 15:29:10 +0200 Subject: [PATCH 5/7] [ML] Hide legacy callout if index pattern is missing. --- .../components/outlier_exploration/outlier_exploration.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx index 5d1d4c5f131a2..0c6f01e1544a3 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx @@ -54,6 +54,7 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = // If feature influence was enabled for the legacy job we'll show a callout // with some additional information for a workaround. const showLegacyFeatureInfluenceFormatCallout = + !needsDestIndexPattern && isOutlierAnalysis(jobConfig?.analysis) && jobConfig?.analysis.outlier_detection.compute_feature_influence === true && columnsWithCharts.findIndex( From dea4599c69bf32ed9310394ca33efca610baeb9e Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 20 Oct 2020 23:28:40 +0200 Subject: [PATCH 6/7] [ML] Show callout when both index patterns are missing. --- .../common/use_results_view_config.ts | 22 +++++++++++++++- .../outlier_exploration.tsx | 25 +++++++++++++++++-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts index 7d2ca86a38083..81c2e246120c0 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts @@ -6,6 +6,8 @@ import { useEffect, useState } from 'react'; +import { i18n } from '@kbn/i18n'; + import { IndexPattern } from '../../../../../../../src/plugins/data/public'; import { extractErrorMessage } from '../../../../common/util/errors'; @@ -32,6 +34,9 @@ export const useResultsViewConfig = (jobId: string) => { const trainedModelsApiService = useTrainedModelsApiService(); const [indexPattern, setIndexPattern] = useState(undefined); + const [indexPatternErrorMessage, setIndexPatternErrorMessage] = useState( + undefined + ); const [isInitialized, setIsInitialized] = useState(false); const [needsDestIndexPattern, setNeedsDestIndexPattern] = useState(false); const [isLoadingJobConfig, setIsLoadingJobConfig] = useState(false); @@ -105,7 +110,11 @@ export const useResultsViewConfig = (jobId: string) => { setNeedsDestIndexPattern(true); const sourceIndex = jobConfigUpdate.source.index[0]; const sourceIndexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex; - indexP = await mlContext.indexPatterns.get(sourceIndexPatternId); + try { + indexP = await mlContext.indexPatterns.get(sourceIndexPatternId); + } catch (e) { + indexP = undefined; + } } if (indexP !== undefined) { @@ -114,6 +123,16 @@ export const useResultsViewConfig = (jobId: string) => { setIndexPattern(indexP); setIsInitialized(true); setIsLoadingJobConfig(false); + } else { + setIndexPatternErrorMessage( + i18n.translate( + 'xpack.ml.dataframe.analytics.results.indexPatternsMissingErrorMessage', + { + defaultMessage: + 'To view this page, a Kibana index pattern is necessary for either the destination or source index of this analytics job.', + } + ) + ); } } catch (e) { setJobCapsServiceErrorMessage(extractErrorMessage(e)); @@ -129,6 +148,7 @@ export const useResultsViewConfig = (jobId: string) => { return { indexPattern, + indexPatternErrorMessage, isInitialized, isLoadingJobConfig, jobCapsServiceErrorMessage, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx index 0c6f01e1544a3..9e30ed3cdfe95 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx @@ -6,7 +6,7 @@ import React, { useState, FC } from 'react'; -import { EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui'; +import { EuiCallOut, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -33,7 +33,12 @@ interface ExplorationProps { } export const OutlierExploration: FC = React.memo(({ jobId }) => { - const { indexPattern, jobConfig, needsDestIndexPattern } = useResultsViewConfig(jobId); + const { + indexPattern, + indexPatternErrorMessage, + jobConfig, + needsDestIndexPattern, + } = useResultsViewConfig(jobId); const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); const outlierData = useOutlierData(indexPattern, jobConfig, searchQuery); @@ -61,6 +66,22 @@ export const OutlierExploration: FC = React.memo(({ jobId }) = (d) => d.id === `${resultsField}.${FEATURE_INFLUENCE}.feature_name` ) === -1; + if (indexPatternErrorMessage !== undefined) { + return ( + + +

{indexPatternErrorMessage}

+
+
+ ); + } + return ( <> {typeof jobConfig?.description !== 'undefined' && ( From dbbc3d0d14dbcc78768c6008e067a22a97356850 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Wed, 21 Oct 2020 01:29:43 +0200 Subject: [PATCH 7/7] [ML] Fix callout for regression/classification. --- .../exploration_page_wrapper.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx index de4d1a97f248f..cdecead21d4de 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_page_wrapper/exploration_page_wrapper.tsx @@ -6,7 +6,7 @@ import React, { FC, useEffect, useState } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; +import { EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useUrlState } from '../../../../../util/url_state'; @@ -70,6 +70,7 @@ export const ExplorationPageWrapper: FC = ({ }) => { const { indexPattern, + indexPatternErrorMessage, isInitialized, isLoadingJobConfig, jobCapsServiceErrorMessage, @@ -99,6 +100,22 @@ export const ExplorationPageWrapper: FC = ({ } }, [jobConfig?.dest.results_field]); + if (indexPatternErrorMessage !== undefined) { + return ( + + +

{indexPatternErrorMessage}

+
+
+ ); + } + if (jobConfigErrorMessage !== undefined || jobCapsServiceErrorMessage !== undefined) { return (