Skip to content

Commit 3c70e2a

Browse files
committed
Merge branch 'main' of https://github.com/open-telemetry/opentelemetry-python into metrics-reader-metrics
2 parents ce30ee6 + 1b7d55b commit 3c70e2a

4 files changed

Lines changed: 43 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
([#4970](https://github.com/open-telemetry/opentelemetry-python/pull/4970))
2525
- `opentelemetry-sdk`: upgrade vendored OTel configuration schema from v1.0.0-rc.3 to v1.0.0
2626
([#4965](https://github.com/open-telemetry/opentelemetry-python/pull/4965))
27+
- `opentelemetry-exporter-prometheus`: Fix metric name prefix
28+
([#4895](https://github.com/open-telemetry/opentelemetry-python/pull/4895))
2729

2830
## Version 1.40.0/0.61b0 (2026-03-04)
2931

docs/examples/metrics/prometheus-grafana/prometheus-monitor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
start_http_server(port=8000, addr="localhost")
1212
# Exporter to export metrics to Prometheus
1313
prefix = "MyAppPrefix"
14-
reader = PrometheusMetricReader(prefix)
14+
reader = PrometheusMetricReader(prefix=prefix)
1515
# Meter is responsible for creating and recording metrics
1616
set_meter_provider(MeterProvider(metric_readers=[reader]))
1717
meter = get_meter_provider().get_meter("view-name-change", "0.1.2")

exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
3939
# Exporter to export metrics to Prometheus
4040
prefix = "MyAppPrefix"
41-
reader = PrometheusMetricReader(prefix)
41+
reader = PrometheusMetricReader(prefix=prefix)
4242
4343
# Meter is responsible for creating and recording metrics
4444
set_meter_provider(MeterProvider(metric_readers=[reader]))
@@ -134,7 +134,9 @@ def _convert_buckets(
134134
class PrometheusMetricReader(MetricReader):
135135
"""Prometheus metric exporter for OpenTelemetry."""
136136

137-
def __init__(self, disable_target_info: bool = False) -> None:
137+
def __init__(
138+
self, disable_target_info: bool = False, prefix: str = ""
139+
) -> None:
138140
super().__init__(
139141
preferred_temporality={
140142
Counter: AggregationTemporality.CUMULATIVE,
@@ -146,9 +148,12 @@ def __init__(self, disable_target_info: bool = False) -> None:
146148
},
147149
otel_component_type=OtelComponentTypeValues.PROMETHEUS_HTTP_TEXT_METRIC_EXPORTER.value,
148150
)
149-
self._collector = _CustomCollector(disable_target_info)
151+
self._collector = _CustomCollector(
152+
disable_target_info=disable_target_info, prefix=prefix
153+
)
150154
REGISTRY.register(self._collector)
151155
self._collector._callback = self.collect
156+
self._prefix = prefix
152157

153158
def _receive_metrics(
154159
self,
@@ -171,11 +176,12 @@ class _CustomCollector:
171176
https://github.com/prometheus/client_python#custom-collectors
172177
"""
173178

174-
def __init__(self, disable_target_info: bool = False):
179+
def __init__(self, disable_target_info: bool = False, prefix: str = ""):
175180
self._callback = None
176181
self._metrics_datas: Deque[MetricsData] = deque()
177182
self._disable_target_info = disable_target_info
178183
self._target_info = None
184+
self._prefix = prefix
179185

180186
def add_metrics_data(self, metrics_data: MetricsData) -> None:
181187
"""Add metrics to Prometheus data"""
@@ -231,7 +237,10 @@ def _translate_to_prometheus(
231237
label_values_data_points = []
232238
values = []
233239

234-
metric_name = sanitize_full_name(metric.name)
240+
metric_name = metric.name
241+
if self._prefix:
242+
metric_name = self._prefix + "_" + metric_name
243+
metric_name = sanitize_full_name(metric_name)
235244
metric_description = metric.description or ""
236245
metric_unit = map_unit(metric.unit)
237246

exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def setUp(self):
5656
)
5757

5858
def verify_text_format(
59-
self, metric: Metric, expect_prometheus_text: str
59+
self, metric: Metric, expect_prometheus_text: str, prefix: str = ""
6060
) -> None:
6161
metrics_data = MetricsData(
6262
resource_metrics=[
@@ -74,7 +74,7 @@ def verify_text_format(
7474
]
7575
)
7676

77-
collector = _CustomCollector(disable_target_info=True)
77+
collector = _CustomCollector(disable_target_info=True, prefix=prefix)
7878
collector.add_metrics_data(metrics_data)
7979
result_bytes = generate_latest(collector)
8080
result = result_bytes.decode("utf-8")
@@ -466,6 +466,30 @@ def test_metric_name(self):
466466
"""
467467
),
468468
)
469+
self.verify_text_format(
470+
_generate_sum(name="test_counter_w_prefix", value=1, unit=""),
471+
dedent(
472+
"""\
473+
# HELP foo_test_counter_w_prefix_total foo
474+
# TYPE foo_test_counter_w_prefix_total counter
475+
foo_test_counter_w_prefix_total{a="1",b="true"} 1.0
476+
"""
477+
),
478+
prefix="foo",
479+
)
480+
self.verify_text_format(
481+
_generate_sum(
482+
name="test_counter_w_invalid_chars_prefix", value=1, unit=""
483+
),
484+
dedent(
485+
"""\
486+
# HELP _foo_test_counter_w_invalid_chars_prefix_total foo
487+
# TYPE _foo_test_counter_w_invalid_chars_prefix_total counter
488+
_foo_test_counter_w_invalid_chars_prefix_total{a="1",b="true"} 1.0
489+
"""
490+
),
491+
prefix="#foo",
492+
)
469493
self.verify_text_format(
470494
_generate_sum(name="1leading_digit", value=1, unit=""),
471495
dedent(

0 commit comments

Comments
 (0)