From 995ec001210d67c3854b428f43b626c70b90ab46 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Wed, 17 Nov 2021 05:34:51 -0500 Subject: [PATCH] Alerting: fix a bug where the metric in the evaluation string was not correctly populated (#41731) (#41793) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using the frame name as the series name, we now use the name of the series value column if the frame name is not set. Queries to some datasources may end up with an empty frame name, which leads to an empty series name. As the series name is used in the frontend to display which metrics were queried etc. it shouldn't be empty. (cherry picked from commit 2319c52c8507583d52ac492461d1634b9472f9c2) Co-authored-by: Jean-Philippe Quéméner --- pkg/expr/mathexp/type_series.go | 7 +++- pkg/expr/mathexp/types_test.go | 60 +++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/pkg/expr/mathexp/type_series.go b/pkg/expr/mathexp/type_series.go index 00962141d43..8bb44439487 100644 --- a/pkg/expr/mathexp/type_series.go +++ b/pkg/expr/mathexp/type_series.go @@ -118,6 +118,11 @@ FIELDS: frame.Fields = fields s.Frame = frame + // We use the frame name as series name if the frame name is set + if s.Frame.Name != "" { + s.Frame.Fields[seriesTypeValIdx].Name = s.Frame.Name + } + return s, nil } @@ -142,7 +147,7 @@ func (s Series) GetLabels() data.Labels { return s.Frame.Fields[seriesTypeValIdx func (s Series) SetLabels(ls data.Labels) { s.Frame.Fields[seriesTypeValIdx].Labels = ls } -func (s Series) GetName() string { return s.Frame.Name } +func (s Series) GetName() string { return s.Frame.Fields[seriesTypeValIdx].Name } func (s Series) GetMeta() interface{} { return s.Frame.Meta.Custom diff --git a/pkg/expr/mathexp/types_test.go b/pkg/expr/mathexp/types_test.go index d5ec735711b..dcdcaf56125 100644 --- a/pkg/expr/mathexp/types_test.go +++ b/pkg/expr/mathexp/types_test.go @@ -6,6 +6,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestSeriesSort(t *testing.T) { @@ -76,7 +77,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]time, []float frame should convert", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{}), data.NewField("value", nil, []float64{}), @@ -86,7 +86,6 @@ func TestSeriesFromFrame(t *testing.T) { Is: assert.Equal, Series: Series{ Frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{}), data.NewField("value", nil, []*float64{}), @@ -97,7 +96,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]time, []*float frame should convert", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), data.NewField("value", nil, []*float64{float64Pointer(5)}), @@ -107,7 +105,6 @@ func TestSeriesFromFrame(t *testing.T) { Is: assert.Equal, Series: Series{ Frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), data.NewField("value", nil, []*float64{float64Pointer(5)}), @@ -118,7 +115,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]*float, []time frame should convert", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("value", nil, []*float64{float64Pointer(5)}), data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), @@ -128,7 +124,6 @@ func TestSeriesFromFrame(t *testing.T) { Is: assert.Equal, Series: Series{ Frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), data.NewField("value", nil, []*float64{float64Pointer(5)}), @@ -139,7 +134,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]*int, []*time frame should convert", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []*time.Time{unixTimePointer(5, 0)}), data.NewField("value", nil, []*int64{int64Pointer(5)}), @@ -149,7 +143,6 @@ func TestSeriesFromFrame(t *testing.T) { Is: assert.Equal, Series: Series{ Frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), data.NewField("value", nil, []*float64{float64Pointer(5)}), @@ -160,7 +153,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]int, []*time frame should convert", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []*time.Time{unixTimePointer(5, 0)}), data.NewField("value", nil, []int64{5}), @@ -170,7 +162,6 @@ func TestSeriesFromFrame(t *testing.T) { Is: assert.Equal, Series: Series{ Frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), data.NewField("value", nil, []*float64{float64Pointer(5)}), @@ -181,7 +172,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]string, []*time frame should convert", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []*time.Time{unixTimePointer(5, 0)}), data.NewField("value", nil, []string{"5"}), @@ -191,7 +181,6 @@ func TestSeriesFromFrame(t *testing.T) { Is: assert.Equal, Series: Series{ Frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), data.NewField("value", nil, []*float64{float64Pointer(5)}), @@ -202,7 +191,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]*string, []*time frame should convert", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []*time.Time{unixTimePointer(5, 0)}), data.NewField("value", nil, []*string{strPointer("5")}), @@ -212,7 +200,6 @@ func TestSeriesFromFrame(t *testing.T) { Is: assert.Equal, Series: Series{ Frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), data.NewField("value", nil, []*float64{float64Pointer(5)}), @@ -223,7 +210,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]bool, []*time frame should convert", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []*time.Time{unixTimePointer(5, 0)}), data.NewField("value", nil, []bool{true}), @@ -233,7 +219,6 @@ func TestSeriesFromFrame(t *testing.T) { Is: assert.Equal, Series: Series{ Frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), data.NewField("value", nil, []*float64{float64Pointer(1)}), @@ -244,7 +229,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]*bool, []*time frame should convert", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []*time.Time{unixTimePointer(5, 0)}), data.NewField("value", nil, []*bool{boolPointer(true)}), @@ -254,7 +238,6 @@ func TestSeriesFromFrame(t *testing.T) { Is: assert.Equal, Series: Series{ Frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []time.Time{time.Unix(5, 0)}), data.NewField("value", nil, []*float64{float64Pointer(1)}), @@ -265,7 +248,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]*time, []*time frame should error", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("time", nil, []*time.Time{}), data.NewField("time", nil, []*time.Time{}), @@ -276,7 +258,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]*float64, []float64 frame should error", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("value", nil, []*float64{}), data.NewField("value", nil, []*float64{}), @@ -287,7 +268,6 @@ func TestSeriesFromFrame(t *testing.T) { { name: "[]*float64 frame should error", frame: &data.Frame{ - Name: "test", Fields: []*data.Field{ data.NewField("value", nil, []*float64{}), }, @@ -305,3 +285,41 @@ func TestSeriesFromFrame(t *testing.T) { }) } } + +func TestSeriesName(t *testing.T) { + tests := []struct { + name string + frame *data.Frame + expectedSeriesName string + }{ + { + name: "when the frame got a name this name should be used", + frame: &data.Frame{ + Name: "test", + Fields: []*data.Field{ + data.NewField("time", nil, []time.Time{}), + data.NewField("value", nil, []float64{}), + }, + }, + expectedSeriesName: "test", + }, + { + name: "when a frame got no name the name of the value column should be used", + frame: &data.Frame{ + Name: "", + Fields: []*data.Field{ + data.NewField("time", nil, []time.Time{}), + data.NewField("value", nil, []float64{}), + }, + }, + expectedSeriesName: "value", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + s, err := SeriesFromFrame(test.frame) + require.NoError(t, err) + require.Equal(t, test.expectedSeriesName, s.GetName()) + }) + } +}