Skip to content

Commit 3d52095

Browse files
committed
feat(cloudwatch): restored dimension keys lookup
1 parent 0912cec commit 3d52095

File tree

5 files changed

+108
-69
lines changed

5 files changed

+108
-69
lines changed

pkg/api/cloudwatch/cloudwatch.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ func init() {
2929
"DescribeInstances": handleDescribeInstances,
3030
"__GetRegions": handleGetRegions,
3131
"__GetNamespaces": handleGetNamespaces,
32-
"__GetMetrics": handleGetMetrics,
32+
"__GetMetrics": handleGetMetrics,
33+
"__GetDimensions": handleGetDimensions,
3334
}
3435
}
3536

pkg/api/cloudwatch/metrics.go

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
)
99

1010
var metricsMap map[string][]string
11+
var dimensionsMap map[string][]string
1112

1213
func init() {
1314
metricsMap = map[string][]string{
@@ -22,52 +23,48 @@ func init() {
2223
"BytesUsedForCacheItems", "BytesReadIntoMemcached", "BytesWrittenOutFromMemcached", "CasBadval", "CasHits", "CasMisses", "CmdFlush", "CmdGet", "CmdSet", "CurrConnections", "CurrItems", "DecrHits", "DecrMisses", "DeleteHits", "DeleteMisses", "Evictions", "GetHits", "GetMisses", "IncrHits", "IncrMisses", "Reclaimed",
2324
"CurrConnections", "Evictions", "Reclaimed", "NewConnections", "BytesUsedForCache", "CacheHits", "CacheMisses", "ReplicationLag", "GetTypeCmds", "SetTypeCmds", "KeyBasedCmds", "StringBasedCmds", "HashBasedCmds", "ListBasedCmds", "SetBasedCmds", "SortedSetBasedCmds", "CurrItems",
2425
},
25-
"AWS/EBS": []string{"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps"},
26-
"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"},
26+
"AWS/EBS": []string{"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps"},
27+
"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"},
28+
"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"},
29+
"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"},
30+
"AWS/ML": []string{"PredictCount", "PredictFailureCount"},
31+
"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"},
32+
"AWS/Redshift": []string{"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"},
33+
"AWS/RDS": []string{"BinLogDiskUsage", "CPUUtilization", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"},
34+
"AWS/Route53": []string{"HealthCheckStatus", "HealthCheckPercentageHealthy"},
35+
"AWS/SNS": []string{"NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"},
36+
"AWS/SQS": []string{"NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"},
37+
"AWS/S3": []string{"BucketSizeBytes", "NumberOfObjects"},
38+
"AWS/SWF": []string{"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut"},
39+
"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"},
40+
"AWS/WorkSpaces": []string{"Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"},
41+
}
42+
dimensionsMap = map[string][]string{
43+
"AWS/AutoScaling": []string{"AutoScalingGroupName"},
44+
"AWS/Billing": []string{"ServiceName", "LinkedAccount", "Currency"},
45+
"AWS/CloudFront": []string{"DistributionId", "Region"},
46+
"AWS/CloudSearch": []string{},
47+
"AWS/DynamoDB": []string{"TableName", "GlobalSecondaryIndexName", "Operation"},
48+
"AWS/ElastiCache": []string{"CacheClusterId", "CacheNodeId"},
49+
"AWS/EBS": []string{"VolumeId"},
50+
"AWS/EC2": []string{"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"},
51+
"AWS/ELB": []string{"LoadBalancerName", "AvailabilityZone"},
52+
"AWS/ElasticMapReduce": []string{"ClusterId", "JobId"},
53+
"AWS/Kinesis": []string{"StreamName"},
54+
"AWS/ML": []string{"MLModelId", "RequestMode"},
55+
"AWS/OpsWorks": []string{"StackId", "LayerId", "InstanceId"},
56+
"AWS/Redshift": []string{"NodeID", "ClusterIdentifier"},
57+
"AWS/RDS": []string{"DBInstanceIdentifier", "DatabaseClass", "EngineName"},
58+
"AWS/Route53": []string{"HealthCheckId"},
59+
"AWS/SNS": []string{"Application", "Platform", "TopicName"},
60+
"AWS/SQS": []string{"QueueName"},
61+
"AWS/S3": []string{"BucketName", "StorageType"},
62+
"AWS/SWF": []string{"Domain", "ActivityTypeName", "ActivityTypeVersion"},
63+
"AWS/StorageGateway": []string{"GatewayId", "GatewayName", "VolumeId"},
64+
"AWS/WorkSpaces": []string{"DirectoryId", "WorkspaceId"},
2765
}
2866
}
2967

