mirror of https://github.com/grafana/grafana.git
				
				
				
			Google Cloud Monitor: Use generated type from schema in backend (#67879)
This commit is contained in:
		
							parent
							
								
									b632eb33b9
								
							
						
					
					
						commit
						adc3735122
					
				|  | @ -31,7 +31,7 @@ export interface CloudMonitoringQuery extends common.DataQuery { | |||
|    * queryType: #QueryType | ||||
|    * Time Series List sub-query properties. | ||||
|    */ | ||||
|   timeSeriesList?: (TimeSeriesList | AnnotationQuery); | ||||
|   timeSeriesList?: TimeSeriesList; | ||||
|   /** | ||||
|    * Time Series sub-query properties. | ||||
|    */ | ||||
|  | @ -96,6 +96,14 @@ export interface TimeSeriesList { | |||
|    * Only present if a preprocessor is selected. Alignment function to be used. Defaults to ALIGN_MEAN. | ||||
|    */ | ||||
|   secondaryPerSeriesAligner?: string; | ||||
|   /** | ||||
|    * Annotation text. | ||||
|    */ | ||||
|   text?: string; | ||||
|   /** | ||||
|    * Annotation title. | ||||
|    */ | ||||
|   title?: string; | ||||
|   /** | ||||
|    * Data view, defaults to FULL. | ||||
|    */ | ||||
|  | @ -117,20 +125,6 @@ export enum PreprocessorType { | |||
|   Rate = 'rate', | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Annotation sub-query properties. | ||||
|  */ | ||||
| export interface AnnotationQuery extends TimeSeriesList { | ||||
|   /** | ||||
|    * Annotation text. | ||||
|    */ | ||||
|   text?: string; | ||||
|   /** | ||||
|    * Annotation title. | ||||
|    */ | ||||
|   title?: string; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Time Series sub-query properties. | ||||
|  */ | ||||
|  | @ -291,7 +285,7 @@ export enum AlignmentTypes { | |||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @deprecated Use AnnotationQuery instead. Legacy annotation query properties for migration purposes. | ||||
|  * @deprecated Use TimeSeriesList instead. Legacy annotation query properties for migration purposes. | ||||
|  */ | ||||
| export interface LegacyCloudMonitoringAnnotationQuery { | ||||
|   /** | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ import ( | |||
| 	"github.com/grafana/grafana/pkg/infra/httpclient" | ||||
| 	"github.com/grafana/grafana/pkg/infra/log" | ||||
| 	"github.com/grafana/grafana/pkg/infra/tracing" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloud-monitoring/kinds/dataquery" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
|  | @ -55,10 +56,10 @@ var ( | |||
| const ( | ||||
| 	gceAuthentication         = "gce" | ||||
| 	jwtAuthentication         = "jwt" | ||||
| 	annotationQueryType       = "annotation" | ||||
| 	timeSeriesListQueryType   = "timeSeriesList" | ||||
| 	timeSeriesQueryQueryType  = "timeSeriesQuery" | ||||
| 	sloQueryType              = "slo" | ||||
| 	annotationQueryType       = dataquery.QueryTypeAnnotation | ||||
| 	timeSeriesListQueryType   = dataquery.QueryTypeTimeSeriesList | ||||
| 	timeSeriesQueryQueryType  = dataquery.QueryTypeTimeSeriesQuery | ||||
| 	sloQueryType              = dataquery.QueryTypeSlo | ||||
| 	crossSeriesReducerDefault = "REDUCE_NONE" | ||||
| 	perSeriesAlignerDefault   = "ALIGN_MEAN" | ||||
| ) | ||||
|  | @ -220,6 +221,10 @@ func migrateMetricTypeFilter(metricTypeFilter string, prevFilters interface{}) [ | |||
| 	return metricTypeFilterArray | ||||
| } | ||||
| 
 | ||||
| func strPtr(s string) *string { | ||||
| 	return &s | ||||
| } | ||||
| 
 | ||||
| func migrateRequest(req *backend.QueryDataRequest) error { | ||||
| 	for i, q := range req.Queries { | ||||
| 		var rawQuery map[string]interface{} | ||||
|  | @ -233,12 +238,12 @@ func migrateRequest(req *backend.QueryDataRequest) error { | |||
| 			rawQuery["timeSeriesList"] == nil && | ||||
| 			rawQuery["sloQuery"] == nil { | ||||
| 			// migrate legacy query
 | ||||
| 			var mq timeSeriesList | ||||
| 			var mq dataquery.TimeSeriesList | ||||
| 			err = json.Unmarshal(q.JSON, &mq) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			q.QueryType = timeSeriesListQueryType | ||||
| 			q.QueryType = string(dataquery.QueryTypeTimeSeriesList) | ||||
| 			gq := grafanaQuery{ | ||||
| 				TimeSeriesList: &mq, | ||||
| 			} | ||||
|  | @ -259,7 +264,7 @@ func migrateRequest(req *backend.QueryDataRequest) error { | |||
| 
 | ||||
| 		// Migrate type to queryType, which is only used for annotations
 | ||||
| 		if rawQuery["type"] != nil && rawQuery["type"].(string) == "annotationQuery" { | ||||
| 			q.QueryType = annotationQueryType | ||||
| 			q.QueryType = string(dataquery.QueryTypeAnnotation) | ||||
| 		} | ||||
| 		if rawQuery["queryType"] != nil { | ||||
| 			q.QueryType = rawQuery["queryType"].(string) | ||||
|  | @ -270,18 +275,18 @@ func migrateRequest(req *backend.QueryDataRequest) error { | |||
| 			metricQuery := rawQuery["metricQuery"].(map[string]interface{}) | ||||
| 
 | ||||
| 			if metricQuery["editorMode"] != nil && toString(metricQuery["editorMode"]) == "mql" { | ||||
| 				rawQuery["timeSeriesQuery"] = &timeSeriesQuery{ | ||||
| 				rawQuery["timeSeriesQuery"] = &dataquery.TimeSeriesQuery{ | ||||
| 					ProjectName: toString(metricQuery["projectName"]), | ||||
| 					Query:       toString(metricQuery["query"]), | ||||
| 					GraphPeriod: toString(metricQuery["graphPeriod"]), | ||||
| 					GraphPeriod: strPtr(toString(metricQuery["graphPeriod"])), | ||||
| 				} | ||||
| 				q.QueryType = timeSeriesQueryQueryType | ||||
| 				q.QueryType = string(dataquery.QueryTypeTimeSeriesQuery) | ||||
| 			} else { | ||||
| 				tslb, err := json.Marshal(metricQuery) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				tsl := &timeSeriesList{} | ||||
| 				tsl := &dataquery.TimeSeriesList{} | ||||
| 				err = json.Unmarshal(tslb, tsl) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
|  | @ -291,7 +296,7 @@ func migrateRequest(req *backend.QueryDataRequest) error { | |||
| 					tsl.Filters = migrateMetricTypeFilter(metricQuery["metricType"].(string), metricQuery["filters"]) | ||||
| 				} | ||||
| 				rawQuery["timeSeriesList"] = tsl | ||||
| 				q.QueryType = timeSeriesListQueryType | ||||
| 				q.QueryType = string(dataquery.QueryTypeTimeSeriesList) | ||||
| 			} | ||||
| 			// AliasBy is now a top level property
 | ||||
| 			if metricQuery["aliasBy"] != nil { | ||||
|  | @ -304,7 +309,7 @@ func migrateRequest(req *backend.QueryDataRequest) error { | |||
| 			q.JSON = b | ||||
| 		} | ||||
| 
 | ||||
| 		if rawQuery["sloQuery"] != nil && q.QueryType == sloQueryType { | ||||
| 		if rawQuery["sloQuery"] != nil && q.QueryType == string(dataquery.QueryTypeSlo) { | ||||
| 			sloQuery := rawQuery["sloQuery"].(map[string]interface{}) | ||||
| 			// AliasBy is now a top level property
 | ||||
| 			if sloQuery["aliasBy"] != nil { | ||||
|  | @ -347,7 +352,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) | |||
| 	} | ||||
| 
 | ||||
| 	switch req.Queries[0].QueryType { | ||||
| 	case annotationQueryType: | ||||
| 	case string(dataquery.QueryTypeAnnotation): | ||||
| 		return s.executeAnnotationQuery(ctx, req, *dsInfo, queries) | ||||
| 	default: | ||||
| 		return s.executeTimeSeriesQuery(ctx, req, *dsInfo, queries) | ||||
|  | @ -396,19 +401,20 @@ func (s *Service) buildQueryExecutors(logger log.Logger, req *backend.QueryDataR | |||
| 
 | ||||
| 		var queryInterface cloudMonitoringQueryExecutor | ||||
| 		switch query.QueryType { | ||||
| 		case timeSeriesListQueryType, annotationQueryType: | ||||
| 		case string(dataquery.QueryTypeTimeSeriesList), string(dataquery.QueryTypeAnnotation): | ||||
| 			cmtsf := &cloudMonitoringTimeSeriesList{ | ||||
| 				refID:   query.RefID, | ||||
| 				logger:  logger, | ||||
| 				aliasBy: q.AliasBy, | ||||
| 			} | ||||
| 			if q.TimeSeriesList.View == "" { | ||||
| 				q.TimeSeriesList.View = "FULL" | ||||
| 			if q.TimeSeriesList.View == nil || *q.TimeSeriesList.View == "" { | ||||
| 				fullString := "FULL" | ||||
| 				q.TimeSeriesList.View = &fullString | ||||
| 			} | ||||
| 			cmtsf.parameters = q.TimeSeriesList | ||||
| 			cmtsf.setParams(startTime, endTime, durationSeconds, query.Interval.Milliseconds()) | ||||
| 			queryInterface = cmtsf | ||||
| 		case timeSeriesQueryQueryType: | ||||
| 		case string(dataquery.QueryTypeTimeSeriesQuery): | ||||
| 			queryInterface = &cloudMonitoringTimeSeriesQuery{ | ||||
| 				refID:      query.RefID, | ||||
| 				aliasBy:    q.AliasBy, | ||||
|  | @ -417,7 +423,7 @@ func (s *Service) buildQueryExecutors(logger log.Logger, req *backend.QueryDataR | |||
| 				timeRange:  req.Queries[0].TimeRange, | ||||
| 				logger:     logger, | ||||
| 			} | ||||
| 		case sloQueryType: | ||||
| 		case string(dataquery.QueryTypeSlo): | ||||
| 			cmslo := &cloudMonitoringSLO{ | ||||
| 				refID:      query.RefID, | ||||
| 				logger:     logger, | ||||
|  | @ -606,7 +612,7 @@ func unmarshalResponse(logger log.Logger, res *http.Response) (cloudMonitoringRe | |||
| 	return data, nil | ||||
| } | ||||
| 
 | ||||
| func addConfigData(frames data.Frames, dl string, unit string, period string) data.Frames { | ||||
| func addConfigData(frames data.Frames, dl string, unit string, period *string) data.Frames { | ||||
| 	for i := range frames { | ||||
| 		if frames[i].Fields[1].Config == nil { | ||||
| 			frames[i].Fields[1].Config = &data.FieldConfig{} | ||||
|  | @ -627,8 +633,8 @@ func addConfigData(frames data.Frames, dl string, unit string, period string) da | |||
| 		if frames[i].Fields[0].Config == nil { | ||||
| 			frames[i].Fields[0].Config = &data.FieldConfig{} | ||||
| 		} | ||||
| 		if period != "" { | ||||
| 			err := addInterval(period, frames[i].Fields[0]) | ||||
| 		if period != nil && *period != "" { | ||||
| 			err := addInterval(*period, frames[i].Fields[0]) | ||||
| 			if err != nil { | ||||
| 				slog.Error("Failed to add interval", "error", err) | ||||
| 			} | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ import ( | |||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend/datasource" | ||||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" | ||||
| 	"github.com/grafana/grafana/pkg/infra/httpclient" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloud-monitoring/kinds/dataquery" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
|  | @ -1103,7 +1104,7 @@ func baseTimeSeriesList() *backend.QueryDataRequest { | |||
| 					From: fromStart, | ||||
| 					To:   fromStart.Add(34 * time.Minute), | ||||
| 				}, | ||||
| 				QueryType: timeSeriesListQueryType, | ||||
| 				QueryType: string(dataquery.QueryTypeTimeSeriesList), | ||||
| 				JSON: json.RawMessage(`{ | ||||
| 					"timeSeriesList": { | ||||
| 						"filters": ["metric.type=\"a/metric/type\""], | ||||
|  | @ -1127,7 +1128,7 @@ func baseTimeSeriesQuery() *backend.QueryDataRequest { | |||
| 					From: fromStart, | ||||
| 					To:   fromStart.Add(34 * time.Minute), | ||||
| 				}, | ||||
| 				QueryType: timeSeriesQueryQueryType, | ||||
| 				QueryType: string(dataquery.QueryTypeTimeSeriesQuery), | ||||
| 				JSON: json.RawMessage(`{ | ||||
| 					"queryType": "metrics", | ||||
| 					"timeSeriesQuery": { | ||||
|  |  | |||
|  | @ -86,18 +86,6 @@ const ( | |||
| // AlignmentTypes defines model for AlignmentTypes.
 | ||||
| type AlignmentTypes string | ||||
| 
 | ||||
| // Annotation sub-query properties.
 | ||||
| type AnnotationQuery struct { | ||||
| 	// TimeSeriesList Time Series List sub-query properties.
 | ||||
| 	TimeSeriesList | ||||
| 
 | ||||
| 	// Annotation text.
 | ||||
| 	Text *string `json:"text,omitempty"` | ||||
| 
 | ||||
| 	// Annotation title.
 | ||||
| 	Title *string `json:"title,omitempty"` | ||||
| } | ||||
| 
 | ||||
| // CloudMonitoringQuery defines model for CloudMonitoringQuery.
 | ||||
| type CloudMonitoringQuery struct { | ||||
| 	// DataQuery These are the common properties available to all queries in all datasources.
 | ||||
|  | @ -114,10 +102,8 @@ type CloudMonitoringQuery struct { | |||
| 	// SLO sub-query properties.
 | ||||
| 	SloQuery *SLOQuery `json:"sloQuery,omitempty"` | ||||
| 
 | ||||
| 	// GCM query type.
 | ||||
| 	// queryType: #QueryType
 | ||||
| 	// Time Series List sub-query properties.
 | ||||
| 	TimeSeriesList *any `json:"timeSeriesList,omitempty"` | ||||
| 	TimeSeriesList *TimeSeriesList `json:"timeSeriesList,omitempty"` | ||||
| 
 | ||||
| 	// Time Series sub-query properties.
 | ||||
| 	TimeSeriesQuery *TimeSeriesQuery `json:"timeSeriesQuery,omitempty"` | ||||
|  | @ -166,7 +152,7 @@ type Filter struct { | |||
| // GoogleCloudMonitoringDataQuery defines model for GoogleCloudMonitoringDataQuery.
 | ||||
| type GoogleCloudMonitoringDataQuery = map[string]any | ||||
| 
 | ||||
| // @deprecated Use AnnotationQuery instead. Legacy annotation query properties for migration purposes.
 | ||||
| // @deprecated Use TimeSeriesList instead. Legacy annotation query properties for migration purposes.
 | ||||
| type LegacyCloudMonitoringAnnotationQuery struct { | ||||
| 	// Array of filters to query data by. Labels that can be filtered on are defined by the metric.
 | ||||
| 	Filters    []string   `json:"filters"` | ||||
|  | @ -305,6 +291,12 @@ type TimeSeriesList struct { | |||
| 	// Only present if a preprocessor is selected. Alignment function to be used. Defaults to ALIGN_MEAN.
 | ||||
| 	SecondaryPerSeriesAligner *string `json:"secondaryPerSeriesAligner,omitempty"` | ||||
| 
 | ||||
| 	// Annotation text.
 | ||||
| 	Text *string `json:"text,omitempty"` | ||||
| 
 | ||||
| 	// Annotation title.
 | ||||
| 	Title *string `json:"title,omitempty"` | ||||
| 
 | ||||
| 	// Data view, defaults to FULL.
 | ||||
| 	View *string `json:"view,omitempty"` | ||||
| } | ||||
|  |  | |||
|  | @ -52,7 +52,7 @@ func (sloQ *cloudMonitoringSLO) getFilter() string { | |||
| 	sloName := fmt.Sprintf("projects/%s/services/%s/serviceLevelObjectives/%s", sloQ.parameters.ProjectName, sloQ.parameters.ServiceId, sloQ.parameters.SloId) | ||||
| 
 | ||||
| 	if sloQ.parameters.SelectorName == "select_slo_burn_rate" { | ||||
| 		return fmt.Sprintf(`%s("%s", "%s")`, sloQ.parameters.SelectorName, sloName, sloQ.parameters.LookbackPeriod) | ||||
| 		return fmt.Sprintf(`%s("%s", "%s")`, sloQ.parameters.SelectorName, sloName, *sloQ.parameters.LookbackPeriod) | ||||
| 	} else { | ||||
| 		return fmt.Sprintf(`%s("%s")`, sloQ.parameters.SelectorName, sloName) | ||||
| 	} | ||||
|  | @ -65,7 +65,7 @@ func (sloQ *cloudMonitoringSLO) setParams(startTime time.Time, endTime time.Time | |||
| 	params.Add("interval.endTime", endTime.UTC().Format(time.RFC3339)) | ||||
| 
 | ||||
| 	params.Add("filter", sloQ.getFilter()) | ||||
| 	params.Add("aggregation.alignmentPeriod", calculateAlignmentPeriod(sloQ.parameters.AlignmentPeriod, intervalMs, durationSeconds)) | ||||
| 	params.Add("aggregation.alignmentPeriod", calculateAlignmentPeriod(*sloQ.parameters.AlignmentPeriod, intervalMs, durationSeconds)) | ||||
| 	if sloQ.parameters.SelectorName == "select_slo_health" { | ||||
| 		params.Add("aggregation.perSeriesAligner", "ALIGN_MEAN") | ||||
| 	} else { | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import ( | |||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloud-monitoring/kinds/dataquery" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
|  | @ -20,7 +21,7 @@ func SLOQuery(t *testing.T) { | |||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringSLO{ | ||||
| 				params: url.Values{}, | ||||
| 				parameters: &sloQuery{ | ||||
| 				parameters: &dataquery.SLOQuery{ | ||||
| 					ProjectName:  "test-proj", | ||||
| 					SelectorName: "select_slo_compliance", | ||||
| 					ServiceId:    "test-service", | ||||
|  | @ -45,7 +46,7 @@ func SLOQuery(t *testing.T) { | |||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringSLO{ | ||||
| 				params: url.Values{}, | ||||
| 				parameters: &sloQuery{ | ||||
| 				parameters: &dataquery.SLOQuery{ | ||||
| 					ProjectName:  "test-proj", | ||||
| 					SelectorName: "select_slo_compliance", | ||||
| 					ServiceId:    "test-service", | ||||
|  | @ -66,7 +67,7 @@ func SLOQuery(t *testing.T) { | |||
| 		assert.Equal(t, 1, len(data.TimeSeries)) | ||||
| 
 | ||||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringSLO{params: url.Values{}, parameters: &sloQuery{SloId: "yes"}} | ||||
| 		query := &cloudMonitoringSLO{params: url.Values{}, parameters: &dataquery.SLOQuery{SloId: "yes"}} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
| 		require.NoError(t, err) | ||||
| 		frames := res.Frames | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ import ( | |||
| 	"github.com/huandu/xstrings" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/infra/tracing" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloud-monitoring/kinds/dataquery" | ||||
| ) | ||||
| 
 | ||||
| func (timeSeriesFilter *cloudMonitoringTimeSeriesList) run(ctx context.Context, req *backend.QueryDataRequest, | ||||
|  | @ -45,7 +46,8 @@ func parseTimeSeriesResponse(queryRes *backend.DataResponse, | |||
| 	} | ||||
| 	if len(response.TimeSeries) > 0 { | ||||
| 		dl := query.buildDeepLink() | ||||
| 		frames = addConfigData(frames, dl, response.Unit, params.Get("aggregation.alignmentPeriod")) | ||||
| 		aggregationAlignmentString := params.Get("aggregation.alignmentPeriod") | ||||
| 		frames = addConfigData(frames, dl, response.Unit, &aggregationAlignmentString) | ||||
| 	} | ||||
| 
 | ||||
| 	queryRes.Frames = frames | ||||
|  | @ -151,11 +153,11 @@ func (timeSeriesFilter *cloudMonitoringTimeSeriesList) setPreprocessor() { | |||
| 	// 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
 | ||||
| 	t := toPreprocessorType(timeSeriesFilter.parameters.Preprocessor) | ||||
| 	if t != PreprocessorTypeNone { | ||||
| 		// Move aggregation to secondaryAggregation
 | ||||
| 	if timeSeriesFilter.parameters.Preprocessor != nil && toPreprocessorType(string(*timeSeriesFilter.parameters.Preprocessor)) != PreprocessorTypeNone { | ||||
| 		// Move aggregation to secondaryAggregations
 | ||||
| 		timeSeriesFilter.parameters.SecondaryAlignmentPeriod = timeSeriesFilter.parameters.AlignmentPeriod | ||||
| 		timeSeriesFilter.parameters.SecondaryCrossSeriesReducer = timeSeriesFilter.parameters.CrossSeriesReducer | ||||
| 		scsr := timeSeriesFilter.parameters.CrossSeriesReducer | ||||
| 		timeSeriesFilter.parameters.SecondaryCrossSeriesReducer = &scsr | ||||
| 		timeSeriesFilter.parameters.SecondaryPerSeriesAligner = timeSeriesFilter.parameters.PerSeriesAligner | ||||
| 		timeSeriesFilter.parameters.SecondaryGroupBys = timeSeriesFilter.parameters.GroupBys | ||||
| 
 | ||||
|  | @ -166,10 +168,10 @@ func (timeSeriesFilter *cloudMonitoringTimeSeriesList) setPreprocessor() { | |||
| 
 | ||||
| 		// Set aligner based on preprocessor type
 | ||||
| 		aligner := "ALIGN_RATE" | ||||
| 		if t == PreprocessorTypeDelta { | ||||
| 		if timeSeriesFilter.parameters.Preprocessor != nil && toPreprocessorType(string(*timeSeriesFilter.parameters.Preprocessor)) == PreprocessorTypeDelta { | ||||
| 			aligner = "ALIGN_DELTA" | ||||
| 		} | ||||
| 		timeSeriesFilter.parameters.PerSeriesAligner = aligner | ||||
| 		timeSeriesFilter.parameters.PerSeriesAligner = &aligner | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -181,39 +183,52 @@ func (timeSeriesFilter *cloudMonitoringTimeSeriesList) setParams(startTime time. | |||
| 	params.Add("interval.endTime", endTime.UTC().Format(time.RFC3339)) | ||||
| 
 | ||||
| 	params.Add("filter", timeSeriesFilter.getFilter()) | ||||
| 	params.Add("view", query.View) | ||||
| 	if query.View != nil { | ||||
| 		params.Add("view", *query.View) | ||||
| 	} | ||||
| 
 | ||||
| 	if query.CrossSeriesReducer == "" { | ||||
| 		query.CrossSeriesReducer = crossSeriesReducerDefault | ||||
| 	} | ||||
| 
 | ||||
| 	if query.PerSeriesAligner == "" { | ||||
| 		query.PerSeriesAligner = perSeriesAlignerDefault | ||||
| 	alignMean := perSeriesAlignerDefault | ||||
| 	if query.PerSeriesAligner == nil { | ||||
| 		query.PerSeriesAligner = &alignMean | ||||
| 	} | ||||
| 
 | ||||
| 	if timeSeriesFilter.parameters.Preprocessor == nil { | ||||
| 		var p dataquery.PreprocessorType = "" | ||||
| 		timeSeriesFilter.parameters.Preprocessor = &p | ||||
| 	} | ||||
| 
 | ||||
| 	alignmentPeriodString := "" | ||||
| 	if query.AlignmentPeriod != nil { | ||||
| 		alignmentPeriodString = *query.AlignmentPeriod | ||||
| 	} | ||||
| 
 | ||||
| 	timeSeriesFilter.setPreprocessor() | ||||
| 
 | ||||
| 	alignmentPeriod := calculateAlignmentPeriod(query.AlignmentPeriod, intervalMs, durationSeconds) | ||||
| 	alignmentPeriod := calculateAlignmentPeriod(alignmentPeriodString, intervalMs, durationSeconds) | ||||
| 	params.Add("aggregation.alignmentPeriod", alignmentPeriod) | ||||
| 	if query.CrossSeriesReducer != "" { | ||||
| 		params.Add("aggregation.crossSeriesReducer", query.CrossSeriesReducer) | ||||
| 	} | ||||
| 	if query.PerSeriesAligner != "" { | ||||
| 		params.Add("aggregation.perSeriesAligner", query.PerSeriesAligner) | ||||
| 	if query.PerSeriesAligner != nil { | ||||
| 		params.Add("aggregation.perSeriesAligner", *query.PerSeriesAligner) | ||||
| 	} | ||||
| 	for _, groupBy := range query.GroupBys { | ||||
| 		params.Add("aggregation.groupByFields", groupBy) | ||||
| 	} | ||||
| 
 | ||||
| 	if query.SecondaryAlignmentPeriod != "" { | ||||
| 		secondaryAlignmentPeriod := calculateAlignmentPeriod(query.AlignmentPeriod, intervalMs, durationSeconds) | ||||
| 	if query.SecondaryAlignmentPeriod != nil && *query.SecondaryAlignmentPeriod != "" { | ||||
| 		secondaryAlignmentPeriod := calculateAlignmentPeriod(alignmentPeriodString, intervalMs, durationSeconds) | ||||
| 		params.Add("secondaryAggregation.alignmentPeriod", secondaryAlignmentPeriod) | ||||
| 	} | ||||
| 	if query.SecondaryCrossSeriesReducer != "" { | ||||
| 		params.Add("secondaryAggregation.crossSeriesReducer", query.SecondaryCrossSeriesReducer) | ||||
| 	if query.SecondaryCrossSeriesReducer != nil && *query.SecondaryCrossSeriesReducer != "" { | ||||
| 		params.Add("secondaryAggregation.crossSeriesReducer", *query.SecondaryCrossSeriesReducer) | ||||
| 	} | ||||
| 	if query.SecondaryPerSeriesAligner != "" { | ||||
| 		params.Add("secondaryAggregation.perSeriesAligner", query.SecondaryPerSeriesAligner) | ||||
| 	if query.SecondaryPerSeriesAligner != nil { | ||||
| 		params.Add("secondaryAggregation.perSeriesAligner", *query.SecondaryPerSeriesAligner) | ||||
| 	} | ||||
| 	for _, groupBy := range query.SecondaryGroupBys { | ||||
| 		params.Add("secondaryAggregation.groupByFields", groupBy) | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend" | ||||
| 	sdkdata "github.com/grafana/grafana-plugin-sdk-go/data" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloud-monitoring/kinds/dataquery" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
|  | @ -19,7 +20,7 @@ import ( | |||
| 
 | ||||
| func TestTimeSeriesFilter(t *testing.T) { | ||||
| 	t.Run("parses params", func(t *testing.T) { | ||||
| 		query := &cloudMonitoringTimeSeriesList{parameters: &timeSeriesList{}} | ||||
| 		query := &cloudMonitoringTimeSeriesList{parameters: &dataquery.TimeSeriesList{}} | ||||
| 		query.setParams(time.Time{}, time.Time{}, 0, 0) | ||||
| 
 | ||||
| 		assert.Equal(t, "0001-01-01T00:00:00Z", query.params.Get("interval.startTime")) | ||||
|  | @ -37,7 +38,8 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 	}) | ||||
| 
 | ||||
| 	t.Run("parses params with preprocessor", func(t *testing.T) { | ||||
| 		query := &cloudMonitoringTimeSeriesList{parameters: &timeSeriesList{Preprocessor: "rate"}} | ||||
| 		var r dataquery.PreprocessorType = "rate" | ||||
| 		query := &cloudMonitoringTimeSeriesList{parameters: &dataquery.TimeSeriesList{Preprocessor: &r}} | ||||
| 		query.setParams(time.Time{}, time.Time{}, 0, 0) | ||||
| 
 | ||||
| 		assert.Equal(t, "0001-01-01T00:00:00Z", query.params.Get("interval.startTime")) | ||||
|  | @ -60,7 +62,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		assert.Equal(t, 1, len(data.TimeSeries)) | ||||
| 
 | ||||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &timeSeriesList{}} | ||||
| 		query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &dataquery.TimeSeriesList{}} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
| 		require.NoError(t, err) | ||||
| 		frames := res.Frames | ||||
|  | @ -83,7 +85,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		require.NoError(t, err) | ||||
| 		assert.Equal(t, 3, len(data.TimeSeries)) | ||||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &timeSeriesList{}} | ||||
| 		query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &dataquery.TimeSeriesList{}} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
| 		require.NoError(t, err) | ||||
| 
 | ||||
|  | @ -123,7 +125,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		require.NoError(t, err) | ||||
| 		assert.Equal(t, 3, len(data.TimeSeries)) | ||||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &timeSeriesList{GroupBys: []string{ | ||||
| 		query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &dataquery.TimeSeriesList{GroupBys: []string{ | ||||
| 			"metric.label.instance_name", "resource.label.zone", | ||||
| 		}}} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
|  | @ -146,7 +148,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		t.Run("and the alias pattern is for metric type, a metric label and a resource label", func(t *testing.T) { | ||||
| 			query := &cloudMonitoringTimeSeriesList{ | ||||
| 				params: url.Values{}, | ||||
| 				parameters: &timeSeriesList{ | ||||
| 				parameters: &dataquery.TimeSeriesList{ | ||||
| 					GroupBys: []string{"metric.label.instance_name", "resource.label.zone"}, | ||||
| 				}, | ||||
| 				aliasBy: "{{metric.type}} - {{metric.label.instance_name}} - {{resource.label.zone}}", | ||||
|  | @ -165,7 +167,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		t.Run("and the alias pattern is for metric name", func(t *testing.T) { | ||||
| 			query := &cloudMonitoringTimeSeriesList{ | ||||
| 				params:     url.Values{}, | ||||
| 				parameters: &timeSeriesList{GroupBys: []string{"metric.label.instance_name", "resource.label.zone"}}, | ||||
| 				parameters: &dataquery.TimeSeriesList{GroupBys: []string{"metric.label.instance_name", "resource.label.zone"}}, | ||||
| 				aliasBy:    "metric {{metric.name}} service {{metric.service}}", | ||||
| 			} | ||||
| 			err = query.parseResponse(res, data, "") | ||||
|  | @ -187,7 +189,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesList{ | ||||
| 			params:     url.Values{}, | ||||
| 			parameters: &timeSeriesList{}, | ||||
| 			parameters: &dataquery.TimeSeriesList{}, | ||||
| 			aliasBy:    "{{bucket}}", | ||||
| 		} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
|  | @ -232,7 +234,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesList{ | ||||
| 			params:     url.Values{}, | ||||
| 			parameters: &timeSeriesList{}, | ||||
| 			parameters: &dataquery.TimeSeriesList{}, | ||||
| 			aliasBy:    "{{bucket}}", | ||||
| 		} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
|  | @ -270,7 +272,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesList{ | ||||
| 			params:     url.Values{}, | ||||
| 			parameters: &timeSeriesList{}, | ||||
| 			parameters: &dataquery.TimeSeriesList{}, | ||||
| 			aliasBy:    "{{bucket}}", | ||||
| 		} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
|  | @ -310,7 +312,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringTimeSeriesList{ | ||||
| 				params:     url.Values{}, | ||||
| 				parameters: &timeSeriesList{}, | ||||
| 				parameters: &dataquery.TimeSeriesList{}, | ||||
| 				aliasBy:    "{{metadata.system_labels.test}}", | ||||
| 			} | ||||
| 			err = query.parseResponse(res, data, "") | ||||
|  | @ -328,7 +330,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringTimeSeriesList{ | ||||
| 				params:     url.Values{}, | ||||
| 				parameters: &timeSeriesList{}, | ||||
| 				parameters: &dataquery.TimeSeriesList{}, | ||||
| 				aliasBy:    "{{metadata.system_labels.test2}}", | ||||
| 			} | ||||
| 			err = query.parseResponse(res, data, "") | ||||
|  | @ -346,7 +348,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 			require.NoError(t, err) | ||||
| 			assert.Equal(t, 1, len(data.TimeSeries)) | ||||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &timeSeriesList{}} | ||||
| 			query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &dataquery.TimeSeriesList{}} | ||||
| 			err = query.parseResponse(res, data, "") | ||||
| 			require.NoError(t, err) | ||||
| 			frames := res.Frames | ||||
|  | @ -359,7 +361,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 			require.NoError(t, err) | ||||
| 			assert.Equal(t, 3, len(data.TimeSeries)) | ||||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &timeSeriesList{}} | ||||
| 			query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &dataquery.TimeSeriesList{}} | ||||
| 			err = query.parseResponse(res, data, "") | ||||
| 			require.NoError(t, err) | ||||
| 			frames := res.Frames | ||||
|  | @ -379,7 +381,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 
 | ||||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringTimeSeriesQuery{ | ||||
| 				parameters: &timeSeriesQuery{ | ||||
| 				parameters: &dataquery.TimeSeriesQuery{ | ||||
| 					ProjectName: "test-proj", | ||||
| 					Query:       "test-query", | ||||
| 				}, | ||||
|  | @ -404,10 +406,10 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 
 | ||||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesQuery{ | ||||
| 			parameters: &timeSeriesQuery{ | ||||
| 			parameters: &dataquery.TimeSeriesQuery{ | ||||
| 				Query:       "fetch gce_instance::compute.googleapis.com/instance/cpu/utilization | sum", | ||||
| 				ProjectName: "test", | ||||
| 				GraphPeriod: "60s", | ||||
| 				GraphPeriod: strPtr("60s"), | ||||
| 			}, | ||||
| 		} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
|  | @ -420,7 +422,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		require.NoError(t, err) | ||||
| 		assert.Equal(t, 3, len(data.TimeSeries)) | ||||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &timeSeriesList{}} | ||||
| 		query := &cloudMonitoringTimeSeriesList{params: url.Values{}, parameters: &dataquery.TimeSeriesList{}} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
| 		require.NoError(t, err) | ||||
| 		frames := res.Frames | ||||
|  | @ -438,7 +440,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesList{params: url.Values{ | ||||
| 			"aggregation.alignmentPeriod": []string{"+60s"}, | ||||
| 		}, parameters: &timeSeriesList{}} | ||||
| 		}, parameters: &dataquery.TimeSeriesList{}} | ||||
| 		err = query.parseResponse(res, data, "") | ||||
| 		require.NoError(t, err) | ||||
| 		frames := res.Frames | ||||
|  | @ -453,7 +455,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 			assert.Equal(t, 1, len(data.TimeSeries)) | ||||
| 
 | ||||
| 			res := &backend.DataResponse{} | ||||
| 			require.NoError(t, (&cloudMonitoringTimeSeriesList{parameters: &timeSeriesList{GroupBys: []string{"test_group_by"}}}).parseResponse(res, data, "test_query")) | ||||
| 			require.NoError(t, (&cloudMonitoringTimeSeriesList{parameters: &dataquery.TimeSeriesList{GroupBys: []string{"test_group_by"}}}).parseResponse(res, data, "test_query")) | ||||
| 
 | ||||
| 			require.NotNil(t, res.Frames[0].Meta) | ||||
| 			assert.Equal(t, sdkdata.FrameMeta{ | ||||
|  | @ -476,7 +478,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 			assert.Equal(t, 1, len(data.TimeSeries)) | ||||
| 
 | ||||
| 			res := &backend.DataResponse{} | ||||
| 			require.NoError(t, (&cloudMonitoringTimeSeriesList{parameters: &timeSeriesList{GroupBys: []string{"test_group_by"}}}).parseResponse(res, data, "test_query")) | ||||
| 			require.NoError(t, (&cloudMonitoringTimeSeriesList{parameters: &dataquery.TimeSeriesList{GroupBys: []string{"test_group_by"}}}).parseResponse(res, data, "test_query")) | ||||
| 
 | ||||
| 			require.NotNil(t, res.Frames[0].Meta) | ||||
| 			assert.Equal(t, sdkdata.FrameMeta{ | ||||
|  | @ -499,7 +501,7 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 			assert.Equal(t, 1, len(data.TimeSeries)) | ||||
| 
 | ||||
| 			res := &backend.DataResponse{} | ||||
| 			require.NoError(t, (&cloudMonitoringTimeSeriesList{parameters: &timeSeriesList{GroupBys: []string{"test_group_by"}}}).parseResponse(res, data, "test_query")) | ||||
| 			require.NoError(t, (&cloudMonitoringTimeSeriesList{parameters: &dataquery.TimeSeriesList{GroupBys: []string{"test_group_by"}}}).parseResponse(res, data, "test_query")) | ||||
| 
 | ||||
| 			require.NotNil(t, res.Frames[0].Meta) | ||||
| 			assert.Equal(t, sdkdata.FrameMeta{ | ||||
|  | @ -520,20 +522,20 @@ func TestTimeSeriesFilter(t *testing.T) { | |||
| 	t.Run("when building filter string", func(t *testing.T) { | ||||
| 		t.Run("and there's no regex operator", func(t *testing.T) { | ||||
| 			t.Run("and there are wildcards in a filter value", func(t *testing.T) { | ||||
| 				tsl := &cloudMonitoringTimeSeriesList{parameters: &timeSeriesList{Filters: []string{"metric.type", "=", "somemetrictype", "AND", "zone", "=", "*-central1*"}}} | ||||
| 				tsl := &cloudMonitoringTimeSeriesList{parameters: &dataquery.TimeSeriesList{Filters: []string{"metric.type", "=", "somemetrictype", "AND", "zone", "=", "*-central1*"}}} | ||||
| 				value := tsl.getFilter() | ||||
| 				assert.Equal(t, `metric.type="somemetrictype" zone=has_substring("-central1")`, value) | ||||
| 			}) | ||||
| 
 | ||||
| 			t.Run("and there are no wildcards in any filter value", func(t *testing.T) { | ||||
| 				tsl := &cloudMonitoringTimeSeriesList{parameters: &timeSeriesList{Filters: []string{"metric.type", "=", "somemetrictype", "AND", "zone", "!=", "us-central1-a"}}} | ||||
| 				tsl := &cloudMonitoringTimeSeriesList{parameters: &dataquery.TimeSeriesList{Filters: []string{"metric.type", "=", "somemetrictype", "AND", "zone", "!=", "us-central1-a"}}} | ||||
| 				value := tsl.getFilter() | ||||
| 				assert.Equal(t, `metric.type="somemetrictype" zone!="us-central1-a"`, value) | ||||
| 			}) | ||||
| 		}) | ||||
| 
 | ||||
| 		t.Run("and there is a regex operator", func(t *testing.T) { | ||||
| 			tsl := &cloudMonitoringTimeSeriesList{parameters: &timeSeriesList{Filters: []string{"metric.type", "=", "somemetrictype", "AND", "zone", "=~", "us-central1-a~"}}} | ||||
| 			tsl := &cloudMonitoringTimeSeriesList{parameters: &dataquery.TimeSeriesList{Filters: []string{"metric.type", "=", "somemetrictype", "AND", "zone", "=~", "us-central1-a~"}}} | ||||
| 			value := tsl.getFilter() | ||||
| 			assert.NotContains(t, value, `=~`) | ||||
| 			assert.Contains(t, value, `zone=`) | ||||
|  |  | |||
|  | @ -16,13 +16,13 @@ import ( | |||
| func (timeSeriesQuery *cloudMonitoringTimeSeriesQuery) appendGraphPeriod(req *backend.QueryDataRequest) string { | ||||
| 	// GraphPeriod needs to be explicitly disabled.
 | ||||
| 	// If not set, the default behavior is to set an automatic value
 | ||||
| 	if timeSeriesQuery.parameters.GraphPeriod != "disabled" { | ||||
| 		if timeSeriesQuery.parameters.GraphPeriod == "auto" || timeSeriesQuery.parameters.GraphPeriod == "" { | ||||
| 	if timeSeriesQuery.parameters.GraphPeriod == nil || *timeSeriesQuery.parameters.GraphPeriod != "disabled" { | ||||
| 		if timeSeriesQuery.parameters.GraphPeriod == nil || *timeSeriesQuery.parameters.GraphPeriod == "auto" || *timeSeriesQuery.parameters.GraphPeriod == "" { | ||||
| 			intervalCalculator := intervalv2.NewCalculator(intervalv2.CalculatorOptions{}) | ||||
| 			interval := intervalCalculator.Calculate(req.Queries[0].TimeRange, time.Duration(timeSeriesQuery.IntervalMS/1000)*time.Second, req.Queries[0].MaxDataPoints) | ||||
| 			timeSeriesQuery.parameters.GraphPeriod = interval.Text | ||||
| 			timeSeriesQuery.parameters.GraphPeriod = &interval.Text | ||||
| 		} | ||||
| 		return fmt.Sprintf(" | graph_period %s", timeSeriesQuery.parameters.GraphPeriod) | ||||
| 		return fmt.Sprintf(" | graph_period %s", *timeSeriesQuery.parameters.GraphPeriod) | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend" | ||||
| 	gdata "github.com/grafana/grafana-plugin-sdk-go/data" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloud-monitoring/kinds/dataquery" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
|  | @ -23,7 +24,7 @@ func TestTimeSeriesQuery(t *testing.T) { | |||
| 		t.Run("and alias template is not specified", func(t *testing.T) { | ||||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringTimeSeriesQuery{ | ||||
| 				parameters: &timeSeriesQuery{ | ||||
| 				parameters: &dataquery.TimeSeriesQuery{ | ||||
| 					ProjectName: "test-proj", | ||||
| 					Query:       "test-query", | ||||
| 				}, | ||||
|  | @ -41,7 +42,7 @@ func TestTimeSeriesQuery(t *testing.T) { | |||
| 		t.Run("and alias template is specified", func(t *testing.T) { | ||||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringTimeSeriesQuery{ | ||||
| 				parameters: &timeSeriesQuery{ | ||||
| 				parameters: &dataquery.TimeSeriesQuery{ | ||||
| 					ProjectName: "test-proj", | ||||
| 					Query:       "test-query", | ||||
| 				}, | ||||
|  | @ -68,7 +69,7 @@ func TestTimeSeriesQuery(t *testing.T) { | |||
| 
 | ||||
| 			res := &backend.DataResponse{} | ||||
| 			query := &cloudMonitoringTimeSeriesQuery{ | ||||
| 				parameters: &timeSeriesQuery{ | ||||
| 				parameters: &dataquery.TimeSeriesQuery{ | ||||
| 					ProjectName: "test-proj", | ||||
| 					Query:       "test-query", | ||||
| 				}, | ||||
|  | @ -93,7 +94,7 @@ func TestTimeSeriesQuery(t *testing.T) { | |||
| 		fromStart := time.Date(2018, 3, 15, 13, 0, 0, 0, time.UTC).In(time.Local) | ||||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesQuery{ | ||||
| 			parameters: &timeSeriesQuery{ | ||||
| 			parameters: &dataquery.TimeSeriesQuery{ | ||||
| 				ProjectName: "test-proj", | ||||
| 				Query:       "test-query", | ||||
| 			}, | ||||
|  | @ -120,10 +121,10 @@ func TestTimeSeriesQuery(t *testing.T) { | |||
| 		fromStart := time.Date(2018, 3, 15, 13, 0, 0, 0, time.UTC).In(time.Local) | ||||
| 		res := &backend.DataResponse{} | ||||
| 		query := &cloudMonitoringTimeSeriesQuery{ | ||||
| 			parameters: &timeSeriesQuery{ | ||||
| 			parameters: &dataquery.TimeSeriesQuery{ | ||||
| 				ProjectName: "test-proj", | ||||
| 				Query:       "test-query", | ||||
| 				GraphPeriod: "60s", | ||||
| 				GraphPeriod: strPtr("60s"), | ||||
| 			}, | ||||
| 			timeRange: backend.TimeRange{ | ||||
| 				From: fromStart, | ||||
|  | @ -138,12 +139,12 @@ func TestTimeSeriesQuery(t *testing.T) { | |||
| 	}) | ||||
| 
 | ||||
| 	t.Run("appends graph_period to the query", func(t *testing.T) { | ||||
| 		query := &cloudMonitoringTimeSeriesQuery{parameters: &timeSeriesQuery{}} | ||||
| 		query := &cloudMonitoringTimeSeriesQuery{parameters: &dataquery.TimeSeriesQuery{}} | ||||
| 		assert.Equal(t, query.appendGraphPeriod(&backend.QueryDataRequest{Queries: []backend.DataQuery{{}}}), " | graph_period 1ms") | ||||
| 	}) | ||||
| 
 | ||||
| 	t.Run("skips graph_period if disabled", func(t *testing.T) { | ||||
| 		query := &cloudMonitoringTimeSeriesQuery{parameters: &timeSeriesQuery{GraphPeriod: "disabled"}} | ||||
| 		query := &cloudMonitoringTimeSeriesQuery{parameters: &dataquery.TimeSeriesQuery{GraphPeriod: strPtr("disabled")}} | ||||
| 		assert.Equal(t, query.appendGraphPeriod(&backend.QueryDataRequest{Queries: []backend.DataQuery{{}}}), "") | ||||
| 	}) | ||||
| } | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/infra/log" | ||||
| 	"github.com/grafana/grafana/pkg/infra/tracing" | ||||
| 	"github.com/grafana/grafana/pkg/tsdb/cloud-monitoring/kinds/dataquery" | ||||
| ) | ||||
| 
 | ||||
| type ( | ||||
|  | @ -30,57 +31,17 @@ type ( | |||
| 	// Plugin API query data request used to generate
 | ||||
| 	// a cloudMonitoringTimeSeriesList or cloudMonitoringTimeSeriesQuery
 | ||||
| 	grafanaQuery struct { | ||||
| 		AliasBy         string           `json:"aliasBy"` | ||||
| 		TimeSeriesList  *timeSeriesList  `json:"timeSeriesList,omitempty"` | ||||
| 		TimeSeriesQuery *timeSeriesQuery `json:"timeSeriesQuery,omitempty"` | ||||
| 		SloQuery        *sloQuery        `json:"sloQuery,omitempty"` | ||||
| 		AliasBy         string                     `json:"aliasBy"` | ||||
| 		TimeSeriesList  *dataquery.TimeSeriesList  `json:"timeSeriesList,omitempty"` | ||||
| 		TimeSeriesQuery *dataquery.TimeSeriesQuery `json:"timeSeriesQuery,omitempty"` | ||||
| 		SloQuery        *dataquery.SLOQuery        `json:"sloQuery,omitempty"` | ||||
| 	} | ||||
| 
 | ||||
| 	// These should reflect GCM APIs
 | ||||
| 	// timeSeries.list https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.timeSeries/list
 | ||||
| 	timeSeriesList struct { | ||||
| 		ProjectName                 string   `json:"projectName"` | ||||
| 		CrossSeriesReducer          string   `json:"crossSeriesReducer"` | ||||
| 		AlignmentPeriod             string   `json:"alignmentPeriod"` | ||||
| 		PerSeriesAligner            string   `json:"perSeriesAligner"` | ||||
| 		GroupBys                    []string `json:"groupBys"` | ||||
| 		Filters                     []string `json:"filters"` | ||||
| 		View                        string   `json:"view"` | ||||
| 		SecondaryAlignmentPeriod    string   `json:"secondaryAlignmentPeriod"` | ||||
| 		SecondaryCrossSeriesReducer string   `json:"secondaryCrossSeriesReducer"` | ||||
| 		SecondaryPerSeriesAligner   string   `json:"secondaryPerSeriesAligner"` | ||||
| 		SecondaryGroupBys           []string `json:"secondaryGroupBys"` | ||||
| 		// Preprocessor is not part of the GCM API but added for simplicity
 | ||||
| 		// It will overwrite AligmentPeriod, CrossSeriesReducer, PerSeriesAligner, GroupBys
 | ||||
| 		// and its secondary counterparts
 | ||||
| 		Preprocessor string `json:"preprocessor"` | ||||
| 	} | ||||
| 
 | ||||
| 	// sloQuery is an internal convention but the API is the same as timeSeriesList
 | ||||
| 	sloQuery struct { | ||||
| 		ProjectName     string `json:"projectName"` | ||||
| 		SelectorName    string `json:"selectorName"` | ||||
| 		ServiceId       string `json:"serviceId"` | ||||
| 		SloId           string `json:"sloId"` | ||||
| 		AlignmentPeriod string `json:"alignmentPeriod"` | ||||
| 		LookbackPeriod  string `json:"lookbackPeriod"` | ||||
| 	} | ||||
| 
 | ||||
| 	// timeSeries.query https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.timeSeries/query
 | ||||
| 	timeSeriesQuery struct { | ||||
| 		ProjectName string `json:"projectName"` | ||||
| 		Query       string `json:"query"` | ||||
| 		// Not part of the GCM API, will be added to Query
 | ||||
| 		GraphPeriod string `json:"graphPeriod"` | ||||
| 	} | ||||
| 
 | ||||
| 	// Internal structs. Include computed values
 | ||||
| 	// cloudMonitoringTimeSeriesList is used to build time series with a filter
 | ||||
| 	cloudMonitoringTimeSeriesList struct { | ||||
| 		refID      string | ||||
| 		aliasBy    string | ||||
| 		logger     log.Logger | ||||
| 		parameters *timeSeriesList | ||||
| 		parameters *dataquery.TimeSeriesList | ||||
| 		// Processed properties
 | ||||
| 		params url.Values | ||||
| 	} | ||||
|  | @ -89,7 +50,7 @@ type ( | |||
| 		refID      string | ||||
| 		aliasBy    string | ||||
| 		logger     log.Logger | ||||
| 		parameters *sloQuery | ||||
| 		parameters *dataquery.SLOQuery | ||||
| 		// Processed properties
 | ||||
| 		params url.Values | ||||
| 	} | ||||
|  | @ -99,7 +60,7 @@ type ( | |||
| 		refID      string | ||||
| 		aliasBy    string | ||||
| 		logger     log.Logger | ||||
| 		parameters *timeSeriesQuery | ||||
| 		parameters *dataquery.TimeSeriesQuery | ||||
| 		// Processed properties
 | ||||
| 		timeRange  backend.TimeRange | ||||
| 		IntervalMS int64 | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import { EditorField, EditorRows } from '@grafana/experimental'; | |||
| import { Input } from '@grafana/ui'; | ||||
| 
 | ||||
| import CloudMonitoringDatasource from '../datasource'; | ||||
| import { AnnotationQuery, CloudMonitoringQuery, QueryType } from '../types/query'; | ||||
| import { TimeSeriesList, CloudMonitoringQuery, QueryType } from '../types/query'; | ||||
| import { CloudMonitoringOptions } from '../types/types'; | ||||
| 
 | ||||
| import { MetricQueryEditor, defaultTimeSeriesList } from './MetricQueryEditor'; | ||||
|  | @ -15,7 +15,7 @@ import { AnnotationsHelp } from './'; | |||
| 
 | ||||
| export type Props = QueryEditorProps<CloudMonitoringDatasource, CloudMonitoringQuery, CloudMonitoringOptions>; | ||||
| 
 | ||||
| export const defaultQuery: (datasource: CloudMonitoringDatasource) => AnnotationQuery = (datasource) => ({ | ||||
| export const defaultQuery: (datasource: CloudMonitoringDatasource) => TimeSeriesList = (datasource) => ({ | ||||
|   ...defaultTimeSeriesList(datasource), | ||||
|   title: '', | ||||
|   text: '', | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ composableKinds: DataQuery: { | |||
| 					// GCM query type. | ||||
| 					// queryType: #QueryType | ||||
| 					// Time Series List sub-query properties. | ||||
| 					timeSeriesList?: #TimeSeriesList | #AnnotationQuery | ||||
| 					timeSeriesList?: #TimeSeriesList | ||||
| 					// Time Series sub-query properties. | ||||
| 					timeSeriesQuery?: #TimeSeriesQuery | ||||
| 					// SLO sub-query properties. | ||||
|  | @ -60,6 +60,11 @@ composableKinds: DataQuery: { | |||
| 					// Data view, defaults to FULL. | ||||
| 					view?: string | ||||
| 
 | ||||
| 					// Annotation title. | ||||
| 					title?: string | ||||
| 					// Annotation text. | ||||
| 					text?: string | ||||
| 
 | ||||
| 					// Only present if a preprocessor is selected. Reducer applied across a set of time-series values. Defaults to REDUCE_NONE. | ||||
| 					secondaryCrossSeriesReducer?: string | ||||
| 					// Only present if a preprocessor is selected. Alignment period to use when regularizing data. Defaults to cloud-monitoring-auto. | ||||
|  | @ -77,14 +82,6 @@ composableKinds: DataQuery: { | |||
| 				// Types of pre-processor available. Defined by the metric. | ||||
| 				#PreprocessorType: "none" | "rate" | "delta" @cuetsy(kind="enum") | ||||
| 
 | ||||
| 				// Annotation sub-query properties. | ||||
| 				#AnnotationQuery: #TimeSeriesList & { | ||||
| 					// Annotation title. | ||||
| 					title?: string | ||||
| 					// Annotation text. | ||||
| 					text?: string | ||||
| 				} @cuetsy(kind="interface") | ||||
| 
 | ||||
| 				// Time Series sub-query properties. | ||||
| 				#TimeSeriesQuery: { | ||||
| 					// GCP project to execute the query against. | ||||
|  | @ -154,7 +151,7 @@ composableKinds: DataQuery: { | |||
| 
 | ||||
| 				#AlignmentTypes: "ALIGN_DELTA" | "ALIGN_RATE" | "ALIGN_INTERPOLATE" | "ALIGN_NEXT_OLDER" | "ALIGN_MIN" | "ALIGN_MAX" | "ALIGN_MEAN" | "ALIGN_COUNT" | "ALIGN_SUM" | "ALIGN_STDDEV" | "ALIGN_COUNT_TRUE" | "ALIGN_COUNT_FALSE" | "ALIGN_FRACTION_TRUE" | "ALIGN_PERCENTILE_99" | "ALIGN_PERCENTILE_95" | "ALIGN_PERCENTILE_50" | "ALIGN_PERCENTILE_05" | "ALIGN_PERCENT_CHANGE" | "ALIGN_NONE" @cuetsy(kind="enum") | ||||
| 
 | ||||
| 				// @deprecated Use AnnotationQuery instead. Legacy annotation query properties for migration purposes. | ||||
| 				// @deprecated Use TimeSeriesList instead. Legacy annotation query properties for migration purposes. | ||||
| 				#LegacyCloudMonitoringAnnotationQuery: { | ||||
| 					// GCP project to execute the query against. | ||||
| 					projectName: string | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ export interface CloudMonitoringQuery extends common.DataQuery { | |||
|    * queryType: #QueryType | ||||
|    * Time Series List sub-query properties. | ||||
|    */ | ||||
|   timeSeriesList?: (TimeSeriesList | AnnotationQuery); | ||||
|   timeSeriesList?: TimeSeriesList; | ||||
|   /** | ||||
|    * Time Series sub-query properties. | ||||
|    */ | ||||
|  | @ -93,6 +93,14 @@ export interface TimeSeriesList { | |||
|    * Only present if a preprocessor is selected. Alignment function to be used. Defaults to ALIGN_MEAN. | ||||
|    */ | ||||
|   secondaryPerSeriesAligner?: string; | ||||
|   /** | ||||
|    * Annotation text. | ||||
|    */ | ||||
|   text?: string; | ||||
|   /** | ||||
|    * Annotation title. | ||||
|    */ | ||||
|   title?: string; | ||||
|   /** | ||||
|    * Data view, defaults to FULL. | ||||
|    */ | ||||
|  | @ -114,20 +122,6 @@ export enum PreprocessorType { | |||
|   Rate = 'rate', | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Annotation sub-query properties. | ||||
|  */ | ||||
| export interface AnnotationQuery extends TimeSeriesList { | ||||
|   /** | ||||
|    * Annotation text. | ||||
|    */ | ||||
|   text?: string; | ||||
|   /** | ||||
|    * Annotation title. | ||||
|    */ | ||||
|   title?: string; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Time Series sub-query properties. | ||||
|  */ | ||||
|  | @ -288,7 +282,7 @@ export enum AlignmentTypes { | |||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @deprecated Use AnnotationQuery instead. Legacy annotation query properties for migration purposes. | ||||
|  * @deprecated Use TimeSeriesList instead. Legacy annotation query properties for migration purposes. | ||||
|  */ | ||||
| export interface LegacyCloudMonitoringAnnotationQuery { | ||||
|   /** | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ export { QueryType }; | |||
| export { | ||||
|   TimeSeriesList, | ||||
|   PreprocessorType, | ||||
|   AnnotationQuery, | ||||
|   TimeSeriesQuery, | ||||
|   SLOQuery, | ||||
|   MetricQuery, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue