Skip to content

decode_prometheus: decode summary and histogram instances without _sum - #316

Open
chrisburr wants to merge 5 commits into
fluent:masterfrom
chrisburr:decode-prometheus-instances-without-sum
Open

chrisburr wants to merge 5 commits into
fluent:masterfrom
chrisburr:decode-prometheus-instances-without-sum

Conversation

@chrisburr

@chrisburr chrisburr commented Nov 9, 2026 •

Copy link
Copy Markdown

This PR fixes an issue I found when using Fluent Bit to scrape Prometheus metrics exposed in Jenkins. With:

Below is the LLM generated description for this fix based on the guidelines in the repo:

🤖 _sum is optional for summaries and histograms (OpenMetrics), and Prometheus accepts payloads without it. Summaries exported from Dropwizard timers, e.g. by the Jenkins Prometheus plugin (jenkins_node_builds{node="..."}), only have quantiles and _count:

# TYPE jenkins_node_builds summary
jenkins_node_builds{node="a",quantile="0.5",} 11
jenkins_node_builds{node="a",quantile="0.999",} 12
jenkins_node_builds_count{node="a",} 1
jenkins_node_builds{node="b",quantile="0.5",} 21
jenkins_node_builds{node="b",quantile="0.999",} 22
jenkins_node_builds_count{node="b",} 2
  • A new instance was only detected once both _sum and _count had been seen. Without _sum, the quantiles of the second instance were added to the first one with the _count sample type, and decoding failed with "not enough samples for summary". That drops the whole scrape, as seen with Fluent Bit 5.1.3 prometheus_scrape. A quantile or bucket that follows a _sum or _count now starts a new instance.
  • Histogram buckets were counted as "samples − 3", assuming _sum and _count are present. Without _sum, the last finite bucket was taken as +Inf, or bucket creation failed. Buckets are now counted, as security: harden decoders, encoders and cat against malformed input #308 did for summary quantiles. A histogram without _count was only rejected because of that arithmetic; it is now rejected explicitly ("missing histogram _count") instead of being decoded with a count of zero.
  • Separate commit for a bug already on master, found in review: _count was written to the bucket slot at the current index, assuming it comes after all buckets. When _count comes first (_sum, _count, then buckets, as in the .NET output of Prometheus Scrape not able to parse endpoint fluent-bit#6534), the first finite bucket overwrote it and the +Inf bucket was decoded as 0. The +Inf sample's own value is now used, and _count only sets the count. The expected output of the existing issue_fluent_bit_6534 test had every +Inf bucket at 0 while _count was 321733, 759, 133, 8 and 618; those five lines now match the input.

Regression tests cover summary and histogram families with several instances and no _sum, a histogram without _count, and histograms with _count before the buckets (with and without _sum).

Compatibility: a summary instance whose quantiles come after its own _sum/_count is now split into two instances. Prometheus client libraries write the quantiles first, and the previous code already split there once both _sum and _count had been seen. Instances without _sum are still encoded with _sum 0, as before. Histograms without _count stay rejected, as on master, but now with an explicit error.

Validation: scripts/agent-verify.sh passes (25/25). Valgrind and ASan are clean for the summary and histogram tests; UBSan reports a misaligned load in the bundled xxhash in label_limits, which also happens on master. A real Jenkins payload (2,395 samples) decodes with every sample identical. Commit b5e2486 alone fails issue_fluent_bit_6534 until the next commit updates its expected +Inf values, which keeps fixes and tests in separate commits.

A new instance of a summary or histogram was only detected once both
_sum and _count of the previous instance had been seen. _sum is optional:
summaries exported from Dropwizard timers, e.g. by the Jenkins Prometheus
plugin, only have quantiles and _count. For a family with several label
sets, the quantiles of the second instance were added to the first one
with the _count sample type, and the decoding failed with "not enough
samples for summary", dropping the whole payload.

Also start a new instance when a quantile follows a _sum or _count line,
and when a bucket follows the _sum or _count of an instance with buckets.

Signed-off-by: Chris Burr <christopher.burr@cern.ch>
@chrisburr
chrisburr requested a review from edsiper as a code owner November 9, 2026 11:08
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-09T11:24:31.118002Z aee043c PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aee043c29c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +467 to +468
if (sample->type == CMT_DECODE_PROMETHEUS_CONTEXT_SAMPLE_TYPE_BUCKET) {
bucket_count++;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve +Inf when _count precedes sum-less buckets

When a valid sum-less histogram emits _count before its buckets (an ordering already represented by tests/data/issue_6534.txt), this new bucket-only sizing accepts it but silently corrupts the implicit bucket. For h_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 +Inf sample leaves the final slot at zero, so re-encoding reports _count 2 but +Inf 0. 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 👍 / 👎.

Copy link
Copy Markdown
Author

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.

Comment on lines +471 to +475
if (bucket_count < 2) {
return report_error(context,
CMT_DECODE_PROMETHEUS_SYNTAX_ERROR,
"not enough buckets for histogram");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject histograms that omit _count

When _count is absent but the input has a finite bucket, +Inf, and _sum, this guard now passes because it checks only the number of bucket samples. The later loop skips the +Inf value, and with no COUNT sample both the implicit bucket and histogram count remain zero, so the decoder succeeds and silently changes the exposed total; the parent implementation rejected this three-sample case. Require count_found (or derive and validate count from +Inf) before constructing the histogram.

AGENTS.md reference: AGENTS.md:L101-L106

Useful? React with 👍 / 👎.

@chrisburr chrisburr Nov 9, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 43b176e, test in 9d7a151.

The number of buckets of a histogram was computed as the number of
samples minus 3, assuming that the "+Inf" bucket, _sum and _count are
all present. Without _sum, which is optional, it was one too low: the
last finite bucket was taken as the "+Inf" one, and a histogram with a
single finite bucket failed with "cmt_histogram_buckets_create_size
failed".

Count the bucket samples instead, as is already done for summary
quantiles, and report a syntax error when there are less than two.

A histogram without _count was only rejected because of that sample
arithmetic. Reject it explicitly, otherwise it would now be decoded
with a count of zero.

Signed-off-by: Chris Burr <christopher.burr@cern.ch>
Decode a summary family with several instances that have quantiles and
_count but no _sum, as exported for Dropwizard timers by the Jenkins
Prometheus plugin, and the same for a histogram family. Check that a
histogram without _count is still rejected.

Signed-off-by: Chris Burr <christopher.burr@cern.ch>
The value of _count was written to the bucket slot at the current bucket
index, assuming that it follows all the buckets of the instance. When
_count comes before the buckets, as in the .NET exporter output of Fluent
Bit issue 6534 (_sum, _count, then the buckets), that slot was
overwritten by the first finite bucket, the "+Inf" sample was skipped,
and the "+Inf" bucket was decoded as zero while _count kept its value.

Store the value of the "+Inf" bucket sample in its own slot, and only
use _count for the histogram count.

Signed-off-by: Chris Burr <christopher.burr@cern.ch>
Decode histograms whose _count is written before the buckets, with and
without _sum, and check the "+Inf" bucket values. The expected output of
the fluent-bit issue 6534 test had every "+Inf" bucket at zero, which
was the decoding error itself: they now match the input and _count.

Signed-off-by: Chris Burr <christopher.burr@cern.ch>
@chrisburr
chrisburr force-pushed the decode-prometheus-instances-without-sum branch from aee043c to 20269b5 Compare November 9, 2026 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant