CloudWatch: add support for put-metric-data with values list (#5658)
This commit is contained in:
parent
9eccce8af3
commit
6b50b8020f
@ -473,22 +473,66 @@ class CloudWatchBackend(BaseBackend):
|
||||
raise InvalidParameterValue(
|
||||
f"The value NaN for parameter MetricData.member.{i + 1}.Value is invalid."
|
||||
)
|
||||
if metric.get("Values.member"):
|
||||
if "Value" in metric:
|
||||
raise InvalidParameterValue(
|
||||
f"The parameters MetricData.member.{i+1}.Value and MetricData.member.{i+1}.Values are mutually exclusive and you have specified both."
|
||||
)
|
||||
if metric.get("Counts.member"):
|
||||
if len(metric["Counts.member"]) != len(metric["Values.member"]):
|
||||
raise InvalidParameterValue(
|
||||
f"The parameters MetricData.member.{i+1}.Values and MetricData.member.{i+1}.Counts must be of the same size."
|
||||
)
|
||||
for value in metric["Values.member"]:
|
||||
if value.lower() == "nan":
|
||||
raise InvalidParameterValue(
|
||||
f"The value {value} for parameter MetricData.member.{i + 1}.Values is invalid."
|
||||
)
|
||||
|
||||
for metric_member in metric_data:
|
||||
# Preserve "datetime" for get_metric_statistics comparisons
|
||||
timestamp = metric_member.get("Timestamp")
|
||||
if timestamp is not None and type(timestamp) != datetime:
|
||||
timestamp = parser.parse(timestamp)
|
||||
self.metric_data.append(
|
||||
MetricDatum(
|
||||
namespace,
|
||||
metric_member["MetricName"],
|
||||
float(metric_member.get("Value", 0)),
|
||||
metric_member.get("Dimensions.member", _EMPTY_LIST),
|
||||
timestamp,
|
||||
metric_member.get("Unit"),
|
||||
metric_name = metric_member["MetricName"]
|
||||
dimension = metric_member.get("Dimensions.member", _EMPTY_LIST)
|
||||
unit = metric_member.get("Unit")
|
||||
|
||||
# put_metric_data can include "value" as single value or "values" as a list
|
||||
if metric_member.get("Values.member"):
|
||||
values = metric_member["Values.member"]
|
||||
# value[i] should be added count[i] times (with default count 1)
|
||||
counts = metric_member.get("Counts.member") or ["1"] * len(values)
|
||||
for i in range(0, len(values)):
|
||||
value = values[i]
|
||||
timestamp = metric_member.get("Timestamp")
|
||||
if timestamp is not None and type(timestamp) != datetime:
|
||||
timestamp = parser.parse(timestamp)
|
||||
|
||||
# add the value count[i] times
|
||||
for _ in range(0, int(float(counts[i]))):
|
||||
self.metric_data.append(
|
||||
MetricDatum(
|
||||
namespace,
|
||||
metric_name,
|
||||
float(value),
|
||||
dimension,
|
||||
timestamp,
|
||||
unit,
|
||||
)
|
||||
)
|
||||
else:
|
||||
# there is only a single value
|
||||
self.metric_data.append(
|
||||
MetricDatum(
|
||||
namespace,
|
||||
metric_name,
|
||||
float(metric_member.get("Value", 0)),
|
||||
dimension,
|
||||
timestamp,
|
||||
unit,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def get_metric_data(
|
||||
self,
|
||||
|
@ -52,6 +52,115 @@ def test_put_metric_data_can_not_have_nan():
|
||||
)
|
||||
|
||||
|
||||
@mock_cloudwatch
|
||||
def test_put_metric_data_can_not_have_value_and_values():
|
||||
client = boto3.client("cloudwatch", region_name="us-west-2")
|
||||
utc_now = datetime.now(tz=pytz.utc)
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.put_metric_data(
|
||||
Namespace="mynamespace",
|
||||
MetricData=[
|
||||
{
|
||||
"MetricName": "mymetric",
|
||||
"Timestamp": utc_now,
|
||||
"Value": 1.5,
|
||||
"Values": [1.0, 10.0],
|
||||
"Unit": "Count",
|
||||
}
|
||||
],
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("InvalidParameterValue")
|
||||
err["Message"].should.equal(
|
||||
"The parameters MetricData.member.1.Value and MetricData.member.1.Values are mutually exclusive and you have specified both."
|
||||
)
|
||||
|
||||
|
||||
@mock_cloudwatch
|
||||
def test_put_metric_data_can_not_have_and_values_mismatched_counts():
|
||||
client = boto3.client("cloudwatch", region_name="us-west-2")
|
||||
utc_now = datetime.now(tz=pytz.utc)
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.put_metric_data(
|
||||
Namespace="mynamespace",
|
||||
MetricData=[
|
||||
{
|
||||
"MetricName": "mymetric",
|
||||
"Timestamp": utc_now,
|
||||
"Values": [1.0, 10.0],
|
||||
"Counts": [2, 4, 1],
|
||||
"Unit": "Count",
|
||||
}
|
||||
],
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("InvalidParameterValue")
|
||||
err["Message"].should.equal(
|
||||
"The parameters MetricData.member.1.Values and MetricData.member.1.Counts must be of the same size."
|
||||
)
|
||||
|
||||
|
||||
@mock_cloudwatch
|
||||
def test_put_metric_data_values_and_counts():
|
||||
client = boto3.client("cloudwatch", region_name="us-west-2")
|
||||
utc_now = datetime.now(tz=pytz.utc)
|
||||
namespace = "values"
|
||||
metric = "mymetric"
|
||||
client.put_metric_data(
|
||||
Namespace=namespace,
|
||||
MetricData=[
|
||||
{
|
||||
"MetricName": metric,
|
||||
"Timestamp": utc_now,
|
||||
"Values": [1.0, 10.0],
|
||||
"Counts": [2, 4],
|
||||
}
|
||||
],
|
||||
)
|
||||
stats = client.get_metric_statistics(
|
||||
Namespace=namespace,
|
||||
MetricName=metric,
|
||||
StartTime=utc_now - timedelta(seconds=60),
|
||||
EndTime=utc_now + timedelta(seconds=60),
|
||||
Period=60,
|
||||
Statistics=["SampleCount", "Sum", "Maximum"],
|
||||
)
|
||||
datapoint = stats["Datapoints"][0]
|
||||
datapoint["SampleCount"].should.equal(6.0)
|
||||
datapoint["Sum"].should.equal(42.0)
|
||||
datapoint["Maximum"].should.equal(10.0)
|
||||
|
||||
|
||||
@mock_cloudwatch
|
||||
def test_put_metric_data_values_without_counts():
|
||||
client = boto3.client("cloudwatch", region_name="us-west-2")
|
||||
utc_now = datetime.now(tz=pytz.utc)
|
||||
namespace = "values"
|
||||
metric = "mymetric"
|
||||
client.put_metric_data(
|
||||
Namespace=namespace,
|
||||
MetricData=[
|
||||
{
|
||||
"MetricName": metric,
|
||||
"Timestamp": utc_now,
|
||||
"Values": [1.0, 10.0, 23.45],
|
||||
}
|
||||
],
|
||||
)
|
||||
stats = client.get_metric_statistics(
|
||||
Namespace=namespace,
|
||||
MetricName=metric,
|
||||
StartTime=utc_now - timedelta(seconds=60),
|
||||
EndTime=utc_now + timedelta(seconds=60),
|
||||
Period=60,
|
||||
Statistics=["SampleCount", "Sum", "Maximum"],
|
||||
)
|
||||
datapoint = stats["Datapoints"][0]
|
||||
datapoint["SampleCount"].should.equal(3.0)
|
||||
datapoint["Sum"].should.equal(34.45)
|
||||
datapoint["Maximum"].should.equal(23.45)
|
||||
|
||||
|
||||
@mock_cloudwatch
|
||||
def test_put_metric_data_with_statistics():
|
||||
conn = boto3.client("cloudwatch", region_name="us-east-1")
|
||||
|
Loading…
Reference in New Issue
Block a user