You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
OpenMetrics content negotiation: escaping=underscores causes name mismatch between HELP/TYPE metadata and sample lines for metrics with colons #1177
When exposing metrics in the OpenMetrics format using content negotiation (via Accept: application/openmetrics-text; version=1.0.0), metrics containing colons (:) have their names escaped in the sample lines but remain unescaped in the # HELP and # TYPE lines.
This produces mismatched exposition output that violates the OpenMetrics standard, causing strict standard parsers (including promtool check metrics and downstream ingesters) to fail or treat them as completely separate metrics (an orphaned metadata set and an untyped metric).
Steps to Reproduce
Create a simple Python server using prometheus_client:
Notice that the Content-Type is negotiated with escaping=underscores, but the comment lines mismatch the sample line:
HTTP/1.0 200 OKContent-Type: application/openmetrics-text; version=1.0.0; charset=utf-8; escaping=underscores# HELP sglang:token_usage Total token usage.# TYPE sglang:token_usage gaugesglang_token_usage 42.0# EOF
Expected Output
The metric name inside the # HELP and # TYPE comment blocks should match the name used in the sample line:
# HELP sglang_token_usage Total token usage.# TYPE sglang_token_usage gaugesglang_token_usage 42.0# EOF
Root Cause
In prometheus_client/openmetrics/exposition.py:
The comment generator uses the unescaped metric.name directly (since a colon is treated as legacy-valid under default validation checks).
The sample line generator, however, strictly sanitizes the sample's name against the narrower OpenMetrics name requirements, replacing the colon with an underscore under escaping=underscores.
A regression test should assert the metadata and sample identifiers together, not only the sample line, for each negotiated escaping scheme. In particular, using one escaped-name helper for HELP, TYPE, and samples would prevent the three paths from drifting again. Including the returned Content-Type parameters in the assertion would also confirm that the encoder behavior matches the negotiated escaping=underscores contract.
Activity
hiSandog commentedon Jul 15, 2026
A regression test should assert the metadata and sample identifiers together, not only the sample line, for each negotiated escaping scheme. In particular, using one escaped-name helper for
HELP,TYPE, and samples would prevent the three paths from drifting again. Including the returnedContent-Typeparameters in the assertion would also confirm that the encoder behavior matches the negotiatedescaping=underscorescontract.