fix(multinode): harness debt — queries-e2e ranges, b0/b1 query endpoint, aggregate_report - #396
Merged
Merged
Conversation
…nt, aggregate_report Three orthogonal fixes surfaced by a clean post-#395 all-arms run: 1. queries-e2e.json: change [1m] → [5m] for the three *_over_time entries (quantile_over_time x2, sum_over_time x1). The agent window is 60s, backend tumbling window 30s, multinode soak 90s — a [1m] range fired early in the soak frequently lands between open windows and returns empty. Convention used everywhere else (smoke test, manual probes, #394 wave queries) is [5m]. Leave `quantile by (zone) (...)` alone — no range arg. 2. run_demo.sh::arm_measure: point the b0/b1 PromQL replay endpoint at VictoriaMetrics :8428, not Prometheus :9090. Diagnosis: the harness brings up `asap-victoriametrics` (not Prometheus) on node2 for b0/b1 (see backend_up, line 104–109), and the agents PRW to `http://victoriametrics:8428/api/v1/write`. The query endpoint at :9090 was unreachable — `curl http://10.10.1.3:9090` → connection refused → urllib URLError → `status: timeout` → 100% of 899 attempts failed with http_code=null. Live probe of :8428 against a fresh b0 arm returns 10000 series of http_requests_total and resolves `sum by (zone) (rate(...[5m]))` into 4 zones with real values; a 15s replay yielded 78/138 success (the 60 empties are the 3 *_latency_ms queries — that metric isn't in the b0 workload). 3. New `deploy/mvp-multinode/scripts/aggregate_report.py` to fill the missing script run_demo.sh::all referenced. Pure stdlib, handles the multinode dir shape (per-arm subdir containing replay.jsonl + edge-<node>.csv + stages-<node>.csv). Emits a summary table, per-query success/empty/error breakdown, edge bandwidth and stages aggregates. Idempotent. Failure stays non-fatal (run_demo.sh swallows it). Validation (all-arms run after fixes): Arm Total Success Empty Error asap 413 332 0 81 b0 829 472 357 0 b1 835 476 359 0 - asap wave queries (sum-by-zone, sum-by-zone-rate, topk-of-rate, sum_over_time): 59/59 each → #395 wave-query gate not regressed. - asap [5m] quantile_over_time: 48/59 (was 0/119 with [1m]) → Fix 1 verified. - b0/b1: 472/829 + 476/835 (was 0/899 + 0/899) → Fix 2 verified. The 357/359 "empty" results are the 3 *_latency_ms queries — the b0/b1 workload's producer emits only http_requests_total, so latency_ms returns [] (not an error). - MVP_REPORT.md emitted at run-dir root with full per-arm tables → Fix 3 verified. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
zzylol
added a commit
that referenced
this pull request
May 18, 2026
…ries-e2e wave queries (#397) Three harness gaps closed (against asap arm post-#396 baseline 332/413): 1. WARMUP_S 30 → 60s in `topology.env`. The 30s warmup wasn't long enough for the agent's first 30s tumbling window to close + flush to backend before replay started. Result: 14 leading "error/200" on 4 queries per arm. 2. `deploy/mvp-multinode/configs/asap/mvp-workload.yaml` was missing `grouping_labels: [zone]` on all 8 entries. ASAPCollector PR #390 added these to the singlenode workload but the multinode equivalent was never swept. Without grouping_labels, the controller's `attributes/keep` processor isn't injected, the agent emits full-attr sketches, the backend stores per-(zone,rack,node,pod) sids, and queries return per-series instead of per-zone. 3. Replaced broken `quantile by (zone) (0.99, http_requests_total_latency_ms)` in `queries-e2e.json` with `max by (zone) (quantile_over_time(0.99, http_requests_total_latency_ms[5m]))`. Original used PromQL's instant `quantile()` aggregator which expects scalar values across series — incompatible with DDSketch state. The replacement is valid PromQL on both raw and sketch tiers: inner computes per-series p99 over 5min (or per-zone p99 directly on asap thanks to the new grouping_labels), outer `max by (zone)` is the per-zone worst-case rollup (SLO-relevant tail). `histogram_quantile` was considered but doesn't apply — the fake-exporter emits a Float64Gauge per fake-exporter/main.go:446, not a Prometheus histogram with `_bucket{le=...}` series. Results post-fix on asap arm: 6/7 wave queries now 100% success (was 4/7 with 14-error leading pattern on the other 3). Baselines b0/b1 unchanged at 100%+empty on the queries the producer emits data for. Known follow-up (asap engine limitation, not harness debt): the new `max by (zone) (quantile_over_time(...))` query still errors on asap because the engine doesn't compose outer aggregation operators on function results — even when the inner already returns per-zone (which makes the outer a no-op identity). The same query succeeds 118/118 on b0/b1 via VictoriaMetrics. Worth a separate ASAPQuery-backend PR. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three orthogonal fixes for the multinode harness, surfaced by a clean post-#395 all-arms run:
queries-e2e.json[1m]→[5m](3 entries). The agent window is 60s, backend tumbling window 30s, soak 90s —[1m]ranges fired early in the soak frequently land between open windows and return empty.[5m]matches the convention used everywhere else (smoke test, manual probes, PR fix(deploy): wire controller into multinode harness + replay typo + wave queries + stale bucket key #394 wave queries).quantile by (zone) (...)left alone — no range arg.arm_measureat VictoriaMetrics:8428, not Prometheus:9090. The harness brings upasap-victoriametrics(not Prometheus) on node2 for b0/b1 (seebackend_up), and the agents PRW tovictoriametrics:8428/api/v1/write.:9090was unreachable → 100% of 899 attempts failed withhttp_code: null(urllib URLError →status: timeout).deploy/mvp-multinode/scripts/aggregate_report.py(new). Fills the missing scriptrun_demo.sh::allreferenced. Pure stdlib; handles the multinode dir shape (per-arm subdir withreplay.jsonl+edge-<node>.csv+stages-<node>.csv). Emits a summary table, per-query success/empty/error breakdown, edge bandwidth and stages aggregates. Idempotent; failure stays non-fatal.Fix 2 — root cause + evidence
Live probe of a fresh b0 arm:
Quick 15s replay against
:8428returned 78/138 success — the 60 empties are the 3*_latency_msqueries (no such metric in the b0 workload).Validation — full all-arms run after fixes
/mydata/mvp-multinode/results/mvp-multinode-20260518-113420/MVP_REPORT.md:asapb0b1Before this PR (same harness, same workload):
asap354/830,b00/899,b10/899.asap arm — wave queries from #291/#292/#394 unchanged (no regression):
sum by (zone) (http_requests_total)sum by (zone) (rate(http_requests_total[5m]))topk(5, sum by (zone) (rate(http_requests_total[5m])))sum_over_time(http_requests_total[5m])asap arm —
[5m]-changed queries:[1m])quantile_over_time(0.99, http_requests_total_latency_ms[5m])quantile_over_time(0.5, http_requests_total_latency_ms[5m])sum_over_time(http_requests_total[5m])The remaining
error/200=81 on asap are 59 ×quantile by (zone) (...)(unsupported PromQL syntax against asap-query-backend, pre-existing) + 11+11 quantile_over_time calls that landed in the first 30s before the first window closed.b0/b1 arms — wave queries:
sum by (zone) (http_requests_total)sum by (zone) (rate(http_requests_total[5m]))sum_over_time(http_requests_total[5m])topk(5, sum by (zone) (rate(http_requests_total[5m])))The 357/359 "empty" results on b0/b1 are the 3
*_latency_msqueries — the workload only emitshttp_requests_total, so latency_ms returns[](success / 200 / empty vector, not an error). MVP_REPORT.md correctly classifies these asemptynoterror.Test plan
[5m]-changed quantile_over_time 48/59 (was 0/119)MVP_REPORT.mdemitted with per-arm tables🤖 Generated with Claude Code