mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
CloudWatch: Add tests for data frame naming in formatAlias (#47899)
This commit is contained in:
parent
15ea6d559a
commit
79d328fcbc
@ -136,3 +136,228 @@ func TestTimeSeriesQuery(t *testing.T) {
|
||||
assert.EqualError(t, err, "invalid time range: start time must be before end time")
|
||||
})
|
||||
}
|
||||
|
||||
type queryDimensions struct {
|
||||
InstanceID []string `json:"InstanceId,omitempty"`
|
||||
}
|
||||
|
||||
type queryParameters struct {
|
||||
MetricQueryType metricQueryType `json:"metricQueryType"`
|
||||
MetricEditorMode metricEditorMode `json:"metricEditorMode"`
|
||||
Dimensions queryDimensions `json:"dimensions"`
|
||||
Expression string `json:"expression"`
|
||||
Alias string `json:"alias"`
|
||||
Statistic string `json:"statistic"`
|
||||
Period string `json:"period"`
|
||||
MatchExact bool `json:"matchExact"`
|
||||
MetricName string `json:"metricName"`
|
||||
}
|
||||
|
||||
var queryId = "query id"
|
||||
|
||||
func newTestQuery(t testing.TB, p queryParameters) json.RawMessage {
|
||||
t.Helper()
|
||||
|
||||
tsq := struct {
|
||||
Type string `json:"type"`
|
||||
MetricQueryType metricQueryType `json:"metricQueryType"`
|
||||
MetricEditorMode metricEditorMode `json:"metricEditorMode"`
|
||||
Namespace string `json:"namespace"`
|
||||
MetricName string `json:"metricName"`
|
||||
Dimensions struct {
|
||||
InstanceID []string `json:"InstanceId,omitempty"`
|
||||
} `json:"dimensions"`
|
||||
Expression string `json:"expression"`
|
||||
Region string `json:"region"`
|
||||
ID string `json:"id"`
|
||||
Alias string `json:"alias"`
|
||||
Statistic string `json:"statistic"`
|
||||
Period string `json:"period"`
|
||||
MatchExact bool `json:"matchExact"`
|
||||
RefID string `json:"refId"`
|
||||
}{
|
||||
Type: "timeSeriesQuery",
|
||||
Region: "us-east-2",
|
||||
ID: queryId,
|
||||
RefID: "A",
|
||||
|
||||
MatchExact: p.MatchExact,
|
||||
MetricQueryType: p.MetricQueryType,
|
||||
MetricEditorMode: p.MetricEditorMode,
|
||||
Dimensions: p.Dimensions,
|
||||
Expression: p.Expression,
|
||||
Alias: p.Alias,
|
||||
Statistic: p.Statistic,
|
||||
Period: p.Period,
|
||||
MetricName: p.MetricName,
|
||||
}
|
||||
|
||||
marshalled, err := json.Marshal(tsq)
|
||||
require.NoError(t, err)
|
||||
|
||||
return marshalled
|
||||
}
|
||||
|
||||
func Test_QueryData_response_data_frame_names(t *testing.T) {
|
||||
origNewCWClient := NewCWClient
|
||||
t.Cleanup(func() {
|
||||
NewCWClient = origNewCWClient
|
||||
})
|
||||
var cwClient fakeCWClient
|
||||
NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
|
||||
return &cwClient
|
||||
}
|
||||
labelFromGetMetricData := "some label"
|
||||
cwClient = fakeCWClient{
|
||||
GetMetricDataOutput: cloudwatch.GetMetricDataOutput{
|
||||
MetricDataResults: []*cloudwatch.MetricDataResult{
|
||||
{StatusCode: aws.String("Complete"), Id: aws.String(queryId), Label: aws.String(labelFromGetMetricData),
|
||||
Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{{}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
im := datasource.NewInstanceManager(func(s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||
return datasourceInfo{}, nil
|
||||
})
|
||||
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
|
||||
|
||||
t.Run("where user defines search expression and alias is defined, then frame name prioritizes period and stat from expression over input", func(t *testing.T) {
|
||||
query := newTestQuery(t, queryParameters{
|
||||
MetricQueryType: MetricQueryTypeSearch, // contributes to isUserDefinedSearchExpression = true
|
||||
MetricEditorMode: MetricEditorModeRaw, // contributes to isUserDefinedSearchExpression = true
|
||||
Alias: "{{period}} {{stat}}",
|
||||
Expression: `SEARCH('{AWS/EC2,InstanceId} MetricName="CPUUtilization"', 'Average', 300)`, // period 300 and stat 'Average' parsed from this expression
|
||||
Statistic: "Maximum", // stat parsed from expression takes precedence over 'Maximum'
|
||||
Period: "1200", // period parsed from expression takes precedence over 1200
|
||||
})
|
||||
|
||||
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
|
||||
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
||||
Queries: []backend.DataQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
TimeRange: backend.TimeRange{From: time.Now().Add(time.Hour * -2), To: time.Now().Add(time.Hour * -1)},
|
||||
JSON: query,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "300 Average", resp.Responses["A"].Frames[0].Name)
|
||||
})
|
||||
|
||||
t.Run("where no alias is provided and query is math expression, then frame name is queryId", func(t *testing.T) {
|
||||
query := newTestQuery(t, queryParameters{
|
||||
MetricQueryType: MetricQueryTypeSearch,
|
||||
MetricEditorMode: MetricEditorModeRaw,
|
||||
})
|
||||
|
||||
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
|
||||
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
||||
Queries: []backend.DataQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
TimeRange: backend.TimeRange{From: time.Now().Add(time.Hour * -2), To: time.Now().Add(time.Hour * -1)},
|
||||
JSON: query,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, queryId, resp.Responses["A"].Frames[0].Name)
|
||||
})
|
||||
|
||||
t.Run("where no alias provided and query type is MetricQueryTypeQuery, then frame name is label", func(t *testing.T) {
|
||||
query := newTestQuery(t, queryParameters{
|
||||
MetricQueryType: MetricQueryTypeQuery,
|
||||
})
|
||||
|
||||
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
|
||||
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
||||
Queries: []backend.DataQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
TimeRange: backend.TimeRange{From: time.Now().Add(time.Hour * -2), To: time.Now().Add(time.Hour * -1)},
|
||||
JSON: query,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, labelFromGetMetricData, resp.Responses["A"].Frames[0].Name)
|
||||
})
|
||||
|
||||
// where query is inferred search expression and not multivalued dimension expression, then frame name is label
|
||||
testCasesReturningLabel := map[string]queryParameters{
|
||||
"with specific dimensions, matchExact false": {Dimensions: queryDimensions{[]string{"some-instance"}}, MatchExact: false},
|
||||
"with wildcard dimensions, matchExact false": {Dimensions: queryDimensions{[]string{"*"}}, MatchExact: false},
|
||||
"with wildcard dimensions, matchExact true": {Dimensions: queryDimensions{[]string{"*"}}, MatchExact: true},
|
||||
"no dimension, matchExact false": {Dimensions: queryDimensions{}, MatchExact: false},
|
||||
}
|
||||
for name, parameters := range testCasesReturningLabel {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
query := newTestQuery(t, parameters)
|
||||
|
||||
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
|
||||
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
||||
Queries: []backend.DataQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
TimeRange: backend.TimeRange{From: time.Now().Add(time.Hour * -2), To: time.Now().Add(time.Hour * -1)},
|
||||
JSON: query,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, labelFromGetMetricData, resp.Responses["A"].Frames[0].Name)
|
||||
})
|
||||
}
|
||||
|
||||
// complementary test cases to above return default of "metricName_stat"
|
||||
testCasesReturningMetricStat := map[string]queryParameters{
|
||||
"with specific dimensions, matchExact true": {
|
||||
Dimensions: queryDimensions{[]string{"some-instance"}},
|
||||
MatchExact: true,
|
||||
MetricName: "CPUUtilization",
|
||||
Statistic: "Maximum",
|
||||
},
|
||||
"no dimensions, matchExact true": {
|
||||
Dimensions: queryDimensions{},
|
||||
MatchExact: true,
|
||||
MetricName: "CPUUtilization",
|
||||
Statistic: "Maximum",
|
||||
},
|
||||
"multivalued dimensions, matchExact true": {
|
||||
Dimensions: queryDimensions{[]string{"some-instance", "another-instance"}},
|
||||
MatchExact: true,
|
||||
MetricName: "CPUUtilization",
|
||||
Statistic: "Maximum",
|
||||
},
|
||||
"multivalued dimensions, matchExact false": {
|
||||
Dimensions: queryDimensions{[]string{"some-instance", "another-instance"}},
|
||||
MatchExact: false,
|
||||
MetricName: "CPUUtilization",
|
||||
Statistic: "Maximum",
|
||||
},
|
||||
}
|
||||
for name, parameters := range testCasesReturningMetricStat {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
query := newTestQuery(t, parameters)
|
||||
|
||||
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
|
||||
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
|
||||
Queries: []backend.DataQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
TimeRange: backend.TimeRange{From: time.Now().Add(time.Hour * -2), To: time.Now().Add(time.Hour * -1)},
|
||||
JSON: query,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "CPUUtilization_Maximum", resp.Responses["A"].Frames[0].Name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user