Skip to content

Commit 473ba1a

Browse files
committed
finish the metrics logger implementation
1 parent 0f3bde4 commit 473ba1a

File tree

6 files changed

+255
-40
lines changed

6 files changed

+255
-40
lines changed

aws_embedded_metrics/logger/metrics_context.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def __init__(
2121
self.dimensions: List[Dict[str, str]] = dimensions or []
2222
self.default_dimensions: Dict[str, str] = default_dimensions or {}
2323
self.metrics: Dict[str, Metric] = {}
24+
self.should_use_default_dimensions = True
2425

2526
def put_metric(self, key: str, value: float, unit: str = None) -> None:
2627
"""
@@ -38,24 +39,18 @@ def put_metric(self, key: str, value: float, unit: str = None) -> None:
3839
else:
3940
self.metrics[key] = Metric(value, unit)
4041

41-
def put_dimension(self, dimensions: Dict[str, str]) -> None:
42+
def put_dimensions(self, dimensions: Dict[str, str]) -> None:
4243
"""
4344
Adds dimensions to the context.
4445
```
45-
context.put_dimension({ "k1": "v1", "k2": "v2" })
46+
context.put_dimensions({ "k1": "v1", "k2": "v2" })
4647
```
4748
"""
4849
if dimensions is None:
4950
# TODO add ability to define failure strategy
5051
return
5152

52-
if self.__has_default_dimensions():
53-
merged_dimensions: Dict = {}
54-
merged_dimensions.update(self.default_dimensions)
55-
merged_dimensions.update(dimensions)
56-
self.dimensions.append(merged_dimensions)
57-
else:
58-
self.dimensions.append(dimensions)
53+
self.dimensions.append(dimensions)
5954

6055
def set_dimensions(self, dimensionSets: List[Dict[str, str]]) -> None:
6156
"""
@@ -66,6 +61,7 @@ def set_dimensions(self, dimensionSets: List[Dict[str, str]]) -> None:
6661
{ "k1": "v1", "k2": "v2" }])
6762
```
6863
"""
64+
self.should_use_default_dimensions = False
6965
self.dimensions = dimensionSets
7066

7167
def set_default_dimensions(self, default_dimensions: Dict) -> None:
@@ -86,13 +82,23 @@ def get_dimensions(self) -> List[Dict]:
8682
"""
8783
Returns the current dimensions on the context
8884
"""
85+
# user has directly called set_dimensions
86+
if not self.should_use_default_dimensions:
87+
return self.dimensions
88+
8989
if not self.__has_default_dimensions():
9090
return self.dimensions
9191

9292
if len(self.dimensions) == 0:
9393
return [self.default_dimensions]
9494

95-
return self.dimensions
95+
# we have to merge dimensions on the read path
96+
# because defaults won't actually get set until the flush
97+
# method is called. This allows us to not block the user
98+
# code while we're detecting the environment
99+
return list(
100+
map(lambda custom: {**self.default_dimensions, **custom}, self.dimensions)
101+
)
96102

97103
def __has_default_dimensions(self) -> bool:
98104
return self.default_dimensions is not None and len(self.default_dimensions) > 0

aws_embedded_metrics/logger/metrics_logger.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from aws_embedded_metrics.environment.environment_provider import EnvironmentProvider
33
from aws_embedded_metrics.logger.metrics_context import MetricsContext
44
from aws_embedded_metrics.config import get_config
5+
from typing import Any, Dict
56

67
Config = get_config()
78

@@ -31,9 +32,28 @@ def __configureContextForEnvironment(self, env: Environment) -> None:
3132
default_dimensions = {
3233
# LogGroup name will entirely depend on the environment since there
3334
# are some cases where the LogGroup cannot be configured (e.g. Lambda)
34-
"log_group": env.get_log_group_name(),
35-
"service_name": Config.service_name or env.get_name(),
36-
"service_type": Config.service_type or env.get_type(),
35+
"LogGroup": env.get_log_group_name(),
36+
"ServiceName": Config.service_name or env.get_name(),
37+
"ServiceType": Config.service_type or env.get_type(),
3738
}
3839
self.context.set_default_dimensions(default_dimensions)
3940
env.configure_context(self.context)
41+
42+
def set_property(self, key: str, value: Any) -> "MetricsLogger":
43+
self.context.set_property(key, value)
44+
return self
45+
46+
def put_dimensions(self, dimensions: Dict[str, str]) -> "MetricsLogger":
47+
self.context.put_dimensions(dimensions)
48+
return self
49+
50+
def set_dimensions(self, *dimensions: Dict[str, str]) -> "MetricsLogger":
51+
self.context.set_dimensions(list(dimensions))
52+
return self
53+
54+
def put_metric(self, key: str, value: float, unit: str = "None") -> "MetricsLogger":
55+
self.context.put_metric(key, value, unit)
56+
return self
57+
58+
def new(self) -> "MetricsLogger":
59+
return MetricsLogger(self.env_provider, self.context.create_copy_with_context())

tests/config/test_config.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,11 @@
22
from faker import Faker
33
import os
44
from importlib import reload
5-
import pytest
65

76

87
fake = Faker()
98

109

11-
@pytest.fixture
12-
def before(self):
13-
os.environ["AWS_EMF_ENABLE_DEBUG_LOGGING"] = None
14-
os.environ["AWS_EMF_SERVICE_NAME"] = None
15-
os.environ["AWS_EMF_SERVICE_TYPE"] = None
16-
os.environ["AWS_EMF_LOG_GROUP_NAME"] = None
17-
os.environ["AWS_EMF_LOG_STREAM_NAME"] = None
18-
os.environ["AWS_EMF_AGENT_ENDPOINT"] = None
19-
20-
2110
def get_config():
2211
# reload the configuration module since it is loaded on
2312
# startup and cached

tests/logger/test_metrics_context.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from _pytest.monkeypatch import MonkeyPatch
44
import pytest
55
from faker import Faker
6+
67
fake = Faker()
78

89

@@ -37,8 +38,7 @@ def test_can_set_property(mock_time):
3738
context.properties[property_key] = property_value
3839

3940
# assert
40-
assert context.properties == {
41-
"Timestamp": mock_time, property_key: property_value}
41+
assert context.properties == {"Timestamp": mock_time, property_key: property_value}
4242

4343

4444
def test_put_dimension_adds_to_dimensions(mock_time):
@@ -49,7 +49,7 @@ def test_put_dimension_adds_to_dimensions(mock_time):
4949
dimension_value = fake.word()
5050

5151
# act
52-
context.put_dimension({dimension_key: dimension_value})
52+
context.put_dimensions({dimension_key: dimension_value})
5353

5454
# assert
5555
assert context.dimensions == [{dimension_key: dimension_value}]
@@ -60,10 +60,10 @@ def test_get_dimensions_returns_only_custom_dimensions_if_no_default_dimensions_
6060
context = MetricsContext()
6161
dimension_key = fake.word()
6262
dimension_value = fake.word()
63-
expected_dimensions = {dimension_key: dimension_value}
63+
expected_dimensions = {dimension_key: dimension_value}
6464

6565
context.set_default_dimensions(None)
66-
context.put_dimension(expected_dimensions)
66+
context.put_dimensions(expected_dimensions)
6767

6868
# act
6969
actual_dimensions = context.get_dimensions()
@@ -77,10 +77,10 @@ def test_get_dimensions_returns_only_custom_dimensions_if_default_dimensions_are
7777
context = MetricsContext()
7878
dimension_key = fake.word()
7979
dimension_value = fake.word()
80-
expected_dimensions = {dimension_key: dimension_value}
80+
expected_dimensions = {dimension_key: dimension_value}
8181

8282
context.set_default_dimensions({})
83-
context.put_dimension(expected_dimensions)
83+
context.put_dimensions(expected_dimensions)
8484

8585
# act
8686
actual_dimensions = context.get_dimensions()
@@ -94,7 +94,7 @@ def test_get_dimensions_returns_default_dimensions_if_custom_dimensions_not_set(
9494
context = MetricsContext()
9595
dimension_key = fake.word()
9696
dimension_value = fake.word()
97-
expected_dimensions = {dimension_key: dimension_value}
97+
expected_dimensions = {dimension_key: dimension_value}
9898
context.set_default_dimensions(expected_dimensions)
9999

100100
# act
@@ -113,12 +113,13 @@ def test_get_dimensions_returns_merged_custom_and_default_dimensions():
113113
default_dimension_key = fake.word()
114114
default_dimension_value = fake.word()
115115

116-
expected_dimensions = {default_dimension_key: default_dimension_value,
117-
custom_dimension_key: custom_dimension_value}
116+
expected_dimensions = {
117+
default_dimension_key: default_dimension_value,
118+
custom_dimension_key: custom_dimension_value,
119+
}
118120

119-
context.set_default_dimensions(
120-
{default_dimension_key: default_dimension_value})
121-
context.put_dimension({custom_dimension_key: custom_dimension_value})
121+
context.set_default_dimensions({default_dimension_key: default_dimension_value})
122+
context.put_dimensions({custom_dimension_key: custom_dimension_value})
122123

123124
# act
124125
actual_dimensions = context.get_dimensions()
@@ -154,7 +155,7 @@ def test_put_metric_uses_None_unit_if_not_provided():
154155

155156
# assert
156157
metric = context.metrics[metric_key]
157-
assert metric.unit == 'None'
158+
assert metric.unit == "None"
158159

159160

160161
def test_create_copy_with_context_creates_new_instance():
@@ -200,7 +201,7 @@ def test_create_copy_with_context_copies_dimensions():
200201
context = MetricsContext()
201202
dimension_key = fake.word()
202203
dimension_value = fake.word()
203-
context.put_dimension({dimension_key: dimension_value})
204+
context.put_dimensions({dimension_key: dimension_value})
204205

205206
# act
206207
new_context = context.create_copy_with_context()
@@ -227,7 +228,7 @@ def test_set_dimensions_overwrites_all_dimensions():
227228
# arrange
228229
context = MetricsContext()
229230
context.set_default_dimensions({fake.word(): fake.word})
230-
context.put_dimension({fake.word(): fake.word})
231+
context.put_dimensions({fake.word(): fake.word})
231232

232233
expected_dimensions = {fake.word(): fake.word}
233234

0 commit comments

Comments
 (0)