-
Notifications
You must be signed in to change notification settings - Fork 830
OM text exposition for NH #1087
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
csmarchbanks
merged 18 commits into
prometheus:master
from
vesari:OM-text-exposition-for-nh
Aug 20, 2025
Merged
Changes from 11 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
1940648
Start implement OM text exposition for nh, add first no obs test
vesari c4d24f9
Correct template for nh sample spans, add test
vesari 928b680
Correct templating and appending for deltas, add longer spans test
vesari 0e54c44
Add tests for nh with labels, remove labels sorting
vesari 00427cc
Break down logic classic vs nh samples, add tests for classic-native …
vesari 28028f7
Move classic sample logic back to where it belongs
vesari bd8072c
Assign nh to value, correct nil values in tests, clean up white spaces
vesari 2fdb24c
Add logic for exposing nh exemplars
vesari 11a6e87
Please linters
vesari b2f5afb
Assign nh_exemplars to exemplarstr
vesari 3103c03
Add Any type to metric_family in OM exposition test
vesari 9f00c9f
Change printing order of nh spans and deltas according to OM 2.0 pro…
vesari 91fa988
Shorten name of spans and deltas as per OM 2.0 proposal
vesari acf7558
Merge remote-tracking branch 'prometheus/master' into OM-text-exposit…
vesari db46de6
Adapt nh with UTF-8 tests to new testing framework
vesari c4a27c4
Update prometheus_client/openmetrics/exposition.py
vesari 2c54330
Update prometheus_client/openmetrics/exposition.py
vesari fad2f60
Eliminate erroneous abbreviation for spans and deltas
vesari File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,29 @@ def _is_valid_exemplar_metric(metric, sample): | |
return False | ||
|
||
|
||
def _compose_exemplar_string(metric, sample, exemplar): | ||
"""Constructs an exemplar string.""" | ||
if not _is_valid_exemplar_metric(metric, sample): | ||
raise ValueError(f"Metric {metric.name} has exemplars, but is not a histogram bucket or counter") | ||
labels = '{{{0}}}'.format(','.join( | ||
['{}="{}"'.format( | ||
k, v.replace('\\', r'\\').replace('\n', r'\n').replace('"', r'\"')) | ||
for k, v in sorted(exemplar.labels.items())])) | ||
if exemplar.timestamp is not None: | ||
exemplarstr = ' # {} {} {}'.format( | ||
labels, | ||
floatToGoString(exemplar.value), | ||
exemplar.timestamp, | ||
) | ||
else: | ||
exemplarstr = ' # {} {}'.format( | ||
labels, | ||
floatToGoString(exemplar.value), | ||
) | ||
|
||
return exemplarstr | ||
|
||
|
||
def generate_latest(registry): | ||
'''Returns the metrics from the registry in latest text format as a string.''' | ||
output = [] | ||
|
@@ -38,7 +61,7 @@ def generate_latest(registry): | |
labelstr += ', ' | ||
else: | ||
labelstr = '' | ||
|
||
if s.labels: | ||
items = sorted(s.labels.items()) | ||
labelstr += ','.join( | ||
|
@@ -47,44 +70,90 @@ def generate_latest(registry): | |
for k, v in items]) | ||
if labelstr: | ||
labelstr = "{" + labelstr + "}" | ||
|
||
if s.exemplar: | ||
if not _is_valid_exemplar_metric(metric, s): | ||
raise ValueError(f"Metric {metric.name} has exemplars, but is not a histogram bucket or counter") | ||
labels = '{{{0}}}'.format(','.join( | ||
['{}="{}"'.format( | ||
k, v.replace('\\', r'\\').replace('\n', r'\n').replace('"', r'\"')) | ||
for k, v in sorted(s.exemplar.labels.items())])) | ||
if s.exemplar.timestamp is not None: | ||
exemplarstr = ' # {} {} {}'.format( | ||
labels, | ||
floatToGoString(s.exemplar.value), | ||
s.exemplar.timestamp, | ||
) | ||
else: | ||
exemplarstr = ' # {} {}'.format( | ||
labels, | ||
floatToGoString(s.exemplar.value), | ||
) | ||
exemplarstr = _compose_exemplar_string(metric, s, s.exemplar) | ||
else: | ||
exemplarstr = '' | ||
|
||
timestamp = '' | ||
if s.timestamp is not None: | ||
timestamp = f' {s.timestamp}' | ||
|
||
native_histogram = '' | ||
positive_spans = '' | ||
positive_deltas = '' | ||
negative_spans = '' | ||
negative_deltas = '' | ||
pos = False | ||
neg = False | ||
|
||
if s.native_histogram: | ||
# Initialize basic nh template | ||
nh_sample_template = '{{count:{},sum:{},schema:{},zero_threshold:{},zero_count:{}' | ||
|
||
args = [ | ||
s.native_histogram.count_value, | ||
s.native_histogram.sum_value, | ||
s.native_histogram.schema, | ||
s.native_histogram.zero_threshold, | ||
s.native_histogram.zero_count, | ||
] | ||
|
||
# If there are pos spans, append them to the template and args | ||
if s.native_histogram.pos_spans: | ||
positive_spans = ','.join([f'{ps[0]}:{ps[1]}' for ps in s.native_histogram.pos_spans]) | ||
positive_deltas = ','.join(f'{pd}' for pd in s.native_histogram.pos_deltas) | ||
nh_sample_template += ',positive_spans:[{}]' | ||
args.append(positive_spans) | ||
|
||
# If there are neg spans exist, append them to the template and args | ||
if s.native_histogram.neg_spans: | ||
negative_spans = ','.join([f'{ns[0]}:{ns[1]}' for ns in s.native_histogram.neg_spans]) | ||
negative_deltas = ','.join(str(nd) for nd in s.native_histogram.neg_deltas) | ||
nh_sample_template += ',negative_spans:[{}]' | ||
args.append(negative_spans) | ||
|
||
# Append pos deltas if pos spans were added | ||
if s.native_histogram.pos_spans: | ||
nh_sample_template += ',positive_deltas:[{}]' | ||
args.append(positive_deltas) | ||
|
||
# Append neg deltas if neg spans were added | ||
if s.native_histogram.neg_spans: | ||
nh_sample_template += ',negative_deltas:[{}]' | ||
args.append(negative_deltas) | ||
|
||
# Add closing brace | ||
nh_sample_template += '}}' | ||
|
||
# Format the template with the args | ||
native_histogram = nh_sample_template.format(*args) | ||
|
||
if s.native_histogram.nh_exemplars: | ||
for nh_ex in s.native_histogram.nh_exemplars: | ||
nh_exemplarstr = _compose_exemplar_string(metric, s, nh_ex) | ||
exemplarstr += nh_exemplarstr | ||
|
||
value = '' | ||
if s.native_histogram: | ||
value = native_histogram | ||
elif s.value is not None: | ||
value = floatToGoString(s.value) | ||
if _is_valid_legacy_metric_name(s.name): | ||
output.append('{}{} {}{}{}\n'.format( | ||
s.name, | ||
labelstr, | ||
floatToGoString(s.value), | ||
value, | ||
timestamp, | ||
exemplarstr, | ||
exemplarstr | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to keep the trailing comma here and below. Helps with future PR conflicts. |
||
)) | ||
else: | ||
output.append('{} {}{}{}\n'.format( | ||
labelstr, | ||
floatToGoString(s.value), | ||
value, | ||
timestamp, | ||
exemplarstr, | ||
exemplarstr | ||
)) | ||
except Exception as exception: | ||
exception.args = (exception.args or ('',)) + (metric,) | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.