Cloudwatch get metric data return by period (#3626)
* Cloudwatch get metric data return by period - addresses https://github.com/localstack/localstack/issues/3493 * fix lint issues * remove unused import * added test cases for min max and average
This commit is contained in:
parent
d382731a14
commit
78a5661093
@ -388,39 +388,62 @@ class CloudWatchBackend(BaseBackend):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_metric_data(self, queries, start_time, end_time):
|
def get_metric_data(
|
||||||
|
self, queries, start_time, end_time, scan_by="TimestampAscending"
|
||||||
|
):
|
||||||
|
|
||||||
period_data = [
|
period_data = [
|
||||||
md for md in self.metric_data if start_time <= md.timestamp <= end_time
|
md for md in self.metric_data if start_time <= md.timestamp <= end_time
|
||||||
]
|
]
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
for query in queries:
|
for query in queries:
|
||||||
|
period_start_time = start_time
|
||||||
query_ns = query["metric_stat._metric._namespace"]
|
query_ns = query["metric_stat._metric._namespace"]
|
||||||
query_name = query["metric_stat._metric._metric_name"]
|
query_name = query["metric_stat._metric._metric_name"]
|
||||||
query_data = [
|
delta = timedelta(seconds=int(query["metric_stat._period"]))
|
||||||
md
|
|
||||||
for md in period_data
|
|
||||||
if md.namespace == query_ns and md.name == query_name
|
|
||||||
]
|
|
||||||
metric_values = [m.value for m in query_data]
|
|
||||||
result_vals = []
|
result_vals = []
|
||||||
|
timestamps = []
|
||||||
stat = query["metric_stat._stat"]
|
stat = query["metric_stat._stat"]
|
||||||
if len(metric_values) > 0:
|
while period_start_time <= end_time:
|
||||||
if stat == "Average":
|
period_end_time = period_start_time + delta
|
||||||
result_vals.append(sum(metric_values) / len(metric_values))
|
period_md = [
|
||||||
elif stat == "Minimum":
|
period_md
|
||||||
result_vals.append(min(metric_values))
|
for period_md in period_data
|
||||||
elif stat == "Maximum":
|
if period_start_time <= period_md.timestamp < period_end_time
|
||||||
result_vals.append(max(metric_values))
|
]
|
||||||
elif stat == "Sum":
|
|
||||||
result_vals.append(sum(metric_values))
|
|
||||||
|
|
||||||
|
query_period_data = [
|
||||||
|
md
|
||||||
|
for md in period_md
|
||||||
|
if md.namespace == query_ns and md.name == query_name
|
||||||
|
]
|
||||||
|
|
||||||
|
metric_values = [m.value for m in query_period_data]
|
||||||
|
|
||||||
|
if len(metric_values) > 0:
|
||||||
|
if stat == "Average":
|
||||||
|
result_vals.append(sum(metric_values) / len(metric_values))
|
||||||
|
elif stat == "Minimum":
|
||||||
|
result_vals.append(min(metric_values))
|
||||||
|
elif stat == "Maximum":
|
||||||
|
result_vals.append(max(metric_values))
|
||||||
|
elif stat == "Sum":
|
||||||
|
result_vals.append(sum(metric_values))
|
||||||
|
timestamps.append(
|
||||||
|
iso_8601_datetime_without_milliseconds(period_start_time)
|
||||||
|
)
|
||||||
|
period_start_time += delta
|
||||||
|
if scan_by == "TimestampDescending" and len(timestamps) > 0:
|
||||||
|
timestamps.reverse()
|
||||||
|
result_vals.reverse()
|
||||||
label = query["metric_stat._metric._metric_name"] + " " + stat
|
label = query["metric_stat._metric._metric_name"] + " " + stat
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
"id": query["id"],
|
"id": query["id"],
|
||||||
"label": label,
|
"label": label,
|
||||||
"vals": result_vals,
|
"vals": result_vals,
|
||||||
"timestamps": [datetime.now() for _ in result_vals],
|
"timestamps": timestamps,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return results
|
return results
|
||||||
|
@ -128,9 +128,11 @@ class CloudWatchResponse(BaseResponse):
|
|||||||
def get_metric_data(self):
|
def get_metric_data(self):
|
||||||
start = dtparse(self._get_param("StartTime"))
|
start = dtparse(self._get_param("StartTime"))
|
||||||
end = dtparse(self._get_param("EndTime"))
|
end = dtparse(self._get_param("EndTime"))
|
||||||
|
scan_by = self._get_param("ScanBy")
|
||||||
|
|
||||||
queries = self._get_list_prefix("MetricDataQueries.member")
|
queries = self._get_list_prefix("MetricDataQueries.member")
|
||||||
results = self.cloudwatch_backend.get_metric_data(
|
results = self.cloudwatch_backend.get_metric_data(
|
||||||
start_time=start, end_time=end, queries=queries
|
start_time=start, end_time=end, queries=queries, scan_by=scan_by
|
||||||
)
|
)
|
||||||
|
|
||||||
template = self.response_template(GET_METRIC_DATA_TEMPLATE)
|
template = self.response_template(GET_METRIC_DATA_TEMPLATE)
|
||||||
|
@ -678,6 +678,7 @@ def test_get_metric_data_partially_within_timeframe():
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
cloudwatch.put_metric_data(
|
cloudwatch.put_metric_data(
|
||||||
Namespace=namespace1,
|
Namespace=namespace1,
|
||||||
MetricData=[
|
MetricData=[
|
||||||
@ -686,31 +687,89 @@ def test_get_metric_data_partially_within_timeframe():
|
|||||||
"Value": 50,
|
"Value": 50,
|
||||||
"Unit": "Seconds",
|
"Unit": "Seconds",
|
||||||
"Timestamp": last_week,
|
"Timestamp": last_week,
|
||||||
}
|
},
|
||||||
],
|
|
||||||
)
|
|
||||||
# get_metric_data
|
|
||||||
response = cloudwatch.get_metric_data(
|
|
||||||
MetricDataQueries=[
|
|
||||||
{
|
{
|
||||||
"Id": "result",
|
"MetricName": "metric1",
|
||||||
"MetricStat": {
|
"Value": 10,
|
||||||
"Metric": {"Namespace": namespace1, "MetricName": "metric1"},
|
"Unit": "Seconds",
|
||||||
"Period": 60,
|
"Timestamp": last_week + timedelta(seconds=10),
|
||||||
"Stat": "Sum",
|
},
|
||||||
},
|
{
|
||||||
}
|
"MetricName": "metric1",
|
||||||
|
"Value": 20,
|
||||||
|
"Unit": "Seconds",
|
||||||
|
"Timestamp": last_week + timedelta(seconds=15),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"MetricName": "metric1",
|
||||||
|
"Value": 40,
|
||||||
|
"Unit": "Seconds",
|
||||||
|
"Timestamp": last_week + timedelta(seconds=30),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
StartTime=yesterday - timedelta(seconds=60),
|
|
||||||
EndTime=utc_now + timedelta(seconds=60),
|
|
||||||
)
|
)
|
||||||
#
|
|
||||||
|
# data for average, min, max
|
||||||
|
|
||||||
|
def get_data(start, end, stat="Sum", scanBy="TimestampAscending"):
|
||||||
|
# get_metric_data
|
||||||
|
response = cloudwatch.get_metric_data(
|
||||||
|
MetricDataQueries=[
|
||||||
|
{
|
||||||
|
"Id": "result",
|
||||||
|
"MetricStat": {
|
||||||
|
"Metric": {"Namespace": namespace1, "MetricName": "metric1"},
|
||||||
|
"Period": 60,
|
||||||
|
"Stat": stat,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
StartTime=start,
|
||||||
|
EndTime=end,
|
||||||
|
ScanBy=scanBy,
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
|
||||||
|
response = get_data(
|
||||||
|
start=yesterday - timedelta(seconds=60), end=utc_now + timedelta(seconds=60),
|
||||||
|
)
|
||||||
|
|
||||||
# Assert Last week's data is not returned
|
# Assert Last week's data is not returned
|
||||||
len(response["MetricDataResults"]).should.equal(1)
|
len(response["MetricDataResults"]).should.equal(1)
|
||||||
sum_ = response["MetricDataResults"][0]
|
sum_ = response["MetricDataResults"][0]
|
||||||
sum_["Label"].should.equal("metric1 Sum")
|
sum_["Label"].should.equal("metric1 Sum")
|
||||||
sum_["StatusCode"].should.equal("Complete")
|
sum_["StatusCode"].should.equal("Complete")
|
||||||
sum_["Values"].should.equal([30.0])
|
sum_["Values"].should.equal([20.0, 10.0])
|
||||||
|
response = get_data(
|
||||||
|
start=yesterday - timedelta(seconds=60),
|
||||||
|
end=utc_now + timedelta(seconds=60),
|
||||||
|
scanBy="TimestampDescending",
|
||||||
|
)
|
||||||
|
response["MetricDataResults"][0]["Values"].should.equal([10.0, 20.0])
|
||||||
|
|
||||||
|
response = get_data(
|
||||||
|
start=last_week - timedelta(seconds=1),
|
||||||
|
end=utc_now + timedelta(seconds=60),
|
||||||
|
stat="Average",
|
||||||
|
)
|
||||||
|
# assert average
|
||||||
|
response["MetricDataResults"][0]["Values"].should.equal([30.0, 20.0, 10.0])
|
||||||
|
|
||||||
|
response = get_data(
|
||||||
|
start=last_week - timedelta(seconds=1),
|
||||||
|
end=utc_now + timedelta(seconds=60),
|
||||||
|
stat="Maximum",
|
||||||
|
)
|
||||||
|
# assert maximum
|
||||||
|
response["MetricDataResults"][0]["Values"].should.equal([50.0, 20.0, 10.0])
|
||||||
|
|
||||||
|
response = get_data(
|
||||||
|
start=last_week - timedelta(seconds=1),
|
||||||
|
end=utc_now + timedelta(seconds=60),
|
||||||
|
stat="Minimum",
|
||||||
|
)
|
||||||
|
# assert minimum
|
||||||
|
response["MetricDataResults"][0]["Values"].should.equal([10.0, 20.0, 10.0])
|
||||||
|
|
||||||
|
|
||||||
@mock_cloudwatch
|
@mock_cloudwatch
|
||||||
|
Loading…
Reference in New Issue
Block a user