datasource.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* global AWS */
  2. define([
  3. 'angular',
  4. 'lodash',
  5. 'kbn',
  6. 'moment',
  7. './queryCtrl',
  8. 'aws-sdk',
  9. ],
  10. function (angular, _, kbn) {
  11. 'use strict';
  12. var module = angular.module('grafana.services');
  13. module.factory('CloudWatchDatasource', function($q, $http, templateSrv) {
  14. function CloudWatchDatasource(datasource) {
  15. this.type = 'cloudwatch';
  16. this.name = datasource.name;
  17. this.supportMetrics = true;
  18. this.defaultRegion = datasource.jsonData.defaultRegion;
  19. this.credentials = {
  20. accessKeyId: datasource.jsonData.accessKeyId,
  21. secretAccessKey: datasource.jsonData.secretAccessKey
  22. };
  23. }
  24. // Called once per panel (graph)
  25. CloudWatchDatasource.prototype.query = function(options) {
  26. var start = convertToCloudWatchTime(options.range.from);
  27. var end = convertToCloudWatchTime(options.range.to);
  28. var queries = [];
  29. _.each(options.targets, _.bind(function(target) {
  30. if (!target.namespace || !target.metricName || _.isEmpty(target.dimensions) || _.isEmpty(target.statistics)) {
  31. return;
  32. }
  33. var query = {};
  34. query.region = templateSrv.replace(target.region, options.scopedVars);
  35. query.namespace = templateSrv.replace(target.namespace, options.scopedVars);
  36. query.metricName = templateSrv.replace(target.metricName, options.scopedVars);
  37. query.dimensions = _.map(_.keys(target.dimensions), function(key) {
  38. return {
  39. Name: key,
  40. Value: target.dimensions[key]
  41. };
  42. });
  43. query.statistics = getActivatedStatistics(target.statistics);
  44. query.period = target.period;
  45. var range = (end.getTime() - start.getTime()) / 1000;
  46. // CloudWatch limit datapoints up to 1440
  47. if (range / query.period >= 1440) {
  48. query.period = Math.floor(range / 1440 / 60) * 60;
  49. }
  50. queries.push(query);
  51. }, this));
  52. // No valid targets, return the empty result to save a round trip.
  53. if (_.isEmpty(queries)) {
  54. var d = $q.defer();
  55. d.resolve({ data: [] });
  56. return d.promise;
  57. }
  58. var allQueryPromise = _.map(queries, _.bind(function(query) {
  59. return this.performTimeSeriesQuery(query, start, end);
  60. }, this));
  61. return $q.all(allQueryPromise)
  62. .then(function(allResponse) {
  63. var result = [];
  64. _.each(allResponse, function(response, index) {
  65. var metrics = transformMetricData(response, options.targets[index]);
  66. _.each(metrics, function(m) {
  67. result.push(m);
  68. });
  69. });
  70. return { data: result };
  71. });
  72. };
  73. CloudWatchDatasource.prototype.performTimeSeriesQuery = function(query, start, end) {
  74. var cloudwatch = this.getCloudWatchClient(query.region);
  75. var params = {
  76. Namespace: query.namespace,
  77. MetricName: query.metricName,
  78. Dimensions: query.dimensions,
  79. Statistics: query.statistics,
  80. StartTime: start,
  81. EndTime: end,
  82. Period: query.period
  83. };
  84. var d = $q.defer();
  85. cloudwatch.getMetricStatistics(params, function(err, data) {
  86. if (err) {
  87. return d.reject(err);
  88. }
  89. return d.resolve(data);
  90. });
  91. return d.promise;
  92. };
  93. CloudWatchDatasource.prototype.performSuggestQuery = function(region, params) {
  94. var cloudwatch = this.getCloudWatchClient(region);
  95. var d = $q.defer();
  96. cloudwatch.listMetrics(params, function(err, data) {
  97. if (err) {
  98. return d.reject(err);
  99. }
  100. return d.resolve(data);
  101. });
  102. return d.promise;
  103. };
  104. CloudWatchDatasource.prototype.testDatasource = function() {
  105. return this.performSuggestQuery({}).then(function () {
  106. return { status: 'success', message: 'Data source is working', title: 'Success' };
  107. });
  108. };
  109. CloudWatchDatasource.prototype.getCloudWatchClient = function(region) {
  110. return new AWS.CloudWatch({
  111. region: region,
  112. accessKeyId: this.credentials.accessKeyId,
  113. secretAccessKey: this.credentials.secretAccessKey
  114. });
  115. };
  116. CloudWatchDatasource.prototype.getDefaultRegion = function() {
  117. return this.defaultRegion;
  118. };
  119. function transformMetricData(md, options) {
  120. var result = [];
  121. var dimensionPart = JSON.stringify(options.dimensions);
  122. _.each(getActivatedStatistics(options.statistics), function(s) {
  123. var metricLabel = md.Label + '_' + s + dimensionPart;
  124. var dps = _.map(md.Datapoints, function(value) {
  125. return [value[s], new Date(value.Timestamp).getTime()];
  126. });
  127. dps = _.sortBy(dps, function(dp) { return dp[1]; });
  128. result.push({ target: metricLabel, datapoints: dps });
  129. });
  130. return result;
  131. }
  132. function getActivatedStatistics(statistics) {
  133. var activatedStatistics = [];
  134. _.each(statistics, function(v, k) {
  135. if (v) {
  136. activatedStatistics.push(k);
  137. }
  138. });
  139. return activatedStatistics;
  140. }
  141. function convertToCloudWatchTime(date) {
  142. return kbn.parseDate(date);
  143. }
  144. return CloudWatchDatasource;
  145. });
  146. });