Просмотр исходного кода

feat(cloudwatch): restored dimension keys lookup

Torkel Ödegaard 10 лет назад
Родитель
Сommit
3d52095765

+ 2 - 1
pkg/api/cloudwatch/cloudwatch.go

@@ -29,7 +29,8 @@ func init() {
 		"DescribeInstances":   handleDescribeInstances,
 		"__GetRegions":        handleGetRegions,
 		"__GetNamespaces":     handleGetNamespaces,
-		"__GetMetrics":     handleGetMetrics,
+		"__GetMetrics":        handleGetMetrics,
+		"__GetDimensions":     handleGetDimensions,
 	}
 }
 

+ 63 - 43
pkg/api/cloudwatch/metrics.go

@@ -8,6 +8,7 @@ import (
 )
 
 var metricsMap map[string][]string
+var dimensionsMap map[string][]string
 
 func init() {
 	metricsMap = map[string][]string{
@@ -22,52 +23,48 @@ func init() {
 			"BytesUsedForCacheItems", "BytesReadIntoMemcached", "BytesWrittenOutFromMemcached", "CasBadval", "CasHits", "CasMisses", "CmdFlush", "CmdGet", "CmdSet", "CurrConnections", "CurrItems", "DecrHits", "DecrMisses", "DeleteHits", "DeleteMisses", "Evictions", "GetHits", "GetMisses", "IncrHits", "IncrMisses", "Reclaimed",
 			"CurrConnections", "Evictions", "Reclaimed", "NewConnections", "BytesUsedForCache", "CacheHits", "CacheMisses", "ReplicationLag", "GetTypeCmds", "SetTypeCmds", "KeyBasedCmds", "StringBasedCmds", "HashBasedCmds", "ListBasedCmds", "SetBasedCmds", "SortedSetBasedCmds", "CurrItems",
 		},
-		"AWS/EBS": []string{"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps"},
-		"AWS/ELB": []string{"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"},
+		"AWS/EBS":              []string{"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps"},
+		"AWS/ELB":              []string{"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"},
+		"AWS/ElasticMapReduce": []string{"CoreNodesPending", "CoreNodesRunning", "HBaseBackupFailed", "HBaseMostRecentBackupDuration", "HBaseTimeSinceLastSuccessfulBackup", "HDFSBytesRead", "HDFSBytesWritten", "HDFSUtilization", "IsIdle", "JobsFailed", "JobsRunning", "LiveDataNodes", "LiveTaskTrackers", "MapSlotsOpen", "MissingBlocks", "ReduceSlotsOpen", "RemainingMapTasks", "RemainingMapTasksPerSlot", "RemainingReduceTasks", "RunningMapTasks", "RunningReduceTasks", "S3BytesRead", "S3BytesWritten", "TaskNodesPending", "TaskNodesRunning", "TotalLoad"},
+		"AWS/Kinesis":          []string{"PutRecord.Bytes", "PutRecord.Latency", "PutRecord.Success", "PutRecords.Bytes", "PutRecords.Latency", "PutRecords.Records", "PutRecords.Success", "IncomingBytes", "IncomingRecords", "GetRecords.Bytes", "GetRecords.IteratorAgeMilliseconds", "GetRecords.Latency", "GetRecords.Success"},
+		"AWS/ML":               []string{"PredictCount", "PredictFailureCount"},
+		"AWS/OpsWorks":         []string{"cpu_idle", "cpu_nice", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_5", "load_15", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"},
+		"AWS/Redshift":         []string{"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"},
+		"AWS/RDS":              []string{"BinLogDiskUsage", "CPUUtilization", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"},
+		"AWS/Route53":          []string{"HealthCheckStatus", "HealthCheckPercentageHealthy"},
+		"AWS/SNS":              []string{"NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"},
+		"AWS/SQS":              []string{"NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"},
+		"AWS/S3":               []string{"BucketSizeBytes", "NumberOfObjects"},
+		"AWS/SWF":              []string{"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut"},
+		"AWS/StorageGateway":   []string{"CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "CloudBytesDownloaded", "CloudDownloadLatency", "CloudBytesUploaded", "UploadBufferFree", "UploadBufferPercentUsed", "UploadBufferUsed", "QueuedWrites", "ReadBytes", "ReadTime", "TotalCacheSize", "WriteBytes", "WriteTime", "WorkingStorageFree", "WorkingStoragePercentUsed", "WorkingStorageUsed", "CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "ReadBytes", "ReadTime", "WriteBytes", "WriteTime", "QueuedWrites"},
+		"AWS/WorkSpaces":       []string{"Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"},
+	}
+	dimensionsMap = map[string][]string{
+		"AWS/AutoScaling":      []string{"AutoScalingGroupName"},
+		"AWS/Billing":          []string{"ServiceName", "LinkedAccount", "Currency"},
+		"AWS/CloudFront":       []string{"DistributionId", "Region"},
+		"AWS/CloudSearch":      []string{},
+		"AWS/DynamoDB":         []string{"TableName", "GlobalSecondaryIndexName", "Operation"},
+		"AWS/ElastiCache":      []string{"CacheClusterId", "CacheNodeId"},
+		"AWS/EBS":              []string{"VolumeId"},
+		"AWS/EC2":              []string{"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"},
+		"AWS/ELB":              []string{"LoadBalancerName", "AvailabilityZone"},
+		"AWS/ElasticMapReduce": []string{"ClusterId", "JobId"},
+		"AWS/Kinesis":          []string{"StreamName"},
+		"AWS/ML":               []string{"MLModelId", "RequestMode"},
+		"AWS/OpsWorks":         []string{"StackId", "LayerId", "InstanceId"},
+		"AWS/Redshift":         []string{"NodeID", "ClusterIdentifier"},
+		"AWS/RDS":              []string{"DBInstanceIdentifier", "DatabaseClass", "EngineName"},
+		"AWS/Route53":          []string{"HealthCheckId"},
+		"AWS/SNS":              []string{"Application", "Platform", "TopicName"},
+		"AWS/SQS":              []string{"QueueName"},
+		"AWS/S3":               []string{"BucketName", "StorageType"},
+		"AWS/SWF":              []string{"Domain", "ActivityTypeName", "ActivityTypeVersion"},
+		"AWS/StorageGateway":   []string{"GatewayId", "GatewayName", "VolumeId"},
+		"AWS/WorkSpaces":       []string{"DirectoryId", "WorkspaceId"},
 	}
 }
 
-//   "AWS/ElasticMapReduce": [
-//     "CoreNodesPending", "CoreNodesRunning", "HBaseBackupFailed", "HBaseMostRecentBackupDuration", "HBaseTimeSinceLastSuccessfulBackup", "HDFSBytesRead", "HDFSBytesWritten", "HDFSUtilization", "IsIdle", "JobsFailed", "JobsRunning", "LiveDataNodes", "LiveTaskTrackers", "MapSlotsOpen", "MissingBlocks", "ReduceSlotsOpen", "RemainingMapTasks", "RemainingMapTasksPerSlot", "RemainingReduceTasks", "RunningMapTasks", "RunningReduceTasks", "S3BytesRead", "S3BytesWritten", "TaskNodesPending", "TaskNodesRunning", "TotalLoad"
-//   ],
-//   "AWS/Kinesis": [
-//     "PutRecord.Bytes", "PutRecord.Latency", "PutRecord.Success", "PutRecords.Bytes", "PutRecords.Latency", "PutRecords.Records", "PutRecords.Success", "IncomingBytes", "IncomingRecords", "GetRecords.Bytes", "GetRecords.IteratorAgeMilliseconds", "GetRecords.Latency", "GetRecords.Success"
-//   ],
-//   "AWS/ML": [
-//     "PredictCount", "PredictFailureCount"
-//   ],
-//   "AWS/OpsWorks": [
-//     "cpu_idle", "cpu_nice", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_5", "load_15", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"
-//   ],
-//   "AWS/Redshift": [
-//     "CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"
-//   ],
-//   "AWS/RDS": [
-//     "BinLogDiskUsage", "CPUUtilization", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"
-//   ],
-//   "AWS/Route53": [
-//     "HealthCheckStatus", "HealthCheckPercentageHealthy"
-//   ],
-//   "AWS/SNS": [
-//     "NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"
-//   ],
-//   "AWS/SQS": [
-//     "NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"
-//   ],
-//   "AWS/S3": [
-//     "BucketSizeBytes", "NumberOfObjects"
-//   ],
-//   "AWS/SWF": [
-//     "DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut"
-//   ],
-//   "AWS/StorageGateway": [
-//     "CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "CloudBytesDownloaded", "CloudDownloadLatency", "CloudBytesUploaded", "UploadBufferFree", "UploadBufferPercentUsed", "UploadBufferUsed", "QueuedWrites", "ReadBytes", "ReadTime", "TotalCacheSize", "WriteBytes", "WriteTime", "WorkingStorageFree", "WorkingStoragePercentUsed", "WorkingStorageUsed", "CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "ReadBytes", "ReadTime", "WriteBytes", "WriteTime", "QueuedWrites"
-//   ],
-//   "AWS/WorkSpaces": [
-//     "Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"
-//   ],
-// };
-
 func handleGetRegions(req *cwRequest, c *middleware.Context) {
 	regions := []string{
 		"us-west-2", "us-west-1", "eu-west-1", "eu-central-1", "ap-southeast-1",
@@ -113,3 +110,26 @@ func handleGetMetrics(req *cwRequest, c *middleware.Context) {
 
 	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)
+
+	dimensionValues, exists := dimensionsMap[reqParam.Parameters.Namespace]
+	if !exists {
+		c.JsonApiErr(404, "Unable to find dimension "+reqParam.Parameters.Namespace, nil)
+		return
+	}
+
+	result := []interface{}{}
+	for _, name := range dimensionValues {
+		result = append(result, util.DynMap{"text": name, "value": name})
+	}
+
+	c.JSON(200, result)
+}

+ 8 - 4
public/app/plugins/datasource/cloudwatch/datasource.js

@@ -104,8 +104,12 @@ function (angular, _) {
     };
 
     CloudWatchDatasource.prototype.getDimensionKeys = function(namespace) {
-      namespace = templateSrv.replace(namespace);
-      return $q.when(this.supportedDimensions[namespace] || []);
+      return this.awsRequest({
+        action: '__GetDimensions',
+        parameters: {
+          namespace: templateSrv.replace(namespace)
+        }
+      });
     };
 
     CloudWatchDatasource.prototype.getDimensionValues = function(region, namespace, metricName, dimensions) {
@@ -120,6 +124,7 @@ function (angular, _) {
       };
 
       return this.awsRequest(request).then(function(result) {
+        console.log(result);
         return _.chain(result.Metrics).map(function(metric) {
           return _.pluck(metric.Dimensions, 'Value');
         }).flatten().uniq().sortBy(function(name) {
@@ -167,8 +172,7 @@ function (angular, _) {
 
       var dimensionKeysQuery = query.match(/^dimension_keys\(([^\)]+?)\)/);
       if (dimensionKeysQuery) {
-        namespace = templateSrv.replace(dimensionKeysQuery[1]);
-        return this.getDimensionKeys(namespace).then(transformSuggestData);
+        return this.getDimensionKeys(dimensionKeysQuery[1]);
       }
 
       var dimensionValuesQuery = query.match(/^dimension_values\(([^,]+?),\s?([^,]+?),\s?([^,]+?)(,\s?([^)]*))?\)/);

+ 1 - 1
public/app/plugins/datasource/cloudwatch/query_ctrl.js

@@ -82,7 +82,7 @@ function (angular, _) {
 
     $scope.suggestDimensionKeys = function(query, callback) { // jshint unused:false
       $scope.datasource.getDimensionKeys($scope.target.namespace).then(function(result) {
-        callback(result);
+        callback(_.pluck(result, 'text'));
       });
     };
 

+ 34 - 20
public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts

@@ -138,25 +138,39 @@ describe('CloudWatchDatasource', function() {
     });
   });
 
-  describe('When performing metricFindQuery', function() {
-    // it('should return suggest list for dimension_keys()', function(done) {
-    //   var query = 'dimension_keys(AWS/EC2)';
-    //   ctx.ds.metricFindQuery(query).then(function(result) {
-    //     result = result.map(function(v) { return v.text; });
-    //     expect(result).to.contain('InstanceId');
-    //     done();
-    //   });
-    //   ctx.$rootScope.$apply();
-    // });
-    //
-    // it('should return suggest list for dimension_values()', function(done) {
-    //   var query = 'dimension_values(us-east-1,AWS/EC2,CPUUtilization)';
-    //   ctx.ds.metricFindQuery(query).then(function(result) {
-    //     result = result.map(function(v) { return v.text; });
-    //     expect(result).to.eql(['i-12345678']);
-    //     done();
-    //   });
-    //   ctx.$rootScope.$apply();
-    // });
+  describeMetricFindQuery('dimension_keys(AWS/EC2)', scenario => {
+    scenario.setup(() => {
+      scenario.requestResponse = [{text: 'InstanceId'}];
+    });
+
+    it('should call __GetDimensions and return result', () => {
+      expect(scenario.result[0].text).to.be('InstanceId');
+      expect(scenario.request.data.action).to.be('__GetDimensions');
+    });
   });
+
+  describeMetricFindQuery('dimension_values(us-east-1,AWS/EC2,CPUUtilization)', scenario => {
+    scenario.setup(() => {
+      scenario.requestResponse = {
+        Metrics: [
+          {
+            Namespace: 'AWS/EC2',
+            MetricName: 'CPUUtilization',
+            Dimensions: [
+              {
+                Name: 'InstanceId',
+                Value: 'i-12345678'
+              }
+            ]
+          }
+        ]
+      };
+    });
+
+    it('should call __GetMetrics and return result', () => {
+      expect(scenario.result[0].text).to.be('i-12345678');
+      expect(scenario.request.data.action).to.be('ListMetrics');
+    });
+  });
+
 });