Skip to content

fix(metrics): widen lean_block_building_time_seconds buckets past 1s - #574

Merged
MegaRedHand merged 4 commits into
mainfrom
metrics/widen-block-building-buckets
Aug 7, 2026
Merged

fix(metrics): widen lean_block_building_time_seconds buckets past 1s#574
MegaRedHand merged 4 commits into
mainfrom
metrics/widen-block-building-buckets

Conversation

@MegaRedHand

Copy link
Copy Markdown
Collaborator

🗒️ Description / Motivation

lean_block_building_time_seconds used the leanMetrics bucket set, whose top finite
bound is 1s. Block builds on our devnets routinely take 2-3s, so in practice every
sample landed in the +Inf bucket.

When a quantile falls in +Inf, histogram_quantile has no finite bucket left to
interpolate in and returns the upper bound of the last finite one. The p99 panel was
reporting a flat 1s line no matter how long builds actually took, so the metric could
not answer the question it exists to answer.

This widens the range to 0.1s - 8s, matching
lean_block_proposal_attestation_build_phase_seconds, whose phases this metric
encloses. The sibling lean_block_building_payload_aggregation_time_seconds already
reaches 4s, so a wider range on the enclosing timer is consistent with what's already
there.

What Changed

  • crates/blockchain/src/metrics.rs — buckets 0.01…10.1, 0.25, 0.5, 0.75, 1, 2, 4, 8,
    plus a comment recording why this deviates from the spec set.
  • docs/metrics.md — updated the Block Production table row and added a note below the
    table explaining the deviation.

Correctness / Behavior Guarantees

No behavior change: this is bucket boundaries on a histogram, nothing on the block
production path.

Tradeoff. Starting at 0.1 drops the 0.01 / 0.025 / 0.05 boundaries.
Attestation-free blocks skip the prover and build in single-digit milliseconds, and
those now all fall into the first bucket. lean_block_proposal_attestation_build_phase_seconds
still resolves that end down to 0.001, and the sub-100ms region isn't the one we need
to watch, so this seemed like the right side to give up.

Cross-client impact: none. Prometheus stores each bucket as an independent series,
so other clients' exposition is untouched, and every boundary that was shared before
(0.1 through 1) is still present here. Divergent bucket sets only corrupt a query
that does sum by (le) across clients; I checked the leanMetrics dashboards, and the
panel for this metric queries per-instance
(rate(..._bucket{network=~, job=~, instance=~})) with no sum by (le), so each
histogram stays internally consistent. rate(_sum)/rate(_count) is unaffected either
way.

This does put us out of step with the leanMetrics spec, which is why both the code and
the docs carry a note: without one, this reads like drift and gets "corrected" back to
a set that can't measure the thing. Worth proposing the wider range upstream so the
other clients get a usable panel too.

Tests Added / Run

No new tests: bucket boundaries have no assertions to make against them.

  • make fmt — clean
  • make lint — clean
  • make test — 30/30 test binaries pass, 0 failures (fork-choice, STF, signature, and
    SSZ spec tests included)

Related Issues / PRs

✅ Verification Checklist

  • Ran make fmt — clean
  • Ran make lint (clippy with -D warnings) — clean
  • Ran make test (cargo test --workspace --profile release-fast) — all passing

The leanMetrics bucket set for this histogram tops out at 1s, but block
builds on our devnets routinely take 2-3s. Every sample therefore landed
in `+Inf`, and `histogram_quantile` had no finite bucket left to
interpolate in, so it returned the upper bound of the last finite bucket.
The panel read as a flat 1s line regardless of how long builds actually
took.

Buckets now span 0.1s to 8s, the same range as
`lean_block_proposal_attestation_build_phase_seconds`, whose phases this
metric encloses. The tradeoff is sub-100ms resolution: attestation-free
blocks skip the prover and build in single-digit milliseconds, and those
now all collapse into the first bucket. The phase histogram still resolves
that end, and it is not the range we need to watch.

This deviates from the leanMetrics spec, so both the histogram and
docs/metrics.md carry a note explaining why, to keep it from being
"corrected" back to a set that cannot measure the thing.

Divergent buckets do not affect other clients: Prometheus stores each
bucket as its own series, and every boundary that was shared before
(0.1 through 1) is still present. The leanMetrics dashboard panel for this
metric queries per-instance rather than `sum by (le)` across clients, so
each histogram stays internally consistent.
@greptile-apps

greptile-apps Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR extends the lean_block_building_time_seconds histogram’s finite range from 1 second to 8 seconds so multi-second block builds produce meaningful quantiles.

  • Replaces the three lowest-duration boundaries with 2, 4, and 8 second boundaries.
  • Documents the intentional leanMetrics specification deviation and its operational rationale.

Confidence Score: 5/5

