[SNMP poller] Collects cap at pool-width per second and about a quarter of the fleet is never polled when more devices fall due per second than pool-width
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 28/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- java, spring-boot
- Domain
- backend, networking, observability
Research direction
Start in InterfaceSnapshotPoller: tick is scheduled with scheduleWithFixedDelay every 1 second and iterates registrations.values() in map order. When budget.tryAcquire() fails a due registration is only marked deferred and is not retried until a later tick, so collects cap at pool-width per second. Confirm with the devices-2500-pw32 metrics and store query in the issue. Done when a 2500-device 60s fleet is fully polled at default or documented pool-width, deferred does not grow unbounded, and the reference sizing rule matches the real constraint.
Written by the indexing model from the issue text.
Description
- Build / Version: ec65137f on branch
spec/snmp-metrics(unreleased SNMP metrics phase 1) - Device & OS: libvirt guest
riptide-snmp-bench, 4 vCPU, 16 GiB, Debian 13, Temurin 25.0.4.1 - Browser / Client: n/a, server process; agents are nl6 v0.32.0
cisco_catalyst_9500(48 interfaces, SNMPv2c) - Severity: Critical, a subset of devices silently produces no series at all while every health counter reads zero failures; workaround exists
- Priority: P1, ships silent data absence at the spec's own target fleet size
- User state: n/a
Preconditions
- 2,500 devices in the inventory, each a
/32agent entry with a v2c credential set and anexportersentry withpoll: always - Polling profile
refresh-interval=PT60S,timeout=500,retries=1,collect[0]=if-mib-interfaces riptide.snmp.poll.pool-width=32(the default is 4),suspect-pool-width=8,max-exporters=8192- Remote-write sink enabled against VictoriaMetrics; agents answer every request within 40 ms
Steps to reproduce
- Start riptide with the inventory above and wait 5 minutes for the cold-start burst to settle.
- Read
snmp_collectsfrom/metricstwice, 60 seconds apart. - Read
snmp_poller_deferredat the same two instants. - In the store, run
count(count by (exporter) (ifHCInOctets{tenant="bench"})).
Expected result
About 2,500 collects per minute, snmp_poller_deferred flat once the burst has drained, and 2,500 exporters with series.
Actual result
1,920 collects per minute, exactly 32 per second, with snmp_poller_inFlight reading 0 at every sample, walk p99 38 ms and load average 0.0; snmp_poller_deferred grows by about 615 per second indefinitely (240,902 to 277,799 in one minute; 1,219,343 after 27 minutes). Only 1,917 of 2,500 exporters ever had a series, and the same 1,917 stay fresh minute after minute, so about 580 devices are never polled. snmp_collects_failed, snmp_poller_collectsFailed, metrics_sink_droppedSamples and metrics_sink_failedSamples all read 0 throughout. At 1,000 devices (16.7 due per second) the same configuration polls every device.
Evidence
- Poller
/metricssnapshots and the store query above, recorded in the benchmark run log (session scratchpadbench/RUNLOG.md, stepdevices-2500-pw32), and the benchmark-capture artifactdevices-2500-pw32(JFR, procfs, pcap, Prometheus dump) - Code observed in the same build:
InterfaceSnapshotPollerschedulestickwithscheduleWithFixedDelay(..., 0, 1, SECONDS); intick, a due registration whosebudget.tryAcquire()fails marksdeferredand continues, and nothing retries it before the next tick; the tick iteratesregistrations.values()in map order every second - Same fleet with
pool-width=128: 2,541 collects per minute, deferred flat, 2,500 of 2,500 exporters fresh
Workaround
Set riptide.snmp.poll.pool-width to at least the fleet's walks per second (devices divided by the interval in seconds), for example 128 for 5,000 devices at 60 seconds. The reference page's sizing rule (permits about walks per second times walk latency) understates this and needs correcting together with the fix.
- Dominant language
- Java
- Stars
- 2
- Forks
- 0
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 52
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Riptide-Labs/riptide
-
enhancement priority: low
Difficulty 1/5 Under an hour Newbie friendliness 92/100
Riptide-Labs/riptide#1060 ·
Maintainers usually reply within 1 day
-
enhancement priority: medium
Difficulty 4/5 3-5 days Newbie friendliness 55/100
Riptide-Labs/riptide#1059 ·
Maintainers usually reply within 1 day
-
dependencies javascript priority: low
Difficulty 1/5 Under an hour Newbie friendliness 15/100
Riptide-Labs/riptide#1045 ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 22/100
Riptide-Labs/riptide#987 ·
Maintainers usually reply within 1 day
-
enhancement priority: low
Difficulty 5/5 Over a week Newbie friendliness 25/100
Riptide-Labs/riptide#983 ·
Maintainers usually reply within 1 day
All issues in Riptide-Labs/riptide
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
Julow/Unexpected-Keyboard#1490 ·
Maintainers usually reply within 4 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
Vakore/ZappierGames#275 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
unitycatalog/unitycatalog#2148 ·
Maintainers usually reply within 2 days
-
bug key bindings source editor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
enhancement good first issue Integration
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
SasanLabs/VulnerableApp#903 · 1 comment ·
Maintainers usually reply within 1 day