From 0e24cb3396be21f2160f9ce5c277e794c908431b Mon Sep 17 00:00:00 2001 From: Quynh Nguyen Date: Thu, 9 Jul 2020 14:45:05 -0500 Subject: [PATCH] [ML] Change SMV annotations to only show series + non-partitioned --- .../annotations_table.test.js.snap | 2 +- .../services/ml_api_service/annotations.ts | 2 + .../get_focus_data.ts | 2 + .../models/annotation_service/annotation.ts | 55 +++++++++++++++++++ .../routes/schemas/annotations_schema.ts | 11 ++++ 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/__snapshots__/annotations_table.test.js.snap b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/__snapshots__/annotations_table.test.js.snap index 8ed16d0959160c..d916dcf6f7167e 100644 --- a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/__snapshots__/annotations_table.test.js.snap +++ b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/__snapshots__/annotations_table.test.js.snap @@ -114,7 +114,7 @@ exports[`AnnotationsTable Initialization with annotations prop. 1`] = ` "incremental": true, "schema": true, }, - "defaultQuery": "event:(user)", + "defaultQuery": "event:(user or delayed_data)", "filters": Array [ Object { "field": "event", 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 b3f5e787325544..f9e19ba6f757ea 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 @@ -19,6 +19,8 @@ export const annotations = { latestMs: number; maxAnnotations: number; fields: FieldToBucket[]; + detectorIndex: number; + entities: any[]; }) { const body = JSON.stringify(obj); return http$({ 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 d63fea6b1ca208..8bac9a51af1740 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 @@ -92,6 +92,8 @@ export function getFocusData( missing: ANNOTATION_EVENT_USER, }, ], + detectorIndex, + entities: nonBlankEntities, }) .pipe( catchError(() => { 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 cc538228935212..630360695e6b2b 100644 --- a/x-pack/plugins/ml/server/models/annotation_service/annotation.ts +++ b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts @@ -9,6 +9,7 @@ import _ from 'lodash'; import { LegacyAPICaller } from 'kibana/server'; import { ANNOTATION_EVENT_USER, ANNOTATION_TYPE } from '../../../common/constants/annotations'; +import { PARTITION_FIELDS } from '../../../common/constants/anomalies'; import { ML_ANNOTATIONS_INDEX_ALIAS_READ, ML_ANNOTATIONS_INDEX_ALIAS_WRITE, @@ -19,6 +20,8 @@ import { Annotations, isAnnotation, isAnnotations, + getAnnotationFieldName, + getAnnotationFieldValue, EsAggregationResult, } from '../../../common/types/annotations'; @@ -40,6 +43,8 @@ export interface IndexAnnotationArgs { latestMs: number; maxAnnotations: number; fields?: FieldToBucket[]; + detectorIndex?: number; + entities?: any[]; } export interface AggTerm { @@ -114,6 +119,8 @@ export function annotationProvider(callAsCurrentUser: LegacyAPICaller) { latestMs, maxAnnotations, fields, + detectorIndex, + entities, }: IndexAnnotationArgs) { const obj: GetResponse = { success: true, @@ -201,6 +208,7 @@ export function annotationProvider(callAsCurrentUser: LegacyAPICaller) { }); } + // Find unique buckets (e.g. events) from the queried annotations to show in dropdowns const aggs: Record = {}; if (fields) { fields.forEach((fieldToBucket) => { @@ -212,6 +220,52 @@ export function annotationProvider(callAsCurrentUser: LegacyAPICaller) { }); } + // 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 + let shouldClauses; + if (detectorIndex !== undefined && Array.isArray(entities)) { + // build clause to get exact match of detector index and by/over/partition fields + const beExactMatch = []; + beExactMatch.push({ + term: { + detector_index: detectorIndex, + }, + }); + + entities.forEach(({ fieldName, fieldType, fieldValue }) => { + beExactMatch.push({ + term: { + [getAnnotationFieldName(fieldType)]: fieldName, + }, + }); + beExactMatch.push({ + term: { + [getAnnotationFieldValue(fieldType)]: fieldValue, + }, + }); + }); + + // clause to get annotations that have no partition fields + const haveAnyPartitionFields: object[] = []; + PARTITION_FIELDS.forEach((field) => { + haveAnyPartitionFields.push({ + exists: { + field: getAnnotationFieldName(field), + }, + }); + haveAnyPartitionFields.push({ + exists: { + field: getAnnotationFieldValue(field), + }, + }); + }); + shouldClauses = [ + { bool: { must_not: haveAnyPartitionFields } }, + { bool: { must: beExactMatch } }, + ]; + } + const params: GetParams = { index: ML_ANNOTATIONS_INDEX_ALIAS_READ, size: maxAnnotations, @@ -231,6 +285,7 @@ export function annotationProvider(callAsCurrentUser: LegacyAPICaller) { }, }, ], + ...(shouldClauses ? { should: shouldClauses, minimum_should_match: 1 } : {}), }, }, ...(fields ? { aggs } : {}), diff --git a/x-pack/plugins/ml/server/routes/schemas/annotations_schema.ts b/x-pack/plugins/ml/server/routes/schemas/annotations_schema.ts index f873b137cb8118..14a2f632419bc2 100644 --- a/x-pack/plugins/ml/server/routes/schemas/annotations_schema.ts +++ b/x-pack/plugins/ml/server/routes/schemas/annotations_schema.ts @@ -34,6 +34,7 @@ export const getAnnotationsSchema = schema.object({ earliestMs: schema.oneOf([schema.nullable(schema.number()), schema.maybe(schema.number())]), latestMs: schema.oneOf([schema.nullable(schema.number()), schema.maybe(schema.number())]), maxAnnotations: schema.number(), + /** Fields to find unique values for (e.g. events or created_by) */ fields: schema.maybe( schema.arrayOf( schema.object({ @@ -42,6 +43,16 @@ export const getAnnotationsSchema = schema.object({ }) ) ), + detectorIndex: schema.maybe(schema.number()), + entities: schema.maybe( + schema.arrayOf( + schema.object({ + fieldType: schema.maybe(schema.string()), + fieldName: schema.maybe(schema.string()), + fieldValue: schema.maybe(schema.string()), + }) + ) + ), }); export const deleteAnnotationSchema = schema.object({ annotationId: schema.string() });