The PR appears safe to merge with no actionable defects identified.

The implementation and documentation consistently apply the widened histogram range, and no established consumer or contract is broken by the changed boundaries.

Important Files Changed

Filename Overview
crates/blockchain/src/metrics.rs Widens the block-building histogram buckets and records why this metric intentionally differs from the specification.
docs/metrics.md Updates the documented bucket set and clearly explains the intentional deviation.

Reviews (1): Last reviewed commit: "fix(metrics): widen lean_block_building_..." | Re-trigger Greptile

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

🤖 Kimi Code Review

The change is correct and well-justified.

Key observations:

  1. Operational necessity: The new bucket range [0.1, 0.25, 0.5, 0.75, 1.0, 2.0, 4.0, 8.0] in crates/blockchain/src/metrics.rs:469 correctly addresses the saturation issue where builds exceeding 1s collapsed into +Inf, making latency analysis impossible.

  2. Continuity preserved: Retaining the overlapping buckets 0.25, 0.5, 0.75, 1.0 allows for reasonable historical comparison in the sub-second range while extending the upper bound to match the phase-level metric (lean_block_proposal_attestation_build_phase_seconds) that tracks sub-components of this duration.

  3. Documentation consistency: The update to docs/metrics.md accurately reflects the new buckets, and the explanatory note clarifies the intentional deviation from the leanMetrics specification.

  4. Safety: The unwrap() at line 470 is acceptable here—metric registration failure during static initialization is a fatal programming error (name collision or invalid label names), not a recoverable runtime condition.

No security vulnerabilities, memory safety issues, or performance regressions introduced.


Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

🤖 Codex Code Review

  1. Medium: changing the bucket boundaries for lean_block_building_time_seconds is a wire-level Prometheus schema change, not just an internal tuning change. Any existing alerts, recording rules, or Grafana panels that select specific le labels from this histogram (0.01, 0.025, 0.05, etc.) will stop matching after rollout. The code/docs explain the motivation, but I don’t see any compatibility or migration handling in this PR. Either audit and update all downstream consumers, or consider publishing a new metric name if backward compatibility matters. See metrics.rs and metrics.md.

No code-correctness, security, memory-safety, or consensus-layer findings beyond that. This is a metrics-only change, and the rationale for widening the buckets is sound.


Automated review by OpenAI Codex · gpt-5.4 · custom prompt

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

🤖 Claude Code Review

Review: fix(metrics): widen lean_block_building_time_seconds buckets past 1s

This is a clean, minimal, well-justified fix. Summary of what I checked:

  • Correctness of the fix: The old bucket set (0.01…1.0) topped out at 1s while actual block builds take 2-3s, so every sample fell into +Inf and histogram_quantile couldn't interpolate a meaningful p99 — this is a real and correctly diagnosed bug. The new set (0.1, 0.25, 0.5, 0.75, 1, 2, 4, 8) fixes it.
  • Consistency claims verified: I checked crates/blockchain/src/metrics.rs directly — lean_block_building_payload_aggregation_time_seconds does indeed use 0.1, 0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 4.0, and lean_block_proposal_attestation_build_phase_seconds (in docs) goes up to 8. The new range is a superset of the shared boundaries with both siblings, so the PR's claims about consistency hold up.
  • Cross-client impact reasoning: The PR body's argument that Prometheus stores buckets as independent le-labeled series, and that divergent bucket boundaries only break sum by (le) queries across clients (not per-instance queries), is accurate. This is a legitimate, low-risk deviation from the leanMetrics spec, and it's properly flagged with a comment in the code and a note in the docs so it doesn't get silently "corrected" back later.
  • Scope: Purely a bucket-boundary change on a histogram — no code path, business logic, fork choice, attestation, or signature logic is touched. No tests are needed for this (bucket boundaries aren't something you assert against).
  • Tradeoff disclosed: Losing the 0.01/0.025/0.05 low end is called out explicitly, with the rationale that the phase-level histogram (lean_block_proposal_attestation_build_phase_seconds) still covers that resolution. Reasonable.

Minor nit (non-blocking): The docs table's "Supported" column still shows ✅ for this row even though the bucket set now diverges from the leanMetrics spec (the column caption implies conformance to the spec elsewhere in the doc). The added note below the table does clarify this, so it's not misleading in practice — just something to be aware of if a future reader skims only the table.

Overall: approve. The change does exactly what it says, the reasoning is sound and independently verifiable in the surrounding code, and the risk surface is essentially zero.


Automated review by Claude (Anthropic) · sonnet · custom prompt

@MegaRedHand
MegaRedHand merged commit b4a8f78 into main Aug 7, 2026
5 checks passed
@MegaRedHand
MegaRedHand deleted the metrics/widen-block-building-buckets branch August 7, 2026 18:52
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.

2 participants