CloudWatch: Use generated type from schema in backend (#66420)
* CloudWatch: Use generated type from schema in backend * address comments * don't explicity set default metric query type
This commit is contained in:
@@ -17,22 +17,23 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
|
||||
)
|
||||
|
||||
type (
|
||||
MetricEditorMode uint32
|
||||
MetricQueryType uint32
|
||||
MetricEditorMode dataquery.MetricEditorMode
|
||||
MetricQueryType dataquery.MetricQueryType
|
||||
GMDApiMode uint32
|
||||
)
|
||||
|
||||
const (
|
||||
MetricEditorModeBuilder MetricEditorMode = iota
|
||||
MetricEditorModeRaw
|
||||
MetricEditorModeBuilder = dataquery.CloudWatchMetricsQueryMetricEditorModeN0
|
||||
MetricEditorModeRaw = dataquery.CloudWatchMetricsQueryMetricEditorModeN1
|
||||
)
|
||||
|
||||
const (
|
||||
MetricQueryTypeSearch MetricQueryType = iota
|
||||
MetricQueryTypeQuery
|
||||
MetricQueryTypeSearch = dataquery.CloudWatchMetricsQueryMetricQueryTypeN0
|
||||
MetricQueryTypeQuery = dataquery.CloudWatchMetricsQueryMetricQueryTypeN1
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -67,8 +68,8 @@ type CloudWatchQuery struct {
|
||||
MatchExact bool
|
||||
UsedExpression string
|
||||
TimezoneUTCOffset string
|
||||
MetricQueryType MetricQueryType
|
||||
MetricEditorMode MetricEditorMode
|
||||
MetricQueryType dataquery.CloudWatchMetricsQueryMetricQueryType
|
||||
MetricEditorMode dataquery.CloudWatchMetricsQueryMetricEditorMode
|
||||
AccountId *string
|
||||
}
|
||||
|
||||
@@ -213,25 +214,9 @@ const timeSeriesQuery = "timeSeriesQuery"
|
||||
var validMetricDataID = regexp.MustCompile(`^[a-z][a-zA-Z0-9_]*$`)
|
||||
|
||||
type metricsDataQuery struct {
|
||||
Dimensions map[string]interface{} `json:"dimensions"`
|
||||
Expression string `json:"expression"`
|
||||
Label *string `json:"label"`
|
||||
Id string `json:"id"`
|
||||
MatchExact *bool `json:"matchExact"`
|
||||
MetricEditorMode *MetricEditorMode `json:"metricEditorMode"`
|
||||
MetricName string `json:"metricName"`
|
||||
MetricQueryType MetricQueryType `json:"metricQueryType"`
|
||||
Namespace string `json:"namespace"`
|
||||
Period string `json:"period"`
|
||||
Region string `json:"region"`
|
||||
SqlExpression string `json:"sqlExpression"`
|
||||
Statistic *string `json:"statistic"`
|
||||
Statistics []*string `json:"statistics"`
|
||||
TimezoneUTCOffset string `json:"timezoneUTCOffset"`
|
||||
QueryType string `json:"type"`
|
||||
Hide *bool `json:"hide"`
|
||||
Alias string `json:"alias"`
|
||||
AccountId *string `json:"accountId"`
|
||||
dataquery.CloudWatchMetricsQuery
|
||||
Type string `json:"type"`
|
||||
TimezoneUTCOffset string `json:"timezoneUTCOffset"`
|
||||
}
|
||||
|
||||
// ParseMetricDataQueries decodes the metric data queries json, validates, sets default values and returns an array of CloudWatchQueries.
|
||||
@@ -246,7 +231,7 @@ func ParseMetricDataQueries(dataQueries []backend.DataQuery, startTime time.Time
|
||||
return nil, &QueryError{Err: err, RefID: query.RefID}
|
||||
}
|
||||
|
||||
queryType := metricsDataQuery.QueryType
|
||||
queryType := metricsDataQuery.Type
|
||||
if queryType != timeSeriesQuery && queryType != "" {
|
||||
continue
|
||||
}
|
||||
@@ -255,19 +240,35 @@ func ParseMetricDataQueries(dataQueries []backend.DataQuery, startTime time.Time
|
||||
}
|
||||
|
||||
result := make([]*CloudWatchQuery, 0, len(metricDataQueries))
|
||||
|
||||
for refId, mdq := range metricDataQueries {
|
||||
cwQuery := &CloudWatchQuery{
|
||||
logger: logger,
|
||||
Alias: mdq.Alias,
|
||||
RefId: refId,
|
||||
Id: mdq.Id,
|
||||
Region: mdq.Region,
|
||||
Namespace: mdq.Namespace,
|
||||
MetricName: mdq.MetricName,
|
||||
MetricQueryType: mdq.MetricQueryType,
|
||||
SqlExpression: mdq.SqlExpression,
|
||||
TimezoneUTCOffset: mdq.TimezoneUTCOffset,
|
||||
Expression: mdq.Expression,
|
||||
}
|
||||
|
||||
if mdq.Alias != nil {
|
||||
cwQuery.Alias = *mdq.Alias
|
||||
}
|
||||
|
||||
if mdq.MetricName != nil {
|
||||
cwQuery.MetricName = *mdq.MetricName
|
||||
}
|
||||
|
||||
if mdq.MetricQueryType != nil {
|
||||
cwQuery.MetricQueryType = *mdq.MetricQueryType
|
||||
}
|
||||
|
||||
if mdq.SqlExpression != nil {
|
||||
cwQuery.SqlExpression = *mdq.SqlExpression
|
||||
}
|
||||
|
||||
if mdq.Expression != nil {
|
||||
cwQuery.Expression = *mdq.Expression
|
||||
}
|
||||
|
||||
if err := cwQuery.validateAndSetDefaults(refId, mdq, startTime, endTime, defaultRegion, crossAccountQueryingEnabled); err != nil {
|
||||
@@ -337,14 +338,14 @@ func (q *CloudWatchQuery) validateAndSetDefaults(refId string, metricsDataQuery
|
||||
if metricsDataQuery.Hide != nil {
|
||||
q.ReturnData = !*metricsDataQuery.Hide
|
||||
}
|
||||
if metricsDataQuery.QueryType == "" {
|
||||
if metricsDataQuery.Type == "" {
|
||||
// If no type is provided we assume we are called by alerting service, which requires to return data!
|
||||
// Note, this is sort of a hack, but the official Grafana interfaces do not carry the information
|
||||
// who (which service) called the TsdbQueryEndpoint.Query(...) function.
|
||||
q.ReturnData = true
|
||||
}
|
||||
|
||||
if metricsDataQuery.MetricEditorMode == nil && len(metricsDataQuery.Expression) > 0 {
|
||||
if metricsDataQuery.MetricEditorMode == nil && metricsDataQuery.Expression != nil && len(*metricsDataQuery.Expression) > 0 {
|
||||
// this should only ever happen if this is an alerting query that has not yet been migrated in the frontend
|
||||
q.MetricEditorMode = MetricEditorModeRaw
|
||||
} else {
|
||||
@@ -369,7 +370,7 @@ func (q *CloudWatchQuery) validateAndSetDefaults(refId string, metricsDataQuery
|
||||
func getStatistic(query metricsDataQuery) string {
|
||||
// If there's not a statistic property in the json, we know it's the legacy format and then it has to be migrated
|
||||
if query.Statistic == nil {
|
||||
return *query.Statistics[0]
|
||||
return query.Statistics[0]
|
||||
}
|
||||
return *query.Statistic
|
||||
}
|
||||
@@ -389,14 +390,17 @@ func getLabel(query metricsDataQuery, dynamicLabelsEnabled bool) string {
|
||||
if query.Label != nil {
|
||||
return *query.Label
|
||||
}
|
||||
if query.Alias == "" {
|
||||
if query.Alias != nil && *query.Alias == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
var result string
|
||||
if dynamicLabelsEnabled {
|
||||
fullAliasField := query.Alias
|
||||
matches := legacyAliasRegexp.FindAllStringSubmatch(query.Alias, -1)
|
||||
fullAliasField := ""
|
||||
if query.Alias != nil {
|
||||
fullAliasField = *query.Alias
|
||||
}
|
||||
matches := legacyAliasRegexp.FindAllStringSubmatch(fullAliasField, -1)
|
||||
|
||||
for _, groups := range matches {
|
||||
fullMatch := groups[0]
|
||||
@@ -428,7 +432,10 @@ func calculatePeriodBasedOnTimeRange(startTime, endTime time.Time) int {
|
||||
}
|
||||
|
||||
func getPeriod(query metricsDataQuery, startTime, endTime time.Time) (int, error) {
|
||||
periodString := query.Period
|
||||
periodString := ""
|
||||
if query.Period != nil {
|
||||
periodString = *query.Period
|
||||
}
|
||||
var period int
|
||||
var err error
|
||||
if strings.ToLower(periodString) == "auto" || periodString == "" {
|
||||
|
||||
@@ -8,10 +8,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/kindsys"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log/logtest"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
|
||||
)
|
||||
|
||||
@@ -294,7 +296,7 @@ func TestQueryJSON(t *testing.T) {
|
||||
var res metricsDataQuery
|
||||
err := json.Unmarshal(jsonString, &res)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "timeSeriesQuery", res.QueryType)
|
||||
assert.Equal(t, "timeSeriesQuery", res.Type)
|
||||
}
|
||||
|
||||
func TestRequestParser(t *testing.T) {
|
||||
@@ -622,11 +624,11 @@ func Test_ParseMetricDataQueries_periods(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_ParseMetricDataQueries_query_type_and_metric_editor_mode_and_GMD_query_api_mode(t *testing.T) {
|
||||
const dummyTestEditorMode MetricEditorMode = 99
|
||||
const dummyTestEditorMode dataquery.CloudWatchMetricsQueryMetricEditorMode = 99
|
||||
testCases := map[string]struct {
|
||||
extraDataQueryJson string
|
||||
expectedMetricQueryType MetricQueryType
|
||||
expectedMetricEditorMode MetricEditorMode
|
||||
expectedMetricQueryType dataquery.CloudWatchMetricsQueryMetricQueryType
|
||||
expectedMetricEditorMode dataquery.CloudWatchMetricsQueryMetricEditorMode
|
||||
expectedGMDApiMode GMDApiMode
|
||||
}{
|
||||
"no metric query type, no metric editor mode, no expression": {
|
||||
@@ -930,16 +932,18 @@ func Test_migrateAliasToDynamicLabel_single_query_preserves_old_alias_and_create
|
||||
false := false
|
||||
|
||||
queryToMigrate := metricsDataQuery{
|
||||
Region: "us-east-1",
|
||||
Namespace: "ec2",
|
||||
MetricName: "CPUUtilization",
|
||||
Alias: tc.inputAlias,
|
||||
Dimensions: map[string]interface{}{
|
||||
"InstanceId": []interface{}{"test"},
|
||||
CloudWatchMetricsQuery: dataquery.CloudWatchMetricsQuery{
|
||||
Region: "us-east-1",
|
||||
Namespace: "ec2",
|
||||
MetricName: kindsys.Ptr("CPUUtilization"),
|
||||
Alias: kindsys.Ptr(tc.inputAlias),
|
||||
Dimensions: map[string]interface{}{
|
||||
"InstanceId": []interface{}{"test"},
|
||||
},
|
||||
Statistic: &average,
|
||||
Period: kindsys.Ptr("600"),
|
||||
Hide: &false,
|
||||
},
|
||||
Statistic: &average,
|
||||
Period: "600",
|
||||
Hide: &false,
|
||||
}
|
||||
|
||||
assert.Equal(t, tc.expectedLabel, getLabel(queryToMigrate, true))
|
||||
|
||||
@@ -1,28 +1,18 @@
|
||||
package models
|
||||
|
||||
type LogGroup struct {
|
||||
ARN string `json:"arn"`
|
||||
Name string `json:"name"`
|
||||
AccountID string `json:"accountId"`
|
||||
}
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
|
||||
)
|
||||
|
||||
type LogsQuery struct {
|
||||
LogType string `json:"type"`
|
||||
SubType string
|
||||
Limit *int64
|
||||
Time int64
|
||||
StartTime *int64
|
||||
EndTime *int64
|
||||
LogGroupName string
|
||||
LogGroupNames []string
|
||||
LogGroups []LogGroup `json:"logGroups"`
|
||||
LogGroupNamePrefix string
|
||||
LogStreamName string
|
||||
StartFromHead bool
|
||||
Region string
|
||||
QueryString string
|
||||
QueryId string
|
||||
StatsGroups []string
|
||||
Subtype string
|
||||
Expression string
|
||||
dataquery.CloudWatchLogsQuery
|
||||
StartTime *int64
|
||||
EndTime *int64
|
||||
Limit *int64
|
||||
LogGroupName string
|
||||
LogStreamName string
|
||||
QueryId string
|
||||
QueryString string
|
||||
StartFromHead bool
|
||||
Subtype string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user