mirror of
https://github.com/grafana/grafana.git
synced 2026-08-13 06:34:55 -05:00
GoogleCloudMonitoring: Refactor query type definition (#58512)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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(¶ms, &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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user