Skip to content
Open
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- `opentelemetry-exporter-prometheus`: Add `preferred_aggregation` parameter to `PrometheusMetricReader` to allow configuring default aggregation per instrument kind
([#5117](https://github.com/open-telemetry/opentelemetry-python/pull/5117))
- Fix incorrect code example in `create_tracer()` docstring
([#5072](https://github.com/open-telemetry/opentelemetry-python/issues/5072))
- `opentelemetry-sdk`: add `load_entry_point` shared utility to declarative file configuration for loading plugins via entry points; refactor propagator loading to use it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@
MetricsData,
Sum,
)
from opentelemetry.sdk.metrics.view import (
Aggregation,
)
from opentelemetry.semconv._incubating.attributes.otel_attributes import (
OtelComponentTypeValues,
)
Expand Down Expand Up @@ -135,7 +138,10 @@ class PrometheusMetricReader(MetricReader):
"""Prometheus metric exporter for OpenTelemetry."""

def __init__(
self, disable_target_info: bool = False, prefix: str = ""
self,
disable_target_info: bool = False,
prefix: str = "",
preferred_aggregation: dict[type, Aggregation] | None = None,
) -> None:
super().__init__(
preferred_temporality={
Expand All @@ -146,6 +152,7 @@ def __init__(
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
ObservableGauge: AggregationTemporality.CUMULATIVE,
},
preferred_aggregation=preferred_aggregation,
otel_component_type=OtelComponentTypeValues.PROMETHEUS_HTTP_TEXT_METRIC_EXPORTER,
)
self._collector = _CustomCollector(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
_CustomCollector,
)
from opentelemetry.metrics import NoOpMeterProvider
from opentelemetry.sdk.metrics import Histogram as HistogramInstrument
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import (
AggregationTemporality,
Expand All @@ -38,6 +39,7 @@
ResourceMetrics,
ScopeMetrics,
)
from opentelemetry.sdk.metrics.view import ExplicitBucketHistogramAggregation
from opentelemetry.sdk.resources import Resource
from opentelemetry.test.metrictestutil import (
_generate_gauge,
Expand All @@ -47,6 +49,7 @@
)


# pylint: disable=too-many-public-methods
class TestPrometheusMetricReader(TestCase):
def setUp(self):
self._mock_registry_register = Mock()
Expand Down Expand Up @@ -719,3 +722,30 @@ def test_multiple_data_points_with_different_label_sets(self):
"""
),
)

def test_preferred_aggregation(self):
"""Test that preferred_aggregation parameter is passed to MetricReader."""
custom_aggregation = {
HistogramInstrument: ExplicitBucketHistogramAggregation(
boundaries=[1.0, 5.0, 10.0]
)
}
reader = PrometheusMetricReader(
preferred_aggregation=custom_aggregation
)
provider = MeterProvider(metric_readers=[reader])
meter = provider.get_meter("test")
histogram = meter.create_histogram("test_histogram")
histogram.record(5)
result = list(reader._collector.collect())
self.assertTrue(len(result) > 0)
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.

Can we do some additional verification here to actually verify that the boundaries specified above are respected?

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! Added verification to check that the custom boundaries [1.0, 5.0, 10.0] are present in the Prometheus output. Thanks for the suggestion.

prometheus_metric = result[1]
bucket_bounds = [
sample.labels["le"]
for sample in prometheus_metric.samples
if "le" in sample.labels
]
self.assertIn("1.0", bucket_bounds)
self.assertIn("5.0", bucket_bounds)
self.assertIn("10.0", bucket_bounds)
reader.shutdown()
Loading