Plugin Metrics
Plugins that have observable runtime state register their own Prometheus metrics
via the existing ConfigureMetrics callback in the Registration struct.
Implementation Pattern
Each plugin follows the same three-step pattern used by bgp-rib and bgp-gr:
-
Registration: Set
ConfigureMetricsin theRegistrationstruct insideinit(). The callback type-asserts theanyparameter tometrics.Registry. -
Storage: Declare a package-level
atomic.Pointerholding a metrics struct. The struct contains the counters and gauges created from the registry. -
Usage: At metric update points, load the pointer. If nil (metrics disabled), skip. Otherwise update the metric.
Naming Policy
Every metric name is built from four parts in fixed order:
ze_{scope}_{subject}_{detail}
| Part | Rule | Examples |
|---|---|---|
ze |
Always. Global prefix for all ze metrics. | |
| scope | Plugin name, hyphens stripped, lowercase. Reactor uses functional area. | rib, gr, fibkernel, systemrib, rpki, persist, watchdog |
| subject | Singular noun: the type of thing being measured. | route, peer, timer, session, vrp |
| detail | What aspect. Depends on metric type (see below). | inserts, active, expired |
Type-Specific Rules
| Type | Pattern | Suffix | Examples |
|---|---|---|---|
| Counter | ze_{scope}_{subject}_{event}_total |
Always _total |
ze_rib_route_inserts_total, ze_gr_timer_expired_total |
| Gauge | ze_{scope}_{subject}_{qualifier} |
Never _total |
ze_gr_active_peers, ze_fibkernel_routes_installed |
| Histogram | ze_{scope}_{subject}_{action}_seconds |
Always unit suffix | ze_peer_dial_seconds |
| CounterVec | Same as Counter, labels for dimensions | _total |
ze_rpki_validation_outcomes_total with {result} label |
| GaugeVec | Same as Gauge, labels for dimensions | ✕ | ze_rib_routes_in with {peer} label |
Subject Rules
The subject is always a singular noun describing the category of thing measured. When the metric counts a quantity of that noun, the grammatical plural appears naturally in the detail.
| Subject (singular) | Gauge (current count) | Counter (cumulative events) |
|---|---|---|
| route | routes_installed |
route_installs_total |
| peer | peers_up |
peer_flaps_total |
| vrp | vrps_cached |
|
| session | sessions_active |
session_teardowns_total |
Detail Rules
For counters, the detail is the event that happened, as a noun or past participle:
inserts, withdrawals, expired, installs, removals, errors.
For gauges, the detail is a qualifier distinguishing this gauge from others
in the same scope: installed, active, up, cached, in, out.
Label Rules
Use labels for runtime dimensions. Never encode variable data in metric names.
| Label | When to use | Example |
|---|---|---|
peer |
Per-peer breakdown | ze_rib_routes_in{peer="10.0.0.1"} |
family |
Per-address-family breakdown | ze_rib_route_inserts_total{family="ipv4/unicast"} |
operation |
Error categorization | ze_fibkernel_errors_total{operation="add"} |
result |
Outcome categorization | ze_rpki_validation_outcomes_total{result="valid"} |
Scope-to-Prefix Mapping
| Plugin (Registration Name) | Metric scope | Rationale |
|---|---|---|
bgp-rib |
rib |
Established; bgp prefix would be redundant |
bgp-gr |
gr |
Established |
fib-kernel |
fibkernel |
Hyphen stripped |
rib (sysrib) |
systemrib |
Registration name is rib but ze_rib_ is taken by bgp-rib; systemrib reads naturally |
bgp-watchdog |
watchdog |
bgp prefix redundant |
bgp-rpki |
rpki |
bgp prefix redundant |
bgp-persist |
persist |
bgp prefix redundant |
Full Inventory
| Metric Name | Type | Labels | Owner |
|---|---|---|---|
ze_rib_routes_in_total |
Gauge | bgp-rib | |
ze_rib_routes_out_total |
Gauge | bgp-rib | |
ze_rib_routes_in |
GaugeVec | peer | bgp-rib |
ze_rib_routes_out |
GaugeVec | peer | bgp-rib |
ze_rib_route_inserts_total |
CounterVec | peer, family | bgp-rib |
ze_rib_route_withdrawals_total |
CounterVec | peer, family | bgp-rib |
ze_attr_pool_intern_total |
GaugeVec | pool | bgp-rib |
ze_attr_pool_dedup_hits_total |
GaugeVec | pool | bgp-rib |
ze_attr_pool_slots_used |
GaugeVec | pool | bgp-rib |
ze_gr_active_peers |
Gauge | bgp-gr | |
ze_gr_stale_routes |
GaugeVec | peer | bgp-gr |
ze_gr_timer_expired_total |
CounterVec | peer | bgp-gr |
ze_fibkernel_routes_installed |
Gauge | fib-kernel | |
ze_fibkernel_route_installs_total |
Counter | fib-kernel | |
ze_fibkernel_route_updates_total |
Counter | fib-kernel | |
ze_fibkernel_route_removals_total |
Counter | fib-kernel | |
ze_fibkernel_errors_total |
CounterVec | operation | fib-kernel |
ze_systemrib_routes_best |
Gauge | rib (sysrib) | |
ze_systemrib_route_changes_total |
CounterVec | action | rib (sysrib) |
ze_systemrib_events_received_total |
Counter | rib (sysrib) | |
ze_watchdog_peers_up |
Gauge | bgp-watchdog | |
ze_watchdog_route_announcements_total |
Counter | bgp-watchdog | |
ze_watchdog_route_withdrawals_total |
Counter | bgp-watchdog | |
ze_rpki_vrps_cached |
Gauge | bgp-rpki | |
ze_rpki_sessions_active |
Gauge | bgp-rpki | |
ze_rpki_validation_outcomes_total |
CounterVec | result | bgp-rpki |
ze_persist_routes_stored |
Gauge | bgp-persist | |
ze_persist_peers_tracked |
Gauge | bgp-persist | |
ze_persist_route_replays_total |
Counter | bgp-persist | |
ze_isis_adjacencies_up |
GaugeVec | level, interface | isis |
ze_isis_adjacencies_total |
GaugeVec | level | isis |
ze_isis_lsps |
GaugeVec | level | isis (lsdb) |
ze_isis_lsp_fragments |
GaugeVec | level | isis (lsdb) |
ze_isis_lsp_originations_total |
CounterVec | level | isis (lsdb) |
ze_isis_sequence_wraps_total |
CounterVec | level | isis (lsdb) |
ze_isis_purges_total |
CounterVec | level | isis (lsdb) |
ze_isis_lsps_received_total |
CounterVec | level | isis (flooding) |
ze_isis_lsps_transmitted_total |
CounterVec | level | isis (flooding) |
ze_isis_csnp_sent_total |
CounterVec | level | isis (flooding) |
ze_isis_csnp_received_total |
CounterVec | level | isis (flooding) |
ze_isis_psnp_sent_total |
CounterVec | level | isis (flooding) |
ze_isis_psnp_received_total |
CounterVec | level | isis (flooding) |
ze_isis_srm_resends_total |
CounterVec | level | isis (flooding) |
ze_isis_lsps_dropped_total |
CounterVec | level, reason | isis (flooding) |
ze_isis_dis_elections_total |
CounterVec | level | isis (dis) |
ze_isis_pseudonode_lsps |
GaugeVec | level | isis (dis) |
ze_isis_auth_failures_total |
CounterVec | level, interface | isis (auth) |
ze_isis_redist_injected_total |
CounterVec | source, afi | isis (redistribute) |
ze_isis_redist_withdrawn_total |
CounterVec | source, afi | isis (redistribute) |
ze_isis_redist_inject_failures_total |
CounterVec | source | isis (redistribute) |
ze_isis_lsp_reoriginations_total |
CounterVec | level | isis (redistribute) |
ze_isis_spf_runs_total |
CounterVec | level | isis (spf) |
ze_isis_spf_duration_seconds |
HistogramVec | level | isis (spf) |
ze_isis_spf_nodes |
GaugeVec | level | isis (spf) |
ze_isis_routes_installed |
GaugeVec | level, afi | isis (spf) |
ze_isis_frames_sent_total |
CounterVec | interface | isis (transport) |
ze_isis_frames_received_total |
CounterVec | interface | isis (transport) |
ze_isis_frames_dropped_total |
CounterVec | interface, reason | isis (transport) |
ze_isis_sockets_open |
Gauge | isis (transport) | |
ze_ospf_packets_sent_total |
CounterVec | interface, type | ospf, ospfv3 (transport) |
ze_ospf_packets_received_total |
CounterVec | interface, type | ospf, ospfv3 (transport) |
ze_ospf_packets_dropped_total |
CounterVec | interface, reason | ospf, ospfv3 (transport) |
ze_ospf_sockets_open |
Gauge | ospf, ospfv3 (transport) | |
ze_ospf_interface_up |
GaugeVec | area, interface | ospf (iface) |
ze_ospf_dr_elections_total |
CounterVec | interface | ospf (iface) |
ze_ospf_neighbors |
GaugeVec | area, interface, state | ospf (neighbor) |
ze_ospf_adjacencies_full |
GaugeVec | area | ospf (neighbor) |
ze_ospf_nsm_events_total |
CounterVec | event | ospf (neighbor) |
ze_ospf_lsdb_lsas |
GaugeVec | area, type | ospf (lsdb) |
ze_ospf_lsa_originations_total |
CounterVec | type | ospf (lsdb) |
ze_ospf_lsa_refreshes_total |
CounterVec | type | ospf (lsdb) |
ze_ospf_lsa_purges_total |
CounterVec | type | ospf (lsdb) |
ze_ospf_lsupdates_sent_total |
CounterVec | interface | ospf (lsdb) |
ze_ospf_lsupdates_received_total |
CounterVec | interface | ospf (lsdb) |
ze_ospf_lsacks_sent_total |
CounterVec | interface | ospf (lsdb) |
ze_ospf_retransmissions_total |
CounterVec | area | ospf (lsdb) |
ze_ospf_spf_runs_total |
CounterVec | area | ospf (spf) |
ze_ospf_spf_duration_seconds |
HistogramVec | area | ospf (spf) |
ze_ospf_routes_installed |
GaugeVec | type, af | ospf (spf) |
ze_ospf_abr |
Gauge | ospf (spf) | |
ze_ospf_summary_lsas |
GaugeVec | area | ospf (spf) |
ze_ospf_asbr |
Gauge | ospf (engine) | |
ze_ospf_external_lsas |
Gauge | ospf (engine) | |
ze_ospf_redist_injected_total |
CounterVec | source | ospf (redistribute) |
ze_ospf_redist_withdrawn_total |
CounterVec | source | ospf (redistribute) |
ze_ospf_nssa_translations_total |
CounterVec | area | ospf (engine) |
ze_ospf_auth_failures_total |
CounterVec | interface, reason | ospf (engine) |
ze_ospf_af_instances |
GaugeVec | af | ospf (RFC 5838 multi-AF) |
ze_ospf_af_bit_mismatch_total |
CounterVec | af | ospf (RFC 5838 multi-AF) |
ze_traffic_usage_ingress_port_bytes_total |
GaugeVec | interface, dst_port, protocol | traffic-usage |
ze_traffic_usage_egress_port_bytes_total |
GaugeVec | interface, src_port, protocol | traffic-usage |
ze_traffic_usage_ingress_bytes_total |
GaugeVec | interface, src_ip | traffic-usage (track-ip) |
ze_traffic_usage_egress_bytes_total |
GaugeVec | interface, dst_ip | traffic-usage (track-ip) |
ze_traffic_usage_map_entries |
GaugeVec | interface, map | traffic-usage |
ze_managed_clients_connected |
Gauge | managed (hub server) | |
ze_managed_config_fetch_total |
CounterVec | result | managed (hub server) |
ze_managed_config_changed_pushed_total |
Counter | managed (hub server) | |
ze_plugin_write_watchdog_total |
CounterVec | transport | plugin (server) |
ze_iface_owned_devices |
GaugeVec | owner | iface (owned-device registry) |
ze_plugin_write_watchdog_total increments when a plugin RPC write on a
transport that does not support SetWriteDeadline (SSH channels, io.Pipe)
stalls past the write-watchdog window (default 30s); the connection is then
closed (fail-fast). Deadline-capable transports (net.Conn) use write
deadlines instead and never contribute to this counter. The transport label
is a low-cardinality bucket (stream, pipe, file).
ze_ospf_packets_dropped_total counts transport drops before packet dispatch or
after a failed send. The Linux receive path currently emits reason
malformed-ipv4 when a raw datagram is too short for an IPv4 header or its IHL
overruns the received bytes; SendPacket emits reason send-error when the
backend transmit call fails.
The two ospf (iface) series track the OSPFv2 Interface State Machine:
ze_ospf_interface_up{area,interface} is 1 for active point-to-point or
broadcast interfaces and 0 for Down, passive, or loopback records;
ze_ospf_dr_elections_total{interface} increments when a broadcast interface's
elected DR or BDR changes. The three ospf (neighbor) series track the Neighbor
State Machine: ze_ospf_neighbors{area,interface,state} gauges neighbours by
NSM state, ze_ospf_adjacencies_full{area} gauges Full adjacencies, and
ze_ospf_nsm_events_total{event} counts state-machine events.
The eight ospf (lsdb) series track the RFC 2328 Section 13 flooding and
Section 14 aging machinery: ze_ospf_lsdb_lsas{area,type} gauges current LSDB
entries, ze_ospf_lsa_originations_total{type},
ze_ospf_lsa_refreshes_total{type}, and ze_ospf_lsa_purges_total{type} count
self-LSA lifecycle events, ze_ospf_lsupdates_sent_total{interface} and
ze_ospf_lsupdates_received_total{interface} count flooding packets,
ze_ospf_lsacks_sent_total{interface} counts explicit acknowledgements, and
ze_ospf_retransmissions_total{area} counts retransmit-list resends.
The five ospf (spf) series track route computation and install state:
ze_ospf_spf_runs_total{area} and ze_ospf_spf_duration_seconds{area} report
SPF scheduling and runtime, ze_ospf_routes_installed{type,af} reports the current
Loc-RIB-owned route count by OSPF path type and address family (RFC 5838), ze_ospf_abr is 1 only while this
router has an active backbone attachment and at least one other active area, and
ze_ospf_summary_lsas{area} reports current self-originated Summary-LSA count by
area.
The two isis (dis) series are the Designated IS / pseudo-node metrics (broadcast
LANs): ze_isis_dis_elections_total counts DIS elections that changed the elected
DIS per level, and ze_isis_pseudonode_lsps gauges the pseudo-node LSPs this node
currently originates as the elected DIS per level.
The isis (auth) series ze_isis_auth_failures_total counts IS-IS PDUs rejected
because authentication verification failed, by level and receiving interface. It
is incremented at the receive verify site (a PDU with no, wrong, or misordered
authentication TLV under configured auth) and is the operator's signal for a
key mismatch, a downgrade attempt, or a spoofed purge.
The four isis (redistribute) series track redistribution into IS-IS:
ze_isis_redist_injected_total{source,afi} and
ze_isis_redist_withdrawn_total{source,afi} count routes imported into IS-IS LSPs
(as TLV 135 IPv4 reachability or TLV 236 IPv6 reachability) and withdrawn, by
originating source (connected, static, bgp) and address family
(afi=ipv4|ipv6); ze_isis_redist_inject_failures_total{source} counts
injections whose LSP re-origination failed; and
ze_isis_lsp_reoriginations_total{level} counts the own-LSP re-originations that
redistribution drove, by level. Exporting IS-IS routes out to BGP uses the
generic redistribute-orchestrator counters, not an IS-IS-specific series.
The four isis (spf) series track the shortest-path computation and its Loc-RIB
install: ze_isis_spf_runs_total{level} counts Dijkstra runs per level,
ze_isis_spf_duration_seconds{level} is a histogram of each run's wall-clock
duration (buckets span 50us..500ms), ze_isis_spf_nodes{level} gauges the node
count of the last run's graph, and ze_isis_routes_installed{level,afi} gauges
the prefixes currently installed into the shared Loc-RIB by level and address
family (afi=ipv4|ipv6). The IPv6 install pass runs over the same shared SPF
tree, so the gauge is the only SPF series carrying an afi label.
The four isis (transport) series track the raw Layer-2 socket I/O:
ze_isis_frames_sent_total{interface} and
ze_isis_frames_received_total{interface} count frames transmitted and received
per circuit, ze_isis_frames_dropped_total{interface,reason} counts frames
dropped on receive by reason, and ze_isis_sockets_open gauges the number of
open IS-IS raw L2 sockets process-wide (unlabelled, a single process-level gauge).
The four ospf (transport) series track raw IPv4 protocol 89 socket I/O:
ze_ospf_packets_sent_total{interface,type} and
ze_ospf_packets_received_total{interface,type} count OSPF packets transmitted
and received per interface, ze_ospf_packets_dropped_total{interface,reason}
counts receive rejects and send failures, and ze_ospf_sockets_open gauges open
OSPF raw sockets process-wide. The ospf (iface) and ospf (neighbor) series
track interface state, DR/BDR election changes, NSM states, Full adjacencies,
and NSM events.
Dual-stack IPv6 (RFC 5308) adds no new IS-IS series: it sets afi=ipv6 on the
labelled series above and on the SPF route-install gauge
ze_isis_routes_installed{level,afi}. IPv4 uses afi=ipv4; the IPv6 install pass
runs over the same shared SPF tree.
NopRegistry Fallback
When telemetry is disabled in config, plugins receive a NopRegistry that returns
no-op metric implementations. The nil-check on the atomic pointer handles the case
where ConfigureMetrics is never called at all (plugin loaded without a metrics
registry).
Which Plugins Need Metrics
Not every plugin needs metrics. NLRI codec plugins (flowspec, evpn, labeled, etc.) are stateless encoders/decoders with no runtime state to observe. Only plugins with state machines, caches, or I/O operations benefit from metrics.
| Has metrics | No metrics needed |
|---|---|
| Plugins with route state (rib, sysrib, persist) | NLRI codecs (bgp-nlri-*) |
| Plugins with external I/O (fib-kernel, rpki) | Capability-only plugins (bgp-role) |
| Plugins with timers/state machines (gr, watchdog) | Format/encoding plugins |
Reference Implementation
The bgp-rib plugin (internal/component/bgp/plugins/rib/) is the reference
implementation. It demonstrates all aspects: registration callback, metrics struct,
atomic pointer, periodic update loop, and per-peer label cleanup.