GoogleCloudMonitoring: Refactor query type definition (#58512)

This commit is contained in:
Andres Martinez Gotor
2022-11-10 09:30:47 +01:00
committed by GitHub
parent 70dac35348
commit 1201170724
8 changed files with 107 additions and 67 deletions
+1 -9
View File
@@ -9,8 +9,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/infra/log"
)
type annotationEvent struct {
@@ -20,15 +18,9 @@ type annotationEvent struct {
Text string
}
func (s *Service) executeAnnotationQuery(ctx context.Context, logger log.Logger, req *backend.QueryDataRequest, dsInfo datasourceInfo) (
func (s *Service) executeAnnotationQuery(ctx context.Context, req *backend.QueryDataRequest, dsInfo datasourceInfo, queries []cloudMonitoringQueryExecutor) (
*backend.QueryDataResponse, error) {
resp := backend.NewQueryDataResponse()
queries, err := s.buildQueryExecutors(logger, req)
if err != nil {
return resp, err
}
queryRes, dr, _, err := queries[0].run(ctx, req, s, dsInfo, s.tracer)
if err != nil {
return resp, err
+55 -48
View File
@@ -59,6 +59,7 @@ var (
const (
gceAuthentication = "gce"
jwtAuthentication = "jwt"
annotationQueryType = "annotation"
metricQueryType = "metrics"
sloQueryType = "slo"
mqlEditorMode = "mql"
@@ -137,10 +138,6 @@ type Service struct {
gceDefaultProjectGetter func(ctx context.Context) (string, error)
}
type QueryModel struct {
Type string `json:"type"`
}
type datasourceInfo struct {
id int64
updated time.Time
@@ -210,19 +207,54 @@ func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.Inst
}
}
func migrateRequest(req *backend.QueryDataRequest) error {
for i, q := range req.Queries {
var rawQuery map[string]interface{}
err := json.Unmarshal(q.JSON, &rawQuery)
if err != nil {
return err
}
if rawQuery["metricQuery"] == nil {
// migrate legacy query
var mq metricQuery
err = json.Unmarshal(q.JSON, &mq)
if err != nil {
return err
}
b, err := json.Marshal(grafanaQuery{
QueryType: metricQueryType,
MetricQuery: mq,
})
if err != nil {
return err
}
q.JSON = b
}
// Migrate type to queryType, which is only used for annotations
if rawQuery["type"] != nil && rawQuery["type"].(string) == "annotationQuery" {
q.QueryType = annotationQueryType
}
req.Queries[i] = q
}
return nil
}
// QueryData takes in the frontend queries, parses them into the CloudMonitoring query format
// executes the queries against the CloudMonitoring API and parses the response into data frames
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
logger := slog.FromContext(ctx)
resp := backend.NewQueryDataResponse()
if len(req.Queries) == 0 {
return resp, fmt.Errorf("query contains no queries")
return nil, fmt.Errorf("query contains no queries")
}
model := &QueryModel{}
err := json.Unmarshal(req.Queries[0].JSON, model)
err := migrateRequest(req)
if err != nil {
return resp, err
return nil, err
}
dsInfo, err := s.getDSInfo(req.PluginContext)
@@ -230,27 +262,23 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
return nil, err
}
switch model.Type {
case "annotationQuery":
resp, err = s.executeAnnotationQuery(ctx, logger, req, *dsInfo)
case "timeSeriesQuery":
fallthrough
default:
resp, err = s.executeTimeSeriesQuery(ctx, logger, req, *dsInfo)
queries, err := s.buildQueryExecutors(logger, req)
if err != nil {
return nil, err
}
return resp, err
switch req.Queries[0].QueryType {
case annotationQueryType:
return s.executeAnnotationQuery(ctx, req, *dsInfo, queries)
default:
return s.executeTimeSeriesQuery(ctx, req, *dsInfo, queries)
}
}
func (s *Service) executeTimeSeriesQuery(ctx context.Context, logger log.Logger, req *backend.QueryDataRequest, dsInfo datasourceInfo) (
func (s *Service) executeTimeSeriesQuery(ctx context.Context, req *backend.QueryDataRequest, dsInfo datasourceInfo, queries []cloudMonitoringQueryExecutor) (
*backend.QueryDataResponse, error) {
resp := backend.NewQueryDataResponse()
queryExecutors, err := s.buildQueryExecutors(logger, req)
if err != nil {
return resp, err
}
for _, queryExecutor := range queryExecutors {
for _, queryExecutor := range queries {
queryRes, dr, executedQueryString, err := queryExecutor.run(ctx, req, s, dsInfo, s.tracer)
if err != nil {
return resp, err
@@ -267,32 +295,11 @@ func (s *Service) executeTimeSeriesQuery(ctx context.Context, logger log.Logger,
}
func queryModel(query backend.DataQuery) (grafanaQuery, error) {
var rawQuery map[string]interface{}
err := json.Unmarshal(query.JSON, &rawQuery)
if err != nil {
return grafanaQuery{}, err
}
if rawQuery["metricQuery"] == nil {
// migrate legacy query
var mq metricQuery
err = json.Unmarshal(query.JSON, &mq)
if err != nil {
return grafanaQuery{}, err
}
return grafanaQuery{
QueryType: metricQueryType,
MetricQuery: mq,
}, nil
}
var q grafanaQuery
err = json.Unmarshal(query.JSON, &q)
err := json.Unmarshal(query.JSON, &q)
if err != nil {
return grafanaQuery{}, err
}
return q, nil
}
@@ -321,7 +328,7 @@ func (s *Service) buildQueryExecutors(logger log.Logger, req *backend.QueryDataR
logger: logger,
}
switch q.QueryType {
case metricQueryType:
case metricQueryType, annotationQueryType:
if q.MetricQuery.EditorMode == mqlEditorMode {
queryInterface = &cloudMonitoringTimeSeriesQuery{
RefID: query.RefID,
@@ -354,7 +361,7 @@ func (s *Service) buildQueryExecutors(logger log.Logger, req *backend.QueryDataR
setSloAggParams(&params, &q.SloQuery, durationSeconds, query.Interval.Milliseconds())
queryInterface = cmtsf
default:
panic(fmt.Sprintf("Unrecognized query type %q", q.QueryType))
return nil, fmt.Errorf("unrecognized query type %q", q.QueryType)
}
target = params.Encode()
@@ -52,7 +52,11 @@ func TestCloudMonitoring(t *testing.T) {
t.Run("Parse migrated queries from frontend and build Google Cloud Monitoring API queries", func(t *testing.T) {
t.Run("and query has no aggregation set", func(t *testing.T) {
qes, err := service.buildQueryExecutors(slog, baseReq())
req := baseReq()
err := migrateRequest(req)
require.NoError(t, err)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
queries := getCloudMonitoringQueriesFromInterface(t, qes)
@@ -92,6 +96,8 @@ func TestCloudMonitoring(t *testing.T) {
"metricType": "a/metric/type",
"filters": ["key", "=", "value", "AND", "key2", "=", "value2", "AND", "resource.type", "=", "another/resource/type"]
}`)
err := migrateRequest(query)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, query)
require.NoError(t, err)
@@ -124,6 +130,8 @@ func TestCloudMonitoring(t *testing.T) {
"alignmentPeriod": "grafana-auto",
"filters": ["key", "=", "value", "AND", "key2", "=", "value2"]
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -152,6 +160,8 @@ func TestCloudMonitoring(t *testing.T) {
"alignmentPeriod": "grafana-auto",
"filters": ["key", "=", "value", "AND", "key2", "=", "value2"]
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -186,6 +196,8 @@ func TestCloudMonitoring(t *testing.T) {
"target": "target",
"alignmentPeriod": "cloud-monitoring-auto"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -201,6 +213,8 @@ func TestCloudMonitoring(t *testing.T) {
"target": "target",
"alignmentPeriod": "cloud-monitoring-auto"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -216,6 +230,8 @@ func TestCloudMonitoring(t *testing.T) {
"target": "target",
"alignmentPeriod": "cloud-monitoring-auto"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -231,6 +247,8 @@ func TestCloudMonitoring(t *testing.T) {
"target": "target",
"alignmentPeriod": "cloud-monitoring-auto"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -250,6 +268,8 @@ func TestCloudMonitoring(t *testing.T) {
"target": "target",
"alignmentPeriod": "stackdriver-auto"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -280,6 +300,8 @@ func TestCloudMonitoring(t *testing.T) {
"target": "target",
"alignmentPeriod": "stackdriver-auto"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -310,6 +332,8 @@ func TestCloudMonitoring(t *testing.T) {
"target": "target",
"alignmentPeriod": "stackdriver-auto"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -340,6 +364,8 @@ func TestCloudMonitoring(t *testing.T) {
"target": "target",
"alignmentPeriod": "stackdriver-auto"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -370,6 +396,8 @@ func TestCloudMonitoring(t *testing.T) {
req.Queries[0].JSON = json.RawMessage(`{
"alignmentPeriod": "+600s"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -400,6 +428,8 @@ func TestCloudMonitoring(t *testing.T) {
"crossSeriesReducer": "REDUCE_SUM",
"view": "FULL"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -444,6 +474,8 @@ func TestCloudMonitoring(t *testing.T) {
"groupBys": ["metric.label.group1", "metric.label.group2"],
"view": "FULL"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -738,6 +770,8 @@ func TestCloudMonitoring(t *testing.T) {
"groupBys": ["labelname"],
"view": "FULL"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -766,6 +800,8 @@ func TestCloudMonitoring(t *testing.T) {
"view": "FULL",
"preprocessor": "none"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -794,6 +830,8 @@ func TestCloudMonitoring(t *testing.T) {
"view": "FULL",
"preprocessor": "rate"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -820,6 +858,8 @@ func TestCloudMonitoring(t *testing.T) {
"view": "FULL",
"preprocessor": "rate"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -848,6 +888,8 @@ func TestCloudMonitoring(t *testing.T) {
"view": "FULL",
"preprocessor": "delta"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
@@ -874,6 +916,8 @@ func TestCloudMonitoring(t *testing.T) {
"view": "FULL",
"preprocessor": "delta"
}`)
err := migrateRequest(req)
require.NoError(t, err)
qes, err := service.buildQueryExecutors(slog, req)
require.NoError(t, err)
+1
View File
@@ -80,6 +80,7 @@ type (
QueryType string
MetricQuery metricQuery
SloQuery sloQuery
Type string
}
cloudMonitoringBucketOptions struct {
@@ -13,8 +13,7 @@ import {
const query: CloudMonitoringQuery = {
refId: 'query',
queryType: QueryType.METRICS,
type: 'annotationQuery',
queryType: QueryType.ANNOTATION,
intervalMs: 0,
metricQuery: {
editorMode: EditorMode.Visual,
@@ -84,9 +83,8 @@ describe('CloudMonitoringAnnotationSupport', () => {
text: 'text',
title: 'title',
},
queryType: 'metrics',
queryType: 'annotation',
refId: 'annotationQuery',
type: 'annotationQuery',
},
};
expect(annotationSupport.prepareAnnotation?.(legacyAnnotationQuery)).toEqual(expectedQuery);
@@ -41,8 +41,7 @@ export const CloudMonitoringAnnotationSupport: (
target: {
intervalMs: ds.intervalMs,
refId: target?.refId || 'annotationQuery',
type: 'annotationQuery',
queryType: QueryType.METRICS,
queryType: QueryType.ANNOTATION,
metricQuery: {
projectName: target?.projectName || ds.getDefaultProject(),
editorMode: EditorMode.Visual,
@@ -198,9 +198,8 @@ export default class CloudMonitoringDatasource extends DataSourceWithBackend<
return {
refId,
intervalMs,
type,
hide,
queryType: QueryType.METRICS,
queryType: type === 'annotationQuery' ? QueryType.ANNOTATION : QueryType.METRICS,
metricQuery: {
...rest,
view: rest.view || 'FULL',
@@ -57,6 +57,7 @@ export interface Aggregation {
export enum QueryType {
METRICS = 'metrics',
SLO = 'slo',
ANNOTATION = 'annotation',
}
export enum EditorMode {
@@ -152,7 +153,6 @@ export interface CloudMonitoringQuery extends DataQuery {
metricQuery: MetricQuery | AnnotationMetricQuery;
sloQuery?: SLOQuery;
intervalMs: number;
type: string;
}
export interface CloudMonitoringOptions extends DataSourceJsonData {