Skip to content

Commit 84c4720

Browse files
author
Meshwa Savalia
committed
Pass storageResolution as enum in putMetric
1 parent 83e6e40 commit 84c4720

File tree

12 files changed

+67
-32
lines changed

12 files changed

+67
-32
lines changed

aws_embedded_metrics/logger/metric.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1111
# See the License for the specific language governing permissions and
1212
# limitations under the License.
13+
from aws_embedded_metrics.storageResolution import StorageResolution
1314

1415

1516
class Metric(object):
16-
def __init__(self, value: float, unit: str = None, storageResolution: int = 60):
17+
def __init__(self, value: float, unit: str = None, storageResolution: StorageResolution = StorageResolution.STANDARD):
1718
self.values = [value]
1819
self.unit = unit or "None"
19-
self.storageResolution = storageResolution
20+
self.storageResolution = storageResolution or StorageResolution.STANDARD
2021

2122
def add_value(self, value: float) -> None:
2223
self.values.append(value)

aws_embedded_metrics/logger/metrics_context.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from aws_embedded_metrics.config import get_config
1717
from aws_embedded_metrics.logger.metric import Metric
1818
from aws_embedded_metrics.validator import validate_dimension_set, validate_metric
19+
from aws_embedded_metrics.storageResolution import StorageResolution
1920
from typing import List, Dict, Any, Set
2021

2122

