cloudwatch: filter 'dimensions' for get_metric_data (#5041)
This commit is contained in:
		
							parent
							
								
									e63fc08db2
								
							
						
					
					
						commit
						f8c2b621db
					
				| @ -41,6 +41,9 @@ class Dimension(object): | ||||
|     def __ne__(self, item):  # Only needed on Py2; Py3 defines it implicitly | ||||
|         return self != item | ||||
| 
 | ||||
|     def __lt__(self, other): | ||||
|         return self.name < other.name and self.value < other.name | ||||
| 
 | ||||
| 
 | ||||
| class Metric(object): | ||||
|     def __init__(self, metric_name, namespace, dimensions): | ||||
| @ -478,6 +481,7 @@ class CloudWatchBackend(BaseBackend): | ||||
|             query_ns = query["metric_stat._metric._namespace"] | ||||
|             query_name = query["metric_stat._metric._metric_name"] | ||||
|             delta = timedelta(seconds=int(query["metric_stat._period"])) | ||||
|             dimensions = self._extract_dimensions_from_get_metric_data_query(query) | ||||
|             result_vals = [] | ||||
|             timestamps = [] | ||||
|             stat = query["metric_stat._stat"] | ||||
| @ -494,11 +498,19 @@ class CloudWatchBackend(BaseBackend): | ||||
|                     for md in period_md | ||||
|                     if md.namespace == query_ns and md.name == query_name | ||||
|                 ] | ||||
|                 if dimensions: | ||||
|                     query_period_data = [ | ||||
|                         md | ||||
|                         for md in period_md | ||||
|                         if sorted(md.dimensions) == sorted(dimensions) | ||||
|                     ] | ||||
| 
 | ||||
|                 metric_values = [m.value for m in query_period_data] | ||||
| 
 | ||||
|                 if len(metric_values) > 0: | ||||
|                     if stat == "Average": | ||||
|                     if stat == "SampleCount": | ||||
|                         result_vals.append(len(metric_values)) | ||||
|                     elif stat == "Average": | ||||
|                         result_vals.append(sum(metric_values) / len(metric_values)) | ||||
|                     elif stat == "Minimum": | ||||
|                         result_vals.append(min(metric_values)) | ||||
| @ -679,5 +691,20 @@ class CloudWatchBackend(BaseBackend): | ||||
|         else: | ||||
|             return None, metrics | ||||
| 
 | ||||
|     def _extract_dimensions_from_get_metric_data_query(self, query): | ||||
|         dimensions = [] | ||||
|         prefix = "metric_stat._metric._dimensions.member." | ||||
|         suffix_name = "._name" | ||||
|         suffix_value = "._value" | ||||
|         counter = 1 | ||||
| 
 | ||||
|         while query.get(f"{prefix}{counter}{suffix_name}") and counter <= 10: | ||||
|             name = query.get(f"{prefix}{counter}{suffix_name}") | ||||
|             value = query.get(f"{prefix}{counter}{suffix_value}") | ||||
|             dimensions.append(Dimension(name=name, value=value)) | ||||
|             counter = counter + 1 | ||||
| 
 | ||||
|         return dimensions | ||||
| 
 | ||||
| 
 | ||||
| cloudwatch_backends = BackendDict(CloudWatchBackend, "cloudwatch") | ||||
|  | ||||
| @ -785,6 +785,114 @@ def test_get_metric_data_for_multiple_metrics(): | ||||
|     res2["Values"].should.equal([25.0]) | ||||
| 
 | ||||
| 
 | ||||
| @mock_cloudwatch | ||||
| def test_get_metric_data_for_dimensions(): | ||||
|     utc_now = datetime.now(tz=pytz.utc) | ||||
|     cloudwatch = boto3.client("cloudwatch", "eu-west-1") | ||||
|     namespace = "my_namespace/" | ||||
| 
 | ||||
|     # If the metric is created with multiple dimensions, then the data points for that metric can be retrieved only by specifying all the configured dimensions. | ||||
|     # https://aws.amazon.com/premiumsupport/knowledge-center/cloudwatch-getmetricstatistics-data/ | ||||
|     server_prod = {"Name": "Server", "Value": "Prod"} | ||||
|     dimension_berlin = [server_prod, {"Name": "Domain", "Value": "Berlin"}] | ||||
|     dimension_frankfurt = [server_prod, {"Name": "Domain", "Value": "Frankfurt"}] | ||||
| 
 | ||||
