Skip to content

feat: move suffix handling to scrape time#1955

Merged
zeitlinger merged 2 commits intomainfrom
scrape-time-suffix-core
Mar 20, 2026
Merged

feat: move suffix handling to scrape time#1955
zeitlinger merged 2 commits intomainfrom
scrape-time-suffix-core

Conversation

@zeitlinger
Copy link
Member

@zeitlinger zeitlinger commented Mar 17, 2026

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)
  • 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)
  • 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
Counter("events") events_total
Counter("events_total") events_total
Counter("req").unit(BYTES) req_bytes_total
Counter("req_bytes").unit(BYTES) req_bytes_total
Gauge("events_total") events_total

PR stack

  1. This PR — core model + OM1/protobuf writers
  2. OTel preserve_names (stacked on this)
  3. OM2 writer no-suffix (stacked on this)

Test plan

  • mise run compile passes
  • New tests for MetricMetadata 5-arg constructor and
    field accessors
  • New PrometheusRegistryTest covers collision detection
  • Existing snapshot tests updated

Part of #1912.

@jaydeluca
Copy link
Collaborator

jaydeluca commented Mar 17, 2026

i accidentally commented on this one because it has a lot of the same changes as #1956 , is this separate?

edit: just noticed the "blocked by" on the other PR, so I guess i did them out of order

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)
- 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)
- 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>
@zeitlinger zeitlinger force-pushed the scrape-time-suffix-core branch from e63ef43 to 0787661 Compare March 18, 2026 08:03
@zeitlinger
Copy link
Member Author

i accidentally commented on this one because it has a lot of the same changes as #1956 , is this separate?

edit: just noticed the "blocked by" on the other PR, so I guess i did them out of order

no worries - I'll apply the feedback to the correct pr

- Fix race condition: use putIfAbsent for atomic exposition name claiming
  with proper rollback on failure
- Extract claimExpositionNames/releaseExpositionNames for single rollback path
- Rename Info test methods to reflect that _info suffix is now allowed
Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
@zeitlinger
Copy link
Member Author

i accidentally commented on this one because it has a lot of the same changes as #1956 , is this separate?
edit: just noticed the "blocked by" on the other PR, so I guess i did them out of order

no worries - I'll apply the feedback to the correct pr

did that now

@zeitlinger zeitlinger merged commit 5a5106c into main Mar 20, 2026
16 of 17 checks passed
@zeitlinger zeitlinger deleted the scrape-time-suffix-core branch March 20, 2026 09:36
zeitlinger added a commit that referenced this pull request Mar 20, 2026
## Summary

Adds `preserve_names` configuration to the OpenTelemetry exporter.
When enabled, metric names are passed through exactly as the user
wrote them instead of stripping `_total` and unit suffixes.
Part of #1942.

### Key changes

- Add `preserve_names` to `ExporterOpenTelemetryProperties`
- `MetricDataFactory` uses `originalName` + `preserve_names` to
  decide naming
- `OtelAutoConfig` wires the new property

### Key table

| User provides | OTel | OTel preserve_names |
|---|---|---|
| `Counter("events")` | `events` | `events` |
| `Counter("events_total")` | `events` | `events_total` |
| `Counter("req").unit(BYTES)` | name `req`, unit `By` | name `req`,
unit `By` |
| `Counter("req_bytes").unit(BYTES)` | name `req`, unit `By` | name
`req_bytes`, unit `By` |
| `Gauge("events_total")` | `events_total` | `events_total` |

### PR stack

1. Core model + OM1/protobuf writers (#1955)
2. **This PR** — OTel `preserve_names`
3. OM2 writer no-suffix (independent)

## Test plan

- [x] `mise run compile` passes
- [x] Tests for `preserve_names=true` with units, unit already in
  name, and without unit
- [x] `OtelAutoConfigTest` covers new property wiring

Part of #1912.

---------

Signed-off-by: Gregor Zeitlinger <gregor.zeitlinger@grafana.com>
zeitlinger added a commit that referenced this pull request Mar 20, 2026
## Summary

The OM2 writer now uses `expositionBaseName` directly instead of
appending `_total` (counters) or unit suffixes. The `_info` suffix
is enforced per the OM2 spec (MUST). Part of #1942.

### Key table

| User provides | OM1 | OM2 |
|---|---|---|
| `Counter("events")` | `events_total` | `events` |
| `Counter("events_total")` | `events_total` | `events_total` |
| `Counter("req").unit(BYTES)` | `req_bytes_total` | `req_bytes` |
| `Counter("req_bytes").unit(BYTES)` | `req_bytes_total` | `req_bytes` |
| `Gauge("events_total")` | `events_total` | `events_total` |
| `Info("target")` | `target_info` | `target_info` |

### PR stack

1. Core model + OM1/protobuf writers (#1955)
2. OTel `preserve_names` (independent)
3. **This PR** — OM2 writer no-suffix

## Test plan

- [x] `mise run compile` passes
- [x] OM2-specific tests verify no `_total`/unit suffix appending
- [x] `_info` suffix enforcement tested

Part of #1912.

---------

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.

Move suffix handling from creation time to scrape time (current release)

2 participants