Elasticsearch: Fix processing of response with multiple group by for alerting (#65165)
* Elasticsearch: Fix processing of response with multiple group by on backend * Remove unused param from createFields * Switch comments
This commit is contained in:
@@ -665,7 +665,7 @@ func processAggregationDocs(esAgg *simplejson.Json, aggDef *BucketAgg, target *Q
|
|||||||
queryResult *backend.DataResponse, props map[string]string) error {
|
queryResult *backend.DataResponse, props map[string]string) error {
|
||||||
propKeys := createPropKeys(props)
|
propKeys := createPropKeys(props)
|
||||||
frames := data.Frames{}
|
frames := data.Frames{}
|
||||||
fields := createFieldsFromPropKeys(queryResult.Frames, propKeys)
|
fields := createFields(queryResult.Frames, propKeys)
|
||||||
|
|
||||||
for _, v := range esAgg.Get("buckets").MustArray() {
|
for _, v := range esAgg.Get("buckets").MustArray() {
|
||||||
bucket := simplejson.NewFromAny(v)
|
bucket := simplejson.NewFromAny(v)
|
||||||
@@ -675,7 +675,8 @@ func processAggregationDocs(esAgg *simplejson.Json, aggDef *BucketAgg, target *Q
|
|||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
for _, propKey := range propKeys {
|
for _, propKey := range propKeys {
|
||||||
if field.Name == propKey {
|
if field.Name == propKey {
|
||||||
field.Append(props[propKey])
|
value := props[propKey]
|
||||||
|
field.Append(&value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if field.Name == aggDef.Field {
|
if field.Name == aggDef.Field {
|
||||||
@@ -1134,9 +1135,15 @@ func setSearchWords(frame *data.Frame, searchWords map[string]bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFieldsFromPropKeys(frames data.Frames, propKeys []string) []*data.Field {
|
func createFields(frames data.Frames, propKeys []string) []*data.Field {
|
||||||
var fields []*data.Field
|
var fields []*data.Field
|
||||||
if frames == nil {
|
// Otherwise use the fields from frames
|
||||||
|
if frames != nil {
|
||||||
|
for _, frame := range frames {
|
||||||
|
fields = append(fields, frame.Fields...)
|
||||||
|
}
|
||||||
|
// If we have no frames, we create fields from propKeys
|
||||||
|
} else {
|
||||||
for _, propKey := range propKeys {
|
for _, propKey := range propKeys {
|
||||||
fields = append(fields, data.NewField(propKey, nil, []*string{}))
|
fields = append(fields, data.NewField(propKey, nil, []*string{}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1472,14 +1472,14 @@ func TestResponseParser(t *testing.T) {
|
|||||||
|
|
||||||
require.Len(t, result.response.Responses, 1)
|
require.Len(t, result.response.Responses, 1)
|
||||||
frames := result.response.Responses["A"].Frames
|
frames := result.response.Responses["A"].Frames
|
||||||
require.True(t, len(frames) > 0) // FIXME
|
require.True(t, len(frames) > 0)
|
||||||
|
|
||||||
for _, field := range frames[0].Fields {
|
for _, field := range frames[0].Fields {
|
||||||
trueValue := true
|
trueValue := true
|
||||||
filterableConfig := data.FieldConfig{Filterable: &trueValue}
|
filterableConfig := data.FieldConfig{Filterable: &trueValue}
|
||||||
|
|
||||||
// we need to test that the only changed setting is `filterable`
|
// we need to test that the only changed setting is `filterable`
|
||||||
require.Equal(t, filterableConfig, *field.Config) // FIXME
|
require.Equal(t, filterableConfig, *field.Config)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -1641,6 +1641,92 @@ func TestResponseParser(t *testing.T) {
|
|||||||
requireFloatAt(t, 2, f3, 0)
|
requireFloatAt(t, 2, f3, 0)
|
||||||
requireFloatAt(t, 2, f3, 1)
|
requireFloatAt(t, 2, f3, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("With max and multiple terms agg", func(t *testing.T) {
|
||||||
|
targets := map[string]string{
|
||||||
|
"A": `{
|
||||||
|
"metrics": [
|
||||||
|
{
|
||||||
|
"type": "max",
|
||||||
|
"field": "counter",
|
||||||
|
"id": "1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bucketAggs": [{ "type": "terms", "field": "label", "id": "2" }, { "type": "terms", "field": "level", "id": "3" }]
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
response := `{
|
||||||
|
"responses": [{
|
||||||
|
"aggregations": {
|
||||||
|
"2": {
|
||||||
|
"buckets": [
|
||||||
|
{
|
||||||
|
"key": "val3",
|
||||||
|
"3": {
|
||||||
|
"buckets": [
|
||||||
|
{ "key": "info", "1": { "value": "299" } }, { "key": "error", "1": {"value": "300"} }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "val2",
|
||||||
|
"3": {
|
||||||
|
"buckets": [
|
||||||
|
{"key": "info", "1": {"value": "300"}}, {"key": "error", "1": {"value": "298"} }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "val1",
|
||||||
|
"3": {
|
||||||
|
"buckets": [
|
||||||
|
{"key": "info", "1": {"value": "299"}}, {"key": "error", "1": {"value": "296"} }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}`
|
||||||
|
|
||||||
|
result, err := parseTestResponse(targets, response)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Len(t, result.Responses, 1)
|
||||||
|
frames := result.Responses["A"].Frames
|
||||||
|
require.Len(t, frames, 1)
|
||||||
|
requireFrameLength(t, frames[0], 6)
|
||||||
|
require.Len(t, frames[0].Fields, 3)
|
||||||
|
|
||||||
|
f1 := frames[0].Fields[0]
|
||||||
|
f2 := frames[0].Fields[1]
|
||||||
|
f3 := frames[0].Fields[2]
|
||||||
|
|
||||||
|
require.Equal(t, "label", f1.Name)
|
||||||
|
require.Equal(t, "level", f2.Name)
|
||||||
|
require.Equal(t, "Max", f3.Name)
|
||||||
|
|
||||||
|
requireStringAt(t, "val3", f1, 0)
|
||||||
|
requireStringAt(t, "val3", f1, 1)
|
||||||
|
requireStringAt(t, "val2", f1, 2)
|
||||||
|
requireStringAt(t, "val2", f1, 3)
|
||||||
|
requireStringAt(t, "val1", f1, 4)
|
||||||
|
requireStringAt(t, "val1", f1, 5)
|
||||||
|
|
||||||
|
requireStringAt(t, "info", f2, 0)
|
||||||
|
requireStringAt(t, "error", f2, 1)
|
||||||
|
requireStringAt(t, "info", f2, 2)
|
||||||
|
requireStringAt(t, "error", f2, 3)
|
||||||
|
requireStringAt(t, "info", f2, 4)
|
||||||
|
requireStringAt(t, "error", f2, 5)
|
||||||
|
|
||||||
|
requireFloatAt(t, 299, f3, 0)
|
||||||
|
requireFloatAt(t, 300, f3, 1)
|
||||||
|
requireFloatAt(t, 300, f3, 2)
|
||||||
|
requireFloatAt(t, 298, f3, 3)
|
||||||
|
requireFloatAt(t, 299, f3, 4)
|
||||||
|
requireFloatAt(t, 296, f3, 5)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTestResponse(tsdbQueries map[string]string, responseBody string) (*backend.QueryDataResponse, error) {
|
func parseTestResponse(tsdbQueries map[string]string, responseBody string) (*backend.QueryDataResponse, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user