SSE/NG: Add expression metadata for EvalMatch (#32213)

- Add the ability to stick metadata attached to a value in expressions. Currently uses Frame.Meta.Custom.
- None of this is consumed by anything yet, so an incremental step.
This commit is contained in:
Kyle Brandt
2021-03-23 12:23:54 -04:00
committed by GitHub
parent 7bb79158ed
commit 1cd8981be4
4 changed files with 76 additions and 9 deletions
+33
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/expr/mathexp"
)
@@ -59,6 +60,13 @@ func (ccc *ConditionsCmd) NeedsVars() []string {
return vars
}
// EvalMatch represents the series violating the threshold.
type EvalMatch struct {
Value *float64 `json:"value"`
Metric string `json:"metric"`
Labels data.Labels `json:"labels"`
}
// Execute runs the command and returns the results or an error if the command
// failed to execute.
func (ccc *ConditionsCmd) Execute(ctx context.Context, vars mathexp.Vars) (mathexp.Results, error) {
@@ -66,8 +74,11 @@ func (ccc *ConditionsCmd) Execute(ctx context.Context, vars mathexp.Vars) (mathe
newRes := mathexp.Results{}
noDataFound := true
matches := []EvalMatch{}
for i, c := range ccc.Conditions {
querySeriesSet := vars[c.QueryRefID]
nilReducedCount := 0
for _, val := range querySeriesSet.Values {
series, ok := val.(mathexp.Series)
if !ok {
@@ -78,8 +89,23 @@ func (ccc *ConditionsCmd) Execute(ctx context.Context, vars mathexp.Vars) (mathe
// TODO handle error / no data signals
thisCondNoDataFound := reducedNum.GetFloat64Value() == nil
if thisCondNoDataFound {
nilReducedCount++
}
evalRes := c.Evaluator.Eval(reducedNum)
if evalRes {
match := EvalMatch{
Value: reducedNum.GetFloat64Value(),
Metric: series.GetName(),
}
if reducedNum.GetLabels() != nil {
match.Labels = reducedNum.GetLabels().Copy()
}
matches = append(matches, match)
}
if i == 0 {
firing = evalRes
noDataFound = thisCondNoDataFound
@@ -93,10 +119,17 @@ func (ccc *ConditionsCmd) Execute(ctx context.Context, vars mathexp.Vars) (mathe
noDataFound = noDataFound && thisCondNoDataFound
}
}
if len(querySeriesSet.Values) == nilReducedCount {
matches = append(matches, EvalMatch{
Metric: "NoData",
})
}
}
num := mathexp.NewNumber("", nil)
num.SetMeta(matches)
var v float64
switch {
case noDataFound:
+17 -9
View File
@@ -114,15 +114,11 @@ func TestUnmarshalConditionCMD(t *testing.T) {
}
func TestConditionsCmdExecute(t *testing.T) {
trueNumber := valBasedNumber(ptr.Float64(1))
falseNumber := valBasedNumber(ptr.Float64(0))
noDataNumber := valBasedNumber(nil)
tests := []struct {
name string
vars mathexp.Vars
conditionsCmd *ConditionsCmd
resultNumber mathexp.Number
resultNumber func() mathexp.Number
}{
{
name: "single query and single condition",
@@ -142,7 +138,11 @@ func TestConditionsCmdExecute(t *testing.T) {
Evaluator: &thresholdEvaluator{Type: "gt", Threshold: 34},
},
}},
resultNumber: trueNumber,
resultNumber: func() mathexp.Number {
v := valBasedNumber(ptr.Float64(1))
v.SetMeta([]EvalMatch{{Value: ptr.Float64(35)}})
return v
},
},
{
name: "single query and single ranged condition",
@@ -163,7 +163,11 @@ func TestConditionsCmdExecute(t *testing.T) {
},
},
},
resultNumber: falseNumber,
resultNumber: func() mathexp.Number {
v := valBasedNumber(ptr.Float64(0))
v.SetMeta([]EvalMatch{})
return v
},
},
{
name: "single query with no data",
@@ -182,7 +186,11 @@ func TestConditionsCmdExecute(t *testing.T) {
},
},
},
resultNumber: noDataNumber,
resultNumber: func() mathexp.Number {
v := valBasedNumber(nil)
v.SetMeta([]EvalMatch{{Metric: "NoData"}})
return v
},
},
}
@@ -193,7 +201,7 @@ func TestConditionsCmdExecute(t *testing.T) {
require.Equal(t, 1, len(res.Values))
require.Equal(t, tt.resultNumber, res.Values[0])
require.Equal(t, tt.resultNumber(), res.Values[0])
})
}
}