Skip to content

Commit 1ac3f82

Browse files
committed
feat: store integration test metrics in metrics.json
For each test store metrics it emits into a metrics.json file. This makes it easier to look at the metrics. Signed-off-by: Egor Lazarchuk <yegorlz@amazon.co.uk>
1 parent 1d5ee0e commit 1ac3f82

File tree

2 files changed

+40
-24
lines changed

2 files changed

+40
-24
lines changed

tests/conftest.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,17 @@ def pytest_runtest_logreport(report):
171171
METRICS.flush()
172172

173173

174+
@pytest.fixture
175+
def test_output_dir(results_dir, request):
176+
raw_data_path = Path(results_dir / request.node.name)
177+
if raw_data_path.is_dir():
178+
shutil.rmtree(raw_data_path)
179+
raw_data_path.mkdir()
180+
return raw_data_path
181+
182+
174183
@pytest.fixture()
175-
def metrics(request):
184+
def metrics(test_output_dir, request):
176185
"""Fixture to pass the metrics scope
177186
178187
We use a fixture instead of the @metrics_scope decorator as that conflicts
@@ -188,6 +197,7 @@ def metrics(request):
188197
metrics_logger.set_property(prop_name, prop_val)
189198
yield metrics_logger
190199
metrics_logger.flush()
200+
metrics_logger.store_data(test_output_dir)
191201

192202

193203
@pytest.fixture

tests/host_tools/metrics.py

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,52 +46,58 @@
4646
import json
4747
import os
4848
import socket
49+
from pathlib import Path
4950
from urllib.parse import urlparse
5051

5152
from aws_embedded_metrics.constants import DEFAULT_NAMESPACE
5253
from aws_embedded_metrics.logger.metrics_logger_factory import create_metrics_logger
5354

5455

55-
class MetricsWrapperDummy:
56-
"""Send metrics to /dev/null"""
56+
class MetricsWrapper:
57+
"""A convenient metrics logger"""
58+
59+
def __init__(self, logger):
60+
self.data = {}
61+
self.logger = logger
5762

5863
def set_dimensions(self, *args, **kwargs):
5964
"""Set dimensions"""
65+
if self.logger:
66+
self.logger.set_dimensions(*args, **kwargs)
6067

61-
def put_metric(self, *args, **kwargs):
68+
def put_metric(self, name, data, unit):
6269
"""Put a datapoint with given dimensions"""
70+
if name not in self.data:
71+
self.data[name] = []
72+
self.data[name].append(data)
73+
74+
if self.logger:
75+
self.logger.put_metric(name, data, unit)
6376

6477
def set_property(self, *args, **kwargs):
6578
"""Set a property"""
79+
if self.logger:
80+
self.logger.set_property(*args, **kwargs)
6681

6782
def flush(self):
6883
"""Flush any remaining metrics"""
84+
if self.logger:
85+
asyncio.run(self.logger.flush())
6986

70-
71-
class MetricsWrapper:
72-
"""A convenient metrics logger"""
73-
74-
def __init__(self, logger):
75-
self.logger = logger
76-
77-
def __getattr__(self, attr):
78-
"""Dispatch methods to logger instance"""
79-
if attr not in self.__dict__:
80-
return getattr(self.logger, attr)
81-
return getattr(self, attr)
82-
83-
def flush(self):
84-
"""Flush any remaining metrics"""
85-
asyncio.run(self.logger.flush())
87+
def store_data(self, dir_path):
88+
metrics_path = Path(dir_path / "metrics.json")
89+
with open(metrics_path, "w") as f:
90+
json.dump(self.data, f)
8691

8792

8893
def get_metrics_logger():
8994
"""Get a new metrics logger object"""
9095
# if no metrics namespace, don't output metrics
91-
if "AWS_EMF_NAMESPACE" not in os.environ:
92-
return MetricsWrapperDummy()
93-
logger = create_metrics_logger()
94-
logger.reset_dimensions(False)
96+
if "AWS_EMF_NAMESPACE" in os.environ:
97+
logger = create_metrics_logger()
98+
logger.reset_dimensions(False)
99+
else:
100+
logger = None
95101
return MetricsWrapper(logger)
96102

97103

0 commit comments

Comments
 (0)