@@ -39,9 +40,9 @@ def __init__(
3940
self.metrics: Dict[str, Metric] = {}
4041
self.should_use_default_dimensions = True
4142
self.meta: Dict[str, Any] = {"Timestamp": utils.now()}
42-
self.metricNameAndResolutionMap: Dict[str, int] = {}
43+
self.metricNameAndResolutionMap: Dict[str, StorageResolution] = {}
4344

44-
def put_metric(self, key: str, value: float, unit: str = None, storageResolution: int = 60) -> None:
45+
def put_metric(self, key: str, value: float, unit: str = None, storageResolution: StorageResolution = StorageResolution.STANDARD) -> None:
4546
"""
4647
Adds a metric measurement to the context.
4748
Multiple calls using the same key will be stored as an

aws_embedded_metrics/logger/metrics_logger.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from aws_embedded_metrics.logger.metrics_context import MetricsContext
1616
from aws_embedded_metrics.validator import validate_namespace
1717
from aws_embedded_metrics.config import get_config
18+
from aws_embedded_metrics.storageResolution import StorageResolution
1819
from typing import Any, Awaitable, Callable, Dict, Tuple
1920
import sys
2021
import traceback
@@ -78,7 +79,9 @@ def set_namespace(self, namespace: str) -> "MetricsLogger":
7879
self.context.namespace = namespace
7980
return self
8081

81-
def put_metric(self, key: str, value: float, unit: str = "None", storageResolution: int = 60) -> "MetricsLogger":
82+
def put_metric(
83+
self, key: str, value: float, unit: str = "None", storageResolution: StorageResolution = StorageResolution.STANDARD
84+
) -> "MetricsLogger":
8285
self.context.put_metric(key, value, unit, storageResolution)
8386
return self
8487

aws_embedded_metrics/serializers/log_serializer.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
MAX_DIMENSION_SET_SIZE, MAX_METRICS_PER_EVENT, MAX_DATAPOINTS_PER_METRIC
1919
)
2020
from aws_embedded_metrics.exceptions import DimensionSetExceededError
21+
from aws_embedded_metrics.storageResolution import StorageResolution
2122
import json
2223
from typing import Any, Dict, List
2324

@@ -88,8 +89,8 @@ def create_body() -> Dict[str, Any]:
8889
remaining_data = True
8990

9091
metricBody = {"Name": metric_name, "Unit": metric.unit}
91-
if metric.storageResolution == 1:
92-
metricBody["StorageResolution"] = metric.storageResolution # type: ignore
92+
if metric.storageResolution == StorageResolution.HIGH:
93+
metricBody["StorageResolution"] = metric.storageResolution.value # type: ignore
9394
if not config.disable_metric_extraction:
9495
current_body["_aws"]["CloudWatchMetrics"][0]["Metrics"].append(metricBody)
9596
num_metrics_in_current_body += 1

aws_embedded_metrics/validator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def validate_dimension_set(dimension_set: Dict[str, str]) -> None:
5858
raise InvalidDimensionError("Dimension name cannot start with ':'")
5959

6060

61-
def validate_metric(name: str, value: float, unit: Optional[str], storageResolution: Optional[int], metricNameAndResolutionMap: dict) -> None: # noqa: E501
61+
def validate_metric(name: str, value: float, unit: Optional[str], storageResolution: StorageResolution, metricNameAndResolutionMap: dict) -> None: # noqa: E501
6262
"""
6363
Validates a metric
6464
@@ -90,7 +90,7 @@ def validate_metric(name: str, value: float, unit: Optional[str], storageResolut
9090
if metricNameAndResolutionMap and name in metricNameAndResolutionMap:
9191
if metricNameAndResolutionMap.get(name) is not storageResolution:
9292
raise InvalidMetricError(
93-
f"Resolution for metrics ${name} is already set. A single log event cannot have a metric with two different resolutions.")
93+
"Resolution for metrics ${name} is already set. A single log event cannot have a metric with two different resolutions.")
9494

9595

9696
def validate_namespace(namespace: str) -> None:

examples/ec2/app.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from aws_embedded_metrics import metric_scope
2+
from aws_embedded_metrics.storageResolution import StorageResolution
23

34
import logging
45

@@ -10,7 +11,7 @@
1011
def my_handler(metrics):
1112
metrics.put_dimensions({"Foo": "Bar"})
1213
metrics.put_metric("ProcessingLatency", 100, "Milliseconds")
13-
metrics.put_metric("CPU Utilization", 87, "Percent", 1)
14+
metrics.put_metric("CPU Utilization", 87, "Percent", StorageResolution.HIGH)
1415
metrics.set_property("AccountId", "123456789012")
1516
metrics.set_property("RequestId", "422b1569-16f6-4a03-b8f0-fe3fd9b100f8")
1617
metrics.set_property("DeviceId", "61270781-c6ac-46f1-baf7-22c808af8162")

examples/lambda/function.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from aws_embedded_metrics import metric_scope
2+
from aws_embedded_metrics.storageResolution import StorageResolution
23

34

45
@metric_scope
56
def my_handler(event, context, metrics):
67
metrics.put_dimensions({"Foo": "Bar"})
78
metrics.put_metric("ProcessingLatency", 100, "Milliseconds")
8-
metrics.put_metric("CPU Utilization", 87, "Percent", 1)
9+
metrics.put_metric("CPU Utilization", 87, "Percent", StorageResolution.HIGH)
910
metrics.set_property("AccountId", "123456789012")
1011
metrics.set_property("RequestId", "422b1569-16f6-4a03-b8f0-fe3fd9b100f8")
1112
metrics.set_property("DeviceId", "61270781-c6ac-46f1-baf7-22c808af8162")

tests/canary/agent/canary.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import aws_embedded_metrics
33
from aws_embedded_metrics import metric_scope
44
from aws_embedded_metrics.config import get_config
5+
from aws_embedded_metrics.storageResolution import StorageResolution
56
from getversion import get_module_version
67
import os
78
import psutil
@@ -26,7 +27,7 @@ async def app(init, last_run_duration, metrics):
2627
metrics.set_dimensions({"Runtime": 'Python', "Platform": 'ECS', "Agent": 'CloudWatchAgent', "Version": version})
2728
metrics.put_metric('Invoke', 1, "Count")
2829
metrics.put_metric('Duration', last_run_duration, 'Seconds')
29-
metrics.put_metric('Memory.RSS', process.memory_info().rss, 'Bytes', 1)
30+
metrics.put_metric('Memory.RSS', process.memory_info().rss, 'Bytes', StorageResolution.HIGH)
3031

3132

3233
async def main():

tests/integ/agent/test_end_to_end.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from aws_embedded_metrics.config import get_config
22
from aws_embedded_metrics import metric_scope
3+
from aws_embedded_metrics.storageResolution import StorageResolution
34
import pytest
45
import boto3
56
import logging
@@ -40,7 +41,7 @@ async def test_end_to_end_tcp_multiple_flushes():
4041
@metric_scope
4142
async def do_work(metrics):
4243
metrics.put_dimensions({"Operation": "Agent"})
43-
metrics.put_metric(metric_name, 100, "Milliseconds")
44+
metrics.put_metric(metric_name, 100, "Milliseconds", StorageResolution.HIGH)
4445
metrics.set_property("RequestId", "422b1569-16f6-4a03-b8f0-fe3fd9b100f8")
4546

4647
# act
@@ -70,7 +71,7 @@ async def test_end_to_end_udp():
7071
@metric_scope
7172
async def do_work(metrics):
7273
metrics.put_dimensions({"Operation": "Agent"})
73-
metrics.put_metric(metric_name, 100, "Milliseconds")
74+
metrics.put_metric(metric_name, 100, "Milliseconds", StorageResolution.HIGH)
7475
metrics.set_property("RequestId", "422b1569-16f6-4a03-b8f0-fe3fd9b100f8")
7576

7677
# act

tests/logger/test_metrics_context.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ def test_put_metric_uses_none_unit_if_not_provided():
290290
assert metric.unit == "None"
291291

292292

293-
def test_put_metric_uses_60_storage_resolution_if_not_provided():
293+
def test_put_metric_uses_standard_storage_resolution_if_not_provided():
294294
# arrange
295295
context = MetricsContext()
296296
metric_key = fake.word()
@@ -301,22 +301,22 @@ def test_put_metric_uses_60_storage_resolution_if_not_provided():
301301

302302
# assert
303303
metric = context.metrics[metric_key]
304-
assert metric.storageResolution == 60
304+
assert metric.storageResolution == StorageResolution.STANDARD
305305

306306

307307
@pytest.mark.parametrize(
308308
"name, value, unit, storageResolution",
309309
[
310-
("", 1, "None", 60),
311-
(" ", 1, "Seconds", 60),
312-
("a" * (constants.MAX_METRIC_NAME_LENGTH + 1), 1, "None", 60),
313-
("metric", float("inf"), "Count", 60),
314-
("metric", float("-inf"), "Count", 60),
315-
("metric", float("nan"), "Count", 60),
316-
("metric", math.inf, "Seconds", 60),
317-
("metric", -math.inf, "Seconds", 60),
318-
("metric", math.nan, "Seconds", 60),
319-
("metric", 1, "Kilometers/Fahrenheit", 60),
310+
("", 1, "None", StorageResolution.STANDARD),
311+
(" ", 1, "Seconds", StorageResolution.STANDARD),
312+
("a" * (constants.MAX_METRIC_NAME_LENGTH + 1), 1, "None", StorageResolution.STANDARD),
313+
("metric", float("inf"), "Count", StorageResolution.STANDARD),
314+
("metric", float("-inf"), "Count", StorageResolution.STANDARD),
315+
("metric", float("nan"), "Count", StorageResolution.STANDARD),
316+
("metric", math.inf, "Seconds", StorageResolution.STANDARD),
317+
("metric", -math.inf, "Seconds", StorageResolution.STANDARD),
318+
("metric", math.nan, "Seconds", StorageResolution.STANDARD),
319+
("metric", 1, "Kilometers/Fahrenheit", StorageResolution.STANDARD),
320320
("metric", 1, "Seconds", 2),
321321
("metric", 1, "Seconds", None)
322322
]

tests/logger/test_metrics_logger.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from aws_embedded_metrics.sinks import Sink
44
from aws_embedded_metrics.environment import Environment
55
from aws_embedded_metrics.exceptions import InvalidNamespaceError, InvalidMetricError
6+
from aws_embedded_metrics.storageResolution import StorageResolution
67
import aws_embedded_metrics.constants as constants
78
import pytest
89
from faker import Faker
@@ -58,7 +59,7 @@ async def test_can_put_metric_with_different_storage_resolution_different_flush(
5859
# arrange
5960
expected_key = fake.word()
6061
expected_value = fake.random.randrange(100)
61-
metric_storageResolution = 1
62+
metric_storageResolution = StorageResolution.HIGH
6263

6364
logger, sink, env = get_logger_and_sink(mocker)
6465

@@ -79,7 +80,7 @@ async def test_can_put_metric_with_different_storage_resolution_different_flush(
7980
context = sink.accept.call_args[0][0]
8081
assert context.metrics[expected_key].values == [expected_value]
8182
assert context.metrics[expected_key].unit == "None"
82-
assert context.metrics[expected_key].storageResolution == 60
83+
assert context.metrics[expected_key].storageResolution == StorageResolution.STANDARD
8384

8485

8586
@pytest.mark.asyncio
@@ -91,9 +92,9 @@ async def test_cannot_put_metric_with_different_storage_resolution_same_flush(mo
9192
logger, sink, env = get_logger_and_sink(mocker)
9293

9394
# act
94-
logger.put_metric(expected_key, expected_value, None, 1)
95+
logger.put_metric(expected_key, expected_value, None, StorageResolution.HIGH)
9596
with pytest.raises(InvalidMetricError):
96-
logger.put_metric(expected_key, expected_value, None, 60)
97+
logger.put_metric(expected_key, expected_value, None, StorageResolution.STANDARD)
9798
await logger.flush()
9899

99100

tests/serializer/test_log_serializer.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from aws_embedded_metrics.exceptions import DimensionSetExceededError
33
from aws_embedded_metrics.logger.metrics_context import MetricsContext
44
from aws_embedded_metrics.serializers.log_serializer import LogSerializer
5+
from aws_embedded_metrics.storageResolution import StorageResolution
56
from collections import Counter
67
from faker import Faker
78
import json
@@ -92,7 +93,30 @@ def test_serialize_metrics():
9293
assert_json_equality(result_json, expected)
9394

9495

95-
def test_serialize_metrics_with_storageResolution():
96+
def test_serialize_metrics_with_Standard_storageResolution():
97+
# arrange
98+
expected_key = fake.word()
99+
expected_value = fake.random.randrange(0, 100)
100+
101+
expected_metric_definition = {"Name": expected_key, "Unit": "None"}
102+
103+
expected = {**get_empty_payload()}
104+
expected[expected_key] = expected_value
105+
expected["_aws"]["CloudWatchMetrics"][0]["Metrics"].append(
106+
expected_metric_definition
107+
)
108+
109+
context = get_context()
110+
context.put_metric(expected_key, expected_value, "None", StorageResolution.STANDARD)
111+
112+
# act
113+
result_json = serializer.serialize(context)[0]
114+
115+
# assert
116+
assert_json_equality(result_json, expected)
117+
118+
119+
def test_serialize_metrics_with_High_storageResolution():
96120
# arrange
97121
expected_key = fake.word()
98122
expected_value = fake.random.randrange(0, 100)
@@ -106,7 +130,7 @@ def test_serialize_metrics_with_storageResolution():
106130
)
107131

108132
context = get_context()
109-
context.put_metric(expected_key, expected_value, "None", 1)
133+
context.put_metric(expected_key, expected_value, "None", StorageResolution.HIGH)
110134

111135
# act
112136
result_json = serializer.serialize(context)[0]

0 commit comments

Comments
 (0)