Skip to content

Commit

Permalink
[ML] Fix for errors when loading data views which are missing index (#…
Browse files Browse the repository at this point in the history
…147916)

Fixes #147886 by manually
checking whether the index behind a data view actually exists before
fetching it. This fixes the issue with the data view service which
displays a toast for every data view which it cannot load the fields
for.

This fix has the potential to increase the amount of requests to es by
quite a large amount.

For example, if a user has 100 data views, 80 of which have existing
indices.
1 request is made to load all data view ids and titles
100 requests are made to fetch the fields for each index. 80 succeed.
80 requests are then made to fetch each data view.

In 8.0 this behaviour has been
[changed](#116455). We no longer
request all of the data views up front on page load.
  • Loading branch information
jgowdyelastic authored Jan 17, 2023
1 parent ee0d177 commit 2b9e617
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => {

const checkIndexPatternExists = async () => {
try {
const dv = (await dataViews.find(indexName)).find(({ title }) => title === indexName);
if (dv !== undefined) {
setIndexPatternExists(true);
} else {
setIndexPatternExists(false);
if (indexName !== '') {
const dv = (await dataViews.find(indexName)).find(({ title }) => title === indexName);
if (dv !== undefined) {
setIndexPatternExists(true);
} else {
setIndexPatternExists(false);
}
}
setIsLoading(false);
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import React from 'react';
import { CustomUrlEditor } from './editor';
import { TIME_RANGE_TYPE, URL_TYPE } from './constants';
import { CustomUrlSettings } from './utils';
import { DataView } from '../../../../../../../../src/plugins/data_views/common';
import { DataViewListItem } from '../../../../../../../../src/plugins/data_views/common';

function prepareTest(customUrl: CustomUrlSettings, setEditCustomUrlFn: (url: UrlConfig) => void) {
const savedCustomUrls = [
Expand Down Expand Up @@ -50,7 +50,7 @@ function prepareTest(customUrl: CustomUrlSettings, setEditCustomUrlFn: (url: Url
const indexPatterns = [
{ id: 'pattern1', title: 'Index Pattern 1' },
{ id: 'pattern2', title: 'Index Pattern 2' },
] as DataView[];
] as DataViewListItem[];

const queryEntityFieldNames = ['airline'];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { isValidLabel } from '../../../util/custom_url_utils';

import { TIME_RANGE_TYPE, URL_TYPE } from './constants';
import { UrlConfig } from '../../../../../common/types/custom_urls';
import { DataView } from '../../../../../../../../src/plugins/data_views/common';
import { DataViewListItem } from '../../../../../../../../src/plugins/data_views/common';

function getLinkToOptions() {
return [
Expand Down Expand Up @@ -59,7 +59,7 @@ interface CustomUrlEditorProps {
setEditCustomUrl: (url: any) => void;
savedCustomUrls: UrlConfig[];
dashboards: any[];
indexPatterns: DataView[];
indexPatterns: DataViewListItem[];
queryEntityFieldNames: string[];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { DataView } from '../../../../../../../../src/plugins/data_views/common';
import { DataViewListItem } from '../../../../../../../../src/plugins/data_views/common';
import { UrlConfig } from '../../../../../common/types/custom_urls';
import { Job } from '../../../../../common/types/anomaly_detection_jobs';
import { TimeRangeType } from './constants';
Expand Down Expand Up @@ -34,7 +34,7 @@ export function isValidCustomUrlSettingsTimeRange(timeRangeSettings: any): boole
export function getNewCustomUrlDefaults(
job: Job,
dashboards: any[],
indexPatterns: DataView[]
indexPatterns: DataViewListItem[]
): CustomUrlSettings;
export function getQueryEntityFieldNames(job: Job): string[];
export function isValidCustomUrlSettings(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import type { DataView } from 'src/plugins/data_views/common';
import type { DataViewListItem } from 'src/plugins/data_views/common';

export function loadSavedDashboards(maxNumber: number): Promise<any[]>;
export function loadIndexPatterns(maxNumber: number): Promise<DataView[]>;
export function loadIndexPatterns(): Promise<DataViewListItem[]>;
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ export function loadSavedDashboards(maxNumber) {
});
}

export function loadIndexPatterns(maxNumber) {
export function loadIndexPatterns() {
// Loads the list of Kibana index patterns, as used in editing custom URLs.
// TODO - amend loadIndexPatterns in index_utils.js to do the request,
// without needing an Angular Provider.
return new Promise((resolve, reject) => {
const dataViewsContract = getDataViews();
dataViewsContract
.find('*', maxNumber)
.getIdsWithTitle()
.then((dataViews) => {
const sortedDataViews = dataViews.sort((a, b) => a.title.localeCompare(b.title));
resolve(sortedDataViews);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ import { loadSavedDashboards, loadIndexPatterns } from '../edit_utils';
import { openCustomUrlWindow } from '../../../../../util/custom_url_utils';
import { Job } from '../../../../../../../common/types/anomaly_detection_jobs';
import { UrlConfig } from '../../../../../../../common/types/custom_urls';
import { DataView } from '../../../../../../../../../../src/plugins/data_views/common';
import { DataViewListItem } from '../../../../../../../../../../src/plugins/data_views/common';
import { MlKibanaReactContextValue } from '../../../../../contexts/kibana';

const MAX_NUMBER_DASHBOARDS = 1000;
const MAX_NUMBER_INDEX_PATTERNS = 1000;

interface CustomUrlsProps {
job: Job;
Expand All @@ -54,7 +53,7 @@ interface CustomUrlsProps {
interface CustomUrlsState {
customUrls: UrlConfig[];
dashboards: any[];
indexPatterns: DataView[];
indexPatterns: DataViewListItem[];
queryEntityFieldNames: string[];
editorOpen: boolean;
editorSettings?: CustomUrlSettings;
Expand Down Expand Up @@ -100,7 +99,7 @@ class CustomUrlsUI extends Component<CustomUrlsProps, CustomUrlsState> {
);
});

loadIndexPatterns(MAX_NUMBER_INDEX_PATTERNS)
loadIndexPatterns()
.then((indexPatterns) => {
this.setState({ indexPatterns });
})
Expand Down
20 changes: 19 additions & 1 deletion x-pack/plugins/ml/public/application/util/index_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,25 @@ let indexPatternsContract: DataViewsContract | null = null;
export async function loadIndexPatterns(indexPatterns: DataViewsContract) {
indexPatternsContract = indexPatterns;
const dataViewsContract = getDataViews();
indexPatternCache = await dataViewsContract.find('*', 10000);
const idsAndTitles = await dataViewsContract.getIdsWithTitle();

const dataViewsThatExist = (
await Promise.allSettled(
// attempt to load the fields for every data view.
// if the index doesn't exist an error is thrown which we can catch.
// This is preferable to the get function which display an
// error toast for every missing index.
idsAndTitles.map(({ title }) => dataViewsContract.getFieldsForIndexPattern({ title }))
)
).reduce<string[]>((acc, { status }, i) => {
if (status === 'fulfilled') {
acc.push(idsAndTitles[i].id);
}
return acc;
}, []);

// load each data view which has a real index behind it.
indexPatternCache = await Promise.all(dataViewsThatExist.map(dataViewsContract.get));
return indexPatternCache;
}

Expand Down

0 comments on commit 2b9e617

Please sign in to comment.