diff --git a/pkg/api/cloudwatch/cloudwatch.go b/pkg/api/cloudwatch/cloudwatch.go
index d5abe4958ea..0995c88da4b 100644
--- a/pkg/api/cloudwatch/cloudwatch.go
+++ b/pkg/api/cloudwatch/cloudwatch.go
@@ -31,13 +31,15 @@ type cwRequest struct {
func init() {
actionHandlers = map[string]actionHandler{
- "GetMetricStatistics": handleGetMetricStatistics,
- "ListMetrics": handleListMetrics,
- "DescribeInstances": handleDescribeInstances,
- "__GetRegions": handleGetRegions,
- "__GetNamespaces": handleGetNamespaces,
- "__GetMetrics": handleGetMetrics,
- "__GetDimensions": handleGetDimensions,
+ "GetMetricStatistics": handleGetMetricStatistics,
+ "ListMetrics": handleListMetrics,
+ "DescribeAlarmsForMetric": handleDescribeAlarmsForMetric,
+ "DescribeAlarmHistory": handleDescribeAlarmHistory,
+ "DescribeInstances": handleDescribeInstances,
+ "__GetRegions": handleGetRegions,
+ "__GetNamespaces": handleGetNamespaces,
+ "__GetMetrics": handleGetMetrics,
+ "__GetDimensions": handleGetDimensions,
}
}
@@ -137,6 +139,98 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) {
c.JSON(200, resp)
}
+func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) {
+ sess := session.New()
+ creds := credentials.NewChainCredentials(
+ []credentials.Provider{
+ &credentials.EnvProvider{},
+ &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database},
+ &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
+ })
+
+ cfg := &aws.Config{
+ Region: aws.String(req.Region),
+ Credentials: creds,
+ }
+
+ svc := cloudwatch.New(session.New(cfg), cfg)
+
+ reqParam := &struct {
+ Parameters struct {
+ Namespace string `json:"namespace"`
+ MetricName string `json:"metricName"`
+ Dimensions []*cloudwatch.Dimension `json:"dimensions"`
+ Statistic string `json:"statistic"`
+ Period int64 `json:"period"`
+ } `json:"parameters"`
+ }{}
+ json.Unmarshal(req.Body, reqParam)
+
+ params := &cloudwatch.DescribeAlarmsForMetricInput{
+ Namespace: aws.String(reqParam.Parameters.Namespace),
+ MetricName: aws.String(reqParam.Parameters.MetricName),
+ Period: aws.Int64(reqParam.Parameters.Period),
+ }
+ if len(reqParam.Parameters.Dimensions) != 0 {
+ params.Dimensions = reqParam.Parameters.Dimensions
+ }
+ if reqParam.Parameters.Statistic != "" {
+ params.Statistic = aws.String(reqParam.Parameters.Statistic)
+ }
+
+ resp, err := svc.DescribeAlarmsForMetric(params)
+ if err != nil {
+ c.JsonApiErr(500, "Unable to call AWS API", err)
+ return
+ }
+
+ c.JSON(200, resp)
+}
+
+func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) {
+ sess := session.New()
+ creds := credentials.NewChainCredentials(
+ []credentials.Provider{
+ &credentials.EnvProvider{},
+ &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database},
+ &ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
+ })
+
+ cfg := &aws.Config{
+ Region: aws.String(req.Region),
+ Credentials: creds,
+ }
+
+ svc := cloudwatch.New(session.New(cfg), cfg)
+
+ reqParam := &struct {
+ Parameters struct {
+ AlarmName string `json:"alarmName"`
+ HistoryItemType string `json:"historyItemType"`
+ StartDate int64 `json:"startDate"`
+ EndDate int64 `json:"endDate"`
+ } `json:"parameters"`
+ }{}
+ json.Unmarshal(req.Body, reqParam)
+
+ params := &cloudwatch.DescribeAlarmHistoryInput{
+ AlarmName: aws.String(reqParam.Parameters.AlarmName),
+ StartDate: aws.Time(time.Unix(reqParam.Parameters.StartDate, 0)),
+ EndDate: aws.Time(time.Unix(reqParam.Parameters.EndDate, 0)),
+ }
+ if reqParam.Parameters.HistoryItemType != "" {
+ params.HistoryItemType = aws.String(reqParam.Parameters.HistoryItemType)
+ }
+
+ resp, err := svc.DescribeAlarmHistory(params)
+ if err != nil {
+ c.JsonApiErr(500, "Unable to call AWS API", err)
+ return
+ }
+
+ c.JSON(200, resp)
+}
+
func handleDescribeInstances(req *cwRequest, c *middleware.Context) {
sess := session.New()
creds := credentials.NewChainCredentials(
diff --git a/public/app/plugins/datasource/cloudwatch/datasource.js b/public/app/plugins/datasource/cloudwatch/datasource.js
index e01bdce6096..f606b6e3dc8 100644
--- a/public/app/plugins/datasource/cloudwatch/datasource.js
+++ b/public/app/plugins/datasource/cloudwatch/datasource.js
@@ -2,10 +2,11 @@ define([
'angular',
'lodash',
'moment',
+ 'app/core/utils/datemath',
'./query_ctrl',
'./directives',
],
-function (angular, _) {
+function (angular, _, moment, dateMath) {
'use strict';
var module = angular.module('grafana.services');
@@ -21,8 +22,8 @@ function (angular, _) {
}
CloudWatchDatasource.prototype.query = function(options) {
- var start = convertToCloudWatchTime(options.range.from);
- var end = convertToCloudWatchTime(options.range.to);
+ var start = convertToCloudWatchTime(options.range.from, false);
+ var end = convertToCloudWatchTime(options.range.to, true);
var queries = [];
options = angular.copy(options);
@@ -209,6 +210,74 @@ function (angular, _) {
return $q.when([]);
};
+ CloudWatchDatasource.prototype.performDescribeAlarmsForMetric = function(region, namespace, metricName, dimensions, statistic, period) {
+ return this.awsRequest({
+ region: region,
+ action: 'DescribeAlarmsForMetric',
+ parameters: { namespace: namespace, metricName: metricName, dimensions: dimensions, statistic: statistic, period: period }
+ });
+ };
+
+ CloudWatchDatasource.prototype.performDescribeAlarmHistory = function(region, alarmName, startDate, endDate) {
+ return this.awsRequest({
+ region: region,
+ action: 'DescribeAlarmHistory',
+ parameters: { alarmName: alarmName, startDate: startDate, endDate: endDate }
+ });
+ };
+
+ CloudWatchDatasource.prototype.annotationQuery = function(options) {
+ var annotation = options.annotation;
+ var region = templateSrv.replace(annotation.region);
+ var namespace = templateSrv.replace(annotation.namespace);
+ var metricName = templateSrv.replace(annotation.metricName);
+ var dimensions = convertDimensionFormat(annotation.dimensions);
+ var statistics = _.map(annotation.statistics, function(s) { return templateSrv.replace(s); });
+ var period = annotation.period || '300';
+ period = parseInt(period, 10);
+
+ if (!region || !namespace || !metricName || _.isEmpty(statistics)) { return $q.when([]); }
+
+ var d = $q.defer();
+ var self = this;
+ var allQueryPromise = _.map(statistics, function(statistic) {
+ return self.performDescribeAlarmsForMetric(region, namespace, metricName, dimensions, statistic, period);
+ });
+ $q.all(allQueryPromise).then(function(alarms) {
+ var eventList = [];
+
+ var start = convertToCloudWatchTime(options.range.from, false);
+ var end = convertToCloudWatchTime(options.range.to, true);
+ _.chain(alarms)
+ .pluck('MetricAlarms')
+ .flatten()
+ .each(function(alarm) {
+ if (!alarm) {
+ d.resolve(eventList);
+ return;
+ }
+
+ self.performDescribeAlarmHistory(region, alarm.AlarmName, start, end).then(function(history) {
+ _.each(history.AlarmHistoryItems, function(h) {
+ var event = {
+ annotation: annotation,
+ time: Date.parse(h.Timestamp),
+ title: h.AlarmName,
+ tags: [h.HistoryItemType],
+ text: h.HistorySummary
+ };
+
+ eventList.push(event);
+ });
+
+ d.resolve(eventList);
+ });
+ });
+ });
+
+ return d.promise;
+ };
+
CloudWatchDatasource.prototype.testDatasource = function() {
/* use billing metrics for test */
var region = this.defaultRegion;
@@ -276,7 +345,10 @@ function (angular, _) {
});
}
- function convertToCloudWatchTime(date) {
+ function convertToCloudWatchTime(date, roundUp) {
+ if (_.isString(date)) {
+ date = dateMath.parse(date, roundUp);
+ }
return Math.round(date.valueOf() / 1000);
}
diff --git a/public/app/plugins/datasource/cloudwatch/directives.js b/public/app/plugins/datasource/cloudwatch/directives.js
index c758aa34e5c..a08d4fc8d9a 100644
--- a/public/app/plugins/datasource/cloudwatch/directives.js
+++ b/public/app/plugins/datasource/cloudwatch/directives.js
@@ -1,5 +1,6 @@
define([
'angular',
+ './query_parameter_ctrl',
],
function (angular) {
'use strict';
@@ -10,4 +11,21 @@ function (angular) {
return {controller: 'CloudWatchQueryCtrl', templateUrl: 'app/plugins/datasource/cloudwatch/partials/query.editor.html'};
});
+ module.directive('annotationsQueryEditorCloudwatch', function() {
+ return {templateUrl: 'app/plugins/datasource/cloudwatch/partials/annotations.editor.html'};
+ });
+
+ module.directive('cloudwatchQueryParameter', function() {
+ return {
+ templateUrl: 'app/plugins/datasource/cloudwatch/partials/query.parameter.html',
+ controller: 'CloudWatchQueryParameterCtrl',
+ restrict: 'E',
+ scope: {
+ target: "=",
+ datasourceName: "@",
+ onChange: "&",
+ }
+ };
+ });
+
});
diff --git a/public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html b/public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html
new file mode 100644
index 00000000000..dfecb80032d
--- /dev/null
+++ b/public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html
@@ -0,0 +1 @@
+
diff --git a/public/app/plugins/datasource/cloudwatch/partials/query.editor.html b/public/app/plugins/datasource/cloudwatch/partials/query.editor.html
index 0984bc521e2..cc2dfa3a601 100644
--- a/public/app/plugins/datasource/cloudwatch/partials/query.editor.html
+++ b/public/app/plugins/datasource/cloudwatch/partials/query.editor.html
@@ -33,61 +33,16 @@
-
-
-
-
-
-
-
+
diff --git a/public/app/plugins/datasource/cloudwatch/partials/query.parameter.html b/public/app/plugins/datasource/cloudwatch/partials/query.parameter.html
new file mode 100644
index 00000000000..6e2dde5bf48
--- /dev/null
+++ b/public/app/plugins/datasource/cloudwatch/partials/query.parameter.html
@@ -0,0 +1,53 @@
+
+
+
+
+
+
diff --git a/public/app/plugins/datasource/cloudwatch/plugin.json b/public/app/plugins/datasource/cloudwatch/plugin.json
index 1fa46416ca6..f1cf0e5512c 100644
--- a/public/app/plugins/datasource/cloudwatch/plugin.json
+++ b/public/app/plugins/datasource/cloudwatch/plugin.json
@@ -12,5 +12,6 @@
"query": "app/plugins/datasource/cloudwatch/partials/query.editor.html"
},
- "metrics": true
+ "metrics": true,
+ "annotations": true
}
diff --git a/public/app/plugins/datasource/cloudwatch/query_ctrl.js b/public/app/plugins/datasource/cloudwatch/query_ctrl.js
index d0f6fe5b52a..e24b73cd068 100644
--- a/public/app/plugins/datasource/cloudwatch/query_ctrl.js
+++ b/public/app/plugins/datasource/cloudwatch/query_ctrl.js
@@ -7,173 +7,10 @@ function (angular, _) {
var module = angular.module('grafana.controllers');
- module.controller('CloudWatchQueryCtrl', function($scope, templateSrv, uiSegmentSrv, $q) {
+ module.controller('CloudWatchQueryCtrl', function($scope) {
$scope.init = function() {
- var target = $scope.target;
- target.namespace = target.namespace || '';
- target.metricName = target.metricName || '';
- target.statistics = target.statistics || ['Average'];
- target.dimensions = target.dimensions || {};
- target.period = target.period || '';
- target.region = target.region || $scope.datasource.getDefaultRegion();
-
$scope.aliasSyntax = '{{metric}} {{stat}} {{namespace}} {{region}} {{}}';
-
- $scope.regionSegment = uiSegmentSrv.getSegmentForValue($scope.target.region, 'select region');
- $scope.namespaceSegment = uiSegmentSrv.getSegmentForValue($scope.target.namespace, 'select namespace');
- $scope.metricSegment = uiSegmentSrv.getSegmentForValue($scope.target.metricName, 'select metric');
-
- $scope.dimSegments = _.reduce($scope.target.dimensions, function(memo, value, key) {
- memo.push(uiSegmentSrv.newKey(key));
- memo.push(uiSegmentSrv.newOperator("="));
- memo.push(uiSegmentSrv.newKeyValue(value));
- return memo;
- }, []);
-
- $scope.statSegments = _.map($scope.target.statistics, function(stat) {
- return uiSegmentSrv.getSegmentForValue(stat);
- });
-
- $scope.ensurePlusButton($scope.statSegments);
- $scope.ensurePlusButton($scope.dimSegments);
- $scope.removeDimSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove dimension --'});
- $scope.removeStatSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove stat --'});
- };
-
- $scope.getStatSegments = function() {
- return $q.when([
- angular.copy($scope.removeStatSegment),
- uiSegmentSrv.getSegmentForValue('Average'),
- uiSegmentSrv.getSegmentForValue('Maximum'),
- uiSegmentSrv.getSegmentForValue('Minimum'),
- uiSegmentSrv.getSegmentForValue('Sum'),
- uiSegmentSrv.getSegmentForValue('SampleCount'),
- ]);
- };
-
- $scope.statSegmentChanged = function(segment, index) {
- if (segment.value === $scope.removeStatSegment.value) {
- $scope.statSegments.splice(index, 1);
- } else {
- segment.type = 'value';
- }
-
- $scope.target.statistics = _.reduce($scope.statSegments, function(memo, seg) {
- if (!seg.fake) { memo.push(seg.value); } return memo;
- }, []);
-
- $scope.ensurePlusButton($scope.statSegments);
- $scope.get_data();
- };
-
- $scope.ensurePlusButton = function(segments) {
- var count = segments.length;
- var lastSegment = segments[Math.max(count-1, 0)];
-
- if (!lastSegment || lastSegment.type !== 'plus-button') {
- segments.push(uiSegmentSrv.newPlusButton());
- }
- };
-
- $scope.getDimSegments = function(segment, $index) {
- if (segment.type === 'operator') { return $q.when([]); }
-
- var target = $scope.target;
- var query = $q.when([]);
-
- if (segment.type === 'key' || segment.type === 'plus-button') {
- query = $scope.datasource.getDimensionKeys($scope.target.namespace);
- } else if (segment.type === 'value') {
- var dimensionKey = $scope.dimSegments[$index-2].value;
- query = $scope.datasource.getDimensionValues(target.region, target.namespace, target.metricName, dimensionKey, {});
- }
-
- return query.then($scope.transformToSegments(true)).then(function(results) {
- if (segment.type === 'key') {
- results.splice(0, 0, angular.copy($scope.removeDimSegment));
- }
- return results;
- });
- };
-
- $scope.dimSegmentChanged = function(segment, index) {
- $scope.dimSegments[index] = segment;
-
- if (segment.value === $scope.removeDimSegment.value) {
- $scope.dimSegments.splice(index, 3);
- }
- else if (segment.type === 'plus-button') {
- $scope.dimSegments.push(uiSegmentSrv.newOperator('='));
- $scope.dimSegments.push(uiSegmentSrv.newFake('select dimension value', 'value', 'query-segment-value'));
- segment.type = 'key';
- segment.cssClass = 'query-segment-key';
- }
-
- $scope.syncDimSegmentsWithModel();
- $scope.ensurePlusButton($scope.dimSegments);
- $scope.get_data();
- };
-
- $scope.syncDimSegmentsWithModel = function() {
- var dims = {};
- var length = $scope.dimSegments.length;
-
- for (var i = 0; i < length - 2; i += 3) {
- var keySegment = $scope.dimSegments[i];
- var valueSegment = $scope.dimSegments[i + 2];
- if (!valueSegment.fake) {
- dims[keySegment.value] = valueSegment.value;
- }
- }
-
- $scope.target.dimensions = dims;
- };
-
- $scope.getRegions = function() {
- return $scope.datasource.metricFindQuery('regions()')
- .then($scope.transformToSegments(true));
- };
-
- $scope.getNamespaces = function() {
- return $scope.datasource.metricFindQuery('namespaces()')
- .then($scope.transformToSegments(true));
- };
-
- $scope.getMetrics = function() {
- return $scope.datasource.metricFindQuery('metrics(' + $scope.target.namespace + ')')
- .then($scope.transformToSegments(true));
- };
-
- $scope.regionChanged = function() {
- $scope.target.region = $scope.regionSegment.value;
- $scope.get_data();
- };
-
- $scope.namespaceChanged = function() {
- $scope.target.namespace = $scope.namespaceSegment.value;
- $scope.get_data();
- };
-
- $scope.metricChanged = function() {
- $scope.target.metricName = $scope.metricSegment.value;
- $scope.get_data();
- };
-
- $scope.transformToSegments = function(addTemplateVars) {
- return function(results) {
- var segments = _.map(results, function(segment) {
- return uiSegmentSrv.newSegment({ value: segment.text, expandable: segment.expandable });
- });
-
- if (addTemplateVars) {
- _.each(templateSrv.variables, function(variable) {
- segments.unshift(uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true }));
- });
- }
-
- return segments;
- };
};
$scope.refreshMetricData = function() {
diff --git a/public/app/plugins/datasource/cloudwatch/query_parameter_ctrl.js b/public/app/plugins/datasource/cloudwatch/query_parameter_ctrl.js
new file mode 100644
index 00000000000..0ed23aff205
--- /dev/null
+++ b/public/app/plugins/datasource/cloudwatch/query_parameter_ctrl.js
@@ -0,0 +1,192 @@
+define([
+ 'angular',
+ 'lodash',
+],
+function (angular, _) {
+ 'use strict';
+
+ var module = angular.module('grafana.controllers');
+
+ module.controller('CloudWatchQueryParameterCtrl', function($scope, templateSrv, uiSegmentSrv, datasourceSrv, $q) {
+
+ $scope.init = function() {
+ var target = $scope.target;
+ target.namespace = target.namespace || '';
+ target.metricName = target.metricName || '';
+ target.statistics = target.statistics || ['Average'];
+ target.dimensions = target.dimensions || {};
+ target.period = target.period || '';
+ target.region = target.region || '';
+
+ $scope.regionSegment = uiSegmentSrv.getSegmentForValue($scope.target.region, 'select region');
+ $scope.namespaceSegment = uiSegmentSrv.getSegmentForValue($scope.target.namespace, 'select namespace');
+ $scope.metricSegment = uiSegmentSrv.getSegmentForValue($scope.target.metricName, 'select metric');
+
+ $scope.dimSegments = _.reduce($scope.target.dimensions, function(memo, value, key) {
+ memo.push(uiSegmentSrv.newKey(key));
+ memo.push(uiSegmentSrv.newOperator("="));
+ memo.push(uiSegmentSrv.newKeyValue(value));
+ return memo;
+ }, []);
+
+ $scope.statSegments = _.map($scope.target.statistics, function(stat) {
+ return uiSegmentSrv.getSegmentForValue(stat);
+ });
+
+ $scope.ensurePlusButton($scope.statSegments);
+ $scope.ensurePlusButton($scope.dimSegments);
+ $scope.removeDimSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove dimension --'});
+ $scope.removeStatSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove stat --'});
+
+ datasourceSrv.get($scope.datasourceName).then(function(datasource) {
+ $scope.datasource = datasource;
+ if (_.isEmpty($scope.target.region)) {
+ $scope.target.region = $scope.datasource.getDefaultRegion();
+ }
+ });
+
+ if (!$scope.onChange) {
+ $scope.onChange = function() {};
+ }
+ };
+
+ $scope.getStatSegments = function() {
+ return $q.when([
+ angular.copy($scope.removeStatSegment),
+ uiSegmentSrv.getSegmentForValue('Average'),
+ uiSegmentSrv.getSegmentForValue('Maximum'),
+ uiSegmentSrv.getSegmentForValue('Minimum'),
+ uiSegmentSrv.getSegmentForValue('Sum'),
+ uiSegmentSrv.getSegmentForValue('SampleCount'),
+ ]);
+ };
+
+ $scope.statSegmentChanged = function(segment, index) {
+ if (segment.value === $scope.removeStatSegment.value) {
+ $scope.statSegments.splice(index, 1);
+ } else {
+ segment.type = 'value';
+ }
+
+ $scope.target.statistics = _.reduce($scope.statSegments, function(memo, seg) {
+ if (!seg.fake) { memo.push(seg.value); } return memo;
+ }, []);
+
+ $scope.ensurePlusButton($scope.statSegments);
+ $scope.onChange();
+ };
+
+ $scope.ensurePlusButton = function(segments) {
+ var count = segments.length;
+ var lastSegment = segments[Math.max(count-1, 0)];
+
+ if (!lastSegment || lastSegment.type !== 'plus-button') {
+ segments.push(uiSegmentSrv.newPlusButton());
+ }
+ };
+
+ $scope.getDimSegments = function(segment, $index) {
+ if (segment.type === 'operator') { return $q.when([]); }
+
+ var target = $scope.target;
+ var query = $q.when([]);
+
+ if (segment.type === 'key' || segment.type === 'plus-button') {
+ query = $scope.datasource.getDimensionKeys($scope.target.namespace);
+ } else if (segment.type === 'value') {
+ var dimensionKey = $scope.dimSegments[$index-2].value;
+ query = $scope.datasource.getDimensionValues(target.region, target.namespace, target.metricName, dimensionKey, {});
+ }
+
+ return query.then($scope.transformToSegments(true)).then(function(results) {
+ if (segment.type === 'key') {
+ results.splice(0, 0, angular.copy($scope.removeDimSegment));
+ }
+ return results;
+ });
+ };
+
+ $scope.dimSegmentChanged = function(segment, index) {
+ $scope.dimSegments[index] = segment;
+
+ if (segment.value === $scope.removeDimSegment.value) {
+ $scope.dimSegments.splice(index, 3);
+ }
+ else if (segment.type === 'plus-button') {
+ $scope.dimSegments.push(uiSegmentSrv.newOperator('='));
+ $scope.dimSegments.push(uiSegmentSrv.newFake('select dimension value', 'value', 'query-segment-value'));
+ segment.type = 'key';
+ segment.cssClass = 'query-segment-key';
+ }
+
+ $scope.syncDimSegmentsWithModel();
+ $scope.ensurePlusButton($scope.dimSegments);
+ $scope.onChange();
+ };
+
+ $scope.syncDimSegmentsWithModel = function() {
+ var dims = {};
+ var length = $scope.dimSegments.length;
+
+ for (var i = 0; i < length - 2; i += 3) {
+ var keySegment = $scope.dimSegments[i];
+ var valueSegment = $scope.dimSegments[i + 2];
+ if (!valueSegment.fake) {
+ dims[keySegment.value] = valueSegment.value;
+ }
+ }
+
+ $scope.target.dimensions = dims;
+ };
+
+ $scope.getRegions = function() {
+ return $scope.datasource.metricFindQuery('regions()')
+ .then($scope.transformToSegments(true));
+ };
+
+ $scope.getNamespaces = function() {
+ return $scope.datasource.metricFindQuery('namespaces()')
+ .then($scope.transformToSegments(true));
+ };
+
+ $scope.getMetrics = function() {
+ return $scope.datasource.metricFindQuery('metrics(' + $scope.target.namespace + ')')
+ .then($scope.transformToSegments(true));
+ };
+
+ $scope.regionChanged = function() {
+ $scope.target.region = $scope.regionSegment.value;
+ $scope.onChange();
+ };
+
+ $scope.namespaceChanged = function() {
+ $scope.target.namespace = $scope.namespaceSegment.value;
+ $scope.onChange();
+ };
+
+ $scope.metricChanged = function() {
+ $scope.target.metricName = $scope.metricSegment.value;
+ $scope.onChange();
+ };
+
+ $scope.transformToSegments = function(addTemplateVars) {
+ return function(results) {
+ var segments = _.map(results, function(segment) {
+ return uiSegmentSrv.newSegment({ value: segment.text, expandable: segment.expandable });
+ });
+
+ if (addTemplateVars) {
+ _.each(templateSrv.variables, function(variable) {
+ segments.unshift(uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true }));
+ });
+ }
+
+ return segments;
+ };
+ };
+
+ $scope.init();
+
+ });
+
+});
diff --git a/public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts b/public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts
index f3b105c5da5..58c6603d37c 100644
--- a/public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts
+++ b/public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts
@@ -2,6 +2,7 @@
///
import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
+import moment = require('moment');
declare var helpers: any;
@@ -189,4 +190,60 @@ describe('CloudWatchDatasource', function() {
});
});
+ describe('When performing annotationQuery', function() {
+ var parameter = {
+ annotation: {
+ region: 'us-east-1',
+ namespace: 'AWS/EC2',
+ metricName: 'CPUUtilization',
+ dimensions: {
+ InstanceId: 'i-12345678'
+ },
+ statistics: ['Average'],
+ period: 300
+ },
+ range: {
+ from: moment(1443438674760),
+ to: moment(1443460274760)
+ }
+ };
+ var alarmResponse = {
+ MetricAlarms: [
+ {
+ AlarmName: 'test_alarm_name'
+ }
+ ]
+ };
+ var historyResponse = {
+ AlarmHistoryItems: [
+ {
+ Timestamp: '2015-01-01T00:00:00.000Z',
+ HistoryItemType: 'StateUpdate',
+ AlarmName: 'test_alarm_name',
+ HistoryData: '{}',
+ HistorySummary: 'test_history_summary'
+ }
+ ]
+ };
+ beforeEach(function() {
+ ctx.backendSrv.datasourceRequest = function(params) {
+ switch (params.data.action) {
+ case 'DescribeAlarmsForMetric':
+ return ctx.$q.when({data: alarmResponse});
+ break;
+ case 'DescribeAlarmHistory':
+ return ctx.$q.when({data: historyResponse});
+ break;
+ }
+ };
+ });
+ it('should return annotation list', function(done) {
+ ctx.ds.annotationQuery(parameter).then(function(result) {
+ expect(result[0].title).to.be('test_alarm_name');
+ expect(result[0].text).to.be('test_history_summary');
+ done();
+ });
+ ctx.$rootScope.$apply();
+ });
+ });
});