From b201f07a5d7dc75c769dbe5deb44d496a3ab9b59 Mon Sep 17 00:00:00 2001 From: Panagiota Mitsopoulou Date: Mon, 2 Feb 2026 11:17:02 +0200 Subject: [PATCH] [SLO] Fix SLO filter containing space and wildcard (#251033) Fixes https://github.com/elastic/kibana/issues/250781 Fixes https://github.com/elastic/kibana/issues/251039 ## Summary Currently in SLO edit/create form when user uses a filter query that contains a space followed by a wildcard character (`tags: hello *`), it behaves as if it's using Lucene syntax instead of KQL (generates `query_string` queries instead of `wildcard` queries for keyword fields). `query_string` uses Lucene syntax which handles spaces and wildcards differently than KQL, leading to queries matching all documents or no documents instead of the intended subset. ## Root cause The `getElasticsearchQueryOrThrow` function accepts an optional `dataView` parameter that is required for `buildEsQuery` to determine field types (keyword vs text vs other types). With a missing dataView [getFields](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-es-query/src/kuery/functions/utils/get_fields.ts#L14)() can't find the field in the dataView, so it falls back to a field with no type info, causing `query_string` instead of `wildcard` This PR fixes various calls to `getElasticsearchQueryOrThrow` to include a `dataView`. It also fixes a visual issue with the preview chart, where it appeared to be empty where sliValue = 0. Now it shows a line at the 0% level for those time intervals where good events might be 0. ## After, tags: hello *, only hello all documents returned 542489023-4f0a0439-3615-436b-a265-132a929563f9 ## SLO documents flyout showing only documents with hello all tag Screenshot 2026-01-30 at 01 43 04 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> (cherry picked from commit 96eb62cfbe06cf210adf56ed71b70d5e618b87ec) --- .../plugins/slo/common/parse_kuery.ts | 35 +++++++---- .../components/common/data_preview_chart.tsx | 4 +- .../components/common/use_table_docs.tsx | 2 +- ...get_custom_metric_indicator_aggregation.ts | 5 +- .../get_histogram_indicator_aggregation.ts | 5 +- ..._timeslice_metric_indicator_aggregation.ts | 5 +- .../server/services/get_preview_data.test.ts | 44 ++++++++++++- .../slo/server/services/get_preview_data.ts | 61 +++++++++++++------ .../transform_generators/histogram.ts | 10 ++- .../transform_generators/kql_custom.ts | 2 +- .../transform_generators/metric_custom.ts | 10 ++- .../synthetics_availability.ts | 5 +- .../transform_generators/timeslice_metric.ts | 7 ++- 13 files changed, 139 insertions(+), 56 deletions(-) diff --git a/x-pack/solutions/observability/plugins/slo/common/parse_kuery.ts b/x-pack/solutions/observability/plugins/slo/common/parse_kuery.ts index 7a59a2462b783..70afe3f395640 100644 --- a/x-pack/solutions/observability/plugins/slo/common/parse_kuery.ts +++ b/x-pack/solutions/observability/plugins/slo/common/parse_kuery.ts @@ -8,22 +8,31 @@ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import type { QuerySchema } from '@kbn/slo-schema'; import { kqlQuerySchema } from '@kbn/slo-schema'; -import { buildEsQuery, fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; +import { buildEsQuery } from '@kbn/es-query'; +import type { DataViewBase } from '@kbn/es-query'; +import { isEmpty } from 'lodash'; -export function getElasticsearchQueryOrThrow(kuery: QuerySchema = ''): QueryDslQueryContainer { +export function getElasticsearchQueryOrThrow( + kuery: QuerySchema = '', + dataView?: DataViewBase +): QueryDslQueryContainer { try { - if (kqlQuerySchema.is(kuery)) { - return toElasticsearchQuery(fromKueryExpression(kuery)); - } else { - return buildEsQuery( - undefined, - { - query: kuery?.kqlQuery, - language: 'kuery', - }, - kuery?.filters - ); + if (isEmpty(kuery)) { + return { match_all: {} }; } + const kqlQuery = kqlQuerySchema.is(kuery) ? kuery : kuery.kqlQuery; + const filters = kqlQuerySchema.is(kuery) ? [] : kuery.filters; + return buildEsQuery( + dataView, + { + query: kqlQuery, + language: 'kuery', + }, + filters, + { + allowLeadingWildcards: true, + } + ); } catch (err) { // @ts-expect-error `getElasticsearchQueryOrThrow` but it doesn't throw :shrug: return []; diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/data_preview_chart.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/data_preview_chart.tsx index 00928463b28ff..baf880e402c94 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/data_preview_chart.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/data_preview_chart.tsx @@ -300,7 +300,7 @@ export function DataPreviewChart({ yAccessors={['value']} data={(previewData?.results ?? []).map((datum) => ({ date: new Date(datum.date).getTime(), - value: datum.sliValue && datum.sliValue >= 0 ? datum.sliValue : null, + value: datum.sliValue != null && datum.sliValue >= 0 ? datum.sliValue : null, events: datum.events, }))} /> @@ -316,7 +316,7 @@ export function DataPreviewChart({ yAccessors={['value']} data={data.map((datum) => ({ date: new Date(datum.date).getTime(), - value: datum.sliValue && datum.sliValue >= 0 ? datum.sliValue : null, + value: datum.sliValue != null && datum.sliValue >= 0 ? datum.sliValue : null, events: datum.events, }))} /> diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/use_table_docs.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/use_table_docs.tsx index 1da3e30afacff..b04fde57242a1 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/use_table_docs.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/use_table_docs.tsx @@ -29,7 +29,7 @@ export const useTableDocs = ({ const errorMessages = getFieldState(name).error?.message; const filter = watch(name) as QuerySchema; - const esFilter = getElasticsearchQueryOrThrow(filter); + const esFilter = getElasticsearchQueryOrThrow(filter, dataView); const { data, loading, error } = useEsSearch( { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_custom_metric_indicator_aggregation.ts b/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_custom_metric_indicator_aggregation.ts index 8d334c090dfbc..9cfe694644816 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_custom_metric_indicator_aggregation.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_custom_metric_indicator_aggregation.ts @@ -7,6 +7,7 @@ import type { MetricCustomIndicator } from '@kbn/slo-schema'; import { metricCustomDocCountMetric } from '@kbn/slo-schema'; +import type { DataView } from '@kbn/data-views-plugin/common'; import { getElasticsearchQueryOrThrow } from '../transform_generators'; type MetricCustomMetricDef = @@ -14,12 +15,12 @@ type MetricCustomMetricDef = | MetricCustomIndicator['params']['total']; export class GetCustomMetricIndicatorAggregation { - constructor(private indicator: MetricCustomIndicator) {} + constructor(private indicator: MetricCustomIndicator, private dataView?: DataView) {} private buildMetricAggregations(type: 'good' | 'total', metricDef: MetricCustomMetricDef) { return metricDef.metrics.reduce((acc, metric) => { const filter = metric.filter - ? getElasticsearchQueryOrThrow(metric.filter) + ? getElasticsearchQueryOrThrow(metric.filter, this.dataView) : { match_all: {} }; if (metricCustomDocCountMetric.is(metric)) { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_histogram_indicator_aggregation.ts b/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_histogram_indicator_aggregation.ts index 3243a11d60e62..e897e2b56ba58 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_histogram_indicator_aggregation.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_histogram_indicator_aggregation.ts @@ -7,6 +7,7 @@ import type { HistogramIndicator } from '@kbn/slo-schema'; import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/types'; +import type { DataView } from '@kbn/data-views-plugin/common'; import { getElasticsearchQueryOrThrow } from '../transform_generators/common'; type HistogramIndicatorDef = @@ -14,11 +15,11 @@ type HistogramIndicatorDef = | HistogramIndicator['params']['total']; export class GetHistogramIndicatorAggregation { - constructor(private indicator: HistogramIndicator) {} + constructor(private indicator: HistogramIndicator, private dataView?: DataView) {} private buildAggregation(indicator: HistogramIndicatorDef): AggregationsAggregationContainer { const filter = indicator.filter - ? getElasticsearchQueryOrThrow(indicator.filter) + ? getElasticsearchQueryOrThrow(indicator.filter, this.dataView) : { match_all: {} }; if (indicator.aggregation === 'value_count') { return { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_timeslice_metric_indicator_aggregation.ts b/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_timeslice_metric_indicator_aggregation.ts index 94efb67581e68..ca0152bf6af26 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_timeslice_metric_indicator_aggregation.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/aggregations/get_timeslice_metric_indicator_aggregation.ts @@ -8,6 +8,7 @@ import type { TimesliceMetricIndicator, timesliceMetricMetricDef } from '@kbn/slo-schema'; import type * as t from 'io-ts'; import { assertNever } from '@kbn/std'; +import type { DataView } from '@kbn/data-views-plugin/common'; import { getElasticsearchQueryOrThrow } from '../transform_generators'; @@ -15,7 +16,7 @@ type TimesliceMetricDef = TimesliceMetricIndicator['params']['metric']; type TimesliceMetricMetricDef = t.TypeOf; export class GetTimesliceMetricIndicatorAggregation { - constructor(private indicator: TimesliceMetricIndicator) {} + constructor(private indicator: TimesliceMetricIndicator, private dataView?: DataView) {} private buildAggregation(metric: TimesliceMetricMetricDef) { const { aggregation } = metric; @@ -85,7 +86,7 @@ export class GetTimesliceMetricIndicatorAggregation { private buildMetricAggregations(metricDef: TimesliceMetricDef) { return metricDef.metrics.reduce((acc, metric) => { const filter = metric.filter - ? getElasticsearchQueryOrThrow(metric.filter) + ? getElasticsearchQueryOrThrow(metric.filter, this.dataView) : { match_all: {} }; const aggs = { metric: this.buildAggregation(metric) }; return { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/get_preview_data.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/get_preview_data.test.ts index 66475b287c99e..cbacf0f91ce47 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/get_preview_data.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/get_preview_data.test.ts @@ -11,14 +11,56 @@ import { dataViewsService } from '@kbn/data-views-plugin/server/mocks'; import type { GetPreviewDataParams } from '@kbn/slo-schema'; import { GetPreviewData } from './get_preview_data'; import { oneMinute } from './fixtures/duration'; +import { createStubDataView } from '@kbn/data-views-plugin/common/data_views/data_view.stub'; +import type { DataViewsService } from '@kbn/data-views-plugin/common'; describe('GetPreviewData', () => { let esClientMock: ElasticsearchClientMock; let service: GetPreviewData; + let mockDataViewsService: jest.Mocked; beforeEach(() => { esClientMock = elasticsearchServiceMock.createElasticsearchClient(); - service = new GetPreviewData(esClientMock, 'default', dataViewsService); + mockDataViewsService = { + ...dataViewsService, + get: jest.fn().mockImplementation((dataViewId: string) => { + if (dataViewId === 'e7744dbe-a7a4-457b-83aa-539e9c88764c') { + return Promise.resolve( + createStubDataView({ + spec: { + id: dataViewId, + title: 'kbn-data-forge-fake_stack.admin-console-*', + timeFieldName: '@timestamp', + fields: { + 'http.response.status_code': { + name: 'http.response.status_code', + type: 'number', + esTypes: ['long'], + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + }, + }, + }) + ); + } + if (dataViewId === '593f894a-3378-42cc-bafc-61b4877b64b0') { + return Promise.resolve( + createStubDataView({ + spec: { + id: dataViewId, + title: 'kbn-data-forge-fake_stack.message_processor-*', + timeFieldName: '@timestamp', + fields: {}, + }, + }) + ); + } + return Promise.reject(new Error('Data view not found')); + }), + } as any; + service = new GetPreviewData(esClientMock, 'default', mockDataViewsService); }); describe("for 'Custom KQL' indicator type", () => { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/get_preview_data.ts b/x-pack/solutions/observability/plugins/slo/server/services/get_preview_data.ts index 9bcc2e2e2d5d2..e7527b0658d21 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/get_preview_data.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/get_preview_data.ts @@ -55,15 +55,20 @@ export class GetPreviewData { private dataViewService: DataViewsService ) {} - private async buildRuntimeMappings({ dataViewId }: { dataViewId?: string }) { - let dataView: DataView | undefined; - if (dataViewId) { - try { - dataView = await this.dataViewService.get(dataViewId); - } catch (e) { - // If the data view is not found, we will continue without it - } + private async getDataView(dataViewId?: string): Promise { + if (!dataViewId) { + return undefined; + } + try { + return await this.dataViewService.get(dataViewId); + } catch (e) { + // If the data view is not found, we will continue without it + return undefined; } + } + + private async buildRuntimeMappings({ dataViewId }: { dataViewId?: string }) { + const dataView = await this.getDataView(dataViewId); return dataView?.getRuntimeMappings?.() ?? {}; } @@ -101,6 +106,7 @@ export class GetPreviewData { indicator: APMTransactionDurationIndicator, options: Options ): Promise { + const dataView = await this.getDataView(indicator.params.dataViewId); const filter: estypes.QueryDslQueryContainer[] = []; const groupingFilters = this.getGroupingFilters(options); if (groupingFilters) { @@ -123,7 +129,7 @@ export class GetPreviewData { match: { 'transaction.type': indicator.params.transactionType }, }); if (!!indicator.params.filter) - filter.push(getElasticsearchQueryOrThrow(indicator.params.filter)); + filter.push(getElasticsearchQueryOrThrow(indicator.params.filter, dataView)); const truncatedThreshold = Math.trunc(indicator.params.threshold * 1000); @@ -227,6 +233,7 @@ export class GetPreviewData { indicator: APMTransactionErrorRateIndicator, options: Options ): Promise { + const dataView = await this.getDataView(indicator.params.dataViewId); const filter: estypes.QueryDslQueryContainer[] = []; const groupingFilters = this.getGroupingFilters(options); if (groupingFilters) { @@ -249,7 +256,7 @@ export class GetPreviewData { match: { 'transaction.type': indicator.params.transactionType }, }); if (!!indicator.params.filter) - filter.push(getElasticsearchQueryOrThrow(indicator.params.filter)); + filter.push(getElasticsearchQueryOrThrow(indicator.params.filter, dataView)); const index = options.remoteName ? `${options.remoteName}:${indicator.params.index}` @@ -345,8 +352,12 @@ export class GetPreviewData { indicator: HistogramIndicator, options: Options ): Promise { - const getHistogramIndicatorAggregations = new GetHistogramIndicatorAggregation(indicator); - const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter); + const dataView = await this.getDataView(indicator.params.dataViewId); + const getHistogramIndicatorAggregations = new GetHistogramIndicatorAggregation( + indicator, + dataView + ); + const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter, dataView); const timestampField = indicator.params.timestampField; const filter: estypes.QueryDslQueryContainer[] = [ @@ -447,9 +458,14 @@ export class GetPreviewData { indicator: MetricCustomIndicator, options: Options ): Promise { + const dataView = await this.getDataView(indicator.params.dataViewId); const timestampField = indicator.params.timestampField; - const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter); - const getCustomMetricIndicatorAggregation = new GetCustomMetricIndicatorAggregation(indicator); + const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter, dataView); + + const getCustomMetricIndicatorAggregation = new GetCustomMetricIndicatorAggregation( + indicator, + dataView + ); const filter: estypes.QueryDslQueryContainer[] = [ { range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } }, @@ -549,10 +565,12 @@ export class GetPreviewData { indicator: TimesliceMetricIndicator, options: Options ): Promise { + const dataView = await this.getDataView(indicator.params.dataViewId); const timestampField = indicator.params.timestampField; - const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter); + const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter, dataView); const getCustomMetricIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation( - indicator + indicator, + dataView ); const filter: estypes.QueryDslQueryContainer[] = [ @@ -629,9 +647,11 @@ export class GetPreviewData { indicator: KQLCustomIndicator, options: Options ): Promise { - const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter); - const goodQuery = getElasticsearchQueryOrThrow(indicator.params.good); - const totalQuery = getElasticsearchQueryOrThrow(indicator.params.total); + const dataView = await this.getDataView(indicator.params.dataViewId); + const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter, dataView); + const goodQuery = getElasticsearchQueryOrThrow(indicator.params.good, dataView); + const totalQuery = getElasticsearchQueryOrThrow(indicator.params.total, dataView); + const timestampField = indicator.params.timestampField; const filter: estypes.QueryDslQueryContainer[] = [ { range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } }, @@ -682,9 +702,10 @@ export class GetPreviewData { response.aggregations?.perInterval.buckets.map((bucket) => { const good = bucket.good?.doc_count ?? 0; const total = bucket.total?.doc_count ?? 0; + const sliValue = computeSLIForPreview(good, total); return { date: bucket.key_as_string, - sliValue: computeSLIForPreview(good, total), + sliValue, events: { good, bad: total - good, diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/histogram.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/histogram.ts index 280f6bbd7de3d..898a80f53bd36 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/histogram.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/histogram.ts @@ -37,7 +37,7 @@ export class HistogramTransformGenerator extends TransformGenerator { await this.buildSource(slo, slo.indicator), this.buildDestination(slo), this.buildCommonGroupBy(slo, slo.indicator.params.timestampField), - this.buildAggregations(slo, slo.indicator), + await this.buildAggregations(slo, slo.indicator), this.buildSettings(slo, slo.indicator.params.timestampField), slo ); @@ -71,8 +71,12 @@ export class HistogramTransformGenerator extends TransformGenerator { }; } - private buildAggregations(slo: SLODefinition, indicator: HistogramIndicator) { - const getHistogramIndicatorAggregations = new GetHistogramIndicatorAggregation(indicator); + private async buildAggregations(slo: SLODefinition, indicator: HistogramIndicator) { + const dataView = await this.getIndicatorDataView(indicator.params.dataViewId); + const getHistogramIndicatorAggregations = new GetHistogramIndicatorAggregation( + indicator, + dataView + ); return { ...getHistogramIndicatorAggregations.execute({ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/kql_custom.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/kql_custom.ts index 190d197a58648..27bd03b9d038f 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/kql_custom.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/kql_custom.ts @@ -54,7 +54,7 @@ export class KQLCustomTransformGenerator extends TransformGenerator { bool: { filter: [ getFilterRange(slo, indicator.params.timestampField, this.isServerless), - getElasticsearchQueryOrThrow(indicator.params.filter), + getElasticsearchQueryOrThrow(indicator.params.filter, dataView), ], }, }, diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/metric_custom.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/metric_custom.ts index 73d1d7d5a534e..82c81633ae509 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/metric_custom.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/metric_custom.ts @@ -39,7 +39,7 @@ export class MetricCustomTransformGenerator extends TransformGenerator { await this.buildSource(slo, slo.indicator), this.buildDestination(slo), this.buildCommonGroupBy(slo, slo.indicator.params.timestampField), - this.buildAggregations(slo, slo.indicator), + await this.buildAggregations(slo, slo.indicator), this.buildSettings(slo, slo.indicator.params.timestampField), slo ); @@ -72,7 +72,7 @@ export class MetricCustomTransformGenerator extends TransformGenerator { }; } - private buildAggregations(slo: SLODefinition, indicator: MetricCustomIndicator) { + private async buildAggregations(slo: SLODefinition, indicator: MetricCustomIndicator) { if (indicator.params.good.equation.match(INVALID_EQUATION_REGEX)) { throw new Error(`Invalid equation: ${indicator.params.good.equation}`); } @@ -81,7 +81,11 @@ export class MetricCustomTransformGenerator extends TransformGenerator { throw new Error(`Invalid equation: ${indicator.params.total.equation}`); } - const getCustomMetricIndicatorAggregation = new GetCustomMetricIndicatorAggregation(indicator); + const dataView = await this.getIndicatorDataView(indicator.params.dataViewId); + const getCustomMetricIndicatorAggregation = new GetCustomMetricIndicatorAggregation( + indicator, + dataView + ); return { ...getCustomMetricIndicatorAggregation.execute({ type: 'good', diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/synthetics_availability.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/synthetics_availability.ts index 2a5ae0d9871ae..ceb3d167a3c43 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/synthetics_availability.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/synthetics_availability.ts @@ -108,6 +108,7 @@ export class SyntheticsAvailabilityTransformGenerator extends TransformGenerator } private async buildSource(slo: SLODefinition, indicator: SyntheticsAvailabilityIndicator) { + const dataView = await this.getIndicatorDataView(indicator.params.dataViewId); const queryFilter: estypes.QueryDslQueryContainer[] = [ { term: { 'summary.final_attempt': true } }, { term: { 'meta.space_id': this.spaceId } }, @@ -144,11 +145,9 @@ export class SyntheticsAvailabilityTransformGenerator extends TransformGenerator } if (!!indicator.params.filter) { - queryFilter.push(getElasticsearchQueryOrThrow(indicator.params.filter)); + queryFilter.push(getElasticsearchQueryOrThrow(indicator.params.filter, dataView)); } - const dataView = await this.getIndicatorDataView(indicator.params.dataViewId); - return { index: SYNTHETICS_INDEX_PATTERN, runtime_mappings: this.buildCommonRuntimeMappings(dataView), diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/timeslice_metric.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/timeslice_metric.ts index 2e783dc2a63f4..daf9d01b086fb 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/timeslice_metric.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/timeslice_metric.ts @@ -43,7 +43,7 @@ export class TimesliceMetricTransformGenerator extends TransformGenerator { await this.buildSource(slo, slo.indicator), this.buildDestination(slo), this.buildCommonGroupBy(slo, slo.indicator.params.timestampField), - this.buildAggregations(slo, slo.indicator), + await this.buildAggregations(slo, slo.indicator), this.buildSettings(slo, slo.indicator.params.timestampField), slo ); @@ -77,7 +77,7 @@ export class TimesliceMetricTransformGenerator extends TransformGenerator { }; } - private buildAggregations(slo: SLODefinition, indicator: TimesliceMetricIndicator) { + private async buildAggregations(slo: SLODefinition, indicator: TimesliceMetricIndicator) { if (indicator.params.metric.equation.match(INVALID_EQUATION_REGEX)) { throw new Error(`Invalid equation: ${indicator.params.metric.equation}`); } @@ -86,7 +86,8 @@ export class TimesliceMetricTransformGenerator extends TransformGenerator { throw new Error('The sli.metric.timeslice indicator MUST have a timeslice budgeting method.'); } - const getIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation(indicator); + const dataView = await this.getIndicatorDataView(indicator.params.dataViewId); + const getIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation(indicator, dataView); const comparator = timesliceMetricComparatorMapping[indicator.params.metric.comparator]; return { ...getIndicatorAggregation.execute('_metric'),