Skip to content

feat: move suffix handling to scrape time with OTel preserve_names - #1947

Closed
zeitlinger wants to merge 3 commits into
mainfrom
scrape-time-suffix-handling
Closed

feat: move suffix handling to scrape time with OTel preserve_names#1947
zeitlinger wants to merge 3 commits into
mainfrom
scrape-time-suffix-handling

Conversation

@zeitlinger

@zeitlinger zeitlinger commented Mar 14, 2026

Copy link
Copy Markdown
Member

Summary

Moves metric name suffix handling (_total, _info, unit suffixes) from creation time to scrape time. Closes #1941, part of #1942.

  • OM1: smart-appends suffixes (skips if already present)
  • OTel: legacy path strips _total + unit suffix; preserve_names=true passes names through exactly as the user wrote them
  • Registry: detects cross-format name collisions at registration time

Key changes

  • Remove all reserved metric name suffixes from PrometheusNaming
  • Store original user-provided name separately from exposition base name in MetricMetadata (originalName vs expositionBaseName)
  • Add preserve_names config to ExporterOpenTelemetryProperties
  • Smart-append logic in OM1/protobuf writers for _total and _info
  • Two-layer collision detection in PrometheusRegistry (base name + exposition names)

Key table

User provides OM1 OTel OTel preserve
Counter("events") events_total events events
Counter("events_total") events_total events events_total
Counter("req").unit(BYTES) req_bytes_total name req, unit By name req, unit By
Counter("req_bytes").unit(BYTES) req_bytes_total name req, unit By name req_bytes, unit By
Gauge("events_total") events_total events_total events_total

Test plan

  • mise run build passes (formatting, static analysis, checkstyle)
  • mise run test passes (all unit tests)
  • New tests for MetricMetadata 5-arg constructor and field accessors
  • New tests for OTel preserve_names=true with units, with unit already in name, and without unit
  • Existing PrometheusRegistryTest covers collision detection
  • Integration tests (mise run test-all)
  • Acceptance tests (mise run acceptance-test)
The OM2 writer selection previously activated when any feature flag was
set, but there was no way to just enable OM2 without opting into a
specific feature. This adds an explicit `enabled` gate
(io.prometheus.openmetrics2.enabled) as the single control for OM2
writer selection. Feature flags alone no longer activate OM2.

The programmatic `enableOpenMetrics2()` configurator sets enabled=true
implicitly, matching its name.
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
Move metric name suffix handling (_total, _info, unit suffixes) from
creation time to scrape time. Each format writer now owns its suffix
conventions:

- OM1: smart-appends suffixes (skip if already present)
- OTel: legacy path strips _total + unit; preserve_names=true passes
  names through exactly as the user wrote them
- Registry detects cross-format name collisions at registration time

Key changes:
- Remove all reserved metric name suffixes from PrometheusNaming
- Store original user-provided name separately from exposition base
  name in MetricMetadata (originalName vs expositionBaseName)
- Add preserve_names config to ExporterOpenTelemetryProperties
- Smart-append logic in OM1/protobuf writers for _total and _info
- Two-layer collision detection in PrometheusRegistry

Closes #1941
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
The OM2 writer now uses expositionBaseName instead of appending
_total (counters) or unit suffixes. The _info suffix is enforced
per the OM2 spec (MUST). Tests updated to verify OM2-specific
output rather than asserting identity with OM1.
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@zeitlinger
zeitlinger force-pushed the scrape-time-suffix-handling branch from e4a579d to 9ebf25a Compare March 17, 2026 08:48
@zeitlinger
zeitlinger marked this pull request as ready for review March 17, 2026 10:02
@zeitlinger
zeitlinger marked this pull request as draft March 17, 2026 10:10
@zeitlinger

Copy link
Copy Markdown
Member Author

Superseded by the split PRs: #1955 (core + OM1 writers), #1956 (OTel preserve_names), #1957 (OM2 writer no-suffix).

@zeitlinger zeitlinger closed this Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant