Skip to content

fix(metrics): skip non-finite metric values with a warning - #8797

Merged
leandrodamascena merged 2 commits into
aws-powertools:developfrom
anishmehta24:fix/metrics-non-finite-values
Nov 15, 2026
Merged

leandrodamascena merged 2 commits into
aws-powertools:developfrom
anishmehta24:fix/metrics-non-finite-values

Conversation

@anishmehta24

@anishmehta24 anishmehta24 commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Issue number: closes #8796

Summary

Changes

add_metric in both AmazonCloudWatchEMFProvider and MetricManager (used by single_metric) now checks math.isfinite(value) after the unit and resolution checks, so a bad unit still raises as before. A NaN or infinite value is skipped with a PowertoolsUserWarning, per the discussion in the issue.

single_metric doesn't flush when its only value was skipped. Otherwise the empty metric set would raise SchemaValidationError: Must contain at least one metric., where today it raises nothing.

It also no longer prints a null line when the with body raises. 3.40.0 does that too, but this block is rewritten here anyway (suggested in review).

Added a docs note under "Creating metrics" and the regenerated agent skill reference for it (I left out the unrelated layer version bump the script also picked up).

User experience

Before: metrics.add_metric(name="Latency", unit=MetricUnit.Milliseconds, value=float("nan")) writes a bare NaN into the EMF line, so CloudWatch drops every metric in that flush without an error. After: a warning names the metric, it's left out, and the rest of the flush is published.

One thing to check: with raise_on_empty_metrics=True, a flush where every value was skipped now raises SchemaValidationError, like any empty flush. Happy to change that if you'd rather it didn't.

Verification

Added test_add_metric_with_non_finite_value (nan, inf, -inf, parses the output with parse_constant so a bare constant fails) and test_single_metric_with_non_finite_value in tests/functional/metrics/required_dependencies/test_metrics_cloudwatch_emf.py. Also added test_single_metric_body_raises. All 5 fail on develop and pass with the fix. pytest tests/unit/metrics tests/functional/metrics on Python 3.12: 170 passed, 1 failed (test_datadog_write_to_log_with_env_variable, which fails the same way on develop when run with the rest of the folder and passes alone). ruff format, ruff check and mypy are clean apart from time.tzset in a logger example, which mypy flags on Windows. I didn't send the output to CloudWatch.

I used an AI assistant (Claude Code) for this change.


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.

@anishmehta24
anishmehta24 requested a review from a team as a code owner November 10, 2026 22:56
@anishmehta24
anishmehta24 requested a review from svozza November 10, 2026 22:56
@boring-cyborg boring-cyborg Bot added documentation Improvements or additions to documentation metrics tests labels Nov 10, 2026
@powertools-for-aws-oss-automation powertools-for-aws-oss-automation Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Nov 10, 2026

@blacksoxx blacksoxx left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment: one P3 inline on the rewritten finally in single_metric; the skip itself reads right. The isfinite check sits before the float(value) conversion that already raised for out-of-range ints and signalling-NaN decimals, so it adds no new failure mode. I did not assess the raise_on_empty_metrics=True question in the description; that is the maintainers' call.

Comment thread aws_lambda_powertools/metrics/base.py Outdated
metric_set = metric.serialize_metric_set()
finally:
print(json.dumps(metric_set, separators=(",", ":")))
if publish:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] publish only turns false on the normal exit path. When the with body raises, metric_set is still None and this prints the literal null that 3.40.0 prints today, so one non-EMF line lands on stdout under every exception:

with single_metric(name="x", unit=MetricUnit.Count, value=1, namespace="ns"):
    raise RuntimeError("boom")
# stdout: 'null\n' on aws-lambda-powertools 3.40.0

Pre-existing, not introduced here. Since this block is being rewritten anyway, if publish and metric_set is not None: covers both cases.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 287b8c4: the finally now prints only when a metric set was serialized, so the raising body prints nothing. I dropped publish along the way. test_single_metric_body_raises covers it, and it fails on develop with null.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, checked 287b8c4: the finally now gates on metric_set is not None, so neither the raising body nor the skipped-value path prints anything, and test_single_metric_body_raises pins the empty stdout. Nothing further from my side.

@sonarqubecloud

Copy link
Copy Markdown

@leandrodamascena leandrodamascena left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @anishmehta24, that was quick! Both add_metric paths covered, and I hadn't noticed the null line when the with body raises, good catch. On raise_on_empty_metrics=True with every value skipped, raising is right: the user asked to be told about an empty flush, and this is one. Goes out in 3.41.0, no need to rebase, you'll be in the release notes.

@leandrodamascena leandrodamascena added this to the 3.41.0 milestone Nov 14, 2026
@leandrodamascena
leandrodamascena merged commit 7a54af5 into aws-powertools:develop Nov 15, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation metrics size/M Denotes a PR that changes 30-99 lines, ignoring generated files. tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: a NaN or infinite metric value makes the whole EMF line invalid JSON

3 participants