Skip to content

Commit 066df53

Browse files
authored
Add a DISABLE_METRIC_EXTRACTION config option (#55)
* Add a DISABLE_METRIC_EXTRACTION config option This adds a new configuration option `DISABLE_METRIC_EXTRACTION` which removes the `_aws` metadata from the EMF log records, thus disabling the extraction of metrics by CloudWatch Metrics. The remaining part of the log records is still getting logged.
1 parent a4d7bc0 commit 066df53

File tree

7 files changed

+70
-7
lines changed

7 files changed

+70
-7
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,21 @@ Config.namespace = "MyApplication"
250250
AWS_EMF_NAMESPACE = MyApplication
251251
```
252252

253+
**DISABLE_METRIC_EXTRACTION**: Disables extraction of metrics by CloudWatch, by omitting EMF
254+
metadata from serialized log records.
255+
256+
Example:
257+
258+
```py
259+
# in process
260+
from aws_embedded_metrics.config import get_config
261+
Config = get_config()
262+
Config.disable_metric_extraction = True
263+
264+
# environment
265+
AWS_EMF_DISABLE_METRIC_EXTRACTION = true
266+
```
267+
253268
## Examples
254269

255270
Check out the [examples](https://github.com/awslabs/aws-embedded-metrics-python/tree/master/examples) directory to get started.

aws_embedded_metrics/config/configuration.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def __init__(
2323
agent_endpoint: str,
2424
ec2_metadata_endpoint: str = None,
2525
namespace: str = None,
26+
disable_metric_extraction: bool = False,
2627
):
2728
self.debug_logging_enabled = debug_logging_enabled
2829
self.service_name = service_name
@@ -32,3 +33,4 @@ def __init__(
3233
self.agent_endpoint = agent_endpoint
3334
self.ec2_metadata_endpoint = ec2_metadata_endpoint
3435
self.namespace = namespace
36+
self.disable_metric_extraction = disable_metric_extraction

aws_embedded_metrics/config/environment_configuration_provider.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
AGENT_ENDPOINT = "AGENT_ENDPOINT"
2525
EC2_METADATA_ENDPOINT = "EC2_METADATA_ENDPOINT"
2626
NAMESPACE = "NAMESPACE"
27+
DISABLE_METRIC_EXTRACTION = "DISABLE_METRIC_EXTRACTION"
2728

2829

2930
class EnvironmentConfigurationProvider:
@@ -41,6 +42,7 @@ def get_configuration(self) -> Configuration:
4142
self.__get_env_var(AGENT_ENDPOINT),
4243
self.__get_env_var(EC2_METADATA_ENDPOINT),
4344
self.__get_env_var(NAMESPACE),
45+
self.__get_bool_env_var(DISABLE_METRIC_EXTRACTION),
4446
)
4547

4648
@staticmethod

aws_embedded_metrics/serializers/log_serializer.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# See the License for the specific language governing permissions and
1212
# limitations under the License.
1313

14+
from aws_embedded_metrics.config import get_config
1415
from aws_embedded_metrics.logger.metrics_context import MetricsContext
1516
from aws_embedded_metrics.serializers import Serializer
1617
from aws_embedded_metrics.constants import MAX_DIMENSIONS, MAX_METRICS_PER_EVENT
@@ -21,6 +22,8 @@
2122
class LogSerializer(Serializer):
2223
@staticmethod
2324
def serialize(context: MetricsContext) -> List[str]:
25+
config = get_config()
26+
2427
dimension_keys = []
2528
dimensions_properties: Dict[str, str] = {}
2629

@@ -30,10 +33,12 @@ def serialize(context: MetricsContext) -> List[str]:
3033
dimensions_properties = {**dimensions_properties, **dimension_set}
3134

3235
def create_body() -> Dict[str, Any]:
33-
return {
36+
body: Dict[str, Any] = {
3437
**dimensions_properties,
3538
**context.properties,
36-
"_aws": {
39+
}
40+
if not config.disable_metric_extraction:
41+
body["_aws"] = {
3742
**context.meta,
3843
"CloudWatchMetrics": [
3944
{
@@ -42,11 +47,12 @@ def create_body() -> Dict[str, Any]:
4247
"Namespace": context.namespace,
4348
},
4449
],
45-
},
46-
}
50+
}
51+
return body
4752

4853
current_body: Dict[str, Any] = create_body()
4954
event_batches: List[str] = []
55+
num_metrics_in_current_body = 0
5056

5157
for metric_name, metric in context.metrics.items():
5258

@@ -55,14 +61,18 @@ def create_body() -> Dict[str, Any]:
5561
else:
5662
current_body[metric_name] = metric.values
5763

58-
current_body["_aws"]["CloudWatchMetrics"][0]["Metrics"].append({"Name": metric_name, "Unit": metric.unit})
64+
if not config.disable_metric_extraction:
65+
current_body["_aws"]["CloudWatchMetrics"][0]["Metrics"].append({"Name": metric_name, "Unit": metric.unit})
66+
67+
num_metrics_in_current_body += 1
5968

60-
should_serialize: bool = len(current_body["_aws"]["CloudWatchMetrics"][0]["Metrics"]) == MAX_METRICS_PER_EVENT
69+
should_serialize: bool = num_metrics_in_current_body == MAX_METRICS_PER_EVENT
6170
if should_serialize:
6271
event_batches.append(json.dumps(current_body))
6372
current_body = create_body()
73+
num_metrics_in_current_body = 0
6474

65-
if not event_batches or current_body["_aws"]["CloudWatchMetrics"][0]["Metrics"]:
75+
if not event_batches or num_metrics_in_current_body > 0:
6676
event_batches.append(json.dumps(current_body))
6777

6878
return event_batches

tests/config/test_config.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def test_can_get_config_from_environment(monkeypatch):
2323
agent_endpoint = fake.word()
2424
ec2_metadata_endpoint = fake.word()
2525
namespace = fake.word()
26+
disable_metric_extraction = True
2627

2728
monkeypatch.setenv("AWS_EMF_ENABLE_DEBUG_LOGGING", str(debug_enabled))
2829
monkeypatch.setenv("AWS_EMF_SERVICE_NAME", service_name)
@@ -32,6 +33,7 @@ def test_can_get_config_from_environment(monkeypatch):
3233
monkeypatch.setenv("AWS_EMF_AGENT_ENDPOINT", agent_endpoint)
3334
monkeypatch.setenv("AWS_EMF_EC2_METADATA_ENDPOINT", ec2_metadata_endpoint)
3435
monkeypatch.setenv("AWS_EMF_NAMESPACE", namespace)
36+
monkeypatch.setenv("AWS_EMF_DISABLE_METRIC_EXTRACTION", str(disable_metric_extraction))
3537

3638
# act
3739
result = get_config()
@@ -45,6 +47,7 @@ def test_can_get_config_from_environment(monkeypatch):
4547
assert result.agent_endpoint == agent_endpoint
4648
assert result.ec2_metadata_endpoint == ec2_metadata_endpoint
4749
assert result.namespace == namespace
50+
assert result.disable_metric_extraction == disable_metric_extraction
4851

4952

5053
def test_can_override_config(monkeypatch):
@@ -57,6 +60,7 @@ def test_can_override_config(monkeypatch):
5760
monkeypatch.setenv("AWS_EMF_AGENT_ENDPOINT", fake.word())
5861
monkeypatch.setenv("AWS_EMF_EC2_METADATA_ENDPOINT", fake.word())
5962
monkeypatch.setenv("AWS_EMF_NAMESPACE", fake.word())
63+
monkeypatch.setenv("AWS_EMF_DISABLE_METRIC_EXTRACTION", str(True))
6064

6165
config = get_config()
6266

@@ -68,6 +72,7 @@ def test_can_override_config(monkeypatch):
6872
agent_endpoint = fake.word()
6973
ec2_metadata_endpoint = fake.word()
7074
namespace = fake.word()
75+
disable_metric_extraction = False
7176

7277
# act
7378
config.debug_logging_enabled = debug_enabled
@@ -78,6 +83,7 @@ def test_can_override_config(monkeypatch):
7883
config.agent_endpoint = agent_endpoint
7984
config.ec2_metadata_endpoint = ec2_metadata_endpoint
8085
config.namespace = namespace
86+
config.disable_metric_extraction = disable_metric_extraction
8187

8288
# assert
8389
assert config.debug_logging_enabled == debug_enabled
@@ -88,3 +94,4 @@ def test_can_override_config(monkeypatch):
8894
assert config.agent_endpoint == agent_endpoint
8995
assert config.ec2_metadata_endpoint == ec2_metadata_endpoint
9096
assert config.namespace == namespace
97+
assert config.disable_metric_extraction == disable_metric_extraction

tests/serializer/test_log_serializer.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from aws_embedded_metrics.config import get_config
12
from aws_embedded_metrics.logger.metrics_context import MetricsContext
23
from aws_embedded_metrics.serializers.log_serializer import LogSerializer
34
from faker import Faker
@@ -177,6 +178,27 @@ def test_serialize_metrics_with_multiple_datapoints():
177178
assert results == [json.dumps(expected)]
178179

179180

181+
def test_serialize_metrics_with_aggregation_disabled():
182+
"""Test log records don't contain metadata when aggregation is disabled."""
183+
# arrange
184+
config = get_config()
185+
config.disable_metric_extraction = True
186+
187+
expected_key = fake.word()
188+
expected_value = fake.random.randrange(0, 100)
189+
190+
expected = {expected_key: expected_value}
191+
192+
context = get_context()
193+
context.put_metric(expected_key, expected_value)
194+
195+
# act
196+
result_json = serializer.serialize(context)[0]
197+
198+
# assert
199+
assert_json_equality(result_json, expected)
200+
201+
180202
# Test utility method
181203

182204

tests/sinks/test_lambda_sink.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from importlib import reload
2+
3+
from aws_embedded_metrics import config
14
from aws_embedded_metrics.sinks.lambda_sink import LambdaSink
25
from aws_embedded_metrics.logger.metrics_context import MetricsContext
36
from faker import Faker
@@ -9,6 +12,8 @@
912

1013
def test_accept_writes_to_stdout(capfd):
1114
# arrange
15+
reload(config)
16+
1217
sink = LambdaSink()
1318
context = MetricsContext.empty()
1419
context.meta["Timestamp"] = 1

0 commit comments

Comments
 (0)