From feed90c0e2d770da21762623d80eb94c09cddef0 Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanda Date: Sun, 10 Sep 2017 04:24:39 +0900 Subject: [PATCH] re-implement get regions --- pkg/api/cloudwatch/cloudwatch.go | 4 - pkg/tsdb/cloudwatch/cloudwatch.go | 14 + pkg/tsdb/cloudwatch/metric_find_query.go | 504 ++++++++++-------- .../datasource/cloudwatch/datasource.js | 28 +- 4 files changed, 311 insertions(+), 239 deletions(-) diff --git a/pkg/api/cloudwatch/cloudwatch.go b/pkg/api/cloudwatch/cloudwatch.go index 8188e3913e9..86161c756e3 100644 --- a/pkg/api/cloudwatch/cloudwatch.go +++ b/pkg/api/cloudwatch/cloudwatch.go @@ -80,10 +80,6 @@ func init() { "DescribeAlarmsForMetric": handleDescribeAlarmsForMetric, "DescribeAlarmHistory": handleDescribeAlarmHistory, "DescribeInstances": handleDescribeInstances, - "__GetRegions": handleGetRegions, - "__GetNamespaces": handleGetNamespaces, - "__GetMetrics": handleGetMetrics, - "__GetDimensions": handleGetDimensions, } } diff --git a/pkg/tsdb/cloudwatch/cloudwatch.go b/pkg/tsdb/cloudwatch/cloudwatch.go index a388bb0d9ee..2e897f86140 100644 --- a/pkg/tsdb/cloudwatch/cloudwatch.go +++ b/pkg/tsdb/cloudwatch/cloudwatch.go @@ -53,6 +53,20 @@ func init() { } func (e *CloudWatchExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, queryContext *tsdb.QueryContext) *tsdb.BatchResult { + var result *tsdb.BatchResult + queryType := queries[0].Model.Get("type").MustString() + switch queryType { + case "timeSeriesQuery": + result = e.executeTimeSeriesQuery(ctx, queries, queryContext) + break + case "metricFindQuery": + result = e.executeMetricFindQuery(ctx, queries, queryContext) + break + } + return result +} + +func (e *CloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, queries tsdb.QuerySlice, queryContext *tsdb.QueryContext) *tsdb.BatchResult { result := &tsdb.BatchResult{ QueryResults: make(map[string]*tsdb.QueryResult), } diff --git a/pkg/tsdb/cloudwatch/metric_find_query.go b/pkg/tsdb/cloudwatch/metric_find_query.go index 0d471efad68..9cc6974fb21 100644 --- a/pkg/tsdb/cloudwatch/metric_find_query.go +++ b/pkg/tsdb/cloudwatch/metric_find_query.go @@ -1,24 +1,21 @@ package cloudwatch import ( - "encoding/json" - "sort" - "strings" - "sync" + "context" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awsutil" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/cloudwatch" - "github.com/grafana/grafana/pkg/metrics" - "github.com/grafana/grafana/pkg/middleware" - "github.com/grafana/grafana/pkg/util" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/tsdb" ) var metricsMap map[string][]string var dimensionsMap map[string][]string +type suggestData struct { + Text string + Value string +} + type CustomMetricsCache struct { Expire time.Time Cache []string @@ -144,236 +141,279 @@ func init() { customMetricsDimensionsMap = make(map[string]map[string]map[string]*CustomMetricsCache) } +func (e *CloudWatchExecutor) executeMetricFindQuery(ctx context.Context, queries tsdb.QuerySlice, queryContext *tsdb.QueryContext) *tsdb.BatchResult { + result := &tsdb.BatchResult{ + QueryResults: make(map[string]*tsdb.QueryResult), + } + queryResult := &tsdb.QueryResult{Meta: simplejson.New(), RefId: queries[0].RefId} + + parameters := queries[0].Model.Get("parameters") + subType := queries[0].Model.Get("subtype").MustString() + var data []suggestData + var err error + switch subType { + case "regions": + data, err = e.handleGetRegions(ctx, parameters, queryContext) + if err != nil { + queryResult.Error = err + } + break + } + transformToTable(data, queryResult) + result.QueryResults[queries[0].RefId] = queryResult + return result +} + +func transformToTable(data []suggestData, result *tsdb.QueryResult) { + table := &tsdb.Table{ + Columns: make([]tsdb.TableColumn, 2), + Rows: make([]tsdb.RowValues, 0), + } + table.Columns[0].Text = "text" + table.Columns[1].Text = "value" + + for _, r := range data { + values := make([]interface{}, 2) + values[0] = r.Text + values[1] = r.Value + table.Rows = append(table.Rows, values) + } + result.Tables = append(result.Tables, table) + result.Meta.Set("rowCount", len(data)) +} + // Whenever this list is updated, frontend list should also be updated. // Please update the region list in public/app/plugins/datasource/cloudwatch/partials/config.html -func handleGetRegions(req *cwRequest, c *middleware.Context) { +func (e *CloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.QueryContext) ([]suggestData, error) { regions := []string{ "ap-northeast-1", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-south-1", "ca-central-1", "cn-north-1", "eu-central-1", "eu-west-1", "eu-west-2", "sa-east-1", "us-east-1", "us-east-2", "us-gov-west-1", "us-west-1", "us-west-2", } - result := []interface{}{} + result := make([]suggestData, 0) for _, region := range regions { - result = append(result, util.DynMap{"text": region, "value": region}) + result = append(result, suggestData{Text: region, Value: region}) } - c.JSON(200, result) + return result, nil } -func handleGetNamespaces(req *cwRequest, c *middleware.Context) { - keys := []string{} - for key := range metricsMap { - keys = append(keys, key) - } - - customNamespaces := req.DataSource.JsonData.Get("customMetricsNamespaces").MustString() - if customNamespaces != "" { - keys = append(keys, strings.Split(customNamespaces, ",")...) - } - - sort.Sort(sort.StringSlice(keys)) - - result := []interface{}{} - for _, key := range keys { - result = append(result, util.DynMap{"text": key, "value": key}) - } - - c.JSON(200, result) -} - -func handleGetMetrics(req *cwRequest, c *middleware.Context) { - reqParam := &struct { - Parameters struct { - Namespace string `json:"namespace"` - } `json:"parameters"` - }{} - - json.Unmarshal(req.Body, reqParam) - - var namespaceMetrics []string - if !isCustomMetrics(reqParam.Parameters.Namespace) { - var exists bool - if namespaceMetrics, exists = metricsMap[reqParam.Parameters.Namespace]; !exists { - c.JsonApiErr(404, "Unable to find namespace "+reqParam.Parameters.Namespace, nil) - return - } - } else { - var err error - cwData := req.GetDatasourceInfo() - cwData.Namespace = reqParam.Parameters.Namespace - - if namespaceMetrics, err = getMetricsForCustomMetrics(cwData, getAllMetrics); err != nil { - c.JsonApiErr(500, "Unable to call AWS API", err) - return - } - } - sort.Sort(sort.StringSlice(namespaceMetrics)) - - result := []interface{}{} - for _, name := range namespaceMetrics { - result = append(result, util.DynMap{"text": name, "value": name}) - } - - c.JSON(200, result) -} - -func handleGetDimensions(req *cwRequest, c *middleware.Context) { - reqParam := &struct { - Parameters struct { - Namespace string `json:"namespace"` - } `json:"parameters"` - }{} - - json.Unmarshal(req.Body, reqParam) - - var dimensionValues []string - if !isCustomMetrics(reqParam.Parameters.Namespace) { - var exists bool - if dimensionValues, exists = dimensionsMap[reqParam.Parameters.Namespace]; !exists { - c.JsonApiErr(404, "Unable to find dimension "+reqParam.Parameters.Namespace, nil) - return - } - } else { - var err error - dsInfo := req.GetDatasourceInfo() - dsInfo.Namespace = reqParam.Parameters.Namespace - - if dimensionValues, err = getDimensionsForCustomMetrics(dsInfo, getAllMetrics); err != nil { - c.JsonApiErr(500, "Unable to call AWS API", err) - return - } - } - sort.Sort(sort.StringSlice(dimensionValues)) - - result := []interface{}{} - for _, name := range dimensionValues { - result = append(result, util.DynMap{"text": name, "value": name}) - } - - c.JSON(200, result) -} - -func getAllMetrics(cwData *DatasourceInfo) (cloudwatch.ListMetricsOutput, error) { - creds, err := GetCredentials(cwData) - if err != nil { - return cloudwatch.ListMetricsOutput{}, err - } - cfg := &aws.Config{ - Region: aws.String(cwData.Region), - Credentials: creds, - } - sess, err := session.NewSession(cfg) - if err != nil { - return cloudwatch.ListMetricsOutput{}, err - } - svc := cloudwatch.New(sess, cfg) - - params := &cloudwatch.ListMetricsInput{ - Namespace: aws.String(cwData.Namespace), - } - - var resp cloudwatch.ListMetricsOutput - err = svc.ListMetricsPages(params, - func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { - metrics.M_Aws_CloudWatch_ListMetrics.Inc() - metrics, _ := awsutil.ValuesAtPath(page, "Metrics") - for _, metric := range metrics { - resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric)) - } - return !lastPage - }) - if err != nil { - return resp, err - } - - return resp, nil -} - -var metricsCacheLock sync.Mutex - -func getMetricsForCustomMetrics(dsInfo *DatasourceInfo, getAllMetrics func(*DatasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { - metricsCacheLock.Lock() - defer metricsCacheLock.Unlock() - - if _, ok := customMetricsMetricsMap[dsInfo.Profile]; !ok { - customMetricsMetricsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache) - } - if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region]; !ok { - customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache) - } - if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok { - customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{} - customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) - } - - if customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) { - return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil - } - result, err := getAllMetrics(dsInfo) - if err != nil { - return []string{}, err - } - customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) - customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute) - - for _, metric := range result.Metrics { - if isDuplicate(customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *metric.MetricName) { - continue - } - customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = append(customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *metric.MetricName) - } - - return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil -} - -var dimensionsCacheLock sync.Mutex - -func getDimensionsForCustomMetrics(dsInfo *DatasourceInfo, getAllMetrics func(*DatasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { - dimensionsCacheLock.Lock() - defer dimensionsCacheLock.Unlock() - - if _, ok := customMetricsDimensionsMap[dsInfo.Profile]; !ok { - customMetricsDimensionsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache) - } - if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region]; !ok { - customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache) - } - if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok { - customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{} - customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) - } - - if customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) { - return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil - } - result, err := getAllMetrics(dsInfo) - if err != nil { - return []string{}, err - } - customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) - customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute) - - for _, metric := range result.Metrics { - for _, dimension := range metric.Dimensions { - if isDuplicate(customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *dimension.Name) { - continue - } - customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = append(customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *dimension.Name) - } - } - - return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil -} - -func isDuplicate(nameList []string, target string) bool { - for _, name := range nameList { - if name == target { - return true - } - } - return false -} - -func isCustomMetrics(namespace string) bool { - return strings.Index(namespace, "AWS/") != 0 -} +//func handleGetNamespaces(req *cwRequest, c *middleware.Context) { +// keys := []string{} +// for key := range metricsMap { +// keys = append(keys, key) +// } +// +// customNamespaces := req.DataSource.JsonData.Get("customMetricsNamespaces").MustString() +// if customNamespaces != "" { +// for _, key := range strings.Split(customNamespaces, ",") { +// keys = append(keys, key) +// } +// } +// +// sort.Sort(sort.StringSlice(keys)) +// +// result := []interface{}{} +// for _, key := range keys { +// result = append(result, util.DynMap{"text": key, "value": key}) +// } +// +// c.JSON(200, result) +//} +// +//func handleGetMetrics(req *cwRequest, c *middleware.Context) { +// reqParam := &struct { +// Parameters struct { +// Namespace string `json:"namespace"` +// } `json:"parameters"` +// }{} +// +// json.Unmarshal(req.Body, reqParam) +// +// var namespaceMetrics []string +// if !isCustomMetrics(reqParam.Parameters.Namespace) { +// var exists bool +// if namespaceMetrics, exists = metricsMap[reqParam.Parameters.Namespace]; !exists { +// c.JsonApiErr(404, "Unable to find namespace "+reqParam.Parameters.Namespace, nil) +// return +// } +// } else { +// var err error +// cwData := req.GetDatasourceInfo() +// cwData.Namespace = reqParam.Parameters.Namespace +// +// if namespaceMetrics, err = getMetricsForCustomMetrics(cwData, getAllMetrics); err != nil { +// c.JsonApiErr(500, "Unable to call AWS API", err) +// return +// } +// } +// sort.Sort(sort.StringSlice(namespaceMetrics)) +// +// result := []interface{}{} +// for _, name := range namespaceMetrics { +// result = append(result, util.DynMap{"text": name, "value": name}) +// } +// +// c.JSON(200, result) +//} +// +//func handleGetDimensions(req *cwRequest, c *middleware.Context) { +// reqParam := &struct { +// Parameters struct { +// Namespace string `json:"namespace"` +// } `json:"parameters"` +// }{} +// +// json.Unmarshal(req.Body, reqParam) +// +// var dimensionValues []string +// if !isCustomMetrics(reqParam.Parameters.Namespace) { +// var exists bool +// if dimensionValues, exists = dimensionsMap[reqParam.Parameters.Namespace]; !exists { +// c.JsonApiErr(404, "Unable to find dimension "+reqParam.Parameters.Namespace, nil) +// return +// } +// } else { +// var err error +// dsInfo := req.GetDatasourceInfo() +// dsInfo.Namespace = reqParam.Parameters.Namespace +// +// if dimensionValues, err = getDimensionsForCustomMetrics(dsInfo, getAllMetrics); err != nil { +// c.JsonApiErr(500, "Unable to call AWS API", err) +// return +// } +// } +// sort.Sort(sort.StringSlice(dimensionValues)) +// +// result := []interface{}{} +// for _, name := range dimensionValues { +// result = append(result, util.DynMap{"text": name, "value": name}) +// } +// +// c.JSON(200, result) +//} +// +//func getAllMetrics(cwData *DatasourceInfo) (cloudwatch.ListMetricsOutput, error) { +// creds, err := GetCredentials(cwData) +// if err != nil { +// return cloudwatch.ListMetricsOutput{}, err +// } +// cfg := &aws.Config{ +// Region: aws.String(cwData.Region), +// Credentials: creds, +// } +// sess, err := session.NewSession(cfg) +// if err != nil { +// return cloudwatch.ListMetricsOutput{}, err +// } +// svc := cloudwatch.New(sess, cfg) +// +// params := &cloudwatch.ListMetricsInput{ +// Namespace: aws.String(cwData.Namespace), +// } +// +// var resp cloudwatch.ListMetricsOutput +// err = svc.ListMetricsPages(params, +// func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool { +// metrics.M_Aws_CloudWatch_ListMetrics.Inc(1) +// metrics, _ := awsutil.ValuesAtPath(page, "Metrics") +// for _, metric := range metrics { +// resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric)) +// } +// return !lastPage +// }) +// if err != nil { +// return resp, err +// } +// +// return resp, nil +//} +// +//var metricsCacheLock sync.Mutex +// +//func getMetricsForCustomMetrics(dsInfo *DatasourceInfo, getAllMetrics func(*DatasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { +// metricsCacheLock.Lock() +// defer metricsCacheLock.Unlock() +// +// if _, ok := customMetricsMetricsMap[dsInfo.Profile]; !ok { +// customMetricsMetricsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache) +// } +// if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region]; !ok { +// customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache) +// } +// if _, ok := customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok { +// customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{} +// customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) +// } +// +// if customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) { +// return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil +// } +// result, err := getAllMetrics(dsInfo) +// if err != nil { +// return []string{}, err +// } +// customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) +// customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute) +// +// for _, metric := range result.Metrics { +// if isDuplicate(customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *metric.MetricName) { +// continue +// } +// customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = append(customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *metric.MetricName) +// } +// +// return customMetricsMetricsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil +//} +// +//var dimensionsCacheLock sync.Mutex +// +//func getDimensionsForCustomMetrics(dsInfo *DatasourceInfo, getAllMetrics func(*DatasourceInfo) (cloudwatch.ListMetricsOutput, error)) ([]string, error) { +// dimensionsCacheLock.Lock() +// defer dimensionsCacheLock.Unlock() +// +// if _, ok := customMetricsDimensionsMap[dsInfo.Profile]; !ok { +// customMetricsDimensionsMap[dsInfo.Profile] = make(map[string]map[string]*CustomMetricsCache) +// } +// if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region]; !ok { +// customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region] = make(map[string]*CustomMetricsCache) +// } +// if _, ok := customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace]; !ok { +// customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace] = &CustomMetricsCache{} +// customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) +// } +// +// if customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire.After(time.Now()) { +// return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil +// } +// result, err := getAllMetrics(dsInfo) +// if err != nil { +// return []string{}, err +// } +// customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = make([]string, 0) +// customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Expire = time.Now().Add(5 * time.Minute) +// +// for _, metric := range result.Metrics { +// for _, dimension := range metric.Dimensions { +// if isDuplicate(customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *dimension.Name) { +// continue +// } +// customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache = append(customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, *dimension.Name) +// } +// } +// +// return customMetricsDimensionsMap[dsInfo.Profile][dsInfo.Region][dsInfo.Namespace].Cache, nil +//} +// +//func isDuplicate(nameList []string, target string) bool { +// for _, name := range nameList { +// if name == target { +// return true +// } +// } +// return false +//} +// +//func isCustomMetrics(namespace string) bool { +// return strings.Index(namespace, "AWS/") != 0 +//} diff --git a/public/app/plugins/datasource/cloudwatch/datasource.js b/public/app/plugins/datasource/cloudwatch/datasource.js index 40094003456..ae0225e6877 100644 --- a/public/app/plugins/datasource/cloudwatch/datasource.js +++ b/public/app/plugins/datasource/cloudwatch/datasource.js @@ -11,7 +11,7 @@ function (angular, _, moment, dateMath, kbn, templatingVariable, CloudWatchAnnot 'use strict'; /** @ngInject */ - function CloudWatchDatasource(instanceSettings, $q, backendSrv, templateSrv) { + function CloudWatchDatasource(instanceSettings, $q, backendSrv, templateSrv, timeSrv) { this.type = 'cloudwatch'; this.name = instanceSettings.name; this.supportMetrics = true; @@ -133,7 +133,21 @@ function (angular, _, moment, dateMath, kbn, templatingVariable, CloudWatchAnnot }; this.getRegions = function() { - return this.awsRequest({action: '__GetRegions'}); + var range = timeSrv.timeRange(); + return backendSrv.post('/api/tsdb/query', { + from: range.from, + to: range.to, + queries: [ + { + refId: 'metricFindQuery', + intervalMs: 1, // dummy + maxDataPoints: 1, // dummy + datasourceId: this.instanceSettings.id, + type: 'metricFindQuery', + subtype: 'regions' + } + ] + }); }; this.getNamespaces = function() { @@ -200,6 +214,14 @@ function (angular, _, moment, dateMath, kbn, templatingVariable, CloudWatchAnnot var namespace; var metricName; + var transformSuggestDataFromTable = function(suggestData) { + return _.map(suggestData.results['metricFindQuery'].tables[0].rows, function (v) { + return { + text: v[0], + value: v[1] + }; + }); + }; var transformSuggestData = function(suggestData) { return _.map(suggestData, function(v) { return { text: v }; @@ -208,7 +230,7 @@ function (angular, _, moment, dateMath, kbn, templatingVariable, CloudWatchAnnot var regionQuery = query.match(/^regions\(\)/); if (regionQuery) { - return this.getRegions(); + return this.getRegions().then(function (r) { return transformSuggestDataFromTable(r); }); } var namespaceQuery = query.match(/^namespaces\(\)/);