mirror of https://github.com/grafana/grafana.git
				
				
				
			stackdriver: tests for parsing api response
This commit is contained in:
		
							parent
							
								
									54f16d5558
								
							
						
					
					
						commit
						2683699ab4
					
				|  | @ -15,7 +15,6 @@ import ( | |||
| 	"golang.org/x/net/context/ctxhttp" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/api/pluginproxy" | ||||
| 	"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger" | ||||
| 	"github.com/grafana/grafana/pkg/components/null" | ||||
| 	"github.com/grafana/grafana/pkg/log" | ||||
| 	"github.com/grafana/grafana/pkg/models" | ||||
|  | @ -25,10 +24,14 @@ import ( | |||
| 	"github.com/opentracing/opentracing-go" | ||||
| ) | ||||
| 
 | ||||
| var slog log.Logger | ||||
| 
 | ||||
| // StackdriverExecutor executes queries for the Stackdriver datasource
 | ||||
| type StackdriverExecutor struct { | ||||
| 	HTTPClient *http.Client | ||||
| } | ||||
| 
 | ||||
| // NewStackdriverExecutor initializes a http client
 | ||||
| func NewStackdriverExecutor(dsInfo *models.DataSource) (tsdb.TsdbQueryEndpoint, error) { | ||||
| 	httpClient, err := dsInfo.GetHttpClient() | ||||
| 	if err != nil { | ||||
|  | @ -40,9 +43,8 @@ func NewStackdriverExecutor(dsInfo *models.DataSource) (tsdb.TsdbQueryEndpoint, | |||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| var glog = log.New("tsdb.stackdriver") | ||||
| 
 | ||||
| func init() { | ||||
| 	slog = log.New("tsdb.stackdriver") | ||||
| 	tsdb.RegisterTsdbQueryEndpoint("stackdriver", NewStackdriverExecutor) | ||||
| } | ||||
| 
 | ||||
|  | @ -66,7 +68,7 @@ func (e *StackdriverExecutor) Query(ctx context.Context, dsInfo *models.DataSour | |||
| 		} | ||||
| 
 | ||||
| 		req.URL.RawQuery = query.Params.Encode() | ||||
| 		logger.Info("tsdbQuery", "req.URL.RawQuery", req.URL.RawQuery) | ||||
| 		slog.Info("tsdbQuery", "req.URL.RawQuery", req.URL.RawQuery) | ||||
| 
 | ||||
| 		httpClient, err := dsInfo.GetHttpClient() | ||||
| 		if err != nil { | ||||
|  | @ -138,7 +140,7 @@ func (e *StackdriverExecutor) parseQueries(tsdbQuery *tsdb.TsdbQuery) ([]*Stackd | |||
| 		params.Add("filter", metricType) | ||||
| 
 | ||||
| 		if setting.Env == setting.DEV { | ||||
| 			glog.Debug("Stackdriver request", "params", params) | ||||
| 			slog.Debug("Stackdriver request", "params", params) | ||||
| 		} | ||||
| 
 | ||||
| 		stackdriverQueries = append(stackdriverQueries, &StackdriverQuery{ | ||||
|  | @ -159,14 +161,14 @@ func (e *StackdriverExecutor) unmarshalResponse(res *http.Response) (StackDriver | |||
| 	} | ||||
| 
 | ||||
| 	if res.StatusCode/100 != 2 { | ||||
| 		glog.Info("Request failed", "status", res.Status, "body", string(body)) | ||||
| 		slog.Info("Request failed", "status", res.Status, "body", string(body)) | ||||
| 		return StackDriverResponse{}, fmt.Errorf("Request failed status: %v", res.Status) | ||||
| 	} | ||||
| 
 | ||||
| 	var data StackDriverResponse | ||||
| 	err = json.Unmarshal(body, &data) | ||||
| 	if err != nil { | ||||
| 		glog.Info("Failed to unmarshal Stackdriver response", "error", err, "status", res.Status, "body", string(body)) | ||||
| 		slog.Info("Failed to unmarshal Stackdriver response", "error", err, "status", res.Status, "body", string(body)) | ||||
| 		return StackDriverResponse{}, err | ||||
| 	} | ||||
| 
 | ||||
|  | @ -182,8 +184,13 @@ func (e *StackdriverExecutor) parseResponse(data StackDriverResponse, queryRefID | |||
| 		for _, point := range series.Points { | ||||
| 			points = append(points, tsdb.NewTimePoint(null.FloatFrom(point.Value.DoubleValue), float64((point.Interval.EndTime).Unix())*1000)) | ||||
| 		} | ||||
| 		metricName := series.Metric.Type | ||||
| 
 | ||||
| 		for _, value := range series.Metric.Labels { | ||||
| 			metricName += " " + value | ||||
| 		} | ||||
| 		queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{ | ||||
| 			Name:   series.Metric.Type, | ||||
| 			Name:   metricName, | ||||
| 			Points: points, | ||||
| 		}) | ||||
| 	} | ||||
|  | @ -197,7 +204,7 @@ func (e *StackdriverExecutor) createRequest(ctx context.Context, dsInfo *models. | |||
| 
 | ||||
| 	req, err := http.NewRequest(http.MethodGet, "https://monitoring.googleapis.com/", nil) | ||||
| 	if err != nil { | ||||
| 		glog.Info("Failed to create request", "error", err) | ||||
| 		slog.Info("Failed to create request", "error", err) | ||||
| 		return nil, fmt.Errorf("Failed to create request. error: %v", err) | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,9 @@ | |||
| package stackdriver | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
|  | @ -13,8 +15,9 @@ import ( | |||
| 
 | ||||
| func TestStackdriver(t *testing.T) { | ||||
| 	Convey("Stackdriver", t, func() { | ||||
| 		executor := &StackdriverExecutor{} | ||||
| 
 | ||||
| 		Convey("Parse query from frontend", func() { | ||||
| 			executor := &StackdriverExecutor{} | ||||
| 			fromStart := time.Date(2018, 3, 15, 13, 0, 0, 0, time.UTC).In(time.Local) | ||||
| 			tsdbQuery := &tsdb.TsdbQuery{ | ||||
| 				TimeRange: &tsdb.TimeRange{ | ||||
|  | @ -43,5 +46,51 @@ func TestStackdriver(t *testing.T) { | |||
| 			So(queries[0].Params["aggregation.perSeriesAligner"][0], ShouldEqual, "ALIGN_NONE") | ||||
| 			So(queries[0].Params["filter"][0], ShouldEqual, "time_series") | ||||
| 		}) | ||||
| 
 | ||||
| 		Convey("Parse stackdriver response for data aggregated to one time series", func() { | ||||
| 			var data StackDriverResponse | ||||
| 
 | ||||
| 			jsonBody, err := ioutil.ReadFile("./test-data/1-series-response-agg-one-metric.json") | ||||
| 			So(err, ShouldBeNil) | ||||
| 			err = json.Unmarshal(jsonBody, &data) | ||||
| 			So(err, ShouldBeNil) | ||||
| 			So(len(data.TimeSeries), ShouldEqual, 1) | ||||
| 
 | ||||
| 			res, err := executor.parseResponse(data, "A") | ||||
| 			So(err, ShouldBeNil) | ||||
| 
 | ||||
| 			So(len(res.Series), ShouldEqual, 1) | ||||
| 			So(res.Series[0].Name, ShouldEqual, "serviceruntime.googleapis.com/api/request_count") | ||||
| 			So(len(res.Series[0].Points), ShouldEqual, 3) | ||||
| 
 | ||||
| 			So(res.Series[0].Points[0][0].Float64, ShouldEqual, 1.0666666666667) | ||||
| 			So(res.Series[0].Points[1][0].Float64, ShouldEqual, 1.05) | ||||
| 			So(res.Series[0].Points[2][0].Float64, ShouldEqual, 0.05) | ||||
| 		}) | ||||
| 
 | ||||
| 		Convey("Parse stackdriver response for data with no aggregation", func() { | ||||
| 			var data StackDriverResponse | ||||
| 
 | ||||
| 			jsonBody, err := ioutil.ReadFile("./test-data/2-series-response-no-agg.json") | ||||
| 			So(err, ShouldBeNil) | ||||
| 			err = json.Unmarshal(jsonBody, &data) | ||||
| 			So(err, ShouldBeNil) | ||||
| 			So(len(data.TimeSeries), ShouldEqual, 3) | ||||
| 
 | ||||
| 			res, err := executor.parseResponse(data, "A") | ||||
| 			So(err, ShouldBeNil) | ||||
| 
 | ||||
| 			Convey("Should add labels to metric name", func() { | ||||
| 				So(len(res.Series), ShouldEqual, 3) | ||||
| 				So(res.Series[0].Name, ShouldEqual, "compute.googleapis.com/instance/cpu/usage_time collector-asia-east-1") | ||||
| 				So(res.Series[1].Name, ShouldEqual, "compute.googleapis.com/instance/cpu/usage_time collector-europe-west-1") | ||||
| 				So(res.Series[2].Name, ShouldEqual, "compute.googleapis.com/instance/cpu/usage_time collector-us-east-1") | ||||
| 
 | ||||
| 				So(len(res.Series[0].Points), ShouldEqual, 3) | ||||
| 				So(res.Series[0].Points[0][0].Float64, ShouldEqual, 9.7730520330369) | ||||
| 				So(res.Series[0].Points[1][0].Float64, ShouldEqual, 9.7323568146676) | ||||
| 				So(res.Series[0].Points[2][0].Float64, ShouldEqual, 9.8566497180145) | ||||
| 			}) | ||||
| 		}) | ||||
| 	}) | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,46 @@ | |||
| { | ||||
|   "timeSeries": [ | ||||
|     { | ||||
|       "metric": { | ||||
|         "type": "serviceruntime.googleapis.com\/api\/request_count" | ||||
|       }, | ||||
|       "resource": { | ||||
|         "type": "consumed_api", | ||||
|         "labels": { | ||||
|           "project_id": "grafana-prod" | ||||
|         } | ||||
|       }, | ||||
|       "metricKind": "GAUGE", | ||||
|       "valueType": "DOUBLE", | ||||
|       "points": [ | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:51:00Z", | ||||
|             "endTime": "2018-09-11T12:51:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 1.0666666666667 | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:48:00Z", | ||||
|             "endTime": "2018-09-11T12:48:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 1.05 | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:47:00Z", | ||||
|             "endTime": "2018-09-11T12:47:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 0.05 | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   ] | ||||
| } | ||||
|  | @ -0,0 +1,145 @@ | |||
| { | ||||
|   "timeSeries": [ | ||||
|     { | ||||
|       "metric": { | ||||
|         "labels": { | ||||
|           "instance_name": "collector-asia-east-1" | ||||
|         }, | ||||
|         "type": "compute.googleapis.com\/instance\/cpu\/usage_time" | ||||
|       }, | ||||
|       "resource": { | ||||
|         "type": "gce_instance", | ||||
|         "labels": { | ||||
|           "instance_id": "1119268429530133111", | ||||
|           "zone": "asia-east1-a", | ||||
|           "project_id": "grafana-prod" | ||||
|         } | ||||
|       }, | ||||
|       "metricKind": "DELTA", | ||||
|       "valueType": "DOUBLE", | ||||
|       "points": [ | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:30:00Z", | ||||
|             "endTime": "2018-09-11T12:31:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 9.7730520330369 | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:29:00Z", | ||||
|             "endTime": "2018-09-11T12:30:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 9.7323568146676 | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:28:00Z", | ||||
|             "endTime": "2018-09-11T12:29:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 9.8566497180145 | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "metric": { | ||||
|         "labels": { | ||||
|           "instance_name": "collector-europe-west-1" | ||||
|         }, | ||||
|         "type": "compute.googleapis.com\/instance\/cpu\/usage_time" | ||||
|       }, | ||||
|       "resource": { | ||||
|         "type": "gce_instance", | ||||
|         "labels": { | ||||
|           "instance_id": "22241654114540837222", | ||||
|           "zone": "europe-west1-b", | ||||
|           "project_id": "grafana-prod" | ||||
|         } | ||||
|       }, | ||||
|       "metricKind": "DELTA", | ||||
|       "valueType": "DOUBLE", | ||||
|       "points": [ | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:30:00Z", | ||||
|             "endTime": "2018-09-11T12:31:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 8.8210971239023 | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:29:00Z", | ||||
|             "endTime": "2018-09-11T12:30:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 8.9689492364414 | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:28:00Z", | ||||
|             "endTime": "2018-09-11T12:29:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 9.0238475054502 | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "metric": { | ||||
|         "labels": { | ||||
|           "instance_name": "collector-us-east-1" | ||||
|         }, | ||||
|         "type": "compute.googleapis.com\/instance\/cpu\/usage_time" | ||||
|       }, | ||||
|       "resource": { | ||||
|         "type": "gce_instance", | ||||
|         "labels": { | ||||
|           "instance_id": "3332264424035095333", | ||||
|           "zone": "us-east1-b", | ||||
|           "project_id": "grafana-prod" | ||||
|         } | ||||
|       }, | ||||
|       "metricKind": "DELTA", | ||||
|       "valueType": "DOUBLE", | ||||
|       "points": [ | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:30:00Z", | ||||
|             "endTime": "2018-09-11T12:31:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 30.807846801355 | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:29:00Z", | ||||
|             "endTime": "2018-09-11T12:30:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 30.903974115849 | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "interval": { | ||||
|             "startTime": "2018-09-11T12:28:00Z", | ||||
|             "endTime": "2018-09-11T12:29:00Z" | ||||
|           }, | ||||
|           "value": { | ||||
|             "doubleValue": 30.829426143318 | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   ] | ||||
| } | ||||
|  | @ -14,18 +14,12 @@ type StackdriverQuery struct { | |||
| type StackDriverResponse struct { | ||||
| 	TimeSeries []struct { | ||||
| 		Metric struct { | ||||
| 			Labels struct { | ||||
| 				InstanceName string `json:"instance_name"` | ||||
| 			} `json:"labels"` | ||||
| 			Type string `json:"type"` | ||||
| 			Labels map[string]string `json:"labels"` | ||||
| 			Type   string            `json:"type"` | ||||
| 		} `json:"metric"` | ||||
| 		Resource struct { | ||||
| 			Type   string `json:"type"` | ||||
| 			Labels struct { | ||||
| 				InstanceID string `json:"instance_id"` | ||||
| 				Zone       string `json:"zone"` | ||||
| 				ProjectID  string `json:"project_id"` | ||||
| 			} `json:"labels"` | ||||
| 			Type   string            `json:"type"` | ||||
| 			Labels map[string]string `json:"labels"` | ||||
| 		} `json:"resource"` | ||||
| 		MetricKind string `json:"metricKind"` | ||||
| 		ValueType  string `json:"valueType"` | ||||
|  |  | |||
|  | @ -17,6 +17,9 @@ export default class StackdriverDatasource { | |||
|       datasourceId: this.id, | ||||
|       metricType: `metric.type="${t.metricType}"`, | ||||
|     })); | ||||
| 
 | ||||
|     const result = []; | ||||
| 
 | ||||
|     try { | ||||
|       const { data } = await this.backendSrv.datasourceRequest({ | ||||
|         url: '/api/tsdb/query', | ||||
|  | @ -28,8 +31,6 @@ export default class StackdriverDatasource { | |||
|         }, | ||||
|       }); | ||||
| 
 | ||||
|       const result = []; | ||||
| 
 | ||||
|       if (data.results) { | ||||
|         Object['values'](data.results).forEach(queryRes => { | ||||
|           queryRes.series.forEach(series => { | ||||
|  | @ -37,11 +38,11 @@ export default class StackdriverDatasource { | |||
|           }); | ||||
|         }); | ||||
|       } | ||||
| 
 | ||||
|       return { data: result }; | ||||
|     } catch (error) { | ||||
|       console.log(error); | ||||
|     } | ||||
| 
 | ||||
|     return { data: result }; | ||||
|   } | ||||
| 
 | ||||
|   testDatasource() { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue