diff --git a/.changelog/5461.fixed b/.changelog/5461.fixed new file mode 100644 index 0000000000..4c6a5896b6 --- /dev/null +++ b/.changelog/5461.fixed @@ -0,0 +1,2 @@ +Reject views with `ExponentialBucketHistogramAggregation` for asynchronous +instruments instead of silently producing no data 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 7c409430bf..6d8e2efa1b 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 281aae9215..81910752eb 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.