|     # put metric data | ||||
|     cloudwatch.put_metric_data( | ||||
|         Namespace=namespace, | ||||
|         MetricData=[ | ||||
|             { | ||||
|                 "MetricName": "metric1", | ||||
|                 "Value": 50, | ||||
|                 "Dimensions": dimension_berlin, | ||||
|                 "Unit": "Seconds", | ||||
|                 "Timestamp": utc_now, | ||||
|             } | ||||
|         ], | ||||
|     ) | ||||
|     cloudwatch.put_metric_data( | ||||
|         Namespace=namespace, | ||||
|         MetricData=[ | ||||
|             { | ||||
|                 "MetricName": "metric1", | ||||
|                 "Value": 25, | ||||
|                 "Unit": "Seconds", | ||||
|                 "Dimensions": dimension_frankfurt, | ||||
|                 "Timestamp": utc_now, | ||||
|             } | ||||
|         ], | ||||
|     ) | ||||
|     # get_metric_data | ||||
|     response = cloudwatch.get_metric_data( | ||||
|         MetricDataQueries=[ | ||||
|             { | ||||
|                 "Id": "result1", | ||||
|                 "MetricStat": { | ||||
|                     "Metric": { | ||||
|                         "Namespace": namespace, | ||||
|                         "MetricName": "metric1", | ||||
|                         "Dimensions": dimension_frankfurt, | ||||
|                     }, | ||||
|                     "Period": 60, | ||||
|                     "Stat": "SampleCount", | ||||
|                 }, | ||||
|             }, | ||||
|             { | ||||
|                 "Id": "result2", | ||||
|                 "MetricStat": { | ||||
|                     "Metric": { | ||||
|                         "Namespace": namespace, | ||||
|                         "MetricName": "metric1", | ||||
|                         "Dimensions": dimension_berlin, | ||||
|                     }, | ||||
|                     "Period": 60, | ||||
|                     "Stat": "Sum", | ||||
|                 }, | ||||
|             }, | ||||
|             { | ||||
|                 "Id": "result3", | ||||
|                 "MetricStat": { | ||||
|                     "Metric": { | ||||
|                         "Namespace": namespace, | ||||
|                         "MetricName": "metric1", | ||||
|                         "Dimensions": [server_prod], | ||||
|                     }, | ||||
|                     "Period": 60, | ||||
|                     "Stat": "Sum", | ||||
|                 }, | ||||
|             }, | ||||
|             { | ||||
|                 "Id": "result4", | ||||
|                 "MetricStat": { | ||||
|                     "Metric": {"Namespace": namespace, "MetricName": "metric1"}, | ||||
|                     "Period": 60, | ||||
|                     "Stat": "Sum", | ||||
|                 }, | ||||
|             }, | ||||
|         ], | ||||
|         StartTime=utc_now - timedelta(seconds=60), | ||||
|         EndTime=utc_now + timedelta(seconds=60), | ||||
|     ) | ||||
|     # | ||||
|     len(response["MetricDataResults"]).should.equal(4) | ||||
| 
 | ||||
|     res1 = [res for res in response["MetricDataResults"] if res["Id"] == "result1"][0] | ||||
|     # expect sample count for dimension_frankfurt | ||||
|     res1["Values"].should.equal([1.0]) | ||||
| 
 | ||||
|     res2 = [res for res in response["MetricDataResults"] if res["Id"] == "result2"][0] | ||||
|     # expect sum for dimension_berlin | ||||
|     res2["Values"].should.equal([50.0]) | ||||
| 
 | ||||
|     res3 = [res for res in response["MetricDataResults"] if res["Id"] == "result3"][0] | ||||
|     # expect no result, as server_prod is only a part of other dimensions, e.g. there is no match | ||||
|     res3["Values"].should.equal([]) | ||||
| 
 | ||||
|     res4 = [res for res in response["MetricDataResults"] if res["Id"] == "result4"][0] | ||||
|     # expect sum of both metrics, as we did not filter for dimensions | ||||
|     res4["Values"].should.equal([75.0]) | ||||
| 
 | ||||
| 
 | ||||
| @mock_cloudwatch | ||||
| @mock_s3 | ||||
| def test_cloudwatch_return_s3_metrics(): | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user