Skip to content

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

Open
anishmehta24 wants to merge 2 commits into
aws-powertools:developfrom
anishmehta24:fix/metrics-non-finite-values
Open

anishmehta24 wants to merge 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

This branch has not been deployed

No deployments
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