30-
// "AWS/ElasticMapReduce": [
31-
// "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"
32-
// ],
33-
// "AWS/Kinesis": [
34-
// "PutRecord.Bytes", "PutRecord.Latency", "PutRecord.Success", "PutRecords.Bytes", "PutRecords.Latency", "PutRecords.Records", "PutRecords.Success", "IncomingBytes", "IncomingRecords", "GetRecords.Bytes", "GetRecords.IteratorAgeMilliseconds", "GetRecords.Latency", "GetRecords.Success"
35-
// ],
36-
// "AWS/ML": [
37-
// "PredictCount", "PredictFailureCount"
38-
// ],
39-
// "AWS/OpsWorks": [
40-
// "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"
41-
// ],
42-
// "AWS/Redshift": [
43-
// "CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"
44-
// ],
45-
// "AWS/RDS": [
46-
// "BinLogDiskUsage", "CPUUtilization", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"
47-
// ],
48-
// "AWS/Route53": [
49-
// "HealthCheckStatus", "HealthCheckPercentageHealthy"
50-
// ],
51-
// "AWS/SNS": [
52-
// "NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"
53-
// ],
54-
// "AWS/SQS": [
55-
// "NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"
56-
// ],
57-
// "AWS/S3": [
58-
// "BucketSizeBytes", "NumberOfObjects"
59-
// ],
60-
// "AWS/SWF": [
61-
// "DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut"
62-
// ],
63-
// "AWS/StorageGateway": [
64-
// "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"
65-
// ],
66-
// "AWS/WorkSpaces": [
67-
// "Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"
68-
// ],
69-
// };
70-
7168
func handleGetRegions(req *cwRequest, c *middleware.Context) {
7269
regions := []string{
7370
"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) {
113110

114111
c.JSON(200, result)
115112
}
113+
114+
func handleGetDimensions(req *cwRequest, c *middleware.Context) {
115+
reqParam := &struct {
116+
Parameters struct {
117+
Namespace string `json:"namespace"`
118+
} `json:"parameters"`
119+
}{}
120+
121+
json.Unmarshal(req.Body, reqParam)
122+
123+
dimensionValues, exists := dimensionsMap[reqParam.Parameters.Namespace]
124+
if !exists {
125+
c.JsonApiErr(404, "Unable to find dimension "+reqParam.Parameters.Namespace, nil)
126+
return
127+
}
128+
129+
result := []interface{}{}
130+
for _, name := range dimensionValues {
131+
result = append(result, util.DynMap{"text": name, "value": name})
132+
}
133+
134+
c.JSON(200, result)
135+
}

public/app/plugins/datasource/cloudwatch/datasource.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,12 @@ function (angular, _) {
104104
};
105105

106106
CloudWatchDatasource.prototype.getDimensionKeys = function(namespace) {
107-
namespace = templateSrv.replace(namespace);
108-
return $q.when(this.supportedDimensions[namespace] || []);
107+
return this.awsRequest({
108+
action: '__GetDimensions',
109+
parameters: {
110+
namespace: templateSrv.replace(namespace)
111+
}
112+
});
109113
};
110114

111115
CloudWatchDatasource.prototype.getDimensionValues = function(region, namespace, metricName, dimensions) {
@@ -120,6 +124,7 @@ function (angular, _) {
120124
};
121125

122126
return this.awsRequest(request).then(function(result) {
127+
console.log(result);
123128
return _.chain(result.Metrics).map(function(metric) {
124129
return _.pluck(metric.Dimensions, 'Value');
125130
}).flatten().uniq().sortBy(function(name) {
@@ -167,8 +172,7 @@ function (angular, _) {
167172

168173
var dimensionKeysQuery = query.match(/^dimension_keys\(([^\)]+?)\)/);
169174
if (dimensionKeysQuery) {
170-
namespace = templateSrv.replace(dimensionKeysQuery[1]);
171-
return this.getDimensionKeys(namespace).then(transformSuggestData);
175+
return this.getDimensionKeys(dimensionKeysQuery[1]);
172176
}
173177

174178
var dimensionValuesQuery = query.match(/^dimension_values\(([^,]+?),\s?([^,]+?),\s?([^,]+?)(,\s?([^)]*))?\)/);

public/app/plugins/datasource/cloudwatch/query_ctrl.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ function (angular, _) {
8282

8383
$scope.suggestDimensionKeys = function(query, callback) { // jshint unused:false
8484
$scope.datasource.getDimensionKeys($scope.target.namespace).then(function(result) {
85-
callback(result);
85+
callback(_.pluck(result, 'text'));
8686
});
8787
};
8888

public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -138,25 +138,39 @@ describe('CloudWatchDatasource', function() {
138138
});
139139
});
140140

141-
describe('When performing metricFindQuery', function() {
142-
// it('should return suggest list for dimension_keys()', function(done) {
143-
// var query = 'dimension_keys(AWS/EC2)';
144-
// ctx.ds.metricFindQuery(query).then(function(result) {
145-
// result = result.map(function(v) { return v.text; });
146-
// expect(result).to.contain('InstanceId');
147-
// done();
148-
// });
149-
// ctx.$rootScope.$apply();
150-
// });
151-
//
152-
// it('should return suggest list for dimension_values()', function(done) {
153-
// var query = 'dimension_values(us-east-1,AWS/EC2,CPUUtilization)';
154-
// ctx.ds.metricFindQuery(query).then(function(result) {
155-
// result = result.map(function(v) { return v.text; });
156-
// expect(result).to.eql(['i-12345678']);
157-
// done();
158-
// });
159-
// ctx.$rootScope.$apply();
160-
// });
141+
describeMetricFindQuery('dimension_keys(AWS/EC2)', scenario => {
142+
scenario.setup(() => {
143+
scenario.requestResponse = [{text: 'InstanceId'}];
144+
});
145+
146+
it('should call __GetDimensions and return result', () => {
147+
expect(scenario.result[0].text).to.be('InstanceId');
148+
expect(scenario.request.data.action).to.be('__GetDimensions');
149+
});
161150
});
151+
152+
describeMetricFindQuery('dimension_values(us-east-1,AWS/EC2,CPUUtilization)', scenario => {
153+
scenario.setup(() => {
154+
scenario.requestResponse = {
155+
Metrics: [
156+
{
157+
Namespace: 'AWS/EC2',
158+
MetricName: 'CPUUtilization',
159+
Dimensions: [
160+
{
161+
Name: 'InstanceId',
162+
Value: 'i-12345678'
163+
}
164+
]
165+
}
166+
]
167+
};
168+
});
169+
170+
it('should call __GetMetrics and return result', () => {
171+
expect(scenario.result[0].text).to.be('i-12345678');
172+
expect(scenario.request.data.action).to.be('ListMetrics');
173+
});
174+
});
175+
162176
});

0 commit comments

Comments
 (0)