Commit 6bf27ed
Filter Bencher alerts to tracked measures (drop orphaned p90 false positives) (#3829)
## Problem
~99% of recent benchmark "performance-regression" alerts on `main` are
false positives from a single **orphaned server-side Bencher
threshold**.
`p90_latency` (and `p99_latency`) were intentionally dropped from
`track_benchmarks.rb` `THRESHOLDS` as too noisy ("tail noise can't meet
the 1/20 target"). But Bencher thresholds are persistent server-side
objects keyed on (branch, testbed, measure) — removing a measure from
the CLI `--threshold-*` args stops *updating* the threshold, it never
*deletes* it. The p90 metric is still submitted (for the dashboard), so
the orphaned p90 threshold keeps evaluating p90 tail noise and firing
alerts on nearly every run.
These alerts are doubly bad:
- They file a `performance-regression` issue (exit≠0), and
- They are **invisible in the summary table** — the p90 column has no
`:direction`, so it is never flagged 🔴. The filed issue names nothing
actionable (this is the #3782 / #3795 "🔴 only appears in the legend"
symptom).
### Evidence (public Bencher API, project `react-on-rails-t8a9ncxo`)
- 255 most-recent active alerts: **248 p90-latency, 4 rps, 3
p50-latency**.
- `main` branch: **164 active alerts → 162 p90-latency, 2 rps** (98.8%
p90).
- #3782 (`dec4b8c`) filed on exactly two p90 alerts —
`/client_side_hello_world: Core` p90 `24.20 > upper 23.61` and
`/rendered_html: Core` p90 — with no rps/p50/failed_pct alert.
- `main`/`github-actions` carries thresholds for `rps, p50-latency,
p90-latency, p99-latency, failed-pct` — two more than the code manages.
(p99 is dormant: no p99 metric is submitted.)
## Fix
Thread the measures we actually track (`THRESHOLDS` names) into
`BencherReport`. An active alert on any **other** measure is classified
as *filtered* rather than a regression. This reuses #3822's existing
`filtered_alert?` exit-normalization, so a p90-only run no longer writes
a candidate or files an issue. The fix is fully in-repo and makes the
orphaned threshold harmless regardless of its server-side state.
- Tracked measures (`rps`, `p50_latency`, `failed_pct`) are unaffected —
including the "hidden" `failed_pct` regressions #3822 added coverage
for.
- Measure-less and benchmark-less alerts keep their existing fail-safe
(still counted).
- `tracked_measures` defaults to `nil` (track every measure) so
non-production callers (`BenchmarkTable`, specs) are unchanged.
## Validation
- `bundle exec rspec benchmarks/spec` — **234 examples, 0 failures** (5
new specs for tracked-measure filtering).
- `bundle exec rubocop benchmarks/...` — no offenses.
- **End-to-end against the real #3782 reports** (fetched from the
Bencher API): `regression?` flips `true → false` (`filtered_alert? =
true`) for both the Core and Pro p90 alerts, while rps/p50 alerts are
untouched.
- `script/ci-changes-detector origin/main` → Benchmark scripts → Lint
(Ruby + JS).
## Companion cleanup (separate, manual — not in this PR)
This neutralizes the orphaned threshold in code. To also stop it
polluting the Bencher dashboard (162 cosmetic active alerts) and being
cloned to every new branch, delete the server-side thresholds (needs
`BENCHER_API_TOKEN`):
- `main` p90 `51fb6a47-0083-4e84-a745-60ee42e3bba4`, p99
`6faa7a68-1835-4cd7-96dc-959220737172`
- `master` p90 `d4ad2066-74cb-41f7-93bb-f0885358c56c`, p99
`61bf5ae6-77fa-474f-b6d8-ded630bd0c20`
## Relationship to other work
Completes the noise fix that #3810 (fresh-runner confirmation) and #3822
(stale-alert filtering) started: #3822 only filters alerts whose metric
*recovered*; a **live** p90 crossing (the dominant case) still passed
through. Substantially removes the p90 tail noise behind #3169 and the
issue explosion researched in #3755.
Refs #3755, #3169, #3795
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes which Bencher alerts count as regressions and can affect
main-push candidate filing and CI exit behavior, though scoped to
benchmark reporting with explicit specs and a nil default for other
callers.
>
> **Overview**
> Adds optional **`tracked_measures`** to `BencherReport.parse` /
`#initialize` so active Bencher alerts on measures the repo no longer
tracks (e.g. orphaned server-side **p90_latency** thresholds) are moved
to **`filtered_alert?`** instead of **`regression?`**, reusing the
existing exit-code normalization for filtered-only runs.
>
> **`track_benchmarks.rb`** now passes `THRESHOLDS.map(&:first)` when
parsing the JSON report, so p90-only false positives no longer write
regression candidates or file issues the summary table cannot flag.
Tracked measures, measure-less fail-safe alerts, and callers that omit
`tracked_measures` stay backward compatible.
>
> Specs cover orphaned p90 filtering, slug/name normalization, and a
small fix for `BencherReport.new` with a Hash root in a perf-links test.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
7693f64. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Bug Fixes**
* Fixed false regression alerts for measures no longer tracked in
performance benchmarks. The system now filters regression reports to
only flag alerts for actively monitored metrics, preventing issue
creation based on orphaned or retired threshold measurements that are no
longer part of the current tracking configuration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 20e1f3d commit 6bf27ed
3 files changed
Lines changed: 96 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
77 | | - | |
78 | | - | |
| 77 | + | |
| 78 | + | |
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
84 | 90 | | |
85 | 91 | | |
| 92 | + | |
86 | 93 | | |
87 | 94 | | |
88 | 95 | | |
| |||
190 | 197 | | |
191 | 198 | | |
192 | 199 | | |
| 200 | + | |
193 | 201 | | |
194 | 202 | | |
195 | 203 | | |
| |||
212 | 220 | | |
213 | 221 | | |
214 | 222 | | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
215 | 233 | | |
216 | 234 | | |
217 | 235 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
207 | 207 | | |
208 | 208 | | |
209 | 209 | | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
210 | 278 | | |
211 | 279 | | |
212 | 280 | | |
| |||
422 | 490 | | |
423 | 491 | | |
424 | 492 | | |
425 | | - | |
| 493 | + | |
426 | 494 | | |
427 | 495 | | |
428 | 496 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
178 | 178 | | |
179 | 179 | | |
180 | 180 | | |
181 | | - | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
182 | 186 | | |
183 | 187 | | |
184 | 188 | | |
| |||
0 commit comments