package azuremonitor import ( "encoding/json" "os" "path/filepath" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/stretchr/testify/require" "github.com/xorcare/pointer" ) func TestInsightsMetricsResultToFrame(t *testing.T) { tests := []struct { name string testFile string metric string alias string agg string dimensions []string expectedFrame func() *data.Frame }{ { name: "single series", testFile: "applicationinsights/4-application-insights-response-metrics-no-segment.json", metric: "value", agg: "avg", expectedFrame: func() *data.Frame { frame := data.NewFrame("", data.NewField("StartTime", nil, []time.Time{ time.Date(2019, 9, 13, 1, 2, 3, 456789000, time.UTC), time.Date(2019, 9, 13, 2, 2, 3, 456789000, time.UTC), }), data.NewField("value", nil, []*float64{ pointer.Float64(1), pointer.Float64(2), }), ) return frame }, }, { name: "empty response", testFile: "applicationinsights/5-application-insights-empty-response.json", metric: "value", agg: "avg", expectedFrame: func() *data.Frame { frame := data.NewFrame("", data.NewField("StartTime", nil, []time.Time{})) return frame }, }, { name: "segmented series", testFile: "applicationinsights/4-application-insights-response-metrics-segmented.json", metric: "value", agg: "avg", dimensions: []string{"blob"}, expectedFrame: func() *data.Frame { frame := data.NewFrame("", data.NewField("StartTime", nil, []time.Time{ time.Date(2019, 9, 13, 1, 2, 3, 456789000, time.UTC), time.Date(2019, 9, 13, 2, 2, 3, 456789000, time.UTC), }), data.NewField("value", data.Labels{"blob": "a"}, []*float64{ pointer.Float64(1), pointer.Float64(2), }), data.NewField("value", data.Labels{"blob": "b"}, []*float64{ pointer.Float64(3), pointer.Float64(4), }), ) return frame }, }, { name: "multi segmented series", testFile: "applicationinsights/4-application-insights-response-metrics-multi-segmented.json", metric: "traces/count", agg: "sum", dimensions: []string{"client/countryOrRegion", "client/city"}, expectedFrame: func() *data.Frame { frame := data.NewFrame("", data.NewField("StartTime", nil, []time.Time{ time.Date(2020, 6, 25, 16, 15, 32, 14e7, time.UTC), time.Date(2020, 6, 25, 16, 16, 0, 0, time.UTC), }), data.NewField("traces/count", data.Labels{"client/city": "Tokyo", "client/countryOrRegion": "Japan"}, []*float64{ nil, pointer.Float64(1), }), data.NewField("traces/count", data.Labels{"client/city": "", "client/countryOrRegion": "United States"}, []*float64{ nil, pointer.Float64(11), }), data.NewField("traces/count", data.Labels{"client/city": "Chicago", "client/countryOrRegion": "United States"}, []*float64{ nil, pointer.Float64(3), }), data.NewField("traces/count", data.Labels{"client/city": "Des Moines", "client/countryOrRegion": "United States"}, []*float64{ pointer.Float64(2), pointer.Float64(1), }), data.NewField("traces/count", data.Labels{"client/city": "Washington", "client/countryOrRegion": "United States"}, []*float64{ pointer.Float64(2), nil, }), ) return frame }, }, { name: "segmented series with alias", testFile: "applicationinsights/4-application-insights-response-metrics-multi-segmented.json", metric: "traces/count", alias: "{{ metric }}: Country,City: {{ client/countryOrRegion }},{{ client/city }}", agg: "sum", dimensions: []string{"client/countryOrRegion", "client/city"}, expectedFrame: func() *data.Frame { frame := data.NewFrame("", data.NewField("StartTime", nil, []time.Time{ time.Date(2020, 6, 25, 16, 15, 32, 14e7, time.UTC), time.Date(2020, 6, 25, 16, 16, 0, 0, time.UTC), }), data.NewField("traces/count", data.Labels{"client/city": "Tokyo", "client/countryOrRegion": "Japan"}, []*float64{ nil, pointer.Float64(1), }).SetConfig(&data.FieldConfig{DisplayName: "traces/count: Country,City: Japan,Tokyo"}), data.NewField("traces/count", data.Labels{"client/city": "", "client/countryOrRegion": "United States"}, []*float64{ nil, pointer.Float64(11), }).SetConfig(&data.FieldConfig{DisplayName: "traces/count: Country,City: United States,"}), data.NewField("traces/count", data.Labels{"client/city": "Chicago", "client/countryOrRegion": "United States"}, []*float64{ nil, pointer.Float64(3), }).SetConfig(&data.FieldConfig{DisplayName: "traces/count: Country,City: United States,Chicago"}), data.NewField("traces/count", data.Labels{"client/city": "Des Moines", "client/countryOrRegion": "United States"}, []*float64{ pointer.Float64(2), pointer.Float64(1), }).SetConfig(&data.FieldConfig{DisplayName: "traces/count: Country,City: United States,Des Moines"}), data.NewField("traces/count", data.Labels{"client/city": "Washington", "client/countryOrRegion": "United States"}, []*float64{ pointer.Float64(2), nil, }).SetConfig(&data.FieldConfig{DisplayName: "traces/count: Country,City: United States,Washington"}), ) return frame }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { res := loadInsightsMetricsResponse(t, tt.testFile) frame, err := InsightsMetricsResultToFrame(res, tt.metric, tt.agg, tt.dimensions) require.NoError(t, err) applyInsightsMetricAlias(frame, tt.alias) if diff := cmp.Diff(tt.expectedFrame(), frame, data.FrameTestCompareOptions()...); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) } } func loadInsightsMetricsResponse(t *testing.T, name string) MetricsResult { t.Helper() path := filepath.Join("testdata", name) // Ignore gosec warning G304 since it's a test // nolint:gosec f, err := os.Open(path) require.NoError(t, err) defer func() { err := f.Close() require.NoError(t, err) }() d := json.NewDecoder(f) var mr MetricsResult err = d.Decode(&mr) require.NoError(t, err) return mr }