feat(anomaly): control-plane saturation correlated detector (valkey#3927) - #348
Conversation
2b83eb1 to
65c4bf9
Compare
|
bugbot run |
65c4bf9 to
0582eb8
Compare
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0582eb8. Configure here.
0582eb8 to
fe43931
Compare
fe43931 to
84a9fa0
Compare
|
bugbot run |
1 similar comment
|
bugbot run |
dc85e3d to
47c5b88
Compare
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 47c5b88. Configure here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit d476252. Configure here.
KIvanow
left a comment
There was a problem hiding this comment.
The detector itself is essentially merge-quality - the CPU-streak + impact-evidence pairing is the right design, and the restart-safety (streak/drop/RTT/event resets) and evidenceFloorAt stale-evidence gating are handled carefully and well-tested. Holding it as draft is the right call given the dependencies:
Blocking (sequencing):
- Stacked on unmerged #347 - can't land until that does.
FAILOVER_CHURNenum duplicated with #346. It's added verbatim here, but nothing in this branch actually emits it, so its entry inCONTROL_PLANE_CORROBORATING_METRICSis a dead corroborator until #346 lands. Let #346 own the enum and drop it from this PR to avoid the duplicate-member conflict.
Design concern worth addressing before promoting out of draft:
3. The synthetic-event marker is implicit and fragile. isControlPlaneSaturationEvent recognizes the synthetic event by sniffing CPU_UTILIZATION AND CRITICAL AND zScore===0 AND threshold===90. This is collision-free today only because the CPU config has no absolute threshold - if anyone later adds criticalThreshold: 90 to the CPU config, a poll where value == mean == 90 produces exactly zScore=0, threshold=90 and gets misclassified. Recommend a dedicated marker field (explicit synthetic/anomalyType flag) and/or a single named constructor for the synthetic event, plus a warning comment at the CPU config guarding against adding an absolute threshold.
4. False-positive scenario is untested: a replica removed for maintenance while a primary sits busy-but-healthy at >=90% produces a single connected_slaves drop within the window -> CRITICAL. Rolling replica restarts under load are realistic - worth an explicit test (and maybe a second-signal requirement).
Verdict: draft - not ready. Sequence: land #347 -> land #346 (with the enum) -> rebase this, de-dupe the enum, add the false-positive test.
d9bac7f to
69c8b14
Compare
|
Addressed in 69c8b14 (stays draft until #347 → #346 land, per your sequencing):
|
69c8b14 to
3a97517
Compare
3a97517 to
6358f32
Compare
…927) - Sustained ≥90% CPU streak paired with control-plane impact evidence: probe-RTT spike vs rolling baseline, graded replica drops (a lone single drop needs a second signal), or recent control-plane anomalies - One synthetic CRITICAL CPU event per episode via a single constructor stamping an explicit syntheticPattern marker; correlator maps it to CONTROL_PLANE_SATURATION - Restart-safety: CPU counter reset clears streak, drops, RTT baseline, and advances the evidence floor
- Re-add FAILOVER_CHURN to CONTROL_PLANE_CORROBORATING_METRICS now that #346 (the enum owner) is merged into the base
6358f32 to
3aa05ea
Compare

Detector #5 of the board batch — the last one, deliberately sequenced after the COB detector whose
REPL_BUFFER_PRESSUREsignal it corroborates against. Stacked on #347 (merge that first).Surfaces the valkey#3927 condition: under CPU saturation the single-threaded event loop starves control-plane traffic — delayed heartbeats and replication events (false node timeouts, replica drops, unnecessary failovers) and admin commands queuing behind the data backlog. Until upstream's trusted-sources QoS lands, this pairs the observable signals.
Detection
The pairing is the whole design — CPU alone never fires, and an RTT blip alone never fires:
Episode cooldown: after firing, quiet until the CPU streak fully resets (recovery + re-trigger). The emit uses the ack-after-success contract so a failed emit retries next poll.
Mechanics
CPU_UTILIZATIONevent carrying a structural marker (zScore 0,threshold 90) thatisControlPlaneSaturationEventrecognizes — no message sniffing. Z-score CPU anomalies (always non-zero zScore) can't collide.performance.nowdelta) — zero added commands; server-sideused_cpu_*remains the primary signal, RTT is corroboration only.FAILOVER_CHURNis included as a corroborator: the enum member is mirrored verbatim from the feat(anomaly): gossip-mode failover-churn detector (valkey#3996) #346 branch, so whichever lands second rebases with a trivial dedupe. A churning shard during sustained saturation is direct starvation evidence.Tests
13 pure-module cases (streak, RTT baseline/floor/spike, corroboration matrix, ack/cooldown/re-arm, null-sample carry) + 3 correlator cases (marker match, z-score non-match, mixed-window priority) + 5 service-integration cases (replica-drop fire, event corroboration, CPU-only silence, one-per-episode + re-arm, cleanup). Full anomaly-detection suite: 263 green.
tscclean.Note
Medium Risk
New detection logic on the hot poll path can mis-alert on restarts or maintenance if corroboration rules misfire; correlator priority changes how mixed CPU/failover windows are labeled.
Overview
Adds control-plane saturation detection for valkey#3927: sustained ≥90% CPU for three polls only raises a CRITICAL when paired with impact evidence (probe INFO RTT spike, replica drops, or recent replication/cluster/COB-style anomalies). High CPU or RTT alone never fires.
A new
control-plane-saturation-detectormodule owns episode state (streaks, RTT baseline, evidence floors, restart handling).AnomalyServicemeasures probe RTT aroundgetInfoParsed, tracksconnected_slavesdrops, runs detection after other poll detectors, and emits one syntheticCPU_UTILIZATIONevent per episode viasyntheticPattern: CONTROL_PLANE_SATURATION(no new metric type). CPU z-score config stays threshold-free to avoid double alerts.The correlator adds a first-priority
CONTROL_PLANE_SATURATIONrule so mixed windows resolve to saturation overNODE_FAILOVER.AnomalyEventgains optionalsyntheticPattern; connection teardown clears saturation maps. Broad unit and service integration tests cover corroboration, cooldown, restart, and cleanup.Reviewed by Cursor Bugbot for commit 3aa05ea. Bugbot is set up for automated code reviews on this repo. Configure here.