Skip to content

Add Prometheus translation strategy support#8346

Open
zeitlinger wants to merge 20 commits into
open-telemetry:mainfrom
zeitlinger:codex/prometheus-translation-strategy
Open

Add Prometheus translation strategy support#8346
zeitlinger wants to merge 20 commits into
open-telemetry:mainfrom
zeitlinger:codex/prometheus-translation-strategy

Conversation

@zeitlinger

@zeitlinger zeitlinger commented Apr 29, 2026

Copy link
Copy Markdown
Member

Summary

  • add TranslationStrategy support to the Prometheus exporter builder and declarative config
  • upgrade Prometheus client_java to 1.6.1, which provides the released naming support this needs
  • preserve existing content negotiation behavior, while enabling non-default strategies to use OM2 name-preservation semantics
  • align underscore-escaping label-name normalization with the OTel Prometheus compatibility rules / prometheus/otlptranslator behavior for invalid characters, repeated underscores, and digit-leading labels
  • keep OTLP-to-Prometheus naming translation owned by the OTel exporter instead of relying on Prometheus Java naming helpers

Notes

  • For non-default translation strategies, this intentionally uses only OM2 name-preservation semantics.
  • No other OM2 features are enabled.
  • Content negotiation remains unchanged, so OpenMetrics responses still use the legacy OM1 content type by design.
  • The behavior change from the new Prometheus release is that metric names can now be passed through as-is for the relevant strategies.
  • prometheus/otlptranslator preserves labels normalized to __...__; Prometheus Java rejects user labels starting with __, so those labels are collapsed to a valid single-underscore form instead.
  • Prometheus Java is still used for the metrics model and exposition, but it only validates and serializes names here; it does not own the OTLP naming mangling.

References

Test plan

  • ./gradlew :exporters:prometheus:test --tests io.opentelemetry.exporter.prometheus.PrometheusHttpServerTest.fetchOpenMetrics --tests io.opentelemetry.exporter.prometheus.PrometheusHttpServerTest.fetchOpenMetrics_translationStrategyEnablesOm2 --tests io.opentelemetry.exporter.prometheus.PrometheusMetricReaderTest --tests io.opentelemetry.exporter.prometheus.Otel2PrometheusConverterTest --tests io.opentelemetry.exporter.prometheus.internal.PrometheusMetricReaderProviderTest :sdk-extensions:declarative-config:test --tests io.opentelemetry.sdk.autoconfigure.declarativeconfig.MetricReaderFactoryTest.create_PullPrometheusConfigured

Resolves #8195

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@codecov

codecov Bot commented Apr 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.85714% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.65%. Comparing base (327f564) to head (9e61219).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
.../exporter/prometheus/Otel2PrometheusConverter.java 90.56% 4 Missing and 6 partials ⚠️
...try/exporter/prometheus/PrometheusUnitsHelper.java 84.61% 3 Missing and 3 partials ⚠️

❌ Your project check has failed because the head coverage (78.36%) is below the target coverage (89.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@              Coverage Diff              @@
##               main    #8346       +/-   ##
=============================================
- Coverage     91.04%   78.65%   -12.39%     
- Complexity     7822     8567      +745     
=============================================
  Files           893     1009      +116     
  Lines         23721    28993     +5272     
  Branches       2364     3599     +1235     
=============================================
+ Hits          21596    22805     +1209     
- Misses         1407     5342     +3935     
- Partials        718      846      +128     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@zeitlinger zeitlinger marked this pull request as ready for review April 29, 2026 12:36
@zeitlinger zeitlinger requested a review from a team as a code owner April 29, 2026 12:36

@psx95 psx95 left a comment

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.

Also might wanna look at this relevant spec issue: open-telemetry/opentelemetry-specification#5062

@github-actions github-actions Bot mentioned this pull request May 4, 2026
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>

@jack-berg jack-berg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small comments and ideas. Thanks!

@github-actions github-actions Bot mentioned this pull request May 7, 2026
@zeitlinger zeitlinger marked this pull request as draft May 8, 2026 06:54
- Replace IllegalArgumentException control flow in PrometheusUnitsHelper.sanitizeUnitName with @nullable return; drop the try/catch in unitOrNull.
- Extract doConvert helper so convert is just the IAE try/catch boundary.
- Inline the getMergeKey ternary at the putOrMerge call site.
- Reorder convertMetadataEscapedWithSuffixes for readability and use the explicit 5-arg MetricMetadata constructor.

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Also bumps protobuf-bom 4.34.1 -> 4.35.0 to match the gencode shipped
inside prometheus-metrics-exposition-formats 1.7.0 (runtime must be
>= gencode version).
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@jaydeluca jaydeluca self-requested a review June 9, 2026 18:35
zeitlinger added a commit to prometheus/client_java that referenced this pull request Jun 10, 2026
## Summary

- Adds `MetricMetadata.builder()` with `name`, `help`, `unit`,
`counterSuffix` fields
- Builder appends unit to the base name when absent, and appends
`_total` to `expositionBaseName` when `counterSuffix=true`
- Deprecates the 4-arg and 5-arg constructors; internal callers
(`MetricMetadataSupport`, `MetricMetadata.escape`) suppress the warning
- Updates `docs/apidiffs/current_vs_latest/prometheus-metrics-model.txt`

## Motivation

The OTel exporter
([opentelemetry/opentelemetry-java#8346](open-telemetry/opentelemetry-java#8346))
needs to express per-strategy counter intent without pre-computing
`expositionBaseName` manually. The builder encapsulates that logic and
provides a cleaner public API for any downstream adapter that constructs
`MetricMetadata` directly.

## Test plan

- [ ] `MetricMetadataTest` — 8 new builder tests covering: no unit, unit
absent/present, counter suffix, counter + unit, UTF-8 name, non-counter,
name-required validation
- [ ] Existing 4-arg/5-arg constructor tests annotated with
`@SuppressWarnings("deprecation")`

---------

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@zeitlinger

Copy link
Copy Markdown
Member Author

Will undraft once the new prom client release has been published.

@zeitlinger

Copy link
Copy Markdown
Member Author

@psx95 please have another look

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
…slation-strategy

# Conflicts:
#	dependencyManagement/build.gradle.kts
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@zeitlinger zeitlinger marked this pull request as ready for review June 11, 2026 12:59

@psx95 psx95 left a comment

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.

Thanks for following up on the updated spec issue, @zeitlinger !

Overall changes LGTM, I just left a couple of small suggestions and mostly verified the translation logic by looking at the tests.

…n tests

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@zeitlinger zeitlinger requested a review from psx95 June 12, 2026 10:13

@psx95 psx95 left a comment

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.

Thanks for addressing the feedback!

@jack-berg jack-berg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed. Two more small nits, but still looks good.

String name = sanitizeMetricName(prometheusName(metricData.getName()));
private static String convertLegacyMetricName(String name) {
if (name.isEmpty()) {
return name;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This returns while convertLegacyLabelName throws for the same case. Should be consistent.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to have a test to show UNDERSCORE_ESCAPING_WITHOUT_SUFFIXES + allow-utf-8

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@zeitlinger

Copy link
Copy Markdown
Member Author

@jack-berg done

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Prometheus translation_strategy configuration

4 participants