Skip to content

SNMP traps

A trap flood shouldn’t fork a process per trap, and it shouldn’t require jaque to link an SNMP stack either. Both are avoided by keeping trap reception entirely outside the core.

No SNMP listener, no MIB parsing, and no trap dependency enters the jaque binary itself. A trap reaches jaque as an ordinary passive check result, produced by a translator the operator runs alongside jaque — the same posture jaque takes for legacy config import (translate outside the binary, never absorb the legacy tooling directly), applied here to another legacy surface.

snmptrapd --(traps.log, one line per trap)--> Vector --(batch POST)--> jaque

snmptrapd receives traps and logs each as one line (peer|trapOID|varbinds) — no per-trap process fork. Vector tails that log, maps each trap OID to a service/status/output via a CSV lookup table, and posts the mapped result to CommandService/ProcessCheckResults in a batch. Because a translator receiving bursts is exactly the batch RPC’s use case, this is the API door, not the FIFO — see FIFO and API. A syslog variant that swaps the source but keeps the same OID-mapping and posting shape works the same way.

What Nagios’s traphandle cost, and what this avoids

Section titled “What Nagios’s traphandle cost, and what this avoids”

A classic traphandle script forks a process per trap — it does not survive a trap storm. snmptrapd here runs once as a daemon and only appends lines to a file; Vector runs once too, holding one persistent connection to jaque. Nothing is spawned per trap.

This is the part a naive integration gets wrong. A trap fires once and is gone; a jaque service holds a status until something changes it. The recipe pairs up/down traps onto the same service (a linkDown trap sets CRITICAL, the matching linkUp clears it to OK) — the same shape as an active check flipping status between runs.

For a trap type with no recovery counterpart, jaque never self-clears: stale_status on a passive check only accepts UNKNOWN | WARNING | CRITICAL — it exists to alarm on staleness, not to reset a problem back to OK — so a bare freshness_threshold cannot substitute for a recovery trap. Either the translator (or a cron beside it) posts the STATUS_OK that clears the condition once it’s genuinely resolved, or that trap isn’t modeled as an object’s state at all, and only flows to an archive or a sink for the record.