Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#4862](https://github.com/open-telemetry/opentelemetry-python/pull/4862))
- `opentelemetry-exporter-otlp-proto-http`: fix retry logic and error handling for connection failures in trace, metric, and log exporters
([#4709](https://github.com/open-telemetry/opentelemetry-python/pull/4709))
- `opentelemetry-exporter-prometheus`: Fix metric name prefix
([#4895](https://github.com/open-telemetry/opentelemetry-python/pull/4895))

## Version 1.39.0/0.60b0 (2025-12-03)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
start_http_server(port=8000, addr="localhost")
# Exporter to export metrics to Prometheus
prefix = "MyAppPrefix"
reader = PrometheusMetricReader(prefix)
reader = PrometheusMetricReader(prefix=prefix)
# Meter is responsible for creating and recording metrics
set_meter_provider(MeterProvider(metric_readers=[reader]))
meter = get_meter_provider().get_meter("view-name-change", "0.1.2")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

# Exporter to export metrics to Prometheus
prefix = "MyAppPrefix"
reader = PrometheusMetricReader(prefix)
reader = PrometheusMetricReader(prefix=prefix)

# Meter is responsible for creating and recording metrics
set_meter_provider(MeterProvider(metric_readers=[reader]))
Expand Down Expand Up @@ -131,7 +131,7 @@ def _convert_buckets(
class PrometheusMetricReader(MetricReader):
"""Prometheus metric exporter for OpenTelemetry."""

def __init__(self, disable_target_info: bool = False) -> None:
def __init__(self, disable_target_info: bool = False, prefix: str = "") -> None:
super().__init__(
preferred_temporality={
Counter: AggregationTemporality.CUMULATIVE,
Expand All @@ -142,9 +142,10 @@ def __init__(self, disable_target_info: bool = False) -> None:
ObservableGauge: AggregationTemporality.CUMULATIVE,
}
)
self._collector = _CustomCollector(disable_target_info)
self._collector = _CustomCollector(disable_target_info=disable_target_info, prefix=prefix)
REGISTRY.register(self._collector)
self._collector._callback = self.collect
self._prefix = prefix

def _receive_metrics(
self,
Expand All @@ -167,11 +168,12 @@ class _CustomCollector:
https://github.com/prometheus/client_python#custom-collectors
"""

def __init__(self, disable_target_info: bool = False):
def __init__(self, disable_target_info: bool = False, prefix: str = ""):
self._callback = None
self._metrics_datas: Deque[MetricsData] = deque()
self._disable_target_info = disable_target_info
self._target_info = None
self._prefix = prefix

def add_metrics_data(self, metrics_data: MetricsData) -> None:
"""Add metrics to Prometheus data"""
Expand Down Expand Up @@ -227,7 +229,10 @@ def _translate_to_prometheus(
label_values_data_points = []
values = []

metric_name = sanitize_full_name(metric.name)
metric_name = metric.name
if self._prefix:
metric_name = self._prefix + "_" + metric_name
metric_name = sanitize_full_name(metric_name)
metric_description = metric.description or ""
metric_unit = map_unit(metric.unit)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def setUp(self):
)

def verify_text_format(
self, metric: Metric, expect_prometheus_text: str
self, metric: Metric, expect_prometheus_text: str, prefix: str = ""
) -> None:
metrics_data = MetricsData(
resource_metrics=[
Expand All @@ -73,7 +73,7 @@ def verify_text_format(
]
)

collector = _CustomCollector(disable_target_info=True)
collector = _CustomCollector(disable_target_info=True, prefix=prefix)
collector.add_metrics_data(metrics_data)
result_bytes = generate_latest(collector)
result = result_bytes.decode("utf-8")
Expand Down Expand Up @@ -463,6 +463,28 @@ def test_metric_name(self):
"""
),
)
self.verify_text_format(
_generate_sum(name="test_counter_w_prefix", value=1, unit=""),
dedent(
"""\
# HELP foo_test_counter_w_prefix_total foo
# TYPE foo_test_counter_w_prefix_total counter
foo_test_counter_w_prefix_total{a="1",b="true"} 1.0
"""
),
prefix="foo"
)
self.verify_text_format(
_generate_sum(name="test_counter_w_invalid_chars_prefix", value=1, unit=""),
dedent(
"""\
# HELP _foo_test_counter_w_invalid_chars_prefix_total foo
# TYPE _foo_test_counter_w_invalid_chars_prefix_total counter
_foo_test_counter_w_invalid_chars_prefix_total{a="1",b="true"} 1.0
"""
),
prefix="#foo"
)
self.verify_text_format(
_generate_sum(name="1leading_digit", value=1, unit=""),
dedent(
Expand Down