GoogleCloudMonitoring: Refactor types (#58644)
This commit is contained in:
@@ -62,7 +62,6 @@ const (
|
||||
annotationQueryType = "annotation"
|
||||
metricQueryType = "metrics"
|
||||
sloQueryType = "slo"
|
||||
mqlEditorMode = "mql"
|
||||
crossSeriesReducerDefault = "REDUCE_NONE"
|
||||
perSeriesAlignerDefault = "ALIGN_MEAN"
|
||||
)
|
||||
@@ -217,16 +216,20 @@ func migrateRequest(req *backend.QueryDataRequest) error {
|
||||
|
||||
if rawQuery["metricQuery"] == nil {
|
||||
// migrate legacy query
|
||||
var mq metricQuery
|
||||
var mq timeSeriesList
|
||||
err = json.Unmarshal(q.JSON, &mq)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
q.QueryType = metricQueryType
|
||||
gq := grafanaQuery{
|
||||
TimeSeriesList: &mq,
|
||||
}
|
||||
if rawQuery["aliasBy"] != nil {
|
||||
gq.AliasBy = rawQuery["aliasBy"].(string)
|
||||
}
|
||||
|
||||
b, err := json.Marshal(grafanaQuery{
|
||||
QueryType: metricQueryType,
|
||||
MetricQuery: mq,
|
||||
})
|
||||
b, err := json.Marshal(gq)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -237,6 +240,62 @@ func migrateRequest(req *backend.QueryDataRequest) error {
|
||||
if rawQuery["type"] != nil && rawQuery["type"].(string) == "annotationQuery" {
|
||||
q.QueryType = annotationQueryType
|
||||
}
|
||||
if rawQuery["queryType"] != nil {
|
||||
q.QueryType = rawQuery["queryType"].(string)
|
||||
}
|
||||
|
||||
// Metric query was divided between timeSeriesList and timeSeriesQuery API calls
|
||||
if rawQuery["metricQuery"] != nil {
|
||||
metricQuery := rawQuery["metricQuery"].(map[string]interface{})
|
||||
|
||||
if metricQuery["editorMode"] != nil && toString(metricQuery["editorMode"]) == "mql" {
|
||||
rawQuery["timeSeriesQuery"] = &timeSeriesQuery{
|
||||
ProjectName: toString(metricQuery["projectName"]),
|
||||
Query: toString(metricQuery["query"]),
|
||||
GraphPeriod: toString(metricQuery["graphPeriod"]),
|
||||
}
|
||||
} else {
|
||||
rawQuery["timeSeriesList"] = metricQuery
|
||||
}
|
||||
if metricQuery["aliasBy"] != nil {
|
||||
rawQuery["aliasBy"] = metricQuery["aliasBy"]
|
||||
}
|
||||
b, err := json.Marshal(rawQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if q.QueryType == "" {
|
||||
q.QueryType = metricQueryType
|
||||
}
|
||||
q.JSON = b
|
||||
}
|
||||
|
||||
// SloQuery was merged into timeSeriesList
|
||||
if rawQuery["sloQuery"] != nil {
|
||||
if rawQuery["timeSeriesList"] == nil {
|
||||
rawQuery["timeSeriesList"] = map[string]interface{}{}
|
||||
}
|
||||
tsl := rawQuery["timeSeriesList"].(map[string]interface{})
|
||||
sloq := rawQuery["sloQuery"].(map[string]interface{})
|
||||
if sloq["projectName"] != nil {
|
||||
tsl["projectName"] = sloq["projectName"]
|
||||
}
|
||||
if sloq["alignmentPeriod"] != nil {
|
||||
tsl["alignmentPeriod"] = sloq["alignmentPeriod"]
|
||||
}
|
||||
if sloq["perSeriesAligner"] != nil {
|
||||
tsl["perSeriesAligner"] = sloq["perSeriesAligner"]
|
||||
}
|
||||
rawQuery["timeSeriesList"] = tsl
|
||||
b, err := json.Marshal(rawQuery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if q.QueryType == "" {
|
||||
q.QueryType = sloQueryType
|
||||
}
|
||||
q.JSON = b
|
||||
}
|
||||
|
||||
req.Queries[i] = q
|
||||
}
|
||||
@@ -315,58 +374,49 @@ func (s *Service) buildQueryExecutors(logger log.Logger, req *backend.QueryDataR
|
||||
return nil, fmt.Errorf("could not unmarshal CloudMonitoringQuery json: %w", err)
|
||||
}
|
||||
|
||||
q.MetricQuery.PreprocessorType = toPreprocessorType(q.MetricQuery.Preprocessor)
|
||||
var target string
|
||||
params := url.Values{}
|
||||
params.Add("interval.startTime", startTime.UTC().Format(time.RFC3339))
|
||||
params.Add("interval.endTime", endTime.UTC().Format(time.RFC3339))
|
||||
|
||||
var queryInterface cloudMonitoringQueryExecutor
|
||||
cmtsf := &cloudMonitoringTimeSeriesFilter{
|
||||
RefID: query.RefID,
|
||||
GroupBys: []string{},
|
||||
logger: logger,
|
||||
cmtsf := &cloudMonitoringTimeSeriesList{
|
||||
refID: query.RefID,
|
||||
logger: logger,
|
||||
aliasBy: q.AliasBy,
|
||||
}
|
||||
switch q.QueryType {
|
||||
switch query.QueryType {
|
||||
case metricQueryType, annotationQueryType:
|
||||
if q.MetricQuery.EditorMode == mqlEditorMode {
|
||||
if q.TimeSeriesQuery != nil {
|
||||
queryInterface = &cloudMonitoringTimeSeriesQuery{
|
||||
RefID: query.RefID,
|
||||
ProjectName: q.MetricQuery.ProjectName,
|
||||
Query: q.MetricQuery.Query,
|
||||
IntervalMS: query.Interval.Milliseconds(),
|
||||
AliasBy: q.MetricQuery.AliasBy,
|
||||
timeRange: req.Queries[0].TimeRange,
|
||||
GraphPeriod: q.MetricQuery.GraphPeriod,
|
||||
refID: query.RefID,
|
||||
aliasBy: q.AliasBy,
|
||||
parameters: q.TimeSeriesQuery,
|
||||
IntervalMS: query.Interval.Milliseconds(),
|
||||
timeRange: req.Queries[0].TimeRange,
|
||||
}
|
||||
} else {
|
||||
cmtsf.AliasBy = q.MetricQuery.AliasBy
|
||||
cmtsf.ProjectName = q.MetricQuery.ProjectName
|
||||
cmtsf.GroupBys = append(cmtsf.GroupBys, q.MetricQuery.GroupBys...)
|
||||
if q.MetricQuery.View == "" {
|
||||
q.MetricQuery.View = "FULL"
|
||||
} else if q.TimeSeriesList != nil {
|
||||
if q.TimeSeriesList.View == "" {
|
||||
q.TimeSeriesList.View = "FULL"
|
||||
}
|
||||
params.Add("filter", buildFilterString(q.MetricQuery.MetricType, q.MetricQuery.Filters))
|
||||
params.Add("view", q.MetricQuery.View)
|
||||
setMetricAggParams(¶ms, &q.MetricQuery, durationSeconds, query.Interval.Milliseconds())
|
||||
cmtsf.parameters = q.TimeSeriesList
|
||||
params.Add("filter", buildFilterString(q.TimeSeriesList.MetricType, q.TimeSeriesList.Filters))
|
||||
params.Add("view", q.TimeSeriesList.View)
|
||||
setMetricAggParams(¶ms, q.TimeSeriesList, durationSeconds, query.Interval.Milliseconds())
|
||||
queryInterface = cmtsf
|
||||
} else {
|
||||
return nil, fmt.Errorf("missing query info")
|
||||
}
|
||||
case sloQueryType:
|
||||
cmtsf.AliasBy = q.SloQuery.AliasBy
|
||||
cmtsf.ProjectName = q.SloQuery.ProjectName
|
||||
cmtsf.Selector = q.SloQuery.SelectorName
|
||||
cmtsf.Service = q.SloQuery.ServiceId
|
||||
cmtsf.Slo = q.SloQuery.SloId
|
||||
params.Add("filter", buildSLOFilterExpression(q.SloQuery))
|
||||
setSloAggParams(¶ms, &q.SloQuery, durationSeconds, query.Interval.Milliseconds())
|
||||
cmtsf.sloQ = q.SloQuery
|
||||
cmtsf.parameters = q.TimeSeriesList
|
||||
params.Add("filter", buildSLOFilterExpression(q.TimeSeriesList.ProjectName, q.SloQuery))
|
||||
setSloAggParams(¶ms, q.SloQuery, q.TimeSeriesList.AlignmentPeriod, durationSeconds, query.Interval.Milliseconds())
|
||||
queryInterface = cmtsf
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized query type %q", q.QueryType)
|
||||
return nil, fmt.Errorf("unrecognized query type %q", query.QueryType)
|
||||
}
|
||||
|
||||
target = params.Encode()
|
||||
cmtsf.Target = target
|
||||
cmtsf.Params = params
|
||||
cmtsf.params = params
|
||||
|
||||
if setting.Env == setting.Dev {
|
||||
logger.Debug("CloudMonitoring request", "params", params)
|
||||
@@ -428,8 +478,8 @@ func buildFilterString(metricType string, filterParts []string) string {
|
||||
return strings.Trim(fmt.Sprintf(`metric.type="%s" %s`, metricType, filterString), " ")
|
||||
}
|
||||
|
||||
func buildSLOFilterExpression(q sloQuery) string {
|
||||
sloName := fmt.Sprintf("projects/%s/services/%s/serviceLevelObjectives/%s", q.ProjectName, q.ServiceId, q.SloId)
|
||||
func buildSLOFilterExpression(projectName string, q *sloQuery) string {
|
||||
sloName := fmt.Sprintf("projects/%s/services/%s/serviceLevelObjectives/%s", projectName, q.ServiceId, q.SloId)
|
||||
|
||||
if q.SelectorName == "select_slo_burn_rate" {
|
||||
return fmt.Sprintf(`%s("%s", "%s")`, q.SelectorName, sloName, q.LookbackPeriod)
|
||||
@@ -438,7 +488,7 @@ func buildSLOFilterExpression(q sloQuery) string {
|
||||
}
|
||||
}
|
||||
|
||||
func setMetricAggParams(params *url.Values, query *metricQuery, durationSeconds int, intervalMs int64) {
|
||||
func setMetricAggParams(params *url.Values, query *timeSeriesList, durationSeconds int, intervalMs int64) {
|
||||
if query.CrossSeriesReducer == "" {
|
||||
query.CrossSeriesReducer = crossSeriesReducerDefault
|
||||
}
|
||||
@@ -452,7 +502,8 @@ func setMetricAggParams(params *url.Values, query *metricQuery, durationSeconds
|
||||
// In case a preprocessor is defined, the preprocessor becomes the primary aggregation
|
||||
// and the aggregation that is specified in the UI becomes the secondary aggregation
|
||||
// Rules are specified in this issue: https://github.com/grafana/grafana/issues/30866
|
||||
if query.PreprocessorType != PreprocessorTypeNone {
|
||||
t := toPreprocessorType(query.Preprocessor)
|
||||
if t != PreprocessorTypeNone {
|
||||
params.Add("secondaryAggregation.alignmentPeriod", alignmentPeriod)
|
||||
params.Add("secondaryAggregation.crossSeriesReducer", query.CrossSeriesReducer)
|
||||
params.Add("secondaryAggregation.perSeriesAligner", query.PerSeriesAligner)
|
||||
@@ -464,7 +515,7 @@ func setMetricAggParams(params *url.Values, query *metricQuery, durationSeconds
|
||||
params.Add("aggregation.crossSeriesReducer", primaryCrossSeriesReducer)
|
||||
|
||||
aligner := "ALIGN_RATE"
|
||||
if query.PreprocessorType == PreprocessorTypeDelta {
|
||||
if t == PreprocessorTypeDelta {
|
||||
aligner = "ALIGN_DELTA"
|
||||
}
|
||||
params.Add("aggregation.perSeriesAligner", aligner)
|
||||
@@ -484,8 +535,8 @@ func setMetricAggParams(params *url.Values, query *metricQuery, durationSeconds
|
||||
}
|
||||
}
|
||||
|
||||
func setSloAggParams(params *url.Values, query *sloQuery, durationSeconds int, intervalMs int64) {
|
||||
params.Add("aggregation.alignmentPeriod", calculateAlignmentPeriod(query.AlignmentPeriod, intervalMs, durationSeconds))
|
||||
func setSloAggParams(params *url.Values, query *sloQuery, alignmentPeriod string, durationSeconds int, intervalMs int64) {
|
||||
params.Add("aggregation.alignmentPeriod", calculateAlignmentPeriod(alignmentPeriod, intervalMs, durationSeconds))
|
||||
if query.SelectorName == "select_slo_health" {
|
||||
params.Add("aggregation.perSeriesAligner", "ALIGN_MEAN")
|
||||
} else {
|
||||
@@ -515,12 +566,12 @@ func calculateAlignmentPeriod(alignmentPeriod string, intervalMs int64, duration
|
||||
}
|
||||
|
||||
func formatLegendKeys(metricType string, defaultMetricName string, labels map[string]string,
|
||||
additionalLabels map[string]string, query *cloudMonitoringTimeSeriesFilter) string {
|
||||
if query.AliasBy == "" {
|
||||
additionalLabels map[string]string, query *cloudMonitoringTimeSeriesList) string {
|
||||
if query.aliasBy == "" {
|
||||
return defaultMetricName
|
||||
}
|
||||
|
||||
result := legendKeyFormat.ReplaceAllFunc([]byte(query.AliasBy), func(in []byte) []byte {
|
||||
result := legendKeyFormat.ReplaceAllFunc([]byte(query.aliasBy), func(in []byte) []byte {
|
||||
metaPartName := strings.Replace(string(in), "{{", "", 1)
|
||||
metaPartName = strings.Replace(metaPartName, "}}", "", 1)
|
||||
metaPartName = strings.TrimSpace(metaPartName)
|
||||
@@ -543,20 +594,20 @@ func formatLegendKeys(metricType string, defaultMetricName string, labels map[st
|
||||
return []byte(val)
|
||||
}
|
||||
|
||||
if metaPartName == "project" && query.ProjectName != "" {
|
||||
return []byte(query.ProjectName)
|
||||
if metaPartName == "project" && query.parameters.ProjectName != "" {
|
||||
return []byte(query.parameters.ProjectName)
|
||||
}
|
||||
|
||||
if metaPartName == "service" && query.Service != "" {
|
||||
return []byte(query.Service)
|
||||
if metaPartName == "service" && query.sloQ.ServiceId != "" {
|
||||
return []byte(query.sloQ.ServiceId)
|
||||
}
|
||||
|
||||
if metaPartName == "slo" && query.Slo != "" {
|
||||
return []byte(query.Slo)
|
||||
if metaPartName == "slo" && query.sloQ.SloId != "" {
|
||||
return []byte(query.sloQ.SloId)
|
||||
}
|
||||
|
||||
if metaPartName == "selector" && query.Selector != "" {
|
||||
return []byte(query.Selector)
|
||||
if metaPartName == "selector" && query.sloQ.SelectorName != "" {
|
||||
return []byte(query.sloQ.SelectorName)
|
||||
}
|
||||
|
||||
return in
|
||||
|
||||
Reference in New Issue
Block a user