[SLOs] Allow slo query wild card filters !! (#213119)

## Summary

Allow slo query wild card filters when kql filter and dsl filter both
are used.

For KQL filter, allowLeadingWildcards was true by default. introduces
the ability to use wildcard filters in SLO queries when DSL filters are
also used.

### Changes Made
1. **Updated `getElasticsearchQueryOrThrow` function:**
- Added support for `dataView` parameter in the `toElasticsearchQuery`
function.
   - Included additional options for `allowLeadingWildcards`.
- Enhanced error handling to differentiate between invalid KQL and KQL
queries with invalid filters.

2. **Test Coverage:**
- Added new test cases to cover scenarios with wildcard queries and
filters.
This commit is contained in:
Shahzad 2025-03-06 17:45:23 +01:00 committed by GitHub
parent 263b85a8b9
commit 33f51f6d6e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 922 additions and 299 deletions

View file

@ -92,14 +92,23 @@ exports[`GetPreviewData for 'APM Availability' indicator type builds the query f
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"some.lable": "bar",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"some.lable": "bar",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -237,14 +246,23 @@ exports[`GetPreviewData for 'APM Availability' indicator type builds the query w
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"some.lable": "bar",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"some.lable": "bar",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -389,14 +407,23 @@ exports[`GetPreviewData for 'APM Availability' indicator type builds the query w
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"some.lable": "bar",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"some.lable": "bar",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -498,14 +525,23 @@ exports[`GetPreviewData for 'APM Availability' indicator type builds the query w
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"some.lable": "bar",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"some.lable": "bar",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -630,14 +666,23 @@ exports[`GetPreviewData for 'APM Latency' indicator type builds the query for a
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"some.lable": "foo",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"some.lable": "foo",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -797,14 +842,23 @@ exports[`GetPreviewData for 'APM Latency' indicator type builds the query with 1
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"some.lable": "foo",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"some.lable": "foo",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -971,14 +1025,23 @@ exports[`GetPreviewData for 'APM Latency' indicator type builds the query with 2
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"some.lable": "foo",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"some.lable": "foo",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -1093,14 +1156,23 @@ exports[`GetPreviewData for 'APM Latency' indicator type builds the query withou
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"some.lable": "foo",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"some.lable": "foo",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -1680,30 +1752,48 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query for a s
"good": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
"total": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -1732,14 +1822,23 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query for a s
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
Object {
@ -1782,30 +1881,48 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query with 1
"good": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
"total": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -1830,30 +1947,48 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query with 1
"good": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
"total": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -1882,14 +2017,23 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query with 1
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -1922,30 +2066,48 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query with 2
"good": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
"total": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -1977,30 +2139,48 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query with 2
"good": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
"total": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -2029,14 +2209,23 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query with 2
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -2067,30 +2256,48 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query without
"good": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"http.response.status_code": Object {
"lt": "500",
},
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
"total": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -2119,14 +2326,23 @@ exports[`GetPreviewData for 'Custom KQL' indicator type builds the query without
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.response.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],

View file

@ -12,14 +12,23 @@ Object {
},
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"test.category": "test",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"test.category": "test",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -94,14 +103,23 @@ Object {
"_A": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"test.category": "test",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"test.category": "test",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},

View file

@ -233,8 +233,25 @@ describe('Summary Search Client', () => {
{ term: { spaceId: 'default' } },
{
bool: {
minimum_should_match: 1,
should: [{ range: { summaryUpdatedAt: { gt: 'now-2h' } } }],
filter: [
{
bool: {
minimum_should_match: 1,
should: [
{
range: {
summaryUpdatedAt: {
gt: 'now-2h',
},
},
},
],
},
},
],
must: [],
must_not: [],
should: [],
},
},
],

View file

@ -53,29 +53,14 @@ Object {
"filter": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"my.field": "value",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"foo": Object {
"gte": "12",
},
"match_phrase": Object {
"my.field": "value",
},
},
],
@ -86,10 +71,31 @@ Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"bar": Object {
"lte": "100",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"foo": Object {
"gte": "12",
},
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"bar": Object {
"lte": "100",
},
},
},
],
},
},
],
@ -99,6 +105,9 @@ Object {
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],

View file

@ -49,29 +49,14 @@ Object {
"filter": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"my.field": "value",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"foo": Object {
"gte": "12",
},
"match_phrase": Object {
"my.field": "value",
},
},
],
@ -82,10 +67,31 @@ Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"bar": Object {
"lte": "100",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"foo": Object {
"gte": "12",
},
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"bar": Object {
"lte": "100",
},
},
},
],
},
},
],
@ -95,6 +101,9 @@ Object {
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],

View file

@ -57,14 +57,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-4",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-4",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -176,14 +185,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -305,14 +323,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -425,14 +452,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],

View file

@ -4,14 +4,23 @@ exports[`KQL Custom Transform Generator aggregates using the denominator kql 1`]
Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"exists": Object {
"field": "http.status_code",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"exists": Object {
"field": "http.status_code",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
}
@ -24,29 +33,16 @@ Object {
"filter": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"latency": Object {
"lt": "400",
},
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"http.status_code": "2xx",
"range": Object {
"latency": Object {
"lt": "400",
},
},
},
],
@ -57,20 +53,39 @@ Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"http.status_code": "3xx",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"http.status_code": "2xx",
},
},
],
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"http.status_code": "4xx",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"http.status_code": "3xx",
},
},
],
},
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"http.status_code": "4xx",
},
},
],
},
},
],
@ -80,6 +95,9 @@ Object {
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
}
@ -98,14 +116,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-4",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-4",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -146,16 +173,25 @@ Object {
"slo.numerator": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"range": Object {
"latency": Object {
"lt": "300",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"latency": Object {
"lt": "300",
},
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -190,14 +226,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -248,16 +293,25 @@ Object {
"slo.numerator": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"range": Object {
"latency": Object {
"lt": "300",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"latency": Object {
"lt": "300",
},
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -292,14 +346,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -341,16 +404,25 @@ Object {
"slo.numerator": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"range": Object {
"latency": Object {
"lt": "300",
},
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"range": Object {
"latency": Object {
"lt": "300",
},
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -385,14 +457,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],

View file

@ -97,14 +97,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-4",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-4",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -227,14 +236,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -358,14 +376,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match": Object {
"labels.groupId": "group-3",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],

View file

@ -13,14 +13,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match_phrase": Object {
"test.category": "test",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"test.category": "test",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -54,28 +63,46 @@ Object {
},
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match_phrase": Object {
"test.category": "test",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"test.category": "test",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
"_B": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match_phrase": Object {
"test.category": "test",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"test.category": "test",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -194,14 +221,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match_phrase": Object {
"test.category": "test",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"test.category": "test",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],
@ -245,28 +281,46 @@ Object {
},
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match_phrase": Object {
"test.category": "test",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"test.category": "test",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
"_B": Object {
"filter": Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match_phrase": Object {
"test.category": "test",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"test.category": "test",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
},
@ -385,14 +439,23 @@ Object {
},
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
"filter": Array [
Object {
"match_phrase": Object {
"test.category": "test",
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
"match_phrase": Object {
"test.category": "test",
},
},
],
},
},
],
"must": Array [],
"must_not": Array [],
"should": Array [],
},
},
],

View file

@ -8,7 +8,13 @@
import { fiveMinute, twoMinute } from '../fixtures/duration';
import { createSLO } from '../fixtures/slo';
import { thirtyDaysRolling } from '../fixtures/time_window';
import { getTimesliceTargetComparator, parseIndex, getFilterRange } from './common';
import {
getTimesliceTargetComparator,
parseIndex,
getFilterRange,
getElasticsearchQueryOrThrow,
} from './common';
import { createStubDataView } from '@kbn/data-views-plugin/common/data_views/data_view.stub';
describe('common', () => {
describe('parseIndex', () => {
@ -103,4 +109,136 @@ describe('common', () => {
});
});
});
describe('getElasticsearchQueryOrThrow', () => {
it('throws an error if the query is not a valid Elasticsearch query', () => {
expect(() => {
getElasticsearchQueryOrThrow('data:');
}).toThrowErrorMatchingInlineSnapshot(`"Invalid KQL: data:"`);
});
it('returns the query if it is a valid Elasticsearch query', () => {
expect(getElasticsearchQueryOrThrow('monitor.status: down')).toEqual({
bool: {
filter: [
{
bool: {
minimum_should_match: 1,
should: [
{
match: {
'monitor.status': 'down',
},
},
],
},
},
],
must: [],
must_not: [],
should: [],
},
});
});
it('works with wildcard queries', () => {
const mockDataView = createStubDataView({
spec: {
id: 'apm-*',
title: 'apm-*',
timeFieldName: '@timestamp',
fields: {
'monitor.status': {
name: 'monitor.status',
type: 'string',
esTypes: ['keyword'],
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
},
},
});
expect(getElasticsearchQueryOrThrow('monitor.status: *own', mockDataView)).toEqual({
bool: {
filter: [
{
bool: {
minimum_should_match: 1,
should: [
{
wildcard: {
'monitor.status': {
value: '*own',
},
},
},
],
},
},
],
must: [],
must_not: [],
should: [],
},
});
});
it('works with wildcard queries and filters', () => {
const mockDataView = createStubDataView({
spec: {
id: 'apm-*',
title: 'apm-*',
timeFieldName: '@timestamp',
fields: {
'monitor.status': {
name: 'monitor.status',
type: 'string',
esTypes: ['keyword'],
searchable: true,
aggregatable: true,
readFromDocValues: true,
},
},
},
});
expect(
getElasticsearchQueryOrThrow(
{ kqlQuery: 'monitor.status: *own', filters: [] },
mockDataView
)
).toEqual({
bool: {
filter: [
{
bool: {
minimum_should_match: 1,
should: [
{
wildcard: {
'monitor.status': {
value: '*own',
},
},
},
],
},
},
],
must: [],
must_not: [],
should: [],
},
});
});
it('works with empty queries and filters', () => {
expect(getElasticsearchQueryOrThrow('')).toEqual({
match_all: {},
});
expect(getElasticsearchQueryOrThrow({} as any)).toEqual({
match_all: {},
});
});
});
});

View file

@ -5,30 +5,39 @@
* 2.0.
*/
import { buildEsQuery, fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
import { buildEsQuery } from '@kbn/es-query';
import { QuerySchema, kqlQuerySchema } from '@kbn/slo-schema';
import { Logger } from '@kbn/logging';
import { DataView } from '@kbn/data-views-plugin/common';
import { isEmpty } from 'lodash';
import { SLODefinition } from '../../domain/models';
import { getDelayInSecondsFromSLO } from '../../domain/services/get_delay_in_seconds_from_slo';
import { InvalidTransformError } from '../../errors';
export function getElasticsearchQueryOrThrow(kuery: QuerySchema = '', dataView?: DataView) {
try {
if (kqlQuerySchema.is(kuery)) {
return toElasticsearchQuery(fromKueryExpression(kuery));
} else {
return buildEsQuery(
dataView,
{
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) {
throw new InvalidTransformError(`Invalid KQL: ${kuery}`);
if (kqlQuerySchema.is(kuery)) {
throw new InvalidTransformError(`Invalid KQL: ${kuery}`);
} else {
throw new InvalidTransformError(`Invalid KQL: ${kuery.kqlQuery}`);
}
}
}