[release-12.0.2] Alerting: Fix $value type when single data source is queried (#106101)

Alerting: Fix $value type when single data source is queried (#106080)

(cherry picked from commit faeddf334a)

Co-authored-by: Alexander Akhmetov <me@alx.cx>
pull/106116/head
grafana-delivery-bot[bot] 2 months ago committed by GitHub
parent 22b6da78a8
commit 982238b4bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 14
      pkg/services/ngalert/state/template/template.go
  2. 59
      pkg/services/ngalert/state/template/template_test.go

@ -77,18 +77,18 @@ type Data struct {
Values map[string]Value
// Value is the .Value and $value variables in templates.
// For single datasource queries, this will be the numeric value of the query.
// For multiple datasource queries, this will be the evaluation string.
Value string
// For single datasource queries, this will be the numeric value of the query (float64).
// For multiple datasource queries, this will be the evaluation string (string).
Value any
}
func NewData(labels map[string]string, res eval.Result) Data {
values := NewValues(res.Values)
// By default, use the evaluation string as the Value
valueStr := res.EvaluationString
var value any = res.EvaluationString
// If there's exactly one datasource node, use its value instead
// If there's exactly one datasource node, use its numeric value instead
// This makes the $value variable compatible with Prometheus templating
// where $value holds the numeric value of the alert query
datasourceNodeCount := 0
@ -105,13 +105,13 @@ func NewData(labels map[string]string, res eval.Result) Data {
}
if datasourceNodeCount == 1 {
valueStr = datasourceNodeValue.String()
value = datasourceNodeValue.Value
}
return Data{
Labels: labels,
Values: values,
Value: valueStr,
Value: value,
}
}

@ -3,6 +3,7 @@ package template
import (
"context"
"errors"
"math"
"net/url"
"testing"
@ -109,7 +110,7 @@ func TestNewData(t *testing.T) {
}
data := NewData(map[string]string{}, res)
assert.Equal(t, "10", data.Value)
assert.Equal(t, 10.0, data.Value)
})
t.Run("uses evaluation string when multiple datasource nodes exist", func(t *testing.T) {
@ -159,7 +160,7 @@ func TestDatasourceValueInTemplating(t *testing.T) {
data := NewData(map[string]string{}, res)
// In Prometheus, a nil value would be rendered as NaN
assert.Equal(t, "NaN", data.Value)
assert.True(t, math.IsNaN(data.Value.(float64)))
})
t.Run("single datasource node uses query value", func(t *testing.T) {
@ -188,7 +189,7 @@ func TestDatasourceValueInTemplating(t *testing.T) {
}
data := NewData(map[string]string{}, res)
assert.Equal(t, "10", data.Value)
assert.Equal(t, 10.0, data.Value)
})
t.Run("multiple datasource nodes uses evaluation string", func(t *testing.T) {
@ -636,8 +637,56 @@ func TestExpandTemplate(t *testing.T) {
name: "check that safeHtml doesn't error or panic",
text: "{{ \"<b>\" | safeHtml }}",
expected: "<b>",
},
}
}, {
name: "$value numeric comparison with single datasource",
text: `{{ if eq $value 1.0 }}equal{{ else }}not equal{{ end }}`,
alertInstance: eval.Result{
Values: map[string]eval.NumberValueCapture{
"A": {
Var: "A",
IsDatasourceNode: true,
Labels: data.Labels{"instance": "foo"},
Value: util.Pointer(1.0),
},
},
},
expected: "equal",
}, {
name: "humanize with string $value (multiple datasources)",
text: `{{ humanize $value }}`,
alertInstance: eval.Result{
EvaluationString: "1234567.0",
Values: map[string]eval.NumberValueCapture{
"A": {
Var: "A",
IsDatasourceNode: true,
Labels: data.Labels{"instance": "foo"},
Value: util.Pointer(10.0),
},
"B": {
Var: "B",
IsDatasourceNode: true,
Labels: data.Labels{"instance": "bar"},
Value: util.Pointer(20.0),
},
},
},
expected: "1.235M",
}, {
name: "humanize with numeric $value (single datasource)",
text: `{{ humanize $value }}`,
alertInstance: eval.Result{
Values: map[string]eval.NumberValueCapture{
"A": {
Var: "A",
IsDatasourceNode: true,
Labels: data.Labels{"instance": "foo"},
Value: util.Pointer(1234567.0),
},
},
},
expected: "1.235M",
}}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {

Loading…
Cancel
Save