SnmpKit.Agent (snmpkit v2.0.1)
An SNMP agent: exposes your application's own data to managers over SNMPv1, v2c and v3.
{:ok, agent} = SnmpKit.Agent.start_link(
port: 1161,
communities: %{"public" => :read, "private" => :write},
system: [descr: "orders-api 3.2", name: "orders-01", location: "rack 4"]
)
SnmpKit.Agent.put(agent, "hrSystemNumUsers.0", :gauge32, fn -> MyApp.Sessions.count() end)
SnmpKit.Agent.register(agent, [1, 3, 6, 1, 4, 1, 99999, 1], MyApp.QueueStats)Or in a supervision tree:
children = [
{SnmpKit.Agent, port: 161, communities: ["public"], name: MyApp.SnmpAgent,
subtrees: [{"ifEntry", SnmpKit.Agent.Table, columns: ..., rows: &MyApp.Ports.rows/0}]}
]The MIB is made of subtrees, each served by a SnmpKit.Agent.Handler
registered at an OID prefix. The longest matching prefix serves an object.
Two handlers are built in: SnmpKit.Agent.Store for scalars (used by
put/4, and pre-loaded with the system group) and SnmpKit.Agent.Table
for tables backed by a function. Every request is answered in its own
process, so handlers run concurrently.
Options
:port- UDP port (default 161; 0 picks a free port, read it withport/1):bind_address- interface to bind (default all IPv4; an IPv6 address binds IPv6):communities-"public", a list of read-only communities, or a map or keyword of community to:read|:write(default"public"read-only):v3_users- USM users as forSnmpKit.Sim.start_device/2(%{name, auth, auth_password, priv, priv_password}), plus an optionalaccess: :read | :write(default:read):engine_id- SNMPv3 engine id (default derived from:nameor the port):system- thesystemgroup:descr,object_id,contact,name,location,services;sysUpTimeis computed. Contact, name and location accept SET from a:writeprincipal:subtrees-{prefix, module}or{prefix, module, opts}to register at start:notify_targets- wherenotify/4sends:"host","host:port",{host, port}, or%{host:, port:, community:, version:, inform:}:name- GenServer registration:max_concurrent_requests,:max_packet_size- as for the simulator server
OIDs everywhere may be lists, dotted strings, or MIB names ("sysName.0",
"ifEntry").
Access control
A principal (community or v3 user) is :read or :write. Reads are
allowed to both; SET needs :write, otherwise the agent answers
noAccess (noSuchName to SNMPv1). A request from a community that is
not configured is dropped without a response, as SNMP requires; a v3
request from a user that is not configured is answered by USM with a
usmStatsUnknownUserNames report and never reaches the MIB. Should a
PDU from an unknown principal reach the request path anyway, it is
dropped there too, for reads as well as writes.
Notifications
notify/4 sends a v2c trap (or inform) to every configured target with
the agent's sysUpTime:
SnmpKit.Agent.notify(agent, "linkDown", [{"ifIndex.3", :integer, 3}])Telemetry
Every answered request emits [:snmpkit, :agent, :request] with
%{duration} and metadata pdu_type, version, principal,
error_status, varbinds. Dropped requests emit nothing; the server
counts them in stats/1 under auth_failures.
Summary
Functions
Removes a scalar from the store.
The SNMPv3 engine id.
The value the agent would answer a GET for oid with, from any subtree.
The object the agent would answer a GETNEXT for oid with.
Sends a notification to every configured target (or to targets: in
opts). trap and varbind OIDs may be names. Options are those of
SnmpKit.SNMP.send_trap/4; inform: true sends informs and waits for
the acknowledgements. Returns :ok, or {:error, [{target, reason}]}
listing the targets that failed.
The UDP port the agent listens on.
Puts a scalar into the agent's store. value may be a zero-arity function,
called on every read. writable: true allows SET from a :write principal.
Registers module (a SnmpKit.Agent.Handler) for the subtree at prefix.
opts go to the module's init/1, or become its ctx when it has none.
Registering at a prefix that is already taken replaces the handler.
Resolves an OID list, dotted string or MIB name to an OID list.
Starts an agent. See the module documentation for options.
Request and error counters, from the underlying server.
Stops the agent.
The registered subtrees as {prefix, module}, most specific first.
Removes the handler registered at prefix.
The agent's sysUpTime in centiseconds.
Types
@type agent() :: GenServer.server()
@type oid() :: [non_neg_integer()] | String.t()
Functions
Removes a scalar from the store.
The SNMPv3 engine id.
The value the agent would answer a GET for oid with, from any subtree.
@spec next(agent(), oid()) :: {:ok, {[non_neg_integer()], atom(), term()}} | :end_of_mib_view | {:error, term()}
The object the agent would answer a GETNEXT for oid with.
@spec notify(agent(), term(), [{term(), atom(), term()}], keyword()) :: :ok | {:error, [{term(), term()}]}
Sends a notification to every configured target (or to targets: in
opts). trap and varbind OIDs may be names. Options are those of
SnmpKit.SNMP.send_trap/4; inform: true sends informs and waits for
the acknowledgements. Returns :ok, or {:error, [{target, reason}]}
listing the targets that failed.
@spec port(agent()) :: :inet.port_number()
The UDP port the agent listens on.
Puts a scalar into the agent's store. value may be a zero-arity function,
called on every read. writable: true allows SET from a :write principal.
Registers module (a SnmpKit.Agent.Handler) for the subtree at prefix.
opts go to the module's init/1, or become its ctx when it has none.
Registering at a prefix that is already taken replaces the handler.
@spec resolve_oid(term()) :: {:ok, [non_neg_integer()]} | {:error, term()}
Resolves an OID list, dotted string or MIB name to an OID list.
@spec start_link(keyword()) :: GenServer.on_start()
Starts an agent. See the module documentation for options.
Request and error counters, from the underlying server.
@spec stop(agent()) :: :ok
Stops the agent.
@spec subtrees(agent()) :: [{[non_neg_integer()], module()}]
The registered subtrees as {prefix, module}, most specific first.
Removes the handler registered at prefix.
@spec uptime(agent()) :: non_neg_integer()
The agent's sysUpTime in centiseconds.