Fixes https://github.com/open-telemetry/opentelemetry-go/issues/7039
Fixes https://github.com/open-telemetry/opentelemetry-go/issues/6704
This uses the common prometheus/otlptranslator library to handle name
conversion. It was a little tricky to work around the fact that the
library only lets us configure whether all suffixes are added or not.
But we want to keep supporting WithoutUnit and WithoutCounterSuffixes
for a while longer. Those will eventually be deprecated and replaced
after
https://github.com/open-telemetry/opentelemetry-specification/pull/4533
is released.
We decided to go ahead with the changes despite it being a small
behavioral change when UTF8 is enabled. See:
https://github.com/prometheus/otlptranslator/issues/44 for the
rationale.
This adds a unit test to verify that it properly handles bracketed
units. The test fails on main with:
```
--- FAIL: TestPrometheusExporter (0.01s)
--- FAIL: TestPrometheusExporter/counter_with_bracketed_unit (0.00s)
exporter_test.go:646:
Error Trace: /usr/local/google/home/dashpole/go/src/go.opentelemetry.io/opentelemetry-go/exporters/prometheus/exporter_test.go:646
Error: Received unexpected error:
-# HELP "foo_{spans}_total" a simple counter
-# TYPE "foo_{spans}_total" counter
-{"foo_{spans}_total",A="B",C="D",E="true",F="42",otel_scope_fizz="buzz",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0"} 24.3
-{"foo_{spans}_total",A="D",C="B",E="true",F="42",otel_scope_fizz="buzz",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0"} 5
+# HELP foo_total a simple counter
+# TYPE foo_total counter
+foo_total{A="B",C="D",E="true",F="42",otel_scope_fizz="buzz",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0"} 24.3
+foo_total{A="D",C="B",E="true",F="42",otel_scope_fizz="buzz",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0"} 5
# HELP target_info Target metadata
# TYPE target_info gauge
target_info{"service.name"="prometheus_test","telemetry.sdk.language"="go","telemetry.sdk.name"="opentelemetry","telemetry.sdk.version"="latest"} 1
Test: TestPrometheusExporter/counter_with_bracketed_unit
2025/07/18 15:07:47 internal_logging.go:50: "msg"="Using existing type definition." "error"="instrument type conflict" "instrument"="foo_total" "existing"="COUNTER" "dropped"="GAUGE"
2025/07/18 15:07:47 internal_logging.go:50: "msg"="Using existing type definition." "error"="instrument type conflict" "instrument"="foo_bytes" "existing"="GAUGE" "dropped"="HISTOGRAM"
FAIL
FAIL go.opentelemetry.io/otel/exporters/prometheus 0.054s
FAIL
```
cc @TylerHelmuth @ywwg @ArthurSens
---------
Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
Co-authored-by: Robert Pająk <pellared@hotmail.com>