From c509747a7b59da5eec63d95792404b1ad3559131 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Thu, 19 Sep 2024 13:19:23 -0400 Subject: [PATCH] Use groupBy when groupings is not populated correctly (#189672) --- .../src/rest_specs/routes/get_instances.ts | 3 +- .../src/rest_specs/routes/get_preview_data.ts | 4 +- .../slo/public/hooks/use_get_preview_data.ts | 2 +- .../components/events_chart_panel.tsx | 1 + .../ingest_templates/slo_pipeline_template.ts | 60 ++++++------------- .../__snapshots__/create_slo.test.ts.snap | 53 ++++------------ .../__snapshots__/reset_slo.test.ts.snap | 53 ++++------------ .../slo/server/services/get_preview_data.ts | 13 ++-- 8 files changed, 58 insertions(+), 131 deletions(-) diff --git a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_instances.ts b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_instances.ts index 135c2f7d6d66f4..da8f59903eebff 100644 --- a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_instances.ts +++ b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_instances.ts @@ -5,13 +5,14 @@ * 2.0. */ import * as t from 'io-ts'; +import { allOrAnyStringOrArray } from '../../schema'; const getSLOInstancesParamsSchema = t.type({ path: t.type({ id: t.string }), }); const getSLOInstancesResponseSchema = t.type({ - groupBy: t.union([t.string, t.array(t.string)]), + groupBy: allOrAnyStringOrArray, instances: t.array(t.string), }); diff --git a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_preview_data.ts b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_preview_data.ts index aa46600cb34429..1b7a0065271acb 100644 --- a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_preview_data.ts +++ b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_preview_data.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; import { indicatorSchema, objectiveSchema } from '../../schema'; -import { dateType } from '../../schema/common'; +import { allOrAnyStringOrArray, dateType } from '../../schema/common'; const getPreviewDataParamsSchema = t.type({ body: t.intersection([ @@ -20,7 +20,7 @@ const getPreviewDataParamsSchema = t.type({ t.partial({ objective: objectiveSchema, instanceId: t.string, - groupBy: t.string, + groupBy: allOrAnyStringOrArray, remoteName: t.string, groupings: t.record(t.string, t.unknown), }), diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/use_get_preview_data.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_get_preview_data.ts index 316c5300b9f9a8..f8e65fea9edff6 100644 --- a/x-pack/plugins/observability_solution/slo/public/hooks/use_get_preview_data.ts +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_get_preview_data.ts @@ -29,7 +29,7 @@ export function useGetPreviewData({ remoteName, }: { isValid: boolean; - groupBy?: string; + groupBy?: string | string[]; instanceId?: string; remoteName?: string; groupings?: Record; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/events_chart_panel.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/events_chart_panel.tsx index cd0251fd5ab64c..78944df1eb4f5b 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/events_chart_panel.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/events_chart_panel.tsx @@ -42,6 +42,7 @@ export function EventsChartPanel({ slo, range, selectedTabId, onBrushed }: Props const { isLoading, data } = useGetPreviewData({ range, isValid: true, + groupBy: slo.groupBy, indicator: slo.indicator, groupings: slo.groupings, instanceId: slo.instanceId, diff --git a/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_pipeline_template.ts b/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_pipeline_template.ts index 03c03a8c6447cf..e5aaa260e2f1d2 100644 --- a/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_pipeline_template.ts +++ b/x-pack/plugins/observability_solution/slo/server/assets/ingest_templates/slo_pipeline_template.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ALL_VALUE } from '@kbn/slo-schema'; import { getSLOPipelineId, SLO_INGEST_PIPELINE_INDEX_NAME_PREFIX, @@ -43,47 +44,24 @@ export const getSLOPipelineTemplate = (slo: SLODefinition) => ({ }, }, { - script: { - description: 'Generated the instanceId field for SLO rollup data', - source: ` - // This function will recursively collect all the values of a HashMap of HashMaps - Collection collectValues(HashMap subject) { - Collection values = new ArrayList(); - // Iterate through the values - for(Object value: subject.values()) { - // If the value is a HashMap, recurse - if (value instanceof HashMap) { - values.addAll(collectValues((HashMap) value)); - } else { - values.add(String.valueOf(value)); - } - } - return values; - } - - // Create the string builder - StringBuilder instanceId = new StringBuilder(); - - if (ctx["slo"]["groupings"] == null) { - ctx["slo"]["instanceId"] = "*"; - } else { - // Get the values as a collection - Collection values = collectValues(ctx["slo"]["groupings"]); - - // Convert to a list and sort - List sortedValues = new ArrayList(values); - Collections.sort(sortedValues); - - // Create comma delimited string - for(String instanceValue: sortedValues) { - instanceId.append(instanceValue); - instanceId.append(","); - } - - // Assign the slo.instanceId - ctx["slo"]["instanceId"] = instanceId.length() > 0 ? instanceId.substring(0, instanceId.length() - 1) : "*"; - } - `, + dot_expander: { + path: 'slo.groupings', + field: '*', + ignore_failure: true, + if: 'ctx.slo.groupings != null', + }, + }, + { + set: { + description: 'Generated the instanceId field based on the groupings field', + field: 'slo.instanceId', + value: + [slo.groupBy].flat().includes(ALL_VALUE) || [slo.groupBy].flat().length === 0 + ? ALL_VALUE + : [slo.groupBy] + .flat() + .map((field) => `{{{slo.groupings.${field}}}}`) + .join(','), }, }, ], diff --git a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap index d516bafa84393c..ef8c79410fb396 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/create_slo.test.ts.snap @@ -43,47 +43,18 @@ Array [ }, }, Object { - "script": Object { - "description": "Generated the instanceId field for SLO rollup data", - "source": " - // This function will recursively collect all the values of a HashMap of HashMaps - Collection collectValues(HashMap subject) { - Collection values = new ArrayList(); - // Iterate through the values - for(Object value: subject.values()) { - // If the value is a HashMap, recurse - if (value instanceof HashMap) { - values.addAll(collectValues((HashMap) value)); - } else { - values.add(String.valueOf(value)); - } - } - return values; - } - - // Create the string builder - StringBuilder instanceId = new StringBuilder(); - - if (ctx[\\"slo\\"][\\"groupings\\"] == null) { - ctx[\\"slo\\"][\\"instanceId\\"] = \\"*\\"; - } else { - // Get the values as a collection - Collection values = collectValues(ctx[\\"slo\\"][\\"groupings\\"]); - - // Convert to a list and sort - List sortedValues = new ArrayList(values); - Collections.sort(sortedValues); - - // Create comma delimited string - for(String instanceValue: sortedValues) { - instanceId.append(instanceValue); - instanceId.append(\\",\\"); - } - - // Assign the slo.instanceId - ctx[\\"slo\\"][\\"instanceId\\"] = instanceId.length() > 0 ? instanceId.substring(0, instanceId.length() - 1) : \\"*\\"; - } - ", + "dot_expander": Object { + "field": "*", + "if": "ctx.slo.groupings != null", + "ignore_failure": true, + "path": "slo.groupings", + }, + }, + Object { + "set": Object { + "description": "Generated the instanceId field based on the groupings field", + "field": "slo.instanceId", + "value": "*", }, }, ], diff --git a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap index 8c20bec0d64243..95f767988708ca 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/reset_slo.test.ts.snap @@ -239,47 +239,18 @@ exports[`ResetSLO resets all associated resources 8`] = ` }, }, Object { - "script": Object { - "description": "Generated the instanceId field for SLO rollup data", - "source": " - // This function will recursively collect all the values of a HashMap of HashMaps - Collection collectValues(HashMap subject) { - Collection values = new ArrayList(); - // Iterate through the values - for(Object value: subject.values()) { - // If the value is a HashMap, recurse - if (value instanceof HashMap) { - values.addAll(collectValues((HashMap) value)); - } else { - values.add(String.valueOf(value)); - } - } - return values; - } - - // Create the string builder - StringBuilder instanceId = new StringBuilder(); - - if (ctx[\\"slo\\"][\\"groupings\\"] == null) { - ctx[\\"slo\\"][\\"instanceId\\"] = \\"*\\"; - } else { - // Get the values as a collection - Collection values = collectValues(ctx[\\"slo\\"][\\"groupings\\"]); - - // Convert to a list and sort - List sortedValues = new ArrayList(values); - Collections.sort(sortedValues); - - // Create comma delimited string - for(String instanceValue: sortedValues) { - instanceId.append(instanceValue); - instanceId.append(\\",\\"); - } - - // Assign the slo.instanceId - ctx[\\"slo\\"][\\"instanceId\\"] = instanceId.length() > 0 ? instanceId.substring(0, instanceId.length() - 1) : \\"*\\"; - } - ", + "dot_expander": Object { + "field": "*", + "if": "ctx.slo.groupings != null", + "ignore_failure": true, + "path": "slo.groupings", + }, + }, + Object { + "set": Object { + "description": "Generated the instanceId field based on the groupings field", + "field": "slo.instanceId", + "value": "*", }, }, ], diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts b/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts index a18c4d035a0961..db95680ecd6550 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts @@ -43,7 +43,7 @@ interface Options { interval: string; instanceId?: string; remoteName?: string; - groupBy?: string; + groupBy?: string | string[]; groupings?: Record; } export class GetPreviewData { @@ -516,15 +516,20 @@ export class GetPreviewData { private getGroupingsFilter(options: Options, filter: estypes.QueryDslQueryContainer[]) { const groupingsKeys = Object.keys(options.groupings || []); + if (groupingsKeys.length) { groupingsKeys.forEach((key) => { filter.push({ term: { [key]: options.groupings?.[key] }, }); }); - } else if (options.instanceId !== ALL_VALUE && options.groupBy) { - filter.push({ - term: { [options.groupBy]: options.instanceId }, + } else if (options.instanceId && options.instanceId !== ALL_VALUE && options.groupBy) { + const instanceIdPart = options.instanceId.split(','); + const groupByPart = Array.isArray(options.groupBy) ? options.groupBy : [options.groupBy]; + groupByPart.forEach((groupBy, index) => { + filter.push({ + term: { [groupBy]: instanceIdPart[index] }, + }); }); } }