feat(metrics): observe PR review queue wait (BLO-30623) - #1572
Conversation
1 similar comment
|
Hey @allyblockcast[bot]! Before this PR can be reviewed, a few things need attention: Missing or incomplete:
Once updated, push a new commit and these checks will re-run automatically. — commitperclip |
|
@ally please review PR #1572 at head 640a1e3 (BLO-30623). This commit was authored on a stale branch and rebased onto current master by hand — a union conflict resolution spliced the new histogram inside an unrelated Gauge definition and dropped a function's closing brace in
Context on the chart being a mirror only ( |
The GitHub review-request delivery counter stops at "durably queued", so a saturated consumer is invisible to it: BLO-20491 found 12 PRs that were received, correctly keyed and correctly queued, then waited 320-584 minutes for a concurrency slot while execution time never moved off 6-16 minutes. Ingest counters read perfectly healthy throughout, because that is exactly what a healthy ingest feeding a starved consumer looks like. Add the missing service-latency signal: - paperclip_pr_review_queue_wait_seconds, a histogram of started_at - created_at observed once at the guarded queued-to-running transition in heartbeatService. Only runs whose context_task_key begins with "pr_review:" are observed, so issue-board runs are excluded; runs that never start are excluded by construction, since the observation hangs off the transition itself. - No repo, PR, agent or delivery labels. The task key that selects the run is deliberately not turned into a label - that is where cardinality would grow without bound. Per-request detail stays in the durable heartbeat_runs.context_task_key and the logs. - PaperclipPrReviewQueueWaitSaturated on p95 > 60m over a rolling 6h window, held 10m, with a runbook link and bounded service/signal labels. Note the chart rule is a mirror only: values.blockcast.yaml keeps prometheusRule.enabled=false because enabling it 403s the whole helm upgrade, and Blockcast's authoritative PrometheusRules are applied from onprem-k8s. Landing the alert in production needs the companion onprem-k8s change; the runbook says so at the point of use. Co-Authored-By: Claude <noreply@anthropic.com>
640a1e3 to
2eca639
Compare
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: 2eca639
Critical Issues (0)
Important Issues (0)
Suggestions (1)
- [native-codex]
server/src/services/heartbeat.ts:19514— add a focused integration/regression test proving that a claimed PR-review run records queue wait using the persistedcontextTaskKeyand that the claim path observes exactly once under concurrent dispatch.
Strengths
- The metric is observed only after the guarded queued-to-running claim, avoiding measurements for never-started runs.
- Labels are intentionally bounded by omitting repository, PR, agent, and delivery identifiers.
- The disabled chart rule and the required authoritative
onprem-k8sfollow-up are documented clearly in the runbook and PR description. - Tests cover valid and invalid timestamps, task-key filtering, bucket output, and label-cardinality protection.
Recommended Action
- No Critical or Important issues found; merge may proceed subject to CI and the documented production alert follow-up.
- Consider adding the claim-path integration coverage in a follow-up.
kkroo
left a comment
There was a problem hiding this comment.
Reran the failed lanes for exact head 2eca6397: General tests (workspaces-a) and verify both pass on rerun. All visible required checks are now green; the earlier failure was a flaky unrelated UI test (CompanyEnvironments.test.tsx:715), and this diff touches no UI files. Ally’s review reports 0 Critical/Important findings; the remaining integration-test suggestion is non-blocking. Good to merge when the repository’s normal merge gate permits.
kkroo
left a comment
There was a problem hiding this comment.
Approved after the exact-head failed-lane rerun: all required checks, including verify, are green. The sole transient failure was the unrelated CompanyEnvironments.test.tsx:715 workspace test; rerun passed. The PR is low-risk metrics/runbook work with no UI changes.
Thinking Path
Linked Issues or Issue Description
heartbeat_runs.queue wait/pr review queue/BLO-30623. Nearest neighbours are fix(dispatch): bound worst-case queue wait for every priority tier (BLO-21792) #1022 (bound worst-case queue wait for every priority tier, merged — changes dispatch behaviour, adds no metric) and fix: yield slots during external waits #1195 (yield slots during external waits, open — also behavioural). Neither instruments queue wait, and no open PR touchespaperclip_pr_review_queue_wait_seconds.What Changed
server/src/services/metrics.ts— addspaperclip_pr_review_queue_wait_seconds, a histogram with buckets[60, 300, 600, 900, 1800, 3600, 7200, 14400, 28800]seconds. ExposescomputePrReviewQueueWaitSeconds(pure, testable) andrecordPrReviewQueueWait(observes). Wired intoensureRegistry's null-check, return object, and__resetMetricsForTestalongside the neighbouring metrics.server/src/services/heartbeat.ts— callsrecordPrReviewQueueWaitat the guarded queued-to-running transition, immediately after theif (!claimed) return nullguard. Placement is the whole design: it observes exactly once per run, and a run that never starts is excluded by construction rather than by a filter that could drift.pr_review:task key selects which runs are observed but is deliberately never promoted to a label — repo and PR number are exactly where cardinality would grow without bound. Per-request detail stays in durableheartbeat_runs.context_task_keyand the logs.deploy/helm/paperclip/templates/prometheusrule.yaml— newpaperclip-pr-review-queuegroup withPaperclipPrReviewQueueWaitSaturated: p95 > 60m over a rolling 6h window, held 10m, carryingrunbook_urland boundedservice/signallabels.deploy/helm/paperclip/values.yaml— parameterises window / hold / threshold / runbook URL rather than hardcoding them in the template.runbooks/pr-review-queue-wait.md— triage PromQL and what to inspect when it fires.Verification
This commit was authored on a branch far behind master and I rebased it by hand, so I re-verified from scratch rather than trusting the pre-rebase result. That mattered: resolving the conflicts as a union spliced the new histogram inside an unrelated Gauge definition and dropped a function's closing brace in
metrics.ts. Both were repaired before the commit.pr_review:*run (3900s), rejection of anissue_board:key, rejection of a never-started run and an unparseable timestamp, bucket emission atle="3600"= 0 /le="7200"= 1 /_count= 1, the exact bucket list, and an assertion that rendered output contains no repo name.for: 10m, and the runbook URL.tsc --noEmit— the error list is identical to pristine master's, modulo a +1 line shift from the added import. Zero new type errors. Both runs report the same 142 pre-existing errors in my sandbox, caused by stale workspace dists there; they are unrelated to this change and reproduce without it.Risks
values.blockcast.yamlkeepsprometheusRule.enabled: false— deliberately, because enabling it 403s the entirehelm upgraderather than just skipping the resource. Blockcast's authoritative PrometheusRules are applied fromBlockcast/onprem-k8s. The metric ships here; the alert needs a companion onprem-k8s change before BLO-30623's deployment AC is met. The runbook states this at the point of use so a reader hitting it at 3am does not assume the alert is live.+Infand be under-resolved.Model Used
Claude Opus 4.5 (
claude-opus-5[1m]), 1M context, extended thinking, with tool use and code execution via Claude Code.Checklist
Fixes: #/Closes #/Refs #OR (b) described the issue in-PR following the relevant issue template🤖 Generated with Claude Code