mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
7bb79158ed
commit
1cd8981be4
@ -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:
|
||||
|
@ -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])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,14 @@ func (s Series) SetLabels(ls data.Labels) { s.Frame.Fields[s.ValueIdx].Labels =
|
||||
|
||||
func (s Series) GetName() string { return s.Frame.Name }
|
||||
|
||||
func (s Series) GetMeta() interface{} {
|
||||
return s.Frame.Meta.Custom
|
||||
}
|
||||
|
||||
func (s Series) SetMeta(v interface{}) {
|
||||
s.Frame.SetMeta(&data.FrameMeta{Custom: v})
|
||||
}
|
||||
|
||||
// AsDataFrame returns the underlying *data.Frame.
|
||||
func (s Series) AsDataFrame() *data.Frame { return s.Frame }
|
||||
|
||||
|
@ -30,6 +30,8 @@ type Value interface {
|
||||
Value() interface{}
|
||||
GetLabels() data.Labels
|
||||
SetLabels(data.Labels)
|
||||
GetMeta() interface{}
|
||||
SetMeta(interface{})
|
||||
AsDataFrame() *data.Frame
|
||||
}
|
||||
|
||||
@ -48,6 +50,14 @@ func (s Scalar) GetLabels() data.Labels { return nil }
|
||||
|
||||
func (s Scalar) SetLabels(ls data.Labels) {}
|
||||
|
||||
func (s Scalar) GetMeta() interface{} {
|
||||
return s.Frame.Meta.Custom
|
||||
}
|
||||
|
||||
func (s Scalar) SetMeta(v interface{}) {
|
||||
s.Frame.SetMeta(&data.FrameMeta{Custom: v})
|
||||
}
|
||||
|
||||
// AsDataFrame returns the underlying *data.Frame.
|
||||
func (s Scalar) AsDataFrame() *data.Frame { return s.Frame }
|
||||
|
||||
@ -105,3 +115,11 @@ func NewNumber(name string, labels data.Labels) Number {
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (n Number) GetMeta() interface{} {
|
||||
return n.Frame.Meta.Custom
|
||||
}
|
||||
|
||||
func (n Number) SetMeta(v interface{}) {
|
||||
n.Frame.SetMeta(&data.FrameMeta{Custom: v})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user