grafana/pkg/services/ngalert/eval/extract_md.go
George Robinson 456dac1303
Expand the value of math and reduce expressions in annotations and labels (#36611)
* Expand the value of math and reduce expressions in annotations and labels

This commit makes it possible to use the values of reduce and math
expressions in annotations and labels via their RefIDs. It uses the
Stringer interface to ensure that "{{ $values.A }}" still prints the
value in decimal format while also making the labels for each RefID
available with "{{ $values.A.Labels }}" and the float64 value with
"{{ $values.A.Value }}"
2021-07-15 13:10:56 +01:00

89 lines
1.9 KiB
Go

package eval
import (
"fmt"
"strings"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/expr/classic"
)
func extractEvalString(frame *data.Frame) (s string) {
if frame == nil {
return "empty frame"
}
if frame.Meta == nil || frame.Meta.Custom == nil {
return
}
if evalMatches, ok := frame.Meta.Custom.([]classic.EvalMatch); ok {
sb := strings.Builder{}
for i, m := range evalMatches {
sb.WriteString("[ ")
sb.WriteString(fmt.Sprintf("metric='%s' ", m.Metric))
sb.WriteString(fmt.Sprintf("labels={%s} ", m.Labels))
valString := "null"
if m.Value != nil {
valString = fmt.Sprintf("%v", *m.Value)
}
sb.WriteString(fmt.Sprintf("value=%v ", valString))
sb.WriteString("]")
if i < len(evalMatches)-1 {
sb.WriteString(", ")
}
}
return sb.String()
}
if caps, ok := frame.Meta.Custom.([]NumberValueCapture); ok {
sb := strings.Builder{}
for i, c := range caps {
sb.WriteString("[ ")
sb.WriteString(fmt.Sprintf("var='%s' ", c.Var))
sb.WriteString(fmt.Sprintf("labels={%s} ", c.Labels))
valString := "null"
if c.Value != nil {
valString = fmt.Sprintf("%v", *c.Value)
}
sb.WriteString(fmt.Sprintf("value=%v ", valString))
sb.WriteString("]")
if i < len(caps)-1 {
sb.WriteString(", ")
}
}
return sb.String()
}
return ""
}
// extractValues returns the RefID and value for all reduce and math expressions
// in the frame. It does not return values for classic conditions as the values
// in classic conditions do not have a RefID. It returns nil if there are
// no results in the frame.
func extractValues(frame *data.Frame) map[string]NumberValueCapture {
if frame == nil {
return nil
}
if frame.Meta == nil || frame.Meta.Custom == nil {
return nil
}
if caps, ok := frame.Meta.Custom.([]NumberValueCapture); ok {
v := make(map[string]NumberValueCapture, len(caps))
for _, c := range caps {
v[c.Var] = c
}
return v
}
return nil
}