Skip to content

feat(metrics): export latency as bucketed histograms, not summaries - #179

Merged
beinan merged 1 commit into
lance-format:mainfrom
beinan:feat/metrics-latency-histograms
Jul 24, 2026
Merged

feat(metrics): export latency as bucketed histograms, not summaries#179
beinan merged 1 commit into
lance-format:mainfrom
beinan:feat/metrics-latency-histograms

Conversation

@beinan

@beinan beinan commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Addresses the metrics issue: lance-context-metrics installs the Prometheus recorder with no bucket config, so metrics-exporter-prometheus 0.16 renders every histogram!() as a rolling summary (quantile series + monotonic _sum/_count) instead of a bucketed histogram (_bucket{le="..."}).

Verified against the exporter source (distribution.rs::get_distribution): with no buckets/overrides it falls through to Distribution::new_summary(...), confirming the issue's core claim. Summary quantiles use an opaque, slow-decaying window — a p99 stays pinned at an old spike long after latency recovers, and consumers can't recompute a quantile over an arbitrary window.

Change

Configure explicit buckets so all *_duration_seconds metrics export as true histograms, enabling query-time histogram_quantile(0.99, rate(..._bucket[5m])):

  • Suffix("_duration_seconds") → request-scale buckets (5ms…60s): covers http_request_duration_seconds, master_scan_duration_seconds.
  • Full(...) overrides → job-scale buckets (…1800s) for master_task_duration_seconds and rollout_compaction_duration_seconds. These jobs (compaction / WAL merge / index) routinely exceed 60s; the issue's proposed single 60s-max bucket set would dump every long job into +Inf and pin high percentiles. A Full matcher outranks the Suffix matcher (exporter precedence Full > Prefix > Suffix), so the override wins for these two names while everything else uses the request set.

Counters (http_requests_total, master_task_enqueued_total, …) are unaffected — this only concerns histogram!-emitted metrics.

Test plan

  • cargo test -p lance-context-metrics — extended the render test to assert # TYPE ... histogram, _bucket{le="..."} series (both the request le="1" and the job-scale le="300"), and the absence of {quantile="..."} summary series.
  • cargo fmt --check + cargo clippy --all-targets clean.

🤖 Generated with Claude Code

With no bucket configuration, metrics-exporter-prometheus 0.16 renders
every histogram!() as a rolling summary (quantile series + monotonic
_sum/_count) rather than a bucketed Prometheus histogram. That makes
latency hard to reason about operationally: _sum/_count give a
since-process-start average that never decays, and the exporter's summary
quantiles use an opaque slow-decaying window, so a p99 stays pinned at an
old spike long after latency recovers and can't be recomputed over an
arbitrary window at query time.

Configure explicit buckets so all *_duration_seconds metrics export as
true histograms (_bucket{le="..."}), letting downstream compute
histogram_quantile() over any window:
- Suffix("_duration_seconds") -> request-scale buckets (5ms..60s), covering
  http_request_duration_seconds and master_scan_duration_seconds.
- Full-name overrides for the job-scale metrics master_task_duration_seconds
  and rollout_compaction_duration_seconds -> coarser buckets extending to
  1800s. A Full matcher outranks the Suffix matcher (exporter precedence is
  Full > Prefix > Suffix), so minute-plus jobs don't collapse into +Inf and
  distort high percentiles.

Counters are unaffected. Extends the metrics test to assert histogram TYPE
+ _bucket series and the absence of summary quantiles.

Co-Authored-By: Claude <noreply@anthropic.com>
@beinan
beinan merged commit 788d460 into lance-format:main Jul 24, 2026
9 checks passed
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