From 9c92ac881a8431b38efc4fd62697cefe5c6d5e87 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Tue, 26 Oct 2021 14:02:43 +0100 Subject: [PATCH] [ML] Fix errors from annotations searches when event mapping is incorrect (#116101) * [ML] Fix errors from annotations searches when event mapping is incorrect * [ML] Delete tests on annotation errors due to incorrect mappings * [ML] Jest test fix and remove unused servuce method * [ML] type fix * [ML] Edits following review --- x-pack/plugins/ml/common/types/annotations.ts | 21 +---- .../annotations_table/annotations_table.js | 56 +++++------- .../public/application/explorer/explorer.js | 7 +- .../application/explorer/explorer_utils.js | 18 +--- .../reducers/explorer_reducer/state.ts | 2 - .../services/ml_api_service/annotations.ts | 8 +- .../timeseries_chart_with_tooltip.tsx | 7 -- .../timeseriesexplorer/timeseriesexplorer.js | 3 - .../get_focus_data.ts | 13 +-- .../__mocks__/get_annotations_request.json | 1 + .../models/annotation_service/annotation.ts | 38 ++------ .../apps/ml/anomaly_detection/annotations.ts | 51 ----------- .../functional/services/ml/test_resources.ts | 86 ------------------- 13 files changed, 37 insertions(+), 274 deletions(-) diff --git a/x-pack/plugins/ml/common/types/annotations.ts b/x-pack/plugins/ml/common/types/annotations.ts index 6234444322a5..dbc146c1175d 100644 --- a/x-pack/plugins/ml/common/types/annotations.ts +++ b/x-pack/plugins/ml/common/types/annotations.ts @@ -118,26 +118,8 @@ export function isAnnotations(arg: any): arg is Annotations { return arg.every((d: Annotation) => isAnnotation(d)); } -export interface FieldToBucket { - field: string; - missing?: string | number; -} - -export interface FieldToBucketResult { - key: string; - doc_count: number; -} - -export interface TermAggregationResult { - doc_count_error_upper_bound: number; - sum_other_doc_count: number; - buckets: FieldToBucketResult[]; -} - -export type EsAggregationResult = Record; - export interface GetAnnotationsResponse { - aggregations?: EsAggregationResult; + totalCount: number; annotations: Record; error?: string; success: boolean; @@ -145,6 +127,5 @@ export interface GetAnnotationsResponse { export interface AnnotationsTable { annotationsData: Annotations; - aggregations: EsAggregationResult; error?: string; } diff --git a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js index 26fddcc6394b..98dc5f4204c3 100644 --- a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js +++ b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js @@ -81,7 +81,6 @@ class AnnotationsTableUI extends Component { super(props); this.state = { annotations: [], - aggregations: null, isLoading: false, queryText: `event:(${ANNOTATION_EVENT_USER} or ${ANNOTATION_EVENT_DELAYED_DATA})`, searchError: undefined, @@ -115,18 +114,11 @@ class AnnotationsTableUI extends Component { earliestMs: null, latestMs: null, maxAnnotations: ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE, - fields: [ - { - field: 'event', - missing: ANNOTATION_EVENT_USER, - }, - ], }) .toPromise() .then((resp) => { this.setState((prevState, props) => ({ annotations: resp.annotations[props.jobs[0].job_id] || [], - aggregations: resp.aggregations, errorMessage: undefined, isLoading: false, jobId: props.jobs[0].job_id, @@ -570,41 +562,35 @@ class AnnotationsTableUI extends Component { onMouseLeave: () => this.onMouseLeaveRow(), }; }; - let filterOptions = []; - const aggregations = this.props.aggregations ?? this.state.aggregations; - if (aggregations) { - const buckets = aggregations.event.buckets; - let foundUser = false; - let foundDelayedData = false; - buckets.forEach((bucket) => { - if (bucket.key === ANNOTATION_EVENT_USER) { - foundUser = true; - } - if (bucket.key === ANNOTATION_EVENT_DELAYED_DATA) { - foundDelayedData = true; - } - }); - const adjustedBuckets = []; - if (!foundUser) { - adjustedBuckets.push({ key: ANNOTATION_EVENT_USER, doc_count: 0 }); - } - if (!foundDelayedData) { - adjustedBuckets.push({ key: ANNOTATION_EVENT_DELAYED_DATA, doc_count: 0 }); - } + // Build the options to show in the Event type filter. + // Do not try and run a search using a terms agg on the event field + // because in 7.9 this field was incorrectly mapped as a text rather than keyword. + + // Always display options for user and delayed data types. + const countsByEvent = { + [ANNOTATION_EVENT_USER]: 0, + [ANNOTATION_EVENT_DELAYED_DATA]: 0, + }; + annotations.forEach((annotation) => { + // Default to user type for annotations created in early releases which didn't have an event field + const event = annotation.event ?? ANNOTATION_EVENT_USER; + if (countsByEvent[event] === undefined) { + countsByEvent[event] = 0; + } + countsByEvent[event]++; + }); - filterOptions = [...adjustedBuckets, ...buckets]; - } const filters = [ { type: 'field_value_selection', field: 'event', name: 'Event', multiSelect: 'or', - options: filterOptions.map((field) => ({ - value: field.key, - name: field.key, - view: `${field.key} (${field.doc_count})`, + options: Object.entries(countsByEvent).map(([key, docCount]) => ({ + value: key, + name: key, + view: `${key} (${docCount})`, })), 'data-test-subj': 'mlAnnotationTableEventFilter', }, diff --git a/x-pack/plugins/ml/public/application/explorer/explorer.js b/x-pack/plugins/ml/public/application/explorer/explorer.js index daecf7585b3e..7d08c0fc1756 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer.js @@ -255,13 +255,9 @@ export class ExplorerUI extends React.Component { tableData, swimLaneSeverity, } = this.props.explorerState; - const { annotationsData, aggregations, error: annotationsError } = annotations; + const { annotationsData, totalCount: allAnnotationsCnt, error: annotationsError } = annotations; const annotationsCnt = Array.isArray(annotationsData) ? annotationsData.length : 0; - const allAnnotationsCnt = Array.isArray(aggregations?.event?.buckets) - ? aggregations.event.buckets.reduce((acc, v) => acc + v.doc_count, 0) - : annotationsCnt; - const badge = allAnnotationsCnt > annotationsCnt ? ( @@ -449,7 +445,6 @@ export class ExplorerUI extends React.Component { diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_utils.js b/x-pack/plugins/ml/public/application/explorer/explorer_utils.js index ecf347e6b142..af2b9b07a43f 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_utils.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_utils.js @@ -35,7 +35,6 @@ import { SWIMLANE_TYPE, VIEW_BY_JOB_LABEL, } from './explorer_constants'; -import { ANNOTATION_EVENT_USER } from '../../../common/constants/annotations'; // create new job objects based on standard job config objects // new job objects just contain job id, bucket span in seconds and a selected flag. @@ -437,10 +436,7 @@ export function loadOverallAnnotations(selectedJobs, interval, bounds) { } export function loadAnnotationsTableData(selectedCells, selectedJobs, interval, bounds) { - const jobIds = - selectedCells !== undefined && selectedCells.viewByFieldName === VIEW_BY_JOB_LABEL - ? selectedCells.lanes - : selectedJobs.map((d) => d.id); + const jobIds = getSelectionJobIds(selectedCells, selectedJobs); const timeRange = getSelectionTimeRange(selectedCells, interval, bounds); return new Promise((resolve) => { @@ -450,12 +446,6 @@ export function loadAnnotationsTableData(selectedCells, selectedJobs, interval, earliestMs: timeRange.earliestMs, latestMs: timeRange.latestMs, maxAnnotations: ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE, - fields: [ - { - field: 'event', - missing: ANNOTATION_EVENT_USER, - }, - ], }) .toPromise() .then((resp) => { @@ -463,7 +453,7 @@ export function loadAnnotationsTableData(selectedCells, selectedJobs, interval, const errorMessage = extractErrorMessage(resp.error); return resolve({ annotationsData: [], - aggregations: {}, + totalCount: 0, error: errorMessage !== '' ? errorMessage : undefined, }); } @@ -485,14 +475,14 @@ export function loadAnnotationsTableData(selectedCells, selectedJobs, interval, d.key = (i + 1).toString(); return d; }), - aggregations: resp.aggregations, + totalCount: resp.totalCount, }); }) .catch((resp) => { const errorMessage = extractErrorMessage(resp); return resolve({ annotationsData: [], - aggregations: {}, + totalCount: 0, error: errorMessage !== '' ? errorMessage : undefined, }); }); diff --git a/x-pack/plugins/ml/public/application/explorer/reducers/explorer_reducer/state.ts b/x-pack/plugins/ml/public/application/explorer/reducers/explorer_reducer/state.ts index 202a4389ef52..cfc9f076fbb3 100644 --- a/x-pack/plugins/ml/public/application/explorer/reducers/explorer_reducer/state.ts +++ b/x-pack/plugins/ml/public/application/explorer/reducers/explorer_reducer/state.ts @@ -71,12 +71,10 @@ export function getExplorerDefaultState(): ExplorerState { overallAnnotations: { error: undefined, annotationsData: [], - aggregations: {}, }, annotations: { error: undefined, annotationsData: [], - aggregations: {}, }, anomalyChartsDataLoading: true, chartsData: getDefaultChartsData(), diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/annotations.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/annotations.ts index f3f9e935a92c..006b70934c71 100644 --- a/x-pack/plugins/ml/public/application/services/ml_api_service/annotations.ts +++ b/x-pack/plugins/ml/public/application/services/ml_api_service/annotations.ts @@ -5,11 +5,7 @@ * 2.0. */ -import { - Annotation, - FieldToBucket, - GetAnnotationsResponse, -} from '../../../../common/types/annotations'; +import { Annotation, GetAnnotationsResponse } from '../../../../common/types/annotations'; import { http, http$ } from '../http_service'; import { basePath } from './index'; @@ -19,7 +15,6 @@ export const annotations = { earliestMs: number; latestMs: number; maxAnnotations: number; - fields?: FieldToBucket[]; detectorIndex?: number; entities?: any[]; }) { @@ -36,7 +31,6 @@ export const annotations = { earliestMs: number | null; latestMs: number | null; maxAnnotations: number; - fields?: FieldToBucket[]; detectorIndex?: number; entities?: any[]; }) { diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart_with_tooltip.tsx b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart_with_tooltip.tsx index 85530de2ea71..174ab8a682b5 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart_with_tooltip.tsx +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart_with_tooltip.tsx @@ -15,7 +15,6 @@ import { extractErrorMessage } from '../../../../../common/util/errors'; import { Annotation } from '../../../../../common/types/annotations'; import { useMlKibana, useNotifications } from '../../../contexts/kibana'; import { getBoundsRoundedToInterval } from '../../../util/time_buckets'; -import { ANNOTATION_EVENT_USER } from '../../../../../common/constants/annotations'; import { getControlsForDetector } from '../../get_controls_for_detector'; import { MlAnnotationUpdatesContext } from '../../../contexts/ml/ml_annotation_updates_context'; @@ -88,12 +87,6 @@ export const TimeSeriesChartWithTooltips: FC = earliestMs: searchBounds.min.valueOf(), latestMs: searchBounds.max.valueOf(), maxAnnotations: ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE, - fields: [ - { - field: 'event', - missing: ANNOTATION_EVENT_USER, - }, - ], detectorIndex, entities: nonBlankEntities, }); diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js index 454bb0b48983..9b8770350909 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js @@ -104,7 +104,6 @@ function getTimeseriesexplorerDefaultState() { entitiesLoading: false, entityValues: {}, focusAnnotationData: [], - focusAggregations: {}, focusAggregationInterval: {}, focusChartData: undefined, focusForecastData: undefined, @@ -935,7 +934,6 @@ export class TimeSeriesExplorer extends React.Component { focusAggregationInterval, focusAnnotationError, focusAnnotationData, - focusAggregations, focusChartData, focusForecastData, fullRefresh, @@ -1257,7 +1255,6 @@ export class TimeSeriesExplorer extends React.Component { detectors={detectors} jobIds={[this.props.selectedJobId]} annotations={focusAnnotationData} - aggregations={focusAggregations} isSingleMetricViewerLinkVisible={false} isNumberBadgeVisible={true} /> diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts index cb1974afd5ed..d4548a43f3f2 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts @@ -26,7 +26,6 @@ import { import { mlForecastService } from '../../services/forecast_service'; import { mlFunctionToESAggregation } from '../../../../common/util/job_utils'; import { GetAnnotationsResponse } from '../../../../common/types/annotations'; -import { ANNOTATION_EVENT_USER } from '../../../../common/constants/annotations'; import { aggregationTypeTransform } from '../../../../common/util/anomaly_utils'; export interface Interval { @@ -42,7 +41,6 @@ export interface FocusData { focusAnnotationError?: string; focusAnnotationData?: any[]; focusForecastData?: any; - focusAggregations?: any; } export function getFocusData( @@ -98,12 +96,6 @@ export function getFocusData( earliestMs: searchBounds.min.valueOf(), latestMs: searchBounds.max.valueOf(), maxAnnotations: ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE, - fields: [ - { - field: 'event', - missing: ANNOTATION_EVENT_USER, - }, - ], detectorIndex, entities: nonBlankEntities, }) @@ -111,7 +103,7 @@ export function getFocusData( catchError((resp) => of({ annotations: {}, - aggregations: {}, + totalCount: 0, error: extractErrorMessage(resp), success: false, } as GetAnnotationsResponse) @@ -168,7 +160,6 @@ export function getFocusData( if (annotations.error !== undefined) { refreshFocusData.focusAnnotationError = annotations.error; refreshFocusData.focusAnnotationData = []; - refreshFocusData.focusAggregations = {}; } else { refreshFocusData.focusAnnotationData = (annotations.annotations[selectedJob.job_id] ?? []) .sort((a, b) => { @@ -178,8 +169,6 @@ export function getFocusData( d.key = (i + 1).toString(); return d; }); - - refreshFocusData.focusAggregations = annotations.aggregations; } } diff --git a/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json b/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json index b91eb94c7fd7..c65185a6172e 100644 --- a/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json +++ b/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json @@ -1,6 +1,7 @@ { "index": ".ml-annotations-read", "size": 500, + "track_total_hits": true, "body": { "query": { "bool": { diff --git a/x-pack/plugins/ml/server/models/annotation_service/annotation.ts b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts index fac35d6255e0..12b2954f6371 100644 --- a/x-pack/plugins/ml/server/models/annotation_service/annotation.ts +++ b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts @@ -24,7 +24,6 @@ import { isAnnotations, getAnnotationFieldName, getAnnotationFieldValue, - EsAggregationResult, } from '../../../common/types/annotations'; import { JobId } from '../../../common/types/anomaly_detection_jobs'; @@ -35,36 +34,27 @@ interface EsResult { _id: string; } -export interface FieldToBucket { - field: string; - missing?: string | number; -} - export interface IndexAnnotationArgs { jobIds: string[]; earliestMs: number | null; latestMs: number | null; maxAnnotations: number; - fields?: FieldToBucket[]; detectorIndex?: number; entities?: any[]; event?: Annotation['event']; } -export interface AggTerm { - terms: FieldToBucket; -} - export interface GetParams { index: string; size: number; body: object; + track_total_hits: boolean; } export interface GetResponse { success: true; annotations: Record; - aggregations: EsAggregationResult; + totalCount: number; } export interface IndexParams { @@ -118,7 +108,6 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { earliestMs, latestMs, maxAnnotations, - fields, detectorIndex, entities, event, @@ -126,7 +115,7 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { const obj: GetResponse = { success: true, annotations: {}, - aggregations: {}, + totalCount: 0, }; const boolCriteria: object[] = []; @@ -215,18 +204,6 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { }); } - // Find unique buckets (e.g. events) from the queried annotations to show in dropdowns - const aggs: Record = {}; - if (fields) { - fields.forEach((fieldToBucket) => { - aggs[fieldToBucket.field] = { - terms: { - ...fieldToBucket, - }, - }; - }); - } - // Build should clause to further query for annotations in SMV // we want to show either the exact match with detector index and by/over/partition fields // OR annotations without any partition fields defined @@ -276,6 +253,7 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { const params: GetParams = { index: ML_ANNOTATIONS_INDEX_ALIAS_READ, size: maxAnnotations, + track_total_hits: true, body: { query: { bool: { @@ -295,7 +273,6 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { ...(shouldClauses ? { should: shouldClauses, minimum_should_match: 1 } : {}), }, }, - ...(fields ? { aggs } : {}), }, }; @@ -308,6 +285,9 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { throw new Error(`Annotations couldn't be retrieved from Elasticsearch.`); } + // @ts-expect-error incorrect search response type + obj.totalCount = body.hits.total.value; + // @ts-expect-error TODO fix search response types const docs: Annotations = get(body, ['hits', 'hits'], []).map((d: EsResult) => { // get the original source document and the document id, we need it @@ -321,10 +301,6 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { } as Annotation; }); - const aggregations = get(body, ['aggregations'], {}) as EsAggregationResult; - if (fields) { - obj.aggregations = aggregations; - } if (isAnnotations(docs) === false) { // No need to translate, this will not be exposed in the UI. throw new Error(`Annotations didn't pass integrity check.`); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts b/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts index 446f8a0549fc..f0d0b898aefc 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts @@ -262,56 +262,5 @@ export default function ({ getService }: FtrProviderContext) { await ml.jobAnnotations.assertAnnotationsRowMissing(annotationId); }); }); - - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/115849 - describe.skip('with errors', function () { - before(async () => { - // Points the read/write aliases of annotations to an index with wrong mappings - // so we can simulate errors when requesting annotations. - await ml.testResources.setupBrokenAnnotationsIndexState(jobId); - }); - - it('displays error on broken annotation index and recovers after fix', async () => { - await ml.testExecution.logTestStep('loads from job list row link'); - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - - await ml.jobTable.waitForJobsToLoad(); - await ml.jobTable.filterWithSearchString(jobId, 1); - - await ml.jobTable.clickOpenJobInSingleMetricViewerButton(jobId); - await ml.commonUI.waitForMlLoadingIndicatorToDisappear(); - - await ml.testExecution.logTestStep( - 'should display the annotations section showing an error' - ); - await ml.singleMetricViewer.assertAnnotationsExists('error'); - - await ml.testExecution.logTestStep('should navigate to anomaly explorer'); - await ml.navigation.navigateToAnomalyExplorerViaSingleMetricViewer(); - - await ml.testExecution.logTestStep( - 'should display the annotations section showing an error' - ); - await ml.anomalyExplorer.assertAnnotationsPanelExists('error'); - - await ml.testExecution.logTestStep( - 'should display the annotations section without an error' - ); - // restores the aliases to point to the original working annotations index - // so we can run tests against successfully loaded annotations sections. - await ml.testResources.restoreAnnotationsIndexState(); - await ml.anomalyExplorer.refreshPage(); - await ml.anomalyExplorer.assertAnnotationsPanelExists('loaded'); - - await ml.testExecution.logTestStep('should navigate to single metric viewer'); - await ml.navigation.navigateToSingleMetricViewerViaAnomalyExplorer(); - - await ml.testExecution.logTestStep( - 'should display the annotations section without an error' - ); - await ml.singleMetricViewer.assertAnnotationsExists('loaded'); - }); - }); }); } diff --git a/x-pack/test/functional/services/ml/test_resources.ts b/x-pack/test/functional/services/ml/test_resources.ts index f1b2ef97e4e0..65a892d124ed 100644 --- a/x-pack/test/functional/services/ml/test_resources.ts +++ b/x-pack/test/functional/services/ml/test_resources.ts @@ -24,7 +24,6 @@ export enum SavedObjectType { export type MlTestResourcesi = ProvidedType; export function MachineLearningTestResourcesProvider({ getService }: FtrProviderContext) { - const es = getService('es'); const kibanaServer = getService('kibanaServer'); const log = getService('log'); const supertest = getService('supertest'); @@ -188,91 +187,6 @@ export function MachineLearningTestResourcesProvider({ getService }: FtrProvider } }, - async setupBrokenAnnotationsIndexState(jobId: string) { - // Creates a temporary annotations index with unsupported mappings. - await es.indices.create({ - index: '.ml-annotations-6-wrong-mapping', - body: { - settings: { - number_of_shards: 1, - }, - mappings: { - properties: { - field1: { type: 'text' }, - }, - }, - }, - }); - - // Ingests an annotation that will cause dynamic mapping to pick up the wrong field type. - es.create({ - id: 'annotation_with_wrong_mapping', - index: '.ml-annotations-6-wrong-mapping', - body: { - annotation: 'Annotation with wrong mapping', - create_time: 1597393915910, - create_username: '_xpack', - timestamp: 1549756800000, - end_timestamp: 1549756800000, - job_id: jobId, - modified_time: 1597393915910, - modified_username: '_xpack', - type: 'annotation', - event: 'user', - detector_index: 0, - }, - }); - - // Points the read/write aliases for annotations to the broken annotations index - // so we can run tests against a state where annotation endpoints return errors. - await es.indices.updateAliases({ - body: { - actions: [ - { - add: { - index: '.ml-annotations-6-wrong-mapping', - alias: '.ml-annotations-read', - is_hidden: true, - }, - }, - { remove: { index: '.ml-annotations-6', alias: '.ml-annotations-read' } }, - { - add: { - index: '.ml-annotations-6-wrong-mapping', - alias: '.ml-annotations-write', - is_hidden: true, - }, - }, - { remove: { index: '.ml-annotations-6', alias: '.ml-annotations-write' } }, - ], - }, - }); - }, - - async restoreAnnotationsIndexState() { - // restore the original working state of pointing read/write aliases - // to the right annotations index. - await es.indices.updateAliases({ - body: { - actions: [ - { add: { index: '.ml-annotations-6', alias: '.ml-annotations-read', is_hidden: true } }, - { remove: { index: '.ml-annotations-6-wrong-mapping', alias: '.ml-annotations-read' } }, - { - add: { index: '.ml-annotations-6', alias: '.ml-annotations-write', is_hidden: true }, - }, - { - remove: { index: '.ml-annotations-6-wrong-mapping', alias: '.ml-annotations-write' }, - }, - ], - }, - }); - - // deletes the temporary annotations index with wrong mappings - await es.indices.delete({ - index: '.ml-annotations-6-wrong-mapping', - }); - }, - async updateSavedSearchRequestBody(body: object, indexPatternTitle: string): Promise { const indexPatternId = await this.getIndexPatternId(indexPatternTitle); if (indexPatternId === undefined) {