Stackdriver: Rename Stackdriver to Google Cloud Monitoring (#25807)

* Update backend

* Update frontend

* Keep old plugin id

* Update docs

* Place doc images to a new directory

* Legacy support for stackdriver-auto alignment

* Consistent plugin name

* Apply suggestions from code review

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
Co-authored-by: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com>

* Update docs

* Update public/app/plugins/datasource/cloud-monitoring/README.md

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>

* Add reference to the data source formerly being named Stackdriver

* Update pkg/models/datasource.go

Co-authored-by: Carl Bergquist <carl@grafana.com>

* Fix gofmt

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
Co-authored-by: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com>
Co-authored-by: Carl Bergquist <carl@grafana.com>
This commit is contained in:
Sofia Papagiannaki
2020-06-30 18:47:13 +03:00
committed by GitHub
co-authored by Marcus Efraimsson Tobias Skarhed Carl Bergquist
parent 05bfd17b00
commit 4bb3f66569
68 changed files with 340 additions and 268 deletions
+1 -1
View File
@@ -20,6 +20,7 @@ import (
_ "github.com/grafana/grafana/pkg/services/alerting/notifiers"
"github.com/grafana/grafana/pkg/setting"
_ "github.com/grafana/grafana/pkg/tsdb/azuremonitor"
_ "github.com/grafana/grafana/pkg/tsdb/cloudmonitoring"
_ "github.com/grafana/grafana/pkg/tsdb/cloudwatch"
_ "github.com/grafana/grafana/pkg/tsdb/elasticsearch"
_ "github.com/grafana/grafana/pkg/tsdb/graphite"
@@ -28,7 +29,6 @@ import (
_ "github.com/grafana/grafana/pkg/tsdb/opentsdb"
_ "github.com/grafana/grafana/pkg/tsdb/postgres"
_ "github.com/grafana/grafana/pkg/tsdb/prometheus"
_ "github.com/grafana/grafana/pkg/tsdb/stackdriver"
_ "github.com/grafana/grafana/pkg/tsdb/testdatasource"
)
+6 -4
View File
@@ -22,9 +22,11 @@ const (
DS_MSSQL = "mssql"
DS_ACCESS_DIRECT = "direct"
DS_ACCESS_PROXY = "proxy"
DS_STACKDRIVER = "stackdriver"
DS_AZURE_MONITOR = "grafana-azure-monitor-datasource"
DS_LOKI = "loki"
// Stackdriver was renamed Google Cloud monitoring 2020-05 but we keep
// "stackdriver" to avoid breaking changes in reporting.
DS_CLOUD_MONITORING = "stackdriver"
DS_AZURE_MONITOR = "grafana-azure-monitor-datasource"
DS_LOKI = "loki"
)
var (
@@ -97,7 +99,7 @@ var knownDatasourcePlugins = map[string]bool{
DS_POSTGRES: true,
DS_MYSQL: true,
DS_MSSQL: true,
DS_STACKDRIVER: true,
DS_CLOUD_MONITORING: true,
DS_AZURE_MONITOR: true,
DS_LOKI: true,
"opennms": true,
+6 -2
View File
@@ -60,8 +60,12 @@ func (fp *FrontendPluginBase) handleModuleDefaults() {
}
fp.IsCorePlugin = true
fp.Module = path.Join("app/plugins", fp.Type, fp.Id, "module")
fp.BaseUrl = path.Join("public/app/plugins", fp.Type, fp.Id)
// Previously there was an assumption that the plugin directory
// should be public/app/plugins/<plugin type>/<plugin id>
// However this can be an issue if the plugin directory should be renamed to something else
currentDir := path.Base(fp.PluginDir)
fp.Module = path.Join("app/plugins", fp.Type, currentDir, "module")
fp.BaseUrl = path.Join("public/app/plugins", fp.Type, currentDir)
}
func isExternalPlugin(pluginDir string) bool {
@@ -1,4 +1,4 @@
package stackdriver
package cloudmonitoring
import (
"context"
@@ -9,7 +9,7 @@ import (
"github.com/grafana/grafana/pkg/tsdb"
)
func (e *StackdriverExecutor) executeAnnotationQuery(ctx context.Context, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
func (e *CloudMonitoringExecutor) executeAnnotationQuery(ctx context.Context, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{
Results: make(map[string]*tsdb.QueryResult),
}
@@ -34,7 +34,7 @@ func (e *StackdriverExecutor) executeAnnotationQuery(ctx context.Context, tsdbQu
return result, err
}
func (e *StackdriverExecutor) parseToAnnotations(queryRes *tsdb.QueryResult, data stackdriverResponse, query *stackdriverQuery, title string, text string, tags string) error {
func (e *CloudMonitoringExecutor) parseToAnnotations(queryRes *tsdb.QueryResult, data cloudMonitoringResponse, query *cloudMonitoringQuery, title string, text string, tags string) error {
annotations := make([]map[string]string, 0)
for _, series := range data.TimeSeries {
@@ -1,4 +1,4 @@
package stackdriver
package cloudmonitoring
import (
"testing"
@@ -9,16 +9,16 @@ import (
. "github.com/smartystreets/goconvey/convey"
)
func TestStackdriverAnnotationQuery(t *testing.T) {
Convey("Stackdriver Annotation Query Executor", t, func() {
executor := &StackdriverExecutor{}
Convey("When parsing the stackdriver api response", func() {
func TestCloudMonitoringAnnotationQuery(t *testing.T) {
Convey("CloudMonitoring Annotation Query Executor", t, func() {
executor := &CloudMonitoringExecutor{}
Convey("When parsing the cloud monitoring api response", func() {
data, err := loadTestFile("./test-data/2-series-response-no-agg.json")
So(err, ShouldBeNil)
So(len(data.TimeSeries), ShouldEqual, 3)
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "annotationQuery"}
query := &stackdriverQuery{}
query := &cloudMonitoringQuery{}
err = executor.parseToAnnotations(res, data, query, "atitle {{metric.label.instance_name}} {{metric.value}}", "atext {{resource.label.zone}}", "atag")
So(err, ShouldBeNil)
@@ -1,4 +1,4 @@
package stackdriver
package cloudmonitoring
import (
"context"
@@ -48,34 +48,34 @@ const (
sloQueryType string = "slo"
)
// StackdriverExecutor executes queries for the Stackdriver datasource
type StackdriverExecutor struct {
// CloudMonitoringExecutor executes queries for the CloudMonitoring datasource
type CloudMonitoringExecutor struct {
httpClient *http.Client
dsInfo *models.DataSource
}
// NewStackdriverExecutor initializes a http client
func NewStackdriverExecutor(dsInfo *models.DataSource) (tsdb.TsdbQueryEndpoint, error) {
// NewCloudMonitoringExecutor initializes a http client
func NewCloudMonitoringExecutor(dsInfo *models.DataSource) (tsdb.TsdbQueryEndpoint, error) {
httpClient, err := dsInfo.GetHttpClient()
if err != nil {
return nil, err
}
return &StackdriverExecutor{
return &CloudMonitoringExecutor{
httpClient: httpClient,
dsInfo: dsInfo,
}, nil
}
func init() {
slog = log.New("tsdb.stackdriver")
tsdb.RegisterTsdbQueryEndpoint("stackdriver", NewStackdriverExecutor)
slog = log.New("tsdb.cloudMonitoring")
tsdb.RegisterTsdbQueryEndpoint("stackdriver", NewCloudMonitoringExecutor)
}
// Query takes in the frontend queries, parses them into the Stackdriver query format
// executes the queries against the Stackdriver API and parses the response into
// Query takes in the frontend queries, parses them into the CloudMonitoring query format
// executes the queries against the CloudMonitoring API and parses the response into
// the time series or table format
func (e *StackdriverExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
func (e *CloudMonitoringExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
var result *tsdb.Response
var err error
queryType := tsdbQuery.Queries[0].Model.Get("type").MustString("")
@@ -94,7 +94,7 @@ func (e *StackdriverExecutor) Query(ctx context.Context, dsInfo *models.DataSour
return result, err
}
func (e *StackdriverExecutor) getGCEDefaultProject(ctx context.Context, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
func (e *CloudMonitoringExecutor) getGCEDefaultProject(ctx context.Context, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{
Results: make(map[string]*tsdb.QueryResult),
}
@@ -112,7 +112,7 @@ func (e *StackdriverExecutor) getGCEDefaultProject(ctx context.Context, tsdbQuer
return result, nil
}
func (e *StackdriverExecutor) executeTimeSeriesQuery(ctx context.Context, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
func (e *CloudMonitoringExecutor) executeTimeSeriesQuery(ctx context.Context, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{
Results: make(map[string]*tsdb.QueryResult),
}
@@ -137,8 +137,8 @@ func (e *StackdriverExecutor) executeTimeSeriesQuery(ctx context.Context, tsdbQu
return result, nil
}
func (e *StackdriverExecutor) buildQueries(tsdbQuery *tsdb.TsdbQuery) ([]*stackdriverQuery, error) {
stackdriverQueries := []*stackdriverQuery{}
func (e *CloudMonitoringExecutor) buildQueries(tsdbQuery *tsdb.TsdbQuery) ([]*cloudMonitoringQuery, error) {
cloudMonitoringQueries := []*cloudMonitoringQuery{}
startTime, err := tsdbQuery.TimeRange.ParseFrom()
if err != nil {
@@ -157,14 +157,14 @@ func (e *StackdriverExecutor) buildQueries(tsdbQuery *tsdb.TsdbQuery) ([]*stackd
q := grafanaQuery{}
model, _ := query.Model.MarshalJSON()
if err := json.Unmarshal(model, &q); err != nil {
return nil, fmt.Errorf("could not unmarshal StackdriverQuery json: %w", err)
return nil, fmt.Errorf("could not unmarshal CloudMonitoringQuery json: %w", err)
}
var target string
params := url.Values{}
params.Add("interval.startTime", startTime.UTC().Format(time.RFC3339))
params.Add("interval.endTime", endTime.UTC().Format(time.RFC3339))
sq := &stackdriverQuery{
sq := &cloudMonitoringQuery{
RefID: query.RefId,
GroupBys: []string{},
}
@@ -194,13 +194,13 @@ func (e *StackdriverExecutor) buildQueries(tsdbQuery *tsdb.TsdbQuery) ([]*stackd
sq.Params = params
if setting.Env == setting.DEV {
slog.Debug("Stackdriver request", "params", params)
slog.Debug("CloudMonitoring request", "params", params)
}
stackdriverQueries = append(stackdriverQueries, sq)
cloudMonitoringQueries = append(cloudMonitoringQueries, sq)
}
return stackdriverQueries, nil
return cloudMonitoringQueries, nil
}
func migrateLegacyQueryModel(query *tsdb.Query) {
@@ -306,7 +306,7 @@ func calculateAlignmentPeriod(alignmentPeriod string, intervalMs int64, duration
alignmentPeriod = "+" + strconv.Itoa(alignmentPeriodValue) + "s"
}
if alignmentPeriod == "stackdriver-auto" {
if alignmentPeriod == "cloud-monitoring-auto" || alignmentPeriod == "stackdriver-auto" { // legacy
alignmentPeriodValue := int(math.Max(float64(durationSeconds), 60.0))
if alignmentPeriodValue < 60*60*23 {
alignmentPeriod = "+60s"
@@ -320,23 +320,23 @@ func calculateAlignmentPeriod(alignmentPeriod string, intervalMs int64, duration
return alignmentPeriod
}
func (e *StackdriverExecutor) executeQuery(ctx context.Context, query *stackdriverQuery, tsdbQuery *tsdb.TsdbQuery) (*tsdb.QueryResult, stackdriverResponse, error) {
func (e *CloudMonitoringExecutor) executeQuery(ctx context.Context, query *cloudMonitoringQuery, tsdbQuery *tsdb.TsdbQuery) (*tsdb.QueryResult, cloudMonitoringResponse, error) {
queryResult := &tsdb.QueryResult{Meta: simplejson.New(), RefId: query.RefID}
projectName := query.ProjectName
if projectName == "" {
defaultProject, err := e.getDefaultProject(ctx)
if err != nil {
queryResult.Error = err
return queryResult, stackdriverResponse{}, nil
return queryResult, cloudMonitoringResponse{}, nil
}
projectName = defaultProject
slog.Info("No project name set on query, using project name from datasource", "projectName", projectName)
}
req, err := e.createRequest(ctx, e.dsInfo, query, fmt.Sprintf("stackdriver%s", "v3/projects/"+projectName+"/timeSeries"))
req, err := e.createRequest(ctx, e.dsInfo, query, fmt.Sprintf("cloudmonitoring%s", "v3/projects/"+projectName+"/timeSeries"))
if err != nil {
queryResult.Error = err
return queryResult, stackdriverResponse{}, nil
return queryResult, cloudMonitoringResponse{}, nil
}
req.URL.RawQuery = query.Params.Encode()
@@ -350,7 +350,7 @@ func (e *StackdriverExecutor) executeQuery(ctx context.Context, query *stackdriv
}
}
span, ctx := opentracing.StartSpanFromContext(ctx, "stackdriver query")
span, ctx := opentracing.StartSpanFromContext(ctx, "cloudMonitoring query")
span.SetTag("target", query.Target)
span.SetTag("from", tsdbQuery.TimeRange.From)
span.SetTag("until", tsdbQuery.TimeRange.To)
@@ -364,47 +364,47 @@ func (e *StackdriverExecutor) executeQuery(ctx context.Context, query *stackdriv
opentracing.HTTPHeaders,
opentracing.HTTPHeadersCarrier(req.Header)); err != nil {
queryResult.Error = err
return queryResult, stackdriverResponse{}, nil
return queryResult, cloudMonitoringResponse{}, nil
}
res, err := ctxhttp.Do(ctx, e.httpClient, req)
if err != nil {
queryResult.Error = err
return queryResult, stackdriverResponse{}, nil
return queryResult, cloudMonitoringResponse{}, nil
}
data, err := e.unmarshalResponse(res)
if err != nil {
queryResult.Error = err
return queryResult, stackdriverResponse{}, nil
return queryResult, cloudMonitoringResponse{}, nil
}
return queryResult, data, nil
}
func (e *StackdriverExecutor) unmarshalResponse(res *http.Response) (stackdriverResponse, error) {
func (e *CloudMonitoringExecutor) unmarshalResponse(res *http.Response) (cloudMonitoringResponse, error) {
body, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
return stackdriverResponse{}, err
return cloudMonitoringResponse{}, err
}
if res.StatusCode/100 != 2 {
slog.Error("Request failed", "status", res.Status, "body", string(body))
return stackdriverResponse{}, fmt.Errorf(string(body))
return cloudMonitoringResponse{}, fmt.Errorf(string(body))
}
var data stackdriverResponse
var data cloudMonitoringResponse
err = json.Unmarshal(body, &data)
if err != nil {
slog.Error("Failed to unmarshal Stackdriver response", "error", err, "status", res.Status, "body", string(body))
return stackdriverResponse{}, err
slog.Error("Failed to unmarshal CloudMonitoring response", "error", err, "status", res.Status, "body", string(body))
return cloudMonitoringResponse{}, err
}
return data, nil
}
func (e *StackdriverExecutor) parseResponse(queryRes *tsdb.QueryResult, data stackdriverResponse, query *stackdriverQuery) error {
func (e *CloudMonitoringExecutor) parseResponse(queryRes *tsdb.QueryResult, data cloudMonitoringResponse, query *cloudMonitoringQuery) error {
labels := make(map[string]map[string]bool)
for _, series := range data.TimeSeries {
@@ -570,7 +570,7 @@ func containsLabel(labels []string, newLabel string) bool {
return false
}
func formatLegendKeys(metricType string, defaultMetricName string, labels map[string]string, additionalLabels map[string]string, query *stackdriverQuery) string {
func formatLegendKeys(metricType string, defaultMetricName string, labels map[string]string, additionalLabels map[string]string, query *cloudMonitoringQuery) string {
if query.AliasBy == "" {
return defaultMetricName
}
@@ -639,7 +639,7 @@ func replaceWithMetricPart(metaPartName string, metricType string) []byte {
return nil
}
func calcBucketBound(bucketOptions stackdriverBucketOptions, n int) string {
func calcBucketBound(bucketOptions cloudMonitoringBucketOptions, n int) string {
bucketBound := "0"
if n == 0 {
return bucketBound
@@ -655,7 +655,7 @@ func calcBucketBound(bucketOptions stackdriverBucketOptions, n int) string {
return bucketBound
}
func (e *StackdriverExecutor) createRequest(ctx context.Context, dsInfo *models.DataSource, query *stackdriverQuery, proxyPass string) (*http.Request, error) {
func (e *CloudMonitoringExecutor) createRequest(ctx context.Context, dsInfo *models.DataSource, query *cloudMonitoringQuery, proxyPass string) (*http.Request, error) {
u, err := url.Parse(dsInfo.Url)
if err != nil {
return nil, err
@@ -674,23 +674,23 @@ func (e *StackdriverExecutor) createRequest(ctx context.Context, dsInfo *models.
// find plugin
plugin, ok := plugins.DataSources[dsInfo.Type]
if !ok {
return nil, errors.New("Unable to find datasource plugin Stackdriver")
return nil, errors.New("Unable to find datasource plugin CloudMonitoring")
}
var stackdriverRoute *plugins.AppPluginRoute
var cloudMonitoringRoute *plugins.AppPluginRoute
for _, route := range plugin.Routes {
if route.Path == "stackdriver" {
stackdriverRoute = route
if route.Path == "cloudmonitoring" {
cloudMonitoringRoute = route
break
}
}
pluginproxy.ApplyRoute(ctx, req, proxyPass, stackdriverRoute, dsInfo)
pluginproxy.ApplyRoute(ctx, req, proxyPass, cloudMonitoringRoute, dsInfo)
return req, nil
}
func (e *StackdriverExecutor) getDefaultProject(ctx context.Context) (string, error) {
func (e *CloudMonitoringExecutor) getDefaultProject(ctx context.Context) (string, error) {
authenticationType := e.dsInfo.JsonData.Get("authenticationType").MustString(jwtAuthentication)
if authenticationType == gceAuthentication {
defaultCredentials, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/monitoring.read")
@@ -1,4 +1,4 @@
package stackdriver
package cloudmonitoring
import (
"encoding/json"
@@ -15,11 +15,11 @@ import (
. "github.com/smartystreets/goconvey/convey"
)
func TestStackdriver(t *testing.T) {
Convey("Stackdriver", t, func() {
executor := &StackdriverExecutor{}
func TestCloudMonitoring(t *testing.T) {
Convey("Google Cloud Monitoring", t, func() {
executor := &CloudMonitoringExecutor{}
Convey("Parse migrated queries from frontend and build Stackdriver API queries", func() {
Convey("Parse migrated queries from frontend and build Google Cloud Monitoring API queries", func() {
fromStart := time.Date(2018, 3, 15, 13, 0, 0, 0, time.UTC).In(time.Local)
tsdbQuery := &tsdb.TsdbQuery{
TimeRange: &tsdb.TimeRange{
@@ -92,7 +92,61 @@ func TestStackdriver(t *testing.T) {
})
})
Convey("and alignmentPeriod is set to stackdriver-auto", func() {
Convey("and alignmentPeriod is set to cloud-monitoring-auto", func() { // legacy
Convey("and range is two hours", func() {
tsdbQuery.TimeRange.From = "1538033322461"
tsdbQuery.TimeRange.To = "1538040522461"
tsdbQuery.Queries[0].Model = simplejson.NewFromAny(map[string]interface{}{
"target": "target",
"alignmentPeriod": "cloud-monitoring-auto",
})
queries, err := executor.buildQueries(tsdbQuery)
So(err, ShouldBeNil)
So(queries[0].Params["aggregation.alignmentPeriod"][0], ShouldEqual, `+60s`)
})
Convey("and range is 22 hours", func() {
tsdbQuery.TimeRange.From = "1538034524922"
tsdbQuery.TimeRange.To = "1538113724922"
tsdbQuery.Queries[0].Model = simplejson.NewFromAny(map[string]interface{}{
"target": "target",
"alignmentPeriod": "cloud-monitoring-auto",
})
queries, err := executor.buildQueries(tsdbQuery)
So(err, ShouldBeNil)
So(queries[0].Params["aggregation.alignmentPeriod"][0], ShouldEqual, `+60s`)
})
Convey("and range is 23 hours", func() {
tsdbQuery.TimeRange.From = "1538034567985"
tsdbQuery.TimeRange.To = "1538117367985"
tsdbQuery.Queries[0].Model = simplejson.NewFromAny(map[string]interface{}{
"target": "target",
"alignmentPeriod": "cloud-monitoring-auto",
})
queries, err := executor.buildQueries(tsdbQuery)
So(err, ShouldBeNil)
So(queries[0].Params["aggregation.alignmentPeriod"][0], ShouldEqual, `+300s`)
})
Convey("and range is 7 days", func() {
tsdbQuery.TimeRange.From = "1538036324073"
tsdbQuery.TimeRange.To = "1538641124073"
tsdbQuery.Queries[0].Model = simplejson.NewFromAny(map[string]interface{}{
"target": "target",
"alignmentPeriod": "cloud-monitoring-auto",
})
queries, err := executor.buildQueries(tsdbQuery)
So(err, ShouldBeNil)
So(queries[0].Params["aggregation.alignmentPeriod"][0], ShouldEqual, `+3600s`)
})
})
Convey("and alignmentPeriod is set to stackdriver-auto", func() { // legacy
Convey("and range is two hours", func() {
tsdbQuery.TimeRange.From = "1538033322461"
tsdbQuery.TimeRange.To = "1538040522461"
@@ -208,7 +262,7 @@ func TestStackdriver(t *testing.T) {
})
Convey("Parse queries from frontend and build Stackdriver API queries", func() {
Convey("Parse queries from frontend and build Google Cloud Monitoring API queries", func() {
fromStart := time.Date(2018, 3, 15, 13, 0, 0, 0, time.UTC).In(time.Local)
tsdbQuery := &tsdb.TsdbQuery{
TimeRange: &tsdb.TimeRange{
@@ -301,14 +355,14 @@ func TestStackdriver(t *testing.T) {
})
})
Convey("Parse stackdriver response in the time series format", func() {
Convey("Parse cloud monitoring response in the time series format", func() {
Convey("when data from query aggregated to one time series", func() {
data, err := loadTestFile("./test-data/1-series-response-agg-one-metric.json")
So(err, ShouldBeNil)
So(len(data.TimeSeries), ShouldEqual, 1)
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{}
query := &cloudMonitoringQuery{}
err = executor.parseResponse(res, data, query)
So(err, ShouldBeNil)
@@ -334,7 +388,7 @@ func TestStackdriver(t *testing.T) {
So(len(data.TimeSeries), ShouldEqual, 3)
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{}
query := &cloudMonitoringQuery{}
err = executor.parseResponse(res, data, query)
So(err, ShouldBeNil)
@@ -376,7 +430,7 @@ func TestStackdriver(t *testing.T) {
So(len(data.TimeSeries), ShouldEqual, 3)
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{GroupBys: []string{"metric.label.instance_name", "resource.label.zone"}}
query := &cloudMonitoringQuery{GroupBys: []string{"metric.label.instance_name", "resource.label.zone"}}
err = executor.parseResponse(res, data, query)
So(err, ShouldBeNil)
@@ -397,7 +451,7 @@ func TestStackdriver(t *testing.T) {
Convey("and the alias pattern is for metric type, a metric label and a resource label", func() {
query := &stackdriverQuery{AliasBy: "{{metric.type}} - {{metric.label.instance_name}} - {{resource.label.zone}}", GroupBys: []string{"metric.label.instance_name", "resource.label.zone"}}
query := &cloudMonitoringQuery{AliasBy: "{{metric.type}} - {{metric.label.instance_name}} - {{resource.label.zone}}", GroupBys: []string{"metric.label.instance_name", "resource.label.zone"}}
err = executor.parseResponse(res, data, query)
So(err, ShouldBeNil)
@@ -411,7 +465,7 @@ func TestStackdriver(t *testing.T) {
Convey("and the alias pattern is for metric name", func() {
query := &stackdriverQuery{AliasBy: "metric {{metric.name}} service {{metric.service}}", GroupBys: []string{"metric.label.instance_name", "resource.label.zone"}}
query := &cloudMonitoringQuery{AliasBy: "metric {{metric.name}} service {{metric.service}}", GroupBys: []string{"metric.label.instance_name", "resource.label.zone"}}
err = executor.parseResponse(res, data, query)
So(err, ShouldBeNil)
@@ -430,7 +484,7 @@ func TestStackdriver(t *testing.T) {
So(len(data.TimeSeries), ShouldEqual, 1)
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{AliasBy: "{{bucket}}"}
query := &cloudMonitoringQuery{AliasBy: "{{bucket}}"}
err = executor.parseResponse(res, data, query)
So(err, ShouldBeNil)
@@ -477,7 +531,7 @@ func TestStackdriver(t *testing.T) {
So(len(data.TimeSeries), ShouldEqual, 1)
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{AliasBy: "{{bucket}}"}
query := &cloudMonitoringQuery{AliasBy: "{{bucket}}"}
err = executor.parseResponse(res, data, query)
So(err, ShouldBeNil)
@@ -517,7 +571,7 @@ func TestStackdriver(t *testing.T) {
So(len(data.TimeSeries), ShouldEqual, 3)
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{AliasBy: "{{bucket}}"}
query := &cloudMonitoringQuery{AliasBy: "{{bucket}}"}
err = executor.parseResponse(res, data, query)
labels := res.Meta.Get("labels").Interface().(map[string][]string)
So(err, ShouldBeNil)
@@ -556,7 +610,7 @@ func TestStackdriver(t *testing.T) {
Convey("and systemlabel contains key with array of string", func() {
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{AliasBy: "{{metadata.system_labels.test}}"}
query := &cloudMonitoringQuery{AliasBy: "{{metadata.system_labels.test}}"}
err = executor.parseResponse(res, data, query)
So(err, ShouldBeNil)
So(len(res.Series), ShouldEqual, 3)
@@ -568,7 +622,7 @@ func TestStackdriver(t *testing.T) {
Convey("and systemlabel contains key with array of string2", func() {
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{AliasBy: "{{metadata.system_labels.test2}}"}
query := &cloudMonitoringQuery{AliasBy: "{{metadata.system_labels.test2}}"}
err = executor.parseResponse(res, data, query)
So(err, ShouldBeNil)
So(len(res.Series), ShouldEqual, 3)
@@ -584,7 +638,7 @@ func TestStackdriver(t *testing.T) {
Convey("and alias by is expanded", func() {
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{
query := &cloudMonitoringQuery{
ProjectName: "test-proj",
Selector: "select_slo_compliance",
Service: "test-service",
@@ -604,7 +658,7 @@ func TestStackdriver(t *testing.T) {
Convey("and alias by is expanded", func() {
res := &tsdb.QueryResult{Meta: simplejson.New(), RefId: "A"}
query := &stackdriverQuery{
query := &cloudMonitoringQuery{
ProjectName: "test-proj",
Selector: "select_slo_compliance",
Service: "test-service",
@@ -710,8 +764,8 @@ func TestStackdriver(t *testing.T) {
})
}
func loadTestFile(path string) (stackdriverResponse, error) {
var data stackdriverResponse
func loadTestFile(path string) (cloudMonitoringResponse, error) {
var data cloudMonitoringResponse
jsonBody, err := ioutil.ReadFile(path)
if err != nil {
@@ -1,4 +1,4 @@
package stackdriver
package cloudmonitoring
import (
"net/url"
@@ -6,7 +6,7 @@ import (
)
type (
stackdriverQuery struct {
cloudMonitoringQuery struct {
Target string
Params url.Values
RefID string
@@ -48,7 +48,7 @@ type (
SloQuery sloQuery
}
stackdriverBucketOptions struct {
cloudMonitoringBucketOptions struct {
LinearBuckets *struct {
NumFiniteBuckets int64 `json:"numFiniteBuckets"`
Width int64 `json:"width"`
@@ -64,7 +64,7 @@ type (
} `json:"explicitBuckets"`
}
stackdriverResponse struct {
cloudMonitoringResponse struct {
TimeSeries []struct {
Metric struct {
Labels map[string]string `json:"labels"`
@@ -95,8 +95,8 @@ type (
Min int `json:"min"`
Max int `json:"max"`
} `json:"range"`
BucketOptions stackdriverBucketOptions `json:"bucketOptions"`
BucketCounts []string `json:"bucketCounts"`
BucketOptions cloudMonitoringBucketOptions `json:"bucketOptions"`
BucketCounts []string `json:"bucketCounts"`
Examplars []struct {
Value float64 `json:"value"`
Timestamp string `json:"timestamp"`