Skip to content

OpenMetrics parser drops native histogram spans with a negative offset #1232

Open

Description

@auraseb

What happens

prometheus_client.openmetrics.parser.text_string_to_metric_families silently drops positive_spans and negative_spans when a span offset is negative. The deltas are still parsed, so the resulting NativeHistogram has pos_spans=None (or neg_spans=None) next to a non empty pos_deltas, which no longer describes the original histogram.

The offset of the first span is the starting bucket index, and it is negative for any bucket whose upper bound is below 1. With schema 0, an observation of 0.3 falls in bucket index -1, so this affects most histograms measured in seconds.

The client's own exposition writes these offsets as is, so its output does not round trip through its own parser.

What should happen

Spans with a negative offset are parsed into BucketSpan objects like any other span.

Minimal repro

from prometheus_client.openmetrics.parser import text_string_to_metric_families

text = """# TYPE nh histogram
nh {count:2,sum:0.7,schema:0,zero_threshold:0.001,zero_count:0,positive_spans:[-2:2],positive_deltas:[1,0]}
# EOF
"""
print(list(text_string_to_metric_families(text))[0].samples[0].native_histogram)

Output:

NativeHistogram(count_value=2, sum_value=0.7, schema=0, zero_threshold=0.001, zero_count=0, pos_spans=None, neg_spans=None, pos_deltas=(1, 0), neg_deltas=None, nh_exemplars=None)

Expected pos_spans=(BucketSpan(offset=-2, length=2),).

Root cause

In _parse_nh_struct in prometheus_client/openmetrics/parser.py the span regex only accepts unsigned offsets:

re_spans = re.compile(r'(positive_spans|negative_spans):\[(\d+:\d+(,\d+:\d+)*)\]')

A list such as [-2:2] does not match, so _compose_spans returns None for it. The deltas regex already allows a leading minus sign.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions