Traps & Notifications
Send SNMP traps (notifications) from your agent to alert managers about events.
Overview
SNMP traps are asynchronous notifications sent from an agent to a manager. Use them for:
- Alerting on threshold violations
- Reporting state changes
- Notifying about errors or events
Sending Traps
Use send_trap() from within an Updater:
from snmpkit.agent import Updater
from snmpkit.core import Oid, Value, VarBind
class MonitorUpdater(Updater):
def __init__(self, threshold: int = 90):
super().__init__()
self.threshold = threshold
self._alerted = False
async def update(self):
cpu_usage = await get_cpu_usage()
self.set_GAUGE32("1.0", cpu_usage)
# Send trap when crossing threshold
if cpu_usage > self.threshold and not self._alerted:
await self.send_trap(
"1.3.6.1.4.1.12345.0.1", # Trap OID
VarBind(
Oid("1.3.6.1.4.1.12345.1.1.0"),
Value.Gauge32(cpu_usage),
),
)
self._alerted = True
elif cpu_usage <= self.threshold:
self._alerted = Falsesend_trap() Reference
async def send_trap(self, oid: str, *varbinds: VarBind) -> NoneParameters:
oid- The trap/notification OID identifying the event typevarbinds- Variable bindings to include with the trap
Creating VarBinds
Import the core types to create VarBinds:
from snmpkit.core import Oid, Value, VarBind
# Integer value
vb1 = VarBind(Oid("1.3.6.1.4.1.12345.1.1.0"), Value.Integer(42))
# String value
vb2 = VarBind(Oid("1.3.6.1.4.1.12345.1.2.0"), Value.OctetString(b"error message"))
# Counter
vb3 = VarBind(Oid("1.3.6.1.4.1.12345.1.3.0"), Value.Counter64(1000000))Value Types
| Method | Description |
|---|---|
Value.Integer(n) | 32-bit signed integer |
Value.OctetString(b) | Bytes (use .encode() for strings) |
Value.Counter32(n) | 32-bit counter |
Value.Counter64(n) | 64-bit counter |
Value.Gauge32(n) | 32-bit gauge |
Value.TimeTicks(n) | Time in centiseconds |
Value.IpAddress(a,b,c,d) | IPv4 address (4 octets) |
Value.ObjectIdentifier(oid) | OID value |
Complete Example
import snmpkit
from snmpkit.agent import Agent, Updater
from snmpkit.core import Oid, Value, VarBind
class TemperatureMonitor(Updater):
def __init__(self, warning_temp: int = 70, critical_temp: int = 85):
super().__init__()
self.warning_temp = warning_temp
self.critical_temp = critical_temp
self._last_state = "normal"
async def update(self):
temp = await read_temperature()
self.set_GAUGE32("1.0", temp)
# Determine state
if temp >= self.critical_temp:
state = "critical"
elif temp >= self.warning_temp:
state = "warning"
else:
state = "normal"
# Send trap on state change
if state != self._last_state:
await self._send_state_trap(state, temp)
self._last_state = state
async def _send_state_trap(self, state: str, temp: int):
# Trap OIDs by state
trap_oids = {
"warning": "1.3.6.1.4.1.12345.0.1", # tempWarning
"critical": "1.3.6.1.4.1.12345.0.2", # tempCritical
"normal": "1.3.6.1.4.1.12345.0.3", # tempNormal
}
await self.send_trap(
trap_oids[state],
VarBind(
Oid("1.3.6.1.4.1.12345.1.1.0"), # currentTemp
Value.Gauge32(temp),
),
VarBind(
Oid("1.3.6.1.4.1.12345.1.2.0"), # tempState
Value.OctetString(state.encode()),
),
)
async def main():
agent = Agent()
agent.register("1.3.6.1.4.1.12345.1", TemperatureMonitor())
await agent.start()
snmpkit.run(main())Configuring snmpd for Traps
To receive traps, configure snmpd to forward them:
# /etc/snmp/snmpd.conf
# Forward traps to a trap receiver
trap2sink localhost:162 publicOr use snmptrapd to receive and log traps:
# Start trap receiver
sudo snmptrapd -f -Lo -c /etc/snmp/snmptrapd.confWith /etc/snmp/snmptrapd.conf:
authCommunity log,execute,net publicTraps are sent via the AgentX Notify PDU. The master agent (snmpd) then forwards them to configured trap destinations.
Best Practices
- Use meaningful trap OIDs - Define a trap OID hierarchy in your MIB
- Include context - Add VarBinds that explain the event
- Avoid trap storms - Implement rate limiting or state-based sending
- Document your traps - Create a MIB file describing your notifications
Rate Limiting Example
import time
class RateLimitedUpdater(Updater):
def __init__(self, min_interval: float = 60.0):
super().__init__()
self._last_trap_time = 0
self._min_interval = min_interval
async def _send_rate_limited_trap(self, oid: str, *varbinds):
now = time.time()
if now - self._last_trap_time >= self._min_interval:
await self.send_trap(oid, *varbinds)
self._last_trap_time = nowNext Steps
Last updated on