Repository navigation
decode_prometheus: decode summary and histogram instances without _sum #316
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
base: master
Are you sure you want to change the base?
Changes from all commits
b430977
43b176e
9d7a151
b5e2486
20269b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -433,6 +433,7 @@ static int add_metric_histogram(struct cmt_decode_prometheus_context *context) | |
| int ret = 0; | ||
| int i; | ||
| int has_le = CMT_FALSE; | ||
| int has_count = CMT_FALSE; | ||
| size_t bucket_count; | ||
| size_t bucket_index; | ||
| size_t label_count = 0; | ||
|
|
@@ -458,11 +459,23 @@ static int add_metric_histogram(struct cmt_decode_prometheus_context *context) | |
| "not enough samples for histogram"); | ||
| } | ||
|
|
||
| /* bucket_count = sample count - 3: | ||
| * - "Inf" bucket | ||
| * - sum | ||
| * - count */ | ||
| bucket_count = cfl_list_size(&context->metric.samples) - 3; | ||
| /* bucket_count = number of bucket samples without the "+Inf" one. Count | ||
| * them instead of assuming that sum and count are present, _sum is | ||
| * optional */ | ||
| bucket_count = 0; | ||
| cfl_list_foreach(head, &context->metric.samples) { | ||
| sample = cfl_list_entry(head, struct cmt_decode_prometheus_context_sample, _head); | ||
| if (sample->type == CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_BUCKET) { | ||
| bucket_count++; | ||
| } | ||
| } | ||
| if (bucket_count < 2) { | ||
| return report_error(context, | ||
| CMT_DECODE_PROMETHEUS_SYNTAX_ERROR, | ||
| "not enough buckets for histogram"); | ||
| } | ||
|
Comment on lines
+472
to
+476
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.
When AGENTS.md reference: AGENTS.md:L101-L106 Useful? React with 👍 / 👎.
Author
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. |
||
| bucket_count--; | ||
|
|
||
| if (context->opts.override_timestamp) { | ||
| timestamp = context->opts.override_timestamp; | ||
| } | ||
|
|
@@ -530,23 +543,26 @@ static int add_metric_histogram(struct cmt_decode_prometheus_context *context) | |
| sample = cfl_list_entry(head, struct cmt_decode_prometheus_context_sample, _head); | ||
| switch (sample->type) { | ||
| case CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_BUCKET: | ||
| if (bucket_index == bucket_count) { | ||
| /* probably last bucket, which has "Inf" */ | ||
| if (bucket_index > bucket_count) { | ||
| break; | ||
| } | ||
| if (!sample->label_values[le_label_index] || | ||
| sample->label_values[le_label_index][0] == '\0') { | ||
| ret = report_error(context, | ||
| CMT_DECODE_PROMETHEUS_SYNTAX_ERROR, | ||
| "missing histogram bucket \"le\" value"); | ||
| goto end; | ||
| } | ||
| if (parse_double(sample->label_values[le_label_index], | ||
| buckets + bucket_index)) { | ||
| ret = report_error(context, | ||
| CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, | ||
| "failed to parse bucket"); | ||
| goto end; | ||
| /* the last bucket is "+Inf": it has no boundary to parse and | ||
| * its value goes to the extra slot of bucket_defaults */ | ||
| if (bucket_index < bucket_count) { | ||
| if (!sample->label_values[le_label_index] || | ||
| sample->label_values[le_label_index][0] == '\0') { | ||
| ret = report_error(context, | ||
| CMT_DECODE_PROMETHEUS_SYNTAX_ERROR, | ||
| "missing histogram bucket \"le\" value"); | ||
| goto end; | ||
| } | ||
| if (parse_double(sample->label_values[le_label_index], | ||
| buckets + bucket_index)) { | ||
| ret = report_error(context, | ||
| CMT_DECODE_PROMETHEUS_CMT_CREATE_ERROR, | ||
| "failed to parse bucket"); | ||
| goto end; | ||
| } | ||
| } | ||
| if (parse_uint64(sample->value1, | ||
| bucket_defaults + bucket_index)) { | ||
|
|
@@ -604,7 +620,7 @@ static int add_metric_histogram(struct cmt_decode_prometheus_context *context) | |
| count = (uint64_t)count_dbl; | ||
| } | ||
| } | ||
| bucket_defaults[bucket_index] = count; | ||
| has_count = CMT_TRUE; | ||
|
|
||
| if (!timestamp) { | ||
| ret = parse_timestamp(context, sample->value2, ×tamp); | ||
|
|
@@ -618,6 +634,13 @@ static int add_metric_histogram(struct cmt_decode_prometheus_context *context) | |
| } | ||
| } | ||
|
|
||
| if (!has_count) { | ||
| ret = report_error(context, | ||
| CMT_DECODE_PROMETHEUS_SYNTAX_ERROR, | ||
| "missing histogram _count"); | ||
| goto end; | ||
| } | ||
|
|
||
| if (!timestamp) { | ||
| /* No timestamp was specified, use default value */ | ||
| timestamp = context->opts.default_timestamp; | ||
|
|
@@ -1043,9 +1066,11 @@ static int parse_histogram_summary_name( | |
| } | ||
|
|
||
| if (name_matched) { | ||
| if (sum_found && count_found) { | ||
| if ((sum_found && count_found) || is_previous_sum_or_count) { | ||
| /* finish instance of the summary/histogram, the samples of the | ||
| * next instance using the base name are quantiles */ | ||
| * next instance using the base name are quantiles. _sum is | ||
| * optional (e.g. summaries of Dropwizard timers), so a quantile | ||
| * following a _sum or _count also starts a new instance */ | ||
| return finish_duplicate_histogram_summary_sum_count( | ||
| context, | ||
| metric_name, | ||
|
|
@@ -1060,8 +1085,9 @@ static int parse_histogram_summary_name( | |
|
|
||
| /* invalid histogram/summary suffix, treat it as a different metric */ | ||
| if (!strcmp(metric_name + parsed_name_len, "_bucket")) { | ||
| if (sum_found && count_found && has_buckets && is_previous_sum_or_count) { | ||
| /* already found both sum and count, so this is a new metric */ | ||
| if (has_buckets && is_previous_sum_or_count) { | ||
| /* a bucket following the _sum or _count of an instance with | ||
| * buckets starts a new instance, _sum being optional */ | ||
| return finish_duplicate_histogram_summary_sum_count( | ||
| context, | ||
| metric_name, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a valid sum-less histogram emits
_countbefore its buckets (an ordering already represented bytests/data/issue_6534.txt), this new bucket-only sizing accepts it but silently corrupts the implicit bucket. Forh_count 2,h_bucket{le="1"} 1,h_bucket{le="+Inf"} 2, the COUNT branch first writes slot 0, the finite bucket overwrites it, and the skipped+Infsample leaves the final slot at zero, so re-encoding reports_count2 but+Inf0. Store the parsed count in the final bucket after the scan rather than at the current bucket index.AGENTS.md reference: AGENTS.md:L101-L104
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a pre-existing bug but I've fixed it in b5e2486.