-
Notifications
You must be signed in to change notification settings - Fork 832
Description
Part of #1942 (full design rationale).
Summary
Today, Counter.Builder strips _total and PrometheusNaming rejects names ending with _total/_info at creation time. Then at exposition time, the format writers append _total back. This conflicts with OM2's principle that metric names should not be modified.
The fix: stop stripping/rejecting at creation time, and let each format writer own its suffix conventions at scrape time.
Key table
The internal name is always exactly what the user provided. Format writers adapt at scrape time.
| User provides | Internal | OM1 | OM2 | OTel legacy | OTel passthrough |
|---|---|---|---|---|---|
Counter("events") |
events |
events_total |
events |
events |
events |
Counter("events_total") |
events_total |
events_total |
events_total |
events |
events_total |
Gauge("connections") |
connections |
connections |
connections |
connections |
connections |
Gauge("events_total") |
events_total |
events_total |
events_total |
events_total |
events_total |
- Rows 1+2 cannot coexist — the registry detects the OM1 collision and rejects the second registration.
- OTel legacy strips
_totalfrom Counters only (type-aware). Gauges keep_total. - OTel passthrough = OM2 = name as provided.
What to change
1. Collision detection in PrometheusRegistry
When registering a metric, compute the names it would produce across all formats (OM1, OM2, OTel). Reject if any collide with an already-registered metric in the same format.
This replaces today's blanket rejection of _total names with precise collision checks:
Gauge("foo_total")+Histogram("foo")→ no collision (OM1:foo_totalvsfoo_count/foo_sum/foo_bucket). Fixes Issue when using @Timed annotation with prometheus-metrics-instrumentation-dropwizard #1321.Gauge("foo_total")+Counter("foo")→ collision in OM1 (foo_totalvsfoo_total). Correctly rejected.
Collision detection must cover all OM1 suffixes: _total (Counter), _info (Info), _bucket/_count/_sum (Histogram/Summary), _created (Counter/Histogram/Summary).
2. Deprecation warnings in builders
When Counter.builder() receives a name ending in _total (or Info with _info), log a deprecation warning. Still strip for now — the warning gives users time to adjust before stripping is removed.
3. Smart-append in OM1/protobuf writers
Change _total appending from "always append" to "append only if not already present." Same for _info. This avoids events_total_total once stripping is removed.
4. Remove stripping + reserved suffixes
- Remove
Counter.stripTotalSuffix()andInfo.stripInfoSuffix() - Remove
_totaland_infofromRESERVED_METRIC_NAME_SUFFIXESinPrometheusNaming validateMetricName()stops rejecting these suffixessanitizeMetricName()stops stripping them
_bucket, _count, _sum, _created remain reserved for now (structurally meaningful in OM1 classic histograms/summaries).
5. OTel exporter: legacy + passthrough modes
Add a feature flag to the OTel exporter:
- Legacy mode (default): strip
_totalfrom Counters + strip unit suffix. This preserves current behavior — no breakage. - Passthrough mode (opt-in): no stripping. Name as provided, same as OM2.
Passthrough becomes the default in the next major release (#1943).
Backward compatibility
Counter.builder().name("events")→ OM1:events_total, OTel:events. Same as today.Counter.builder().name("events_total")→ OM1:events_total(smart-append skips), OTel legacy:events(exporter strips). Same exposed names as today.Gauge("events_total")→ OM1:events_total, OTel:events_total. New capability (previously rejected). No existing app affected.- Dropwizard:
sanitizeMetricName("foo_total")→foo_total(wasfoo). Fixes Issue when using @Timed annotation with prometheus-metrics-instrumentation-dropwizard #1321.
disableSuffixAppending not needed
Suffix behavior is per-format, not a standalone config flag. OM2 config (#1939) should focus on contentNegotiation, compositeValues, exemplarCompliance, nativeHistograms. Suffix handling follows the format automatically.