Skip to content

Commit a93ed25

Browse files
fix(metrics): preserve default_tags when metric-specific tag is set in Datadog provider (#2997)
* fix(metrics): Fix precedence problem when using default_tags and metric tags * fix(metrics): Adding dependency * fix(metrics): wording
1 parent 659bcc5 commit a93ed25

File tree

4 files changed

+115
-70
lines changed

4 files changed

+115
-70
lines changed

aws_lambda_powertools/metrics/provider/datadog/datadog.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,11 @@ def _serialize_datadog_tags(metric_tags: Dict[str, Any], default_tags: Dict[str,
327327
>>> serialize_datadog_tags(metric_tags, None)
328328
['environment:production', 'service:web']
329329
"""
330-
tags = metric_tags or default_tags
330+
331+
# We need to create a new dictionary by combining default_tags first,
332+
# and then metric_tags on top of it. This ensures that the keys from metric_tags take precedence
333+
# and replace corresponding keys in default_tags.
334+
tags = {**default_tags, **metric_tags}
331335

332336
return [f"{tag_key}:{tag_value}" for tag_key, tag_value in tags.items()]
333337

poetry.lock

+69-69
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ fastjsonschema = { version = "^2.14.5", optional = true }
3434
pydantic = { version = "^1.8.2", optional = true }
3535
boto3 = { version = "^1.20.32", optional = true }
3636
typing-extensions = "^4.6.2"
37+
datadog-lambda = { version = "^4.77.0", optional = true }
3738

3839
[tool.poetry.dev-dependencies]
3940
coverage = {extras = ["toml"], version = "^7.2"}

tests/functional/metrics/test_metrics_datadog.py

+40
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,46 @@ def lambda_handler(evt, ctx):
240240
assert "environment" in second_invocation
241241

242242

243+
def test_log_metrics_precedence_metrics_tags_over_default_tags(capsys):
244+
# GIVEN DatadogMetrics is initialized and we persist a set of default tags
245+
my_metrics = DatadogMetrics(flush_to_log=True)
246+
default_tags = {"environment": "test", "log_group": "/lambda/test"}
247+
248+
# WHEN we use log_metrics with default_tags to serialize
249+
# and create metrics with a tag that has the same name as one of the default_tags
250+
@my_metrics.log_metrics(default_tags=default_tags)
251+
def lambda_handler(evt, ctx):
252+
my_metrics.add_metric(name="item_sold", value=1, environment="metric_precedence")
253+
254+
lambda_handler({}, {})
255+
output = json.loads(capsys.readouterr().out.strip())
256+
257+
# THEN tag defined in add_metric must have preference over default_tags
258+
assert "environment:metric_precedence" in output["t"]
259+
assert "environment:test" not in output["t"]
260+
261+
262+
def test_log_metrics_merge_metrics_tags_and_default_tags(capsys):
263+
# GIVEN DatadogMetrics is initialized and we persist a set of default tags
264+
my_metrics = DatadogMetrics(flush_to_log=True)
265+
default_tags = {"environment": "test", "log_group": "/lambda/test"}
266+
267+
# WHEN we use log_metrics with default_tags to serialize
268+
# and create metrics with a tag that has the same name as one of the default_tags
269+
@my_metrics.log_metrics(default_tags=default_tags)
270+
def lambda_handler(evt, ctx):
271+
my_metrics.add_metric(name="item_sold", value=1, product="powertools")
272+
273+
lambda_handler({}, {})
274+
output = json.loads(capsys.readouterr().out.strip())
275+
276+
# THEN there should be serialized default_tags and metric tags
277+
output["e"] = ""
278+
assert output == json.loads(
279+
'{"m":"item_sold","v":1,"e":"","t":["environment:test","log_group:/lambda/test", "product:powertools"]}',
280+
)
281+
282+
243283
def test_clear_default_tags():
244284
# GIVEN DatadogMetrics is initialized and we persist a set of default tags
245285
my_metrics = DatadogMetrics()

0 commit comments

Comments
 (0)