From 9e42847c5ae72b3472488c1a21baaa4b258708b5 Mon Sep 17 00:00:00 2001 From: Eason Chen Date: Sun, 26 Jul 2026 22:20:45 +0800 Subject: [PATCH 1/2] Reject exponential histogram aggregation views for async instruments --- .../_internal/metric_reader_storage.py | 7 +++- .../metrics/test_metric_reader_storage.py | 40 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/metric_reader_storage.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/metric_reader_storage.py index 7c409430bf9..6d8e2efa1ba 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/metric_reader_storage.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/metric_reader_storage.py @@ -17,6 +17,7 @@ Aggregation, AggregationTemporality, ExplicitBucketHistogramAggregation, + ExponentialBucketHistogramAggregation, _DropAggregation, _ExplicitBucketHistogramAggregation, _ExponentialBucketHistogramAggregation, @@ -293,7 +294,11 @@ def _check_view_instrument_compatibility( # pylint: disable=protected-access if isinstance(instrument, Asynchronous) and isinstance( - view._aggregation, ExplicitBucketHistogramAggregation + view._aggregation, + ( + ExplicitBucketHistogramAggregation, + ExponentialBucketHistogramAggregation, + ), ): _logger.warning( "View %s and instrument %s will produce " diff --git a/opentelemetry-sdk/tests/metrics/test_metric_reader_storage.py b/opentelemetry-sdk/tests/metrics/test_metric_reader_storage.py index 281aae92158..81910752eb4 100644 --- a/opentelemetry-sdk/tests/metrics/test_metric_reader_storage.py +++ b/opentelemetry-sdk/tests/metrics/test_metric_reader_storage.py @@ -31,6 +31,7 @@ DefaultAggregation, DropAggregation, ExplicitBucketHistogramAggregation, + ExponentialBucketHistogramAggregation, SumAggregation, View, ) @@ -453,6 +454,45 @@ def test_conflicting_view_configuration(self): _DEFAULT_VIEW, ) + def test_conflicting_view_configuration_exponential_histogram(self): + observable_counter = _ObservableCounter( + "observable_counter", + Mock(), + [Mock()], + unit="unit", + description="description", + ) + metric_reader_storage = MetricReaderStorage( + SdkConfiguration( + exemplar_filter=Mock(), + resource=Mock(), + views=( + View( + instrument_name="observable_counter", + aggregation=ExponentialBucketHistogramAggregation(), + ), + ), + ), + MagicMock( + **{ + "__getitem__.return_value": AggregationTemporality.CUMULATIVE + } + ), + MagicMock(**{"__getitem__.return_value": DefaultAggregation()}), + ) + + with self.assertLogs(level=WARNING): + metric_reader_storage.consume_measurement( + Measurement(1, time_ns(), observable_counter, Context()) + ) + + self.assertIs( + metric_reader_storage._instrument_view_instrument_matches[ + observable_counter + ][0]._view, + _DEFAULT_VIEW, + ) + def test_view_instrument_match_conflict_0(self): # There is a conflict between views and instruments. From 64ab962a77b164ded6da401c88a88b9d0c26b763 Mon Sep 17 00:00:00 2001 From: Eason Chen Date: Sun, 26 Jul 2026 22:31:07 +0800 Subject: [PATCH 2/2] Add changelog --- .changelog/5461.fixed | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/5461.fixed diff --git a/.changelog/5461.fixed b/.changelog/5461.fixed new file mode 100644 index 00000000000..4c6a5896b60 --- /dev/null +++ b/.changelog/5461.fixed @@ -0,0 +1,2 @@ +Reject views with `ExponentialBucketHistogramAggregation` for asynchronous +instruments instead of silently producing no data