mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[SLOs] Added unified search into form (#176496)
## Summary
Fixes https://github.com/elastic/kibana/issues/176276
Added unified search into form !!
Update schema to reflect new changes !!
<img width="1189" alt="image"
src="b1ba4da4
-f23e-435c-8778-b819bc2ff7be">
This commit is contained in:
parent
0481436d0e
commit
2d36a14de9
30 changed files with 505 additions and 122 deletions
|
@ -34,6 +34,8 @@ import {
|
|||
timesliceMetricBasicMetricWithField,
|
||||
timesliceMetricDocCountMetric,
|
||||
timesliceMetricPercentileMetric,
|
||||
kqlWithFiltersSchema,
|
||||
querySchema,
|
||||
} from '../schema';
|
||||
|
||||
const createSLOParamsSchema = t.type({
|
||||
|
@ -71,6 +73,8 @@ const getPreviewDataParamsSchema = t.type({
|
|||
}),
|
||||
t.partial({
|
||||
objective: objectiveSchema,
|
||||
instanceId: t.string,
|
||||
groupBy: t.string,
|
||||
}),
|
||||
]),
|
||||
});
|
||||
|
@ -334,6 +338,8 @@ type TimesclieMetricPercentileMetric = t.OutputOf<typeof timesliceMetricPercenti
|
|||
type HistogramIndicator = t.OutputOf<typeof histogramIndicatorSchema>;
|
||||
type KQLCustomIndicator = t.OutputOf<typeof kqlCustomIndicatorSchema>;
|
||||
type GroupSummary = t.TypeOf<typeof groupSummarySchema>;
|
||||
type KqlWithFiltersSchema = t.TypeOf<typeof kqlWithFiltersSchema>;
|
||||
type QuerySchema = t.TypeOf<typeof querySchema>;
|
||||
|
||||
export {
|
||||
createSLOParamsSchema,
|
||||
|
@ -409,4 +415,6 @@ export type {
|
|||
KQLCustomIndicator,
|
||||
TimeWindow,
|
||||
GroupSummary,
|
||||
KqlWithFiltersSchema,
|
||||
QuerySchema,
|
||||
};
|
||||
|
|
|
@ -83,6 +83,35 @@ const previewDataSchema = t.intersection([
|
|||
|
||||
const dateRangeSchema = t.type({ from: dateType, to: dateType });
|
||||
|
||||
const kqlQuerySchema = t.string;
|
||||
|
||||
const kqlWithFiltersSchema = t.type({
|
||||
kqlQuery: t.string,
|
||||
filters: t.array(
|
||||
t.type({
|
||||
meta: t.partial({
|
||||
alias: t.union([t.string, t.null]),
|
||||
disabled: t.boolean,
|
||||
negate: t.boolean,
|
||||
// controlledBy is there to identify who owns the filter
|
||||
controlledBy: t.string,
|
||||
// allows grouping of filters
|
||||
group: t.string,
|
||||
// index and type are optional only because when you create a new filter, there are no defaults
|
||||
index: t.string,
|
||||
isMultiIndex: t.boolean,
|
||||
type: t.string,
|
||||
key: t.string,
|
||||
params: t.any,
|
||||
value: t.string,
|
||||
}),
|
||||
query: t.record(t.string, t.any),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
||||
const querySchema = t.union([kqlQuerySchema, kqlWithFiltersSchema]);
|
||||
|
||||
export {
|
||||
ALL_VALUE,
|
||||
allOrAnyString,
|
||||
|
@ -94,4 +123,7 @@ export {
|
|||
statusSchema,
|
||||
summarySchema,
|
||||
groupSummarySchema,
|
||||
kqlWithFiltersSchema,
|
||||
querySchema,
|
||||
kqlQuerySchema,
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { allOrAnyString, dateRangeSchema } from './common';
|
||||
import { allOrAnyString, dateRangeSchema, querySchema } from './common';
|
||||
|
||||
const apmTransactionDurationIndicatorTypeSchema = t.literal('sli.apm.transactionDuration');
|
||||
const apmTransactionDurationIndicatorSchema = t.type({
|
||||
|
@ -21,7 +21,7 @@ const apmTransactionDurationIndicatorSchema = t.type({
|
|||
index: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]),
|
||||
});
|
||||
|
@ -38,7 +38,7 @@ const apmTransactionErrorRateIndicatorSchema = t.type({
|
|||
index: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]),
|
||||
});
|
||||
|
@ -49,12 +49,12 @@ const kqlCustomIndicatorSchema = t.type({
|
|||
params: t.intersection([
|
||||
t.type({
|
||||
index: t.string,
|
||||
good: t.string,
|
||||
total: t.string,
|
||||
good: querySchema,
|
||||
total: querySchema,
|
||||
timestampField: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]),
|
||||
});
|
||||
|
@ -83,7 +83,7 @@ const timesliceMetricBasicMetricWithField = t.intersection([
|
|||
field: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
@ -93,7 +93,7 @@ const timesliceMetricDocCountMetric = t.intersection([
|
|||
aggregation: t.literal('doc_count'),
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
@ -105,7 +105,7 @@ const timesliceMetricPercentileMetric = t.intersection([
|
|||
percentile: t.number,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
@ -131,7 +131,7 @@ const timesliceMetricIndicatorSchema = t.type({
|
|||
timestampField: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]),
|
||||
});
|
||||
|
@ -142,7 +142,7 @@ const metricCustomDocCountMetric = t.intersection([
|
|||
aggregation: t.literal('doc_count'),
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
@ -153,7 +153,7 @@ const metricCustomBasicMetric = t.intersection([
|
|||
field: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
@ -172,7 +172,7 @@ const metricCustomIndicatorSchema = t.type({
|
|||
timestampField: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]),
|
||||
});
|
||||
|
@ -186,7 +186,7 @@ const rangeBasedHistogramMetricDef = t.intersection([
|
|||
to: t.number,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
@ -197,7 +197,7 @@ const valueCountBasedHistogramMetricDef = t.intersection([
|
|||
aggregation: valueCountHistogramMetricType,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
@ -217,7 +217,7 @@ const histogramIndicatorSchema = t.type({
|
|||
total: histogramMetricDef,
|
||||
}),
|
||||
t.partial({
|
||||
filter: t.string,
|
||||
filter: querySchema,
|
||||
}),
|
||||
]),
|
||||
});
|
||||
|
|
|
@ -1020,6 +1020,85 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"filter_meta": {
|
||||
"title": "FilterMeta",
|
||||
"description": "Defines properties for a filter",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"alias": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"disabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"negate": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"controlledBy": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"type": "string"
|
||||
},
|
||||
"index": {
|
||||
"type": "string"
|
||||
},
|
||||
"isMultiIndex": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"type": "object"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"filter": {
|
||||
"title": "Filter",
|
||||
"description": "Defines properties for a filter",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {
|
||||
"type": "object"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/components/schemas/filter_meta"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kql_with_filters": {
|
||||
"title": "KQL with filters",
|
||||
"description": "Defines properties for a filter",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "the KQL query to filter the documents with.",
|
||||
"type": "string",
|
||||
"example": "field.environment : \"production\" and service.name : \"my-service\""
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kqlQuery": {
|
||||
"type": "string"
|
||||
},
|
||||
"filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/filter"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"indicator_properties_custom_kql": {
|
||||
"title": "Custom KQL",
|
||||
"required": [
|
||||
|
@ -1047,17 +1126,16 @@
|
|||
},
|
||||
"filter": {
|
||||
"description": "the KQL query to filter the documents with.",
|
||||
"type": "string",
|
||||
"example": "field.environment : \"production\" and service.name : \"my-service\""
|
||||
"$ref": "#/components/schemas/kql_with_filters"
|
||||
},
|
||||
"good": {
|
||||
"description": "the KQL query used to define the good events.",
|
||||
"type": "string",
|
||||
"$ref": "#/components/schemas/kql_with_filters",
|
||||
"example": "request.latency <= 150 and request.status_code : \"2xx\""
|
||||
},
|
||||
"total": {
|
||||
"description": "the KQL query used to define all events.",
|
||||
"type": "string",
|
||||
"$ref": "#/components/schemas/kql_with_filters",
|
||||
"example": ""
|
||||
},
|
||||
"timestampField": {
|
||||
|
|
|
@ -634,6 +634,58 @@ components:
|
|||
description: The type of indicator.
|
||||
type: string
|
||||
example: sli.apm.transactionDuration
|
||||
filter_meta:
|
||||
title: FilterMeta
|
||||
description: Defines properties for a filter
|
||||
type: object
|
||||
properties:
|
||||
alias:
|
||||
type: string
|
||||
nullable: true
|
||||
disabled:
|
||||
type: boolean
|
||||
negate:
|
||||
type: boolean
|
||||
controlledBy:
|
||||
type: string
|
||||
group:
|
||||
type: string
|
||||
index:
|
||||
type: string
|
||||
isMultiIndex:
|
||||
type: boolean
|
||||
type:
|
||||
type: string
|
||||
key:
|
||||
type: string
|
||||
params:
|
||||
type: object
|
||||
value:
|
||||
type: string
|
||||
filter:
|
||||
title: Filter
|
||||
description: Defines properties for a filter
|
||||
type: object
|
||||
properties:
|
||||
query:
|
||||
type: object
|
||||
meta:
|
||||
$ref: '#/components/schemas/filter_meta'
|
||||
kql_with_filters:
|
||||
title: KQL with filters
|
||||
description: Defines properties for a filter
|
||||
oneOf:
|
||||
- description: the KQL query to filter the documents with.
|
||||
type: string
|
||||
example: 'field.environment : "production" and service.name : "my-service"'
|
||||
- type: object
|
||||
properties:
|
||||
kqlQuery:
|
||||
type: string
|
||||
filters:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/filter'
|
||||
indicator_properties_custom_kql:
|
||||
title: Custom KQL
|
||||
required:
|
||||
|
@ -658,15 +710,14 @@ components:
|
|||
example: my-service-*
|
||||
filter:
|
||||
description: the KQL query to filter the documents with.
|
||||
type: string
|
||||
example: 'field.environment : "production" and service.name : "my-service"'
|
||||
$ref: '#/components/schemas/kql_with_filters'
|
||||
good:
|
||||
description: the KQL query used to define the good events.
|
||||
type: string
|
||||
$ref: '#/components/schemas/kql_with_filters'
|
||||
example: 'request.latency <= 150 and request.status_code : "2xx"'
|
||||
total:
|
||||
description: the KQL query used to define all events.
|
||||
type: string
|
||||
$ref: '#/components/schemas/kql_with_filters'
|
||||
example: ''
|
||||
timestampField:
|
||||
description: |
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
title: Filter
|
||||
description: Defines properties for a filter
|
||||
type: object
|
||||
properties:
|
||||
query:
|
||||
type: object
|
||||
meta:
|
||||
$ref: "filter_meta.yaml"
|
|
@ -0,0 +1,27 @@
|
|||
title: FilterMeta
|
||||
description: Defines properties for a filter
|
||||
type: object
|
||||
properties:
|
||||
alias:
|
||||
type: string
|
||||
nullable: true
|
||||
disabled:
|
||||
type: boolean
|
||||
negate:
|
||||
type: boolean
|
||||
controlledBy:
|
||||
type: string
|
||||
group:
|
||||
type: string
|
||||
index:
|
||||
type: string
|
||||
isMultiIndex:
|
||||
type: boolean
|
||||
type:
|
||||
type: string
|
||||
key:
|
||||
type: string
|
||||
params:
|
||||
type: object
|
||||
value:
|
||||
type: string
|
|
@ -21,15 +21,14 @@ properties:
|
|||
example: my-service-*
|
||||
filter:
|
||||
description: the KQL query to filter the documents with.
|
||||
type: string
|
||||
example: 'field.environment : "production" and service.name : "my-service"'
|
||||
$ref: "kql_with_filters.yaml"
|
||||
good:
|
||||
description: the KQL query used to define the good events.
|
||||
type: string
|
||||
$ref: "kql_with_filters.yaml"
|
||||
example: 'request.latency <= 150 and request.status_code : "2xx"'
|
||||
total:
|
||||
description: the KQL query used to define all events.
|
||||
type: string
|
||||
$ref: "kql_with_filters.yaml"
|
||||
example: ''
|
||||
timestampField:
|
||||
description: >
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
title: KQL with filters
|
||||
description: Defines properties for a filter
|
||||
oneOf:
|
||||
- description: the KQL query to filter the documents with.
|
||||
type: string
|
||||
example: 'field.environment : "production" and service.name : "my-service"'
|
||||
- type: object
|
||||
properties:
|
||||
kqlQuery:
|
||||
type: string
|
||||
filters:
|
||||
type: array
|
||||
items:
|
||||
$ref: "filter.yaml"
|
||||
|
|
@ -18,12 +18,21 @@ export interface UseGetPreviewData {
|
|||
isError: boolean;
|
||||
}
|
||||
|
||||
export function useGetPreviewData(
|
||||
isValid: boolean,
|
||||
indicator: Indicator,
|
||||
range: { start: number; end: number },
|
||||
objective?: Objective
|
||||
): UseGetPreviewData {
|
||||
export function useGetPreviewData({
|
||||
isValid,
|
||||
range,
|
||||
indicator,
|
||||
objective,
|
||||
groupBy,
|
||||
instanceId,
|
||||
}: {
|
||||
isValid: boolean;
|
||||
groupBy?: string;
|
||||
instanceId?: string;
|
||||
objective?: Objective;
|
||||
indicator: Indicator;
|
||||
range: { start: number; end: number };
|
||||
}): UseGetPreviewData {
|
||||
const { http } = useKibana().services;
|
||||
|
||||
const { isInitialLoading, isLoading, isError, isSuccess, data } = useQuery({
|
||||
|
@ -35,6 +44,8 @@ export function useGetPreviewData(
|
|||
body: JSON.stringify({
|
||||
indicator,
|
||||
range,
|
||||
groupBy,
|
||||
instanceId,
|
||||
...(objective ? { objective } : null),
|
||||
}),
|
||||
signal,
|
||||
|
|
|
@ -32,8 +32,8 @@ import {
|
|||
import numeral from '@elastic/numeral';
|
||||
import { useActiveCursor } from '@kbn/charts-plugin/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ALL_VALUE, SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
import { cloneDeep, max, min } from 'lodash';
|
||||
import { SLOWithSummaryResponse } from '@kbn/slo-schema';
|
||||
import { max, min } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import React, { useRef } from 'react';
|
||||
import { useGetPreviewData } from '../../../hooks/slo/use_get_preview_data';
|
||||
|
@ -57,16 +57,13 @@ export function EventsChartPanel({ slo, range }: Props) {
|
|||
isDateHistogram: true,
|
||||
});
|
||||
|
||||
const instanceIdFilter =
|
||||
slo.instanceId !== ALL_VALUE ? `${slo.groupBy}: "${slo.instanceId}"` : null;
|
||||
const sloIndicator = cloneDeep(slo.indicator);
|
||||
if (instanceIdFilter) {
|
||||
sloIndicator.params.filter =
|
||||
!!sloIndicator.params.filter && sloIndicator.params.filter.length > 0
|
||||
? `${sloIndicator.params.filter} and ${instanceIdFilter}`
|
||||
: instanceIdFilter;
|
||||
}
|
||||
const { isLoading, data } = useGetPreviewData(true, sloIndicator, range, slo.objective);
|
||||
const { isLoading, data } = useGetPreviewData({
|
||||
range,
|
||||
isValid: true,
|
||||
indicator: slo.indicator,
|
||||
groupBy: slo.groupBy,
|
||||
instanceId: slo.instanceId,
|
||||
});
|
||||
|
||||
const dateFormat = uiSettings.get('dateFormat');
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
import { EuiFormRow } from '@elastic/eui';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { Controller, FieldPath, useFormContext } from 'react-hook-form';
|
||||
import styled from 'styled-components';
|
||||
import { kqlQuerySchema } from '@kbn/slo-schema';
|
||||
import { useCreateDataView } from '../../../../hooks/use_create_data_view';
|
||||
import { useKibana } from '../../../../utils/kibana_react';
|
||||
import { CreateSLOForm } from '../../types';
|
||||
|
@ -34,7 +36,7 @@ export function QueryBuilder({
|
|||
}: Props) {
|
||||
const {
|
||||
unifiedSearch: {
|
||||
ui: { QueryStringInput },
|
||||
ui: { SearchBar },
|
||||
},
|
||||
} = useKibana().services;
|
||||
|
||||
|
@ -67,23 +69,56 @@ export function QueryBuilder({
|
|||
required: Boolean(required) && Boolean(dataView),
|
||||
}}
|
||||
render={({ field, fieldState }) => (
|
||||
<QueryStringInput
|
||||
appName="Observability"
|
||||
dataTestSubj={dataTestSubj}
|
||||
disableLanguageSwitcher
|
||||
indexPatterns={dataView ? [dataView] : []}
|
||||
isDisabled={!dataView}
|
||||
isInvalid={fieldState.invalid}
|
||||
languageSwitcherPopoverAnchorPosition="rightDown"
|
||||
placeholder={placeholder}
|
||||
query={{ query: String(field.value), language: 'kuery' }}
|
||||
size="s"
|
||||
onChange={(value) => {
|
||||
field.onChange(value.query);
|
||||
}}
|
||||
/>
|
||||
<Container>
|
||||
<SearchBar
|
||||
appName="Observability"
|
||||
dataTestSubj={dataTestSubj}
|
||||
indexPatterns={dataView ? [dataView] : []}
|
||||
isDisabled={!dataView}
|
||||
placeholder={placeholder}
|
||||
query={{
|
||||
query: kqlQuerySchema.is(field.value) ? String(field.value) : field.value.kqlQuery,
|
||||
language: 'kuery',
|
||||
}}
|
||||
onQuerySubmit={(value) => {
|
||||
if (kqlQuerySchema.is(field.value)) {
|
||||
field.onChange(String(value.query?.query));
|
||||
} else {
|
||||
field.onChange({
|
||||
...(field.value ?? {}),
|
||||
kqlQuery: String(value.query?.query),
|
||||
});
|
||||
}
|
||||
}}
|
||||
onFiltersUpdated={(filters) => {
|
||||
if (kqlQuerySchema.is(field.value)) {
|
||||
field.onChange({
|
||||
filters,
|
||||
kqlQuery: field.value,
|
||||
});
|
||||
} else {
|
||||
field.onChange({
|
||||
...(field.value ?? {}),
|
||||
filters,
|
||||
});
|
||||
}
|
||||
}}
|
||||
showDatePicker={false}
|
||||
showSubmitButton={false}
|
||||
showQueryInput={true}
|
||||
disableQueryLanguageSwitcher={true}
|
||||
onClearSavedQuery={() => {}}
|
||||
filters={kqlQuerySchema.is(field.value) ? [] : field.value?.filters ?? []}
|
||||
/>
|
||||
</Container>
|
||||
)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
.uniSearchBar {
|
||||
padding: 0;
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -105,6 +105,45 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Transform partial URL state into form state handles the 'filters' URL state 1`] = `
|
||||
Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
"description": "",
|
||||
"groupBy": "*",
|
||||
"indicator": Object {
|
||||
"params": Object {
|
||||
"filter": "",
|
||||
"good": Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"alias": "override-alias",
|
||||
"disabled": true,
|
||||
"key": "override",
|
||||
"negate": true,
|
||||
},
|
||||
},
|
||||
],
|
||||
"kqlQuery": "some.override.filter:'foo'",
|
||||
},
|
||||
"index": "override-index",
|
||||
"timestampField": "",
|
||||
"total": "",
|
||||
},
|
||||
"type": "sli.kql.custom",
|
||||
},
|
||||
"name": "",
|
||||
"objective": Object {
|
||||
"target": 99,
|
||||
},
|
||||
"tags": Array [],
|
||||
"timeWindow": Object {
|
||||
"duration": "30d",
|
||||
"type": "rolling",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Transform partial URL state into form state handles the 'objective' URL state 1`] = `
|
||||
Object {
|
||||
"budgetingMethod": "occurrences",
|
||||
|
|
|
@ -95,4 +95,30 @@ describe('Transform partial URL state into form state', () => {
|
|||
transform({ objective: { target: 0.945, timesliceTarget: 0.95, timesliceWindow: '2m' } })
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("handles the 'filters' URL state", () => {
|
||||
expect(
|
||||
transform({
|
||||
indicator: {
|
||||
type: 'sli.kql.custom',
|
||||
params: {
|
||||
good: {
|
||||
kqlQuery: "some.override.filter:'foo'",
|
||||
filters: [
|
||||
{
|
||||
meta: {
|
||||
alias: 'override-alias',
|
||||
negate: true,
|
||||
disabled: true,
|
||||
key: 'override',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
index: 'override-index',
|
||||
},
|
||||
},
|
||||
})
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -29,5 +29,9 @@ export function useDebouncedGetPreviewData(
|
|||
}
|
||||
}, [indicatorState, serializedIndicator, store]);
|
||||
|
||||
return useGetPreviewData(isIndicatorValid, JSON.parse(indicatorState), range);
|
||||
return useGetPreviewData({
|
||||
isValid: isIndicatorValid,
|
||||
indicator: JSON.parse(indicatorState),
|
||||
range,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ const mockKibana = (license: ILicense | null = licenseMock) => {
|
|||
unifiedSearch: {
|
||||
ui: {
|
||||
QueryStringInput: () => <div>Query String Input</div>,
|
||||
SearchBar: () => <div>Search Bar</div>,
|
||||
},
|
||||
autocomplete: {
|
||||
hasQuerySuggestions: () => {},
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
ALL_VALUE,
|
||||
apmTransactionDurationIndicatorSchema,
|
||||
apmTransactionErrorRateIndicatorSchema,
|
||||
kqlQuerySchema,
|
||||
SLOResponse,
|
||||
} from '@kbn/slo-schema';
|
||||
|
||||
|
@ -48,7 +49,7 @@ export function convertSliApmParamsToApmAppDeeplinkUrl(slo: SLOResponse): string
|
|||
if (transactionName && transactionName !== ALL_VALUE) {
|
||||
kueryParams.push(`transaction.name : "${transactionName}"`);
|
||||
}
|
||||
if (filter && filter.length > 0) {
|
||||
if (filter && kqlQuerySchema.is(filter) && filter.length > 0) {
|
||||
kueryParams.push(filter);
|
||||
}
|
||||
if (groupBy !== ALL_VALUE && instanceId !== ALL_VALUE) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { metricCustomDocCountMetric, MetricCustomIndicator } from '@kbn/slo-schema';
|
||||
import { getElastichsearchQueryOrThrow } from '../transform_generators';
|
||||
import { getElasticsearchQueryOrThrow } from '../transform_generators';
|
||||
|
||||
type MetricCustomMetricDef =
|
||||
| MetricCustomIndicator['params']['good']
|
||||
|
@ -18,7 +18,7 @@ export class GetCustomMetricIndicatorAggregation {
|
|||
private buildMetricAggregations(type: 'good' | 'total', metricDef: MetricCustomMetricDef) {
|
||||
return metricDef.metrics.reduce((acc, metric) => {
|
||||
const filter = metric.filter
|
||||
? getElastichsearchQueryOrThrow(metric.filter)
|
||||
? getElasticsearchQueryOrThrow(metric.filter)
|
||||
: { match_all: {} };
|
||||
|
||||
if (metricCustomDocCountMetric.is(metric)) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { HistogramIndicator } from '@kbn/slo-schema';
|
||||
import { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { getElastichsearchQueryOrThrow } from '../transform_generators/common';
|
||||
import { getElasticsearchQueryOrThrow } from '../transform_generators/common';
|
||||
|
||||
type HistogramIndicatorDef =
|
||||
| HistogramIndicator['params']['good']
|
||||
|
@ -18,7 +18,7 @@ export class GetHistogramIndicatorAggregation {
|
|||
|
||||
private buildAggregation(indicator: HistogramIndicatorDef): AggregationsAggregationContainer {
|
||||
const filter = indicator.filter
|
||||
? getElastichsearchQueryOrThrow(indicator.filter)
|
||||
? getElasticsearchQueryOrThrow(indicator.filter)
|
||||
: { match_all: {} };
|
||||
if (indicator.aggregation === 'value_count') {
|
||||
return {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { TimesliceMetricIndicator, timesliceMetricMetricDef } from '@kbn/slo-sch
|
|||
import * as t from 'io-ts';
|
||||
import { assertNever } from '@kbn/std';
|
||||
|
||||
import { getElastichsearchQueryOrThrow } from '../transform_generators';
|
||||
import { getElasticsearchQueryOrThrow } from '../transform_generators';
|
||||
|
||||
type TimesliceMetricDef = TimesliceMetricIndicator['params']['metric'];
|
||||
type TimesliceMetricMetricDef = t.TypeOf<typeof timesliceMetricMetricDef>;
|
||||
|
@ -85,7 +85,7 @@ export class GetTimesliceMetricIndicatorAggregation {
|
|||
private buildMetricAggregations(metricDef: TimesliceMetricDef) {
|
||||
return metricDef.metrics.reduce((acc, metric) => {
|
||||
const filter = metric.filter
|
||||
? getElastichsearchQueryOrThrow(metric.filter)
|
||||
? getElasticsearchQueryOrThrow(metric.filter)
|
||||
: { match_all: {} };
|
||||
const aggs = { metric: this.buildAggregation(metric) };
|
||||
return {
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
DEFAULT_SLO_GROUPS_PAGE_SIZE,
|
||||
} from '../../../common/slo/constants';
|
||||
import { Status } from '../../domain/models';
|
||||
import { getElastichsearchQueryOrThrow } from './transform_generators';
|
||||
import { getElasticsearchQueryOrThrow } from './transform_generators';
|
||||
|
||||
const DEFAULT_PAGE = 1;
|
||||
const MAX_PER_PAGE = 5000;
|
||||
|
@ -66,7 +66,7 @@ export class FindSLOGroups {
|
|||
bool: {
|
||||
filter: [
|
||||
{ term: { spaceId: this.spaceId } },
|
||||
getElastichsearchQueryOrThrow(kqlQuery),
|
||||
getElasticsearchQueryOrThrow(kqlQuery),
|
||||
...(parsedFilters.filter ?? []),
|
||||
],
|
||||
},
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import { calculateAuto } from '@kbn/calculate-auto';
|
||||
import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
|
||||
import {
|
||||
ALL_VALUE,
|
||||
APMTransactionErrorRateIndicator,
|
||||
|
@ -21,10 +20,10 @@ import { assertNever } from '@kbn/std';
|
|||
import moment from 'moment';
|
||||
import { ElasticsearchClient } from '@kbn/core/server';
|
||||
import { estypes } from '@elastic/elasticsearch';
|
||||
import { getElasticsearchQueryOrThrow } from './transform_generators';
|
||||
import { typedSearch } from '../../utils/queries';
|
||||
import { APMTransactionDurationIndicator } from '../../domain/models';
|
||||
import { computeSLI } from '../../domain/services';
|
||||
import { InvalidQueryError } from '../../errors';
|
||||
import {
|
||||
GetCustomMetricIndicatorAggregation,
|
||||
GetHistogramIndicatorAggregation,
|
||||
|
@ -37,6 +36,8 @@ interface Options {
|
|||
end: number;
|
||||
};
|
||||
interval: string;
|
||||
instanceId?: string;
|
||||
groupBy?: string;
|
||||
}
|
||||
export class GetPreviewData {
|
||||
constructor(private esClient: ElasticsearchClient) {}
|
||||
|
@ -46,6 +47,11 @@ export class GetPreviewData {
|
|||
options: Options
|
||||
): Promise<GetPreviewDataResponse> {
|
||||
const filter: estypes.QueryDslQueryContainer[] = [];
|
||||
if (options.instanceId !== ALL_VALUE && options.groupBy) {
|
||||
filter.push({
|
||||
term: { [options.groupBy]: options.instanceId },
|
||||
});
|
||||
}
|
||||
if (indicator.params.service !== ALL_VALUE)
|
||||
filter.push({
|
||||
match: { 'service.name': indicator.params.service },
|
||||
|
@ -138,7 +144,12 @@ export class GetPreviewData {
|
|||
indicator: APMTransactionErrorRateIndicator,
|
||||
options: Options
|
||||
): Promise<GetPreviewDataResponse> {
|
||||
const filter = [];
|
||||
const filter: estypes.QueryDslQueryContainer[] = [];
|
||||
if (options.instanceId !== ALL_VALUE && options.groupBy) {
|
||||
filter.push({
|
||||
term: { [options.groupBy]: options.instanceId },
|
||||
});
|
||||
}
|
||||
if (indicator.params.service !== ALL_VALUE)
|
||||
filter.push({
|
||||
match: { 'service.name': indicator.params.service },
|
||||
|
@ -225,15 +236,24 @@ export class GetPreviewData {
|
|||
const getHistogramIndicatorAggregations = new GetHistogramIndicatorAggregation(indicator);
|
||||
const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter);
|
||||
const timestampField = indicator.params.timestampField;
|
||||
|
||||
const filter: estypes.QueryDslQueryContainer[] = [
|
||||
{ range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } },
|
||||
filterQuery,
|
||||
];
|
||||
|
||||
if (options.instanceId !== ALL_VALUE && options.groupBy) {
|
||||
filter.push({
|
||||
term: { [options.groupBy]: options.instanceId },
|
||||
});
|
||||
}
|
||||
|
||||
const result = await this.esClient.search({
|
||||
index: indicator.params.index,
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } },
|
||||
filterQuery,
|
||||
],
|
||||
filter,
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
|
@ -280,15 +300,23 @@ export class GetPreviewData {
|
|||
const timestampField = indicator.params.timestampField;
|
||||
const filterQuery = getElasticsearchQueryOrThrow(indicator.params.filter);
|
||||
const getCustomMetricIndicatorAggregation = new GetCustomMetricIndicatorAggregation(indicator);
|
||||
|
||||
const filter: estypes.QueryDslQueryContainer[] = [
|
||||
{ range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } },
|
||||
filterQuery,
|
||||
];
|
||||
if (options.instanceId !== ALL_VALUE && options.groupBy) {
|
||||
filter.push({
|
||||
term: { [options.groupBy]: options.instanceId },
|
||||
});
|
||||
}
|
||||
|
||||
const result = await this.esClient.search({
|
||||
index: indicator.params.index,
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } },
|
||||
filterQuery,
|
||||
],
|
||||
filter,
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
|
@ -337,15 +365,24 @@ export class GetPreviewData {
|
|||
const getCustomMetricIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation(
|
||||
indicator
|
||||
);
|
||||
|
||||
const filter: estypes.QueryDslQueryContainer[] = [
|
||||
{ range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } },
|
||||
filterQuery,
|
||||
];
|
||||
|
||||
if (options.instanceId !== ALL_VALUE && options.groupBy) {
|
||||
filter.push({
|
||||
term: { [options.groupBy]: options.instanceId },
|
||||
});
|
||||
}
|
||||
|
||||
const result = await this.esClient.search({
|
||||
index: indicator.params.index,
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } },
|
||||
filterQuery,
|
||||
],
|
||||
filter,
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
|
@ -380,15 +417,23 @@ export class GetPreviewData {
|
|||
const goodQuery = getElasticsearchQueryOrThrow(indicator.params.good);
|
||||
const totalQuery = getElasticsearchQueryOrThrow(indicator.params.total);
|
||||
const timestampField = indicator.params.timestampField;
|
||||
const filter: estypes.QueryDslQueryContainer[] = [
|
||||
{ range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } },
|
||||
filterQuery,
|
||||
];
|
||||
|
||||
if (options.instanceId !== ALL_VALUE && options.groupBy) {
|
||||
filter.push({
|
||||
term: { [options.groupBy]: options.instanceId },
|
||||
});
|
||||
}
|
||||
|
||||
const result = await this.esClient.search({
|
||||
index: indicator.params.index,
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ range: { [timestampField]: { gte: options.range.start, lte: options.range.end } } },
|
||||
filterQuery,
|
||||
],
|
||||
filter,
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
|
@ -442,7 +487,9 @@ export class GetPreviewData {
|
|||
1
|
||||
);
|
||||
const options: Options = {
|
||||
instanceId: params.instanceId,
|
||||
range: params.range,
|
||||
groupBy: params.groupBy,
|
||||
interval: `${bucketSize}m`,
|
||||
};
|
||||
|
||||
|
@ -468,11 +515,3 @@ export class GetPreviewData {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getElasticsearchQueryOrThrow(kuery: string | undefined = '') {
|
||||
try {
|
||||
return toElasticsearchQuery(fromKueryExpression(kuery));
|
||||
} catch (err) {
|
||||
throw new InvalidQueryError(`Invalid kuery: ${kuery}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import { SearchTotalHits } from '@elastic/elasticsearch/lib/api/types';
|
|||
import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/slo/constants';
|
||||
import { SLOId, Status, Summary } from '../../domain/models';
|
||||
import { toHighPrecision } from '../../utils/number';
|
||||
import { getElastichsearchQueryOrThrow } from './transform_generators';
|
||||
import { getElasticsearchQueryOrThrow } from './transform_generators';
|
||||
|
||||
interface EsSummaryDocument {
|
||||
slo: {
|
||||
|
@ -81,7 +81,7 @@ export class DefaultSummarySearchClient implements SummarySearchClient {
|
|||
bool: {
|
||||
filter: [
|
||||
{ term: { spaceId: this.spaceId } },
|
||||
getElastichsearchQueryOrThrow(kqlQuery),
|
||||
getElasticsearchQueryOrThrow(kqlQuery),
|
||||
...(parsedFilters.filter ?? []),
|
||||
],
|
||||
must_not: [...(parsedFilters.must_not ?? [])],
|
||||
|
|
|
@ -12,7 +12,8 @@ import {
|
|||
timeslicesBudgetingMethodSchema,
|
||||
} from '@kbn/slo-schema';
|
||||
import { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { getElastichsearchQueryOrThrow, TransformGenerator } from '.';
|
||||
import { estypes } from '@elastic/elasticsearch';
|
||||
import { getElasticsearchQueryOrThrow, TransformGenerator } from '.';
|
||||
import {
|
||||
getSLOTransformId,
|
||||
SLO_DESTINATION_INDEX_NAME,
|
||||
|
@ -22,7 +23,6 @@ import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo
|
|||
import { APMTransactionDurationIndicator, SLO } from '../../../domain/models';
|
||||
import { InvalidTransformError } from '../../../errors';
|
||||
import { parseIndex } from './common';
|
||||
import { Query } from './types';
|
||||
|
||||
export class ApmTransactionDurationTransformGenerator extends TransformGenerator {
|
||||
public getTransformParams(slo: SLO): TransformPutTransformRequest {
|
||||
|
@ -69,7 +69,7 @@ export class ApmTransactionDurationTransformGenerator extends TransformGenerator
|
|||
}
|
||||
|
||||
private buildSource(slo: SLO, indicator: APMTransactionDurationIndicator) {
|
||||
const queryFilter: Query[] = [
|
||||
const queryFilter: estypes.QueryDslQueryContainer[] = [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
|
@ -112,7 +112,7 @@ export class ApmTransactionDurationTransformGenerator extends TransformGenerator
|
|||
}
|
||||
|
||||
if (!!indicator.params.filter) {
|
||||
queryFilter.push(getElastichsearchQueryOrThrow(indicator.params.filter));
|
||||
queryFilter.push(getElasticsearchQueryOrThrow(indicator.params.filter));
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -11,7 +11,8 @@ import {
|
|||
apmTransactionErrorRateIndicatorSchema,
|
||||
timeslicesBudgetingMethodSchema,
|
||||
} from '@kbn/slo-schema';
|
||||
import { getElastichsearchQueryOrThrow, TransformGenerator } from '.';
|
||||
import { estypes } from '@elastic/elasticsearch';
|
||||
import { getElasticsearchQueryOrThrow, TransformGenerator } from '.';
|
||||
import {
|
||||
getSLOTransformId,
|
||||
SLO_DESTINATION_INDEX_NAME,
|
||||
|
@ -21,7 +22,6 @@ import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo
|
|||
import { APMTransactionErrorRateIndicator, SLO } from '../../../domain/models';
|
||||
import { InvalidTransformError } from '../../../errors';
|
||||
import { parseIndex } from './common';
|
||||
import { Query } from './types';
|
||||
|
||||
export class ApmTransactionErrorRateTransformGenerator extends TransformGenerator {
|
||||
public getTransformParams(slo: SLO): TransformPutTransformRequest {
|
||||
|
@ -68,7 +68,7 @@ export class ApmTransactionErrorRateTransformGenerator extends TransformGenerato
|
|||
}
|
||||
|
||||
private buildSource(slo: SLO, indicator: APMTransactionErrorRateIndicator) {
|
||||
const queryFilter: Query[] = [
|
||||
const queryFilter: estypes.QueryDslQueryContainer[] = [
|
||||
{
|
||||
range: {
|
||||
'@timestamp': {
|
||||
|
@ -111,7 +111,7 @@ export class ApmTransactionErrorRateTransformGenerator extends TransformGenerato
|
|||
}
|
||||
|
||||
if (indicator.params.filter) {
|
||||
queryFilter.push(getElastichsearchQueryOrThrow(indicator.params.filter));
|
||||
queryFilter.push(getElasticsearchQueryOrThrow(indicator.params.filter));
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -5,12 +5,24 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
|
||||
import { buildEsQuery, fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
|
||||
import { QuerySchema, kqlQuerySchema } from '@kbn/slo-schema';
|
||||
import { InvalidTransformError } from '../../../errors';
|
||||
|
||||
export function getElastichsearchQueryOrThrow(kuery: string | undefined = '') {
|
||||
export function getElasticsearchQueryOrThrow(kuery: QuerySchema = '') {
|
||||
try {
|
||||
return toElasticsearchQuery(fromKueryExpression(kuery));
|
||||
if (kqlQuerySchema.is(kuery)) {
|
||||
return toElasticsearchQuery(fromKueryExpression(kuery));
|
||||
} else {
|
||||
return buildEsQuery(
|
||||
undefined,
|
||||
{
|
||||
query: kuery?.kqlQuery,
|
||||
language: 'kuery',
|
||||
},
|
||||
kuery?.filters
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
throw new InvalidTransformError(`Invalid KQL: ${kuery}`);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
|
||||
import { InvalidTransformError } from '../../../errors';
|
||||
import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template';
|
||||
import { getElastichsearchQueryOrThrow, parseIndex, TransformGenerator } from '.';
|
||||
import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_NAME,
|
||||
SLO_INGEST_PIPELINE_NAME,
|
||||
|
@ -58,7 +58,7 @@ export class HistogramTransformGenerator extends TransformGenerator {
|
|||
},
|
||||
},
|
||||
},
|
||||
getElastichsearchQueryOrThrow(indicator.params.filter),
|
||||
getElasticsearchQueryOrThrow(indicator.params.filter),
|
||||
],
|
||||
},
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@ import { kqlCustomIndicatorSchema, timeslicesBudgetingMethodSchema } from '@kbn/
|
|||
|
||||
import { InvalidTransformError } from '../../../errors';
|
||||
import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template';
|
||||
import { getElastichsearchQueryOrThrow, parseIndex, TransformGenerator } from '.';
|
||||
import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_NAME,
|
||||
SLO_INGEST_PIPELINE_NAME,
|
||||
|
@ -53,7 +53,7 @@ export class KQLCustomTransformGenerator extends TransformGenerator {
|
|||
},
|
||||
},
|
||||
},
|
||||
getElastichsearchQueryOrThrow(indicator.params.filter),
|
||||
getElasticsearchQueryOrThrow(indicator.params.filter),
|
||||
],
|
||||
},
|
||||
},
|
||||
|
@ -68,8 +68,8 @@ export class KQLCustomTransformGenerator extends TransformGenerator {
|
|||
}
|
||||
|
||||
private buildAggregations(slo: SLO, indicator: KQLCustomIndicator) {
|
||||
const numerator = getElastichsearchQueryOrThrow(indicator.params.good);
|
||||
const denominator = getElastichsearchQueryOrThrow(indicator.params.total);
|
||||
const numerator = getElasticsearchQueryOrThrow(indicator.params.good);
|
||||
const denominator = getElasticsearchQueryOrThrow(indicator.params.total);
|
||||
|
||||
return {
|
||||
'slo.numerator': {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { metricCustomIndicatorSchema, timeslicesBudgetingMethodSchema } from '@k
|
|||
|
||||
import { InvalidTransformError } from '../../../errors';
|
||||
import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template';
|
||||
import { getElastichsearchQueryOrThrow, parseIndex, TransformGenerator } from '.';
|
||||
import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_NAME,
|
||||
SLO_INGEST_PIPELINE_NAME,
|
||||
|
@ -56,7 +56,7 @@ export class MetricCustomTransformGenerator extends TransformGenerator {
|
|||
},
|
||||
},
|
||||
},
|
||||
getElastichsearchQueryOrThrow(indicator.params.filter),
|
||||
getElasticsearchQueryOrThrow(indicator.params.filter),
|
||||
],
|
||||
},
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
|
||||
import { InvalidTransformError } from '../../../errors';
|
||||
import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template';
|
||||
import { getElastichsearchQueryOrThrow, parseIndex, TransformGenerator } from '.';
|
||||
import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.';
|
||||
import {
|
||||
SLO_DESTINATION_INDEX_NAME,
|
||||
SLO_INGEST_PIPELINE_NAME,
|
||||
|
@ -61,7 +61,7 @@ export class TimesliceMetricTransformGenerator extends TransformGenerator {
|
|||
},
|
||||
},
|
||||
},
|
||||
getElastichsearchQueryOrThrow(indicator.params.filter),
|
||||
getElasticsearchQueryOrThrow(indicator.params.filter),
|
||||
],
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue