Skip to content

record_min_max=False exports histogram min=+Infinity and max=-Infinity - #5571

Open
dwin-gharibi wants to merge 2 commits into
open-telemetry:mainfrom
dwin-gharibi:fix/histogram-record-min-max-unset
Open

record_min_max=False exports histogram min=+Infinity and max=-Infinity#5571
dwin-gharibi wants to merge 2 commits into
open-telemetry:mainfrom
dwin-gharibi:fix/histogram-record-min-max-unset

Conversation

@dwin-gharibi

Copy link
Copy Markdown

Closes #5570.

Description

Both histogram aggregations seed _min/_max with math.inf and -math.inf and never consult self._record_min_max in collect(). With min/max recording disabled the sentinels are handed straight to the data point, and the OTLP encoder sets both optional fields as present - so a backend receives a histogram whose minimum is +Infinity and maximum is -Infinity.

to_json has the same problem and emits the bare literals Infinity and -Infinity, which are not valid JSON.

Root cause

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py. _ExplicitBucketHistogramAggregation.collect reads self._min/self._max at lines 498-499 and _ExponentialBucketHistogramAggregation.collect at lines 767-768, neither guarded by self._record_min_max. The delta-to-cumulative merge at lines 542 and 927 then folds the sentinels into _previous_min/_previous_max, so they persist across collections.

Approach

Read None instead of the sentinel when record_min_max is disabled, in both aggregations and in both cumulative merge branches. Widen HistogramDataPoint.min/max and ExponentialHistogramDataPoint.min/max to float | None.

No encoder change is needed: protobuf treats None as "field not set", which is exactly the intended wire representation.

Files changed

  • opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py
  • opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py
  • opentelemetry-sdk/tests/metrics/test_histogram_record_min_max.py
  • .changelog/5566.fixed

Testing

A dedicated module drives both aggregations through a real reader and asserts the SDK fields are None, the OTLP fields report HasField(...) == False, and to_json survives a strict RFC 8259 parser that rejects Infinity.

The delta-to-cumulative merge gets its own test across two collections, since that is where the sentinels were being carried forward, and DELTA temporality is covered separately.

A second class pins the record_min_max=True path - values recorded, cumulative min/max spanning collections, OTLP fields present - so the fix cannot silently disable the default behaviour.

Nine of the sixteen fail before the change.

Result: 863 passed in opentelemetry-sdk, 20 passed in opentelemetry-exporter-otlp-proto-common.

Risk / compatibility

HistogramDataPoint.min/max may now be None. Anything reading them unconditionally would previously have received inf/-inf in this configuration, which was already unusable, so no correct consumer regresses. The default record_min_max=True path is untouched.

The aggregators seed min/max with +inf/-inf. Assert those sentinels never
reach a data point when record_min_max is disabled: the SDK fields are None,
the OTLP fields are absent, to_json stays valid JSON, and the
delta-to-cumulative merge does not resurrect them.

Both histogram aggregations and both temporalities are covered, along with
the record_min_max=True path to guard against over-correcting.

These tests fail against the current implementation.
Both histogram aggregations seed _min/_max with +inf/-inf and never consulted
record_min_max in collect(). With min/max recording disabled the sentinels
reached the data point, and the OTLP encoder set both optional fields as
present -- so backends received a histogram with min=+Infinity and
max=-Infinity, violating the min <= max invariant. to_json emitted the bare
literals Infinity and -Infinity, which are not valid JSON.

Report None instead, in both aggregations and in both delta-to-cumulative
merge branches, and widen the data point fields to float | None. Protobuf
treats None as "field not set", so no encoder change is required.
Copilot AI lite review requested due to automatic review settings August 23, 2026 16:19
@dwin-gharibi
dwin-gharibi requested a review from a team as a code owner August 23, 2026 16:19

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@opentelemetry-pr-dashboard

Copy link
Copy Markdown

Pull request dashboard status

Waiting on reviewers · refreshed 2026-08-23 16:19 UTC

Review the latest changes.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

record_min_max=False exports histogram min=+Infinity and max=-Infinity

2 participants