Skip to content

ExplicitBucketHistogramAggregation silently accepts unsorted boundaries, producing wrong bucket assignments #5338

Description

@RudraDudhat2509

What happened

I was exploring the metrics SDK and found that ExplicitBucketHistogramAggregation accepts unsorted boundary lists without any validation or warning. Internally, aggregate() calls bisect_left(self._boundaries, value) which requires sorted input when boundaries are unsorted, measurements land in the wrong buckets silently.

Reproducer

from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import InMemoryMetricReader
from opentelemetry.sdk.metrics.view import View
from opentelemetry.sdk.metrics._internal.aggregation import ExplicitBucketHistogramAggregation

reader = InMemoryMetricReader()
provider = MeterProvider(
    metric_readers=[reader],
    views=[View(
        instrument_name="latency",
        aggregation=ExplicitBucketHistogramAggregation(boundaries=[100, 10, 50]),  # unsorted
    )]
)
meter = provider.get_meter("test")
hist = meter.create_histogram("latency")
hist.record(25)
hist.record(75)
hist.record(150)

data = reader.get_metrics_data()
pt = data.resource_metrics[0].scope_metrics[0].metrics[0].data.data_points[0]
print("bounds:", pt.explicit_bounds)  # (100, 10, 50)
print("counts:", pt.bucket_counts)    # (0, 0, 1, 2)  <-- wrong, 2/3 values misplaced
# with sorted [10, 50, 100] the correct output is (0, 1, 1, 1)

Root cause

aggregation.py#L478-L511 stores boundaries as-is and passes them directly to bisect_left, which assumes sorted input. No validation happens anywhere in the chain.

How other SDKs handle it

Proposed fix

A 2-3 line check in ExplicitBucketHistogramAggregation.__init__ that validates boundaries are strictly increasing. Happy to open a PR if this looks good.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions