Join keys
Query-time enrichment works by joining NetBox context onto another data source's results in a Grafana panel (the Outer join / Join by field transformation). A join matches rows when a field has the same name and the same value in both frames. Real telemetry rarely matches NetBox out of the box, so this plugin gives you a set of composable tools to make them line up. None of these are required; reach for the one that fits your setup.
The tools
1. Configurable join keys (per query)
On any Objects or IP enrichment query, add one or more Join keys.
Each maps a source field to a new output column, with an optional transform:
| Transform | Effect | Example |
|---|---|---|
none | copy as-is | name → device |
lowercase / UPPERCASE | case-fold | LEAF1 → leaf1 |
strip domain | hostname before first dot (IPs left intact) | leaf1.dc1.example.com → leaf1 |
IP host | drop CIDR mask | 10.0.0.1/24 → 10.0.0.1 |
interface short name | canonical → SNMP-style abbreviation (netutils) | GigabitEthernet0/1 → Gi0/1 |
regex | extract a capture group, or replace with a template | Ethernet1/1 → Eth1/1 |
The point is to name the output column exactly like the label on your metric
(e.g. instance) and shape the value to match. This happens server-side, so you
don't need extra Grafana transforms.
On an IP enrichment query the source may be any context field, whether or not
it is in the query's Context fields selection: joining on device_name while
displaying only ip and prefix_cidr works. The field is fetched so the key can
be derived and is then dropped, so the table gains the output column and nothing
else. Note that a source only a lookup hop can supply still costs that hop —
joining on prefix_* runs the (serial) prefix fallback, see
RECIPES.md.
2. Multiple mappings on one query
You can add several mappings to a single query, so the same NetBox result can be joined different ways downstream. For example, emit both:
instance=name(strip domain), to join Prometheusnode_exporterseries, anddevice=name(lowercase), to join SNMP series that use a lowercased name.
One NetBox query, reused by multiple panels / metric sources.
3. Automatic ip column
Whenever a query returns an address column (IPAM), the plugin also emits a
host-only ip column (mask stripped). Join flow/host metrics that carry a bare
IP directly against ip.
4. IP enrichment query type (address, device and longest-prefix match)
Value-equality can't map an arbitrary observed IP to its containing NetBox
prefix, let alone the device it belongs to. The IP enrichment query type does
both, but not both at once for the same IP: give it a list of IPs (literally, or
from a $variable sourced from your flow data) and, per IP, it either finds a
registered address record - returning whatever owns it: a device and its
interface (device_name, interface_name, device_site, …), or
vm_name when the address sits on a virtual machine's interface instead
(is_primary_ip is un-namespaced because it answers for either owner) - or,
only when no address record matches at all, falls back to
the longest-matching prefix's context (prefix_tenant, prefix_role,
prefix_vrf, prefix_vlan, prefix_scope, …). prefix_* and
address_*/interface_*/device_*/vm_name are mutually exclusive per row,
and device_name and vm_name are never both set on the same row either - but
neither is guaranteed to be set. An address is assigned to a device interface,
to a VM interface, or to neither (an FHRP/VRRP group, or nothing at all), and in
that last case both names stay blank, as they do on every prefix-fallback row.
So don't read a blank device_name as "therefore a VM":
address_assigned_object_type is the column that tells those cases apart, and
it only means anything on a row that matched an address record in the first
place. Join on whichever name your metrics are labelled by - they are separate
columns because NetBox permits a device and a VM with the same name, and merging
them would silently join the wrong host. See
RECIPES.md for the full
field list and worked examples of each outcome. Join your flow metrics to the
result on ip. This is the one enrichment that genuinely needs NetBox at query
time; no relabeling pipeline required.
Recipes by source
Prometheus / SNMP exporter (by device name)
Metric label is instance (often an FQDN or IP); NetBox has name.
- NetBox Objects query → object type Devices; Join key:
name→instance, transform strip domain; returnsite, role, tenant. - Your Prometheus query (any).
- Panel Transformations → Outer join, field
instance. - NetBox
site/role/tenantnow hang off every metric series. Group, filter or color by them.
If your metric label is
devicerather thaninstance, set the output column todeviceinstead; match whatever your series use.
SNMP by ifIndex / interface
SNMP series key interfaces by an abbreviated ifName (Gi0/1, Et1/1) or by
ifIndex (10101); NetBox stores canonical names (GigabitEthernet0/1).
- Abbreviated names: add a join key
name→ifName, transform interface short name, netutils' canonicalize-then-abbreviate pipeline: every spelling netutils recognizes (canonicalGigabitEthernet0/1, aliases likePortChannel10orTwentyFiveGigabitEthernet…, abbreviations likeEth1/1) normalizes to the standard short form (Gi0/1,Po10,Twe…,Et1/1). Aliases match case-sensitively (netutils keepsPoPort-channel andPOPOS distinct); canonical long names also match case-insensitively. Unknown prefixes pass through unchanged. To emit a non-standard short form your exporter uses, fall back to a regex transform, or add both mappings; multiple join keys can emit several variants from one query. - ifIndex: record it on the NetBox interface as a custom field (e.g.
ifindex); it surfaces as acf_ifindexcolumn. Add a join keycf_ifindex→ifIndex(transform none) and join onifIndex.
Loki / logs (by host)
Logs usually carry a host or hostname label. Use a join key
name → host (strip domain) on a Devices query. Note: a Loki instant
metric query returns one frame per stream, so use Labels to fields
followed by Merge series/tables (not Join by field) to correlate them
with the NetBox rows on the shared host column. The Loki recipe in
RECIPES.md shows the full transform chain.
Flow / NetFlow (by IP)
Use the IP enrichment query type. Surface the observed source/destination
IPs as a Grafana query variable (from your flow data source), reference it as
$flow_ips in the query's IPs box, and join your flow metrics on ip.
Caveats
- Prefer keys that survive a rename. A display name is what people edit in
NetBox; a slug or an id is not. Where your series carry them, join
site_slugto asitelabel andidto anetbox_idlabel rather than joining on names. Numeric sources come out as plain strings (42, never42.0), so an id matches a Prometheus label without a transform. - Duplicate names. NetBox permits the same device name in different sites. If your fleet has duplicates, a name join can fan out. Prefer a unique key (asset tag, primary IP) where it matters.
- Cardinality / scale. Joins run client-side in the browser; very large
tables get heavy. Keep NetBox queries scoped (filters,
Return fields); a dedicated high-volume enrichment backend is planned for this. - Stale vs live. Query-time joins are always current. If you instead need the
context frozen into the metric historically, that's the ingest-time relabeling
pattern (
netbox-plugin-prometheus-sd), complementary, not replaced.