src/go/plugin/go.d/collector/snmp/profile-format.md
An SNMP profile defines how a specific class of devices is monitored through SNMP.
:::info
SNMP profiles are reusable and declarative — you never need to modify the collector source code to support new devices.
:::
It tells the Netdata SNMP collector:
Profiles make it possible to describe entire device families (switches, routers, UPSes, firewalls, printers, etc.) declaratively — so you don’t need to hard-code logic in Go or manually define metrics for each device.
Each profile is a single YAML file that can be reused, extended, and combined.
When Netdata connects to an SNMP device, the collector:
Profile Lifecycle
┌──────────────────────┐
│ SNMP Device │ → provides sysObjectID/sysDescr
└──────────┬───────────┘
↓
┌──────────────────────┐
│ selector │ → matches device profile
├──────────────────────┤
│ extends │ → inherits base profiles
├──────────────────────┤
│ metadata │ → device info (vendor, model, etc.)
├──────────────────────┤
│ metrics │ → OIDs to collect
├──────────────────────┤
│ metric_tags │ → dynamic tags for all metrics
├──────────────────────┤
│ static_tags │ → fixed tags for all metrics
├──────────────────────┤
│ virtual_metrics │ → calculated or aggregated metrics
└──────────┬───────────┘
↓
┌──────────────────────┐
│ Netdata charts & UI │ → visualized in dashboard
└──────────────────────┘
# example-device.yaml
# selects which devices this profile applies to.
selector:
- sysobjectid:
include: ["1.3.6.1.4.1.9.*"] # Cisco devices
sysdescr:
include: ["IOS"]
# imports common base metrics
extends:
- _system-base.yaml
- _std-if-mib.yaml
# defines device-level labels (virtual node)
metadata:
device:
fields:
vendor:
value: "Cisco"
model:
symbol:
OID: 1.3.6.1.2.1.47.1.1.1.1.2.1
name: entPhysicalModelName
# specifies which OIDs to collect
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.2.2
name: ifTable
symbols:
- OID: 1.3.6.1.2.1.2.2.1.10
name: ifInOctets
chart_meta:
description: Interface inbound traffic
family: 'Network/Interface/Traffic/In'
unit: "bit/s"
scale_factor: 8
metric_tags:
- tag: interface
symbol:
OID: 1.3.6.1.2.1.31.1.1.1.1
name: ifName
# add dynamic tags to all metrics
metric_tags:
- tag: fs_sys_version
symbol:
OID: 1.3.6.1.4.1.9.2.1.73.0
name: fsSysVersion
# add fixed tags to all metrics
static_tags:
- tag: region
value: "us-east-1"
- tag: environment
value: "production"
# computes combined metrics
virtual_metrics:
- name: ifTotalTraffic
sources:
- { metric: _ifHCInOctets, table: ifXTable, as: in }
- { metric: _ifHCOutOctets, table: ifXTable, as: out }
chart_meta:
description: Total traffic across all interfaces
family: 'Network/Total/Traffic'
unit: "bit/s"
Each SNMP profile is a YAML file that defines how Netdata collects, interprets, and labels SNMP metrics from a device.
Profiles are modular — you can extend others, define metadata, and specify what to collect.
selector: <device matching pattern>
extends: <base profiles to include>
metadata: <device information>
metrics: <what to collect>
metric_tags: <global tags>
static_tags: <static tags>
virtual_metrics: <calculated metrics>
| Section | Purpose |
|---|---|
| selector | Defines which devices the profile applies to. |
| extends | Inherits and merges other base profiles. |
| metadata | Collects device-level information (host labels). |
| metrics | Defines which OIDs to collect and how to chart them. |
| metric_tags | Defines global dynamic tags collected once per device and attached to all metrics. |
| static_tags | Defines fixed tags applied to all metrics. |
| virtual_metrics | Defines calculated or aggregated metrics based on others. |
You use the selector to:
During discovery, Netdata evaluates all profiles; any profile whose selector matches a device is **applied **.
selector:
- sysobjectid:
include: ["1.3.6.1.4.1.9.*"] # regex: Cisco enterprise OID subtree
exclude: ["1.3.6.1.4.1.9.9.666"] # optional excludes
sysdescr:
include: ["IOS"] # substring (case-insensitive)
exclude: ["emulator", "lab"] # optional excludes
How it works:
sysobjectid, sysdescr, etc.).selector list matches the device.sysobjectid and sysdescr are defined within the same rule, both must succeed.Supported conditions:
| Key | What It Checks | Match Criteria (Pass) | Fails When... |
|---|---|---|---|
sysobjectid.include | Device sysObjectID | Matches at least one pattern in the list. | No items match. |
sysobjectid.exclude | Device sysObjectID | Matches none of the listed patterns. | Any item matches. |
sysdescr.include | Device sysDescr (case-insensitive) | Contains at least one substring in the list. | No listed substrings are found. |
sysdescr.exclude | Device sysDescr (case-insensitive) | Contains none of the listed substrings. | Any listed substring is found. |
Use extends to inherit metrics, tags, and metadata from another profile instead of duplicating common metrics — perfect for vendor-specific variations of a base MIB.
Most real profiles extend a few shared building blocks and then add device-specific definitions.
extends:
- _system-base.yaml # System basics (uptime, contact, location)
- _std-if-mib.yaml # Network interfaces (IF-MIB)
- _std-ip-mib.yaml # IP statistics
The final profile is the merged result of all inherited profiles plus the content in the current file.
How inheritance works:
Common base profiles
| Profile | Provides | Typical Use |
|---|---|---|
_system-base.yaml | Basic system info (uptime, name, contact) | All devices |
_std-if-mib.yaml | Interface statistics (IF-MIB) | Network devices |
_std-ip-mib.yaml | IP-level statistics (IP-MIB) | Routers, switches |
_std-tcp-mib.yaml | TCP statistics | Servers, firewalls |
_std-udp-mib.yaml | UDP statistics | Servers, firewalls |
_std-ups-mib.yaml | Power and UPS metrics | UPS devices |
The metadata section defines device-level information (not metric tags).
It is collected once per device and populates the device’s host labels in Netdata (the “virtual node” labels shown on the device page).
It always follows the structure metadata → device → fields, where each field defines a single label.
Each field can be:
value: is a fixed string.symbol — a single OID to read from.symbols — an ordered list of OIDs to try, first non-empty wins.metadata:
device:
fields:
vendor:
value: "Cisco" # static label
model:
symbols: # dynamic label with fallback
- OID: 1.3.6.1.4.1.9.3.6.3.0
name: ciscoModelA
- OID: 1.3.6.1.2.1.47.1.1.1.1.13.1
name: entPhysicalModelName
How it works:
vendor is set statically to "Cisco".model is collected dynamically. The collector tries the listed OIDs in order and uses the first one that returns a non-empty value.:::tip
See Tag Transformation for supported transformations and syntax examples.
:::
The metrics section defines what data to collect from the device — which OIDs to query, how to interpret them, and how to display them as charts in Netdata.
Metrics can be:
:::note
A metric is either scalar (single value) or table-based (multiple rows). Never mix both in the same metric entry.
:::
The collector automatically uses SNMP GET for scalars and SNMP BULKWALK for tables.
metrics:
- MIB: HOST-RESOURCES-MIB
symbol:
OID: 1.3.6.1.2.1.1.3.0
name: systemUptime
scale_factor: 0.01 # Value is in hundredths of a second
chart_meta:
description: Time since the system was last rebooted or powered on
family: 'System/Uptime'
unit: "s"
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.31.1.1
name: ifXTable
symbols:
- OID: 1.3.6.1.2.1.31.1.1.1.6
name: ifHCInOctets
chart_meta:
description: Traffic
family: 'Network/Interface/Traffic/In'
unit: "bit/s"
scale_factor: 8 # Octets → bits
metric_tags:
- tag: interface
symbol:
OID: 1.3.6.1.2.1.31.1.1.1.1
name: ifName
How it works:
symbol, while tables define a table and one or more symbols.extract_value, scale_factor, etc.) and chart metadata.metric_tags) to identify rows by interface, disk, or other attributes.:::tip
See also
:::
Metric names that start with an underscore (e.g., _ifHCInOctets) are private: they’re collected but not propagated to the SNMP collector output. Use them as internal building blocks (typically as inputs for virtual_metrics) so the final metric set remains clean. After virtual metrics are computed, the collector drops underscored metrics from the exported set.
# IF-MIB::ifXTable
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.31.1.1
name: ifXTable
symbols:
- { OID: 1.3.6.1.2.1.31.1.1.1.6, name: _ifHCInOctets, scale_factor: 8 }
- { OID: 1.3.6.1.2.1.31.1.1.1.10, name: _ifHCOutOctets, scale_factor: 8 }
virtual_metrics:
- name: ifTraffic
per_row: true
group_by: ["interface"]
sources:
- { metric: _ifHCInOctets, table: ifXTable, as: in }
- { metric: _ifHCOutOctets, table: ifXTable, as: out }
You can express “try this OID, otherwise try that OID” by declaring multiple metrics with the same symbol.name, each pointing to a different OID. At runtime the collector GETs all declared scalar OIDs, marks missing ones, and emits the metric from whichever OID returns data. Missing OIDs are skipped cleanly.
metrics:
- MIB: HOST-RESOURCES-MIB
symbol:
OID: 1.3.6.1.2.1.25.1.1.0
name: systemUptime
scale_factor: 0.01
chart_meta:
description: Time since the system was last rebooted or powered on.
family: 'System/Uptime'
unit: "s"
- MIB: HOST-RESOURCES-MIB
symbol:
OID: 1.3.6.1.2.1.1.3.0
name: systemUptime
scale_factor: 0.01
chart_meta:
description: Time since the system was last rebooted or powered on.
family: 'System/Uptime'
unit: "s"
The metric_tags section defines global dynamic tags — values collected once from the device and applied to every metric in the profile.
They are evaluated during collection, just like other SNMP symbols, and remain the same for all metrics within that device.
Typical uses:
metric_tags:
- tag: fs_sys_serial
symbol:
OID: 1.3.6.1.4.1.12356.106.1.1.1.0
name: fsSysSerial
- tag: fs_sys_version
symbol:
OID: 1.3.6.1.4.1.12356.106.4.1.1.0
name: fsSysVersion
How it works:
:::tip
See Tag Transformation for supported transformations and syntax examples.
:::
Tag names that start with an underscore (e.g., _if_type) are emitted as labels but are ignored for chart-ID composition by the SNMP collector that consumes these metrics. Use underscore tags to keep chart IDs short when another tag already guarantees uniqueness (for example, interface). (You still get the underscore-tag value as a chart label.)
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.31.1.1
name: ifXTable
symbols:
- OID: 1.3.6.1.2.1.31.1.1.1.6
name: ifHCInOctets
chart_meta:
description: Traffic
family: 'Network/Interface/Traffic/In'
unit: "bit/s"
scale_factor: 8
metric_tags:
- tag: interface
symbol: { OID: 1.3.6.1.2.1.31.1.1.1.1, name: ifName }
- tag: _if_type
table: ifTable
symbol: { OID: 1.3.6.1.2.1.2.2.1.3, name: ifType }
mapping:
1: "other"
6: "ethernet"
24: "loopback"
131: "tunnel"
161: "lag"
If you declare the same tag name multiple times, tags are evaluated in order and the first non-empty value is kept. This lets you fall back from a preferred column to an alternative. (Internally, the tag adder only sets a tag if it isn’t already set or is empty.)
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.31.1.1
name: ifXTable
symbols:
- OID: 1.3.6.1.2.1.31.1.1.1.6
name: ifHCInOctets
chart_meta:
description: Traffic
family: 'Network/Interface/Traffic/In'
unit: "bit/s"
scale_factor: 8 # Octets → bits
metric_tags:
- tag: interface
symbol: { OID: 1.3.6.1.2.1.31.1.1.1.1, name: ifName } # preferred
- tag: interface
table: ifTable
symbol: { OID: 1.3.6.1.2.1.2.2.1.2, name: ifDescr } # fallback
The static_tags section defines fixed key–value pairs that are attached to every metric collected by the profile.
They don’t depend on SNMP data and remain constant for all devices using the profile.
Typical uses:
environment, region, or service).static_tags:
- tag: environment
value: production
- tag: region
value: us-east-1
- tag: service
value: network
How it works:
metric_tags.The virtual_metrics section defines calculated metrics built from other metrics already collected by the profile.
They don’t query SNMP directly — instead, they reuse existing metric values to produce totals, sums, or fallbacks.
:::tip
See Virtual Metrics for the complete reference, configuration options, and advanced examples.
:::
Typical uses:
in + out traffic or errors). - name: ifTotalTraffic
sources:
- { metric: ifHCInOctets, table: ifXTable, as: in }
- { metric: ifHCOutOctets, table: ifXTable, as: out }
chart_meta:
description: Total traffic across all interfaces
family: 'Network/Total/Traffic'
unit: "bit/s"
How it works:
ifTotalTraffic.ifHCInOctets, ifHCOutOctets) as sources.as field names the resulting dimensions (in, out).This section explains how SNMP data is structured and how it maps to metrics in a Netdata profile.
SNMP data is organized as a hierarchical tree of numeric identifiers called OIDs (Object Identifiers).
Each OID uniquely identifies a value on a device — similar to a file path in a filesystem.
1.3.6.1.2.1.1.3.0
│ │ │ │ │ │ │ └── Instance (0 = scalar)
│ │ │ │ │ │ └──── Object (3 = sysUpTime)
│ │ │ │ │ └────── Branch: system (MIB-2)
│ │ │ └────────── MIB-2 root
└─ SNMP global prefix
MIBs (Management Information Bases) are named collections of related OIDs.
Examples: IF-MIB (interfaces), IP-MIB (IP statistics), HOST-RESOURCES-MIB (system info).
Each OID maps to a typed value, such as Counter64, Gauge32, Integer, or TimeTicks.
Some OIDs represent single values (scalars), while others represent tables of related values (rows).
Scalar metrics represent a single value for the entire device.
Their OIDs always end with .0, which denotes the instance number for a scalar object.
metrics:
- MIB: HOST-RESOURCES-MIB
symbol:
OID: 1.3.6.1.2.1.1.3.0
name: systemUptime
scale_factor: 0.01 # Value is in hundredths of a second
chart_meta:
description: Time since the system was last rebooted or powered on.
family: 'System/Uptime'
unit: "s"
What this does:
sysUpTime value once per device..0 at the end indicates there is only one instance of this value.Table metrics represent lists of related values, such as one entry per network interface, disk, or CPU.
Each row in a table is identified by an index appended to the base OID — for example:
ifHCInOctets.1 = 1024
ifHCInOctets.2 = 2048
.1, .2, … are row indexes that identify the instance (e.g., interface #1, interface #2).Table metrics must define at least one tag (
metric_tags) to identify each row. Without tags, only a single row can be emitted.
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.31.1.1
name: ifXTable
symbols:
- OID: 1.3.6.1.2.1.31.1.1.1.6
name: ifHCInOctets
chart_meta:
description: Traffic
family: 'Network/Interface/Traffic/In'
unit: "bit/s"
scale_factor: 8 # Octets → bits
metric_tags:
- tag: interface
symbol:
OID: 1.3.6.1.2.1.31.1.1.1.1
name: ifName
How Table Metrics Expand into Rows
SNMP Table: ifTable
───────────────────────────────────────────────
Index | ifName | ifHCInOctets
───────────────────────────────────────────────
1 | eth0 | 1024
2 | eth1 | 2048
───────────────────────────────────────────────
metric_tags:
- tag: interface
symbol:
OID: 1.3.6.1.2.1.31.1.1.1.1 # ifName
Resulting metrics:
───────────────────────────────────────────────
ifHCInOctets{interface="eth0"} = 1024
ifHCInOctets{interface="eth1"} = 2048
───────────────────────────────────────────────
How it works:
ifHCInOctets and ifName) from the same table.1, 2, …).What this does:
ifHCInOctets) from each interface.ifName) from the same index.ifHCInOctets{interface="eth0"} = 1024
ifHCInOctets{interface="eth1"} = 2048
Each SNMP value has a data type that determines how Netdata interprets and displays it.
The collector automatically detects the appropriate metric type (e.g., gauge or rate), but you can override it manually.
Automatic Type Detection
| SNMP Type | Default Netdata Type | Typical Use |
|---|---|---|
Counter32, Counter64 | rate | Network traffic, packet counters |
Gauge32, Integer | gauge | Temperatures, usage levels, statuses |
TimeTicks | gauge | Uptime, time-based values |
Overriding the Metric Type
You can explicitly set a metric’s type using the metric_type field inside a symbol definition.
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.2.2
name: ifTable
symbols:
- OID: 1.3.6.1.2.1.2.2.1.10
name: ifInOctets
metric_type: gauge # Override default 'rate'
What this does:
ifInOctets to be treated as a gauge (instantaneous value) instead of a rate.Counter types are automatically converted to per-second rates.Each metric or virtual metric can include an optional chart_meta block that defines how it appears in Netdata charts.
This metadata does not affect data collection — it only controls how the chart is named and grouped in the Netdata dashboard.
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.2.2
name: ifTable
symbols:
- OID: 1.3.6.1.2.1.2.2.1.10
name: ifInOctets
chart_meta:
description: Inbound network traffic
family: 'Network/Interface/Traffic/In'
unit: "bit/s"
| Field | Type | Required | Description |
|---|---|---|---|
description | string | no | Human-readable description shown in dashboards and alerts. |
family | string | no | Chart grouping path (slashes / define hierarchy). Helps organize charts by system or subsystem. |
unit | string | no | Display unit, e.g. "bit/s", "%", "{status}", "Cel". |
type | string | no | Optional chart style override: line, area, or stacked. Defaults depend on metric type. |
Tags add context and identity to SNMP metrics.
They let you distinguish between instances (for example, which interface, disk, or IP) and allow filtering and grouping in the Netdata UI.
The collector:
Key Concepts:
| Concept | Description |
|---|---|
| Table metrics must have tags | Each table row must be uniquely identified by at least one tag (for example, interface name or index). Without tags, only one row is emitted. |
| Scalar metrics don’t need tags | Scalars represent one value for the entire device, not per-instance data. |
| Static tags | Fixed values that never change (for example, datacenter, environment). |
| Dynamic tags | Extracted from SNMP data — from table columns, related tables, or row indexes. |
| Global tags | Defined in the profile’s top-level metric_tags section and applied to all metrics. |
Tag Types and Available Transformations:
| Tag Type | Description | Supported Transformations |
|---|---|---|
| Static | Fixed tags with constant values. | None (value is fixed). |
| Same-Table | Values from columns in the same table as the metric. | mapping, extract_value, match_pattern + match_value, match + tags |
| Cross-Table | Values from another table. | mapping, extract_value, match_pattern + match_value, match + tags |
| Index-Based | Values derived from the OID index of each row. | mapping (optional) |
| Index Transform | Adjusts multi-part indexes so cross-table tags align correctly. | — (structural, not a transformation) |
Summary:
metric_tags) to distinguish rows.mapping, extract_value, match_pattern, match + tags) can modify or extract parts of raw values.How the Collector Matches Values and Tags:
SNMP Table (ifTable)
───────────────────────────────────────────────
Index | ifDescr | ifInOctets
───────────────────────────────────────────────
1 | eth0 | 1024
2 | eth1 | 2048
───────────────────────────────────────────────
metric_tags:
- tag: interface
symbol:
OID: 1.3.6.1.2.1.2.2.1.2 # ifDescr
Resulting metrics:
───────────────────────────────────────────────
ifInOctets{interface="eth0"} = 1024
ifInOctets{interface="eth1"} = 2048
───────────────────────────────────────────────
How it works:
ifInOctets (value) and ifDescr (tag source).1, 2, …).Cross-Table Example:
SNMP Tables: ifTable + ifXTable
───────────────────────────────────────────────
ifTable.ifInOctets.1 = 1024
ifTable.ifInOctets.2 = 2048
ifXTable.ifName.1 = "eth0"
ifXTable.ifName.2 = "eth1"
───────────────────────────────────────────────
metric_tags:
- tag: interface
table: ifXTable
symbol:
OID: 1.3.6.1.2.1.31.1.1.1.1 # ifName
Result:
───────────────────────────────────────────────
ifInOctets{interface="eth0"} = 1024
ifInOctets{interface="eth1"} = 2048
───────────────────────────────────────────────
How it works:
ifTable but fetches tag values from ifXTable..1, .2, …).interface tag is populated from ifXTable.ifName for each matching rowStatic tags define fixed key–value pairs that are attached to metrics without being collected from SNMP.
They are useful for identifying environment, location, or other context that applies to all collected data.
Profile-level static tags apply to all metrics defined in the profile.
# Global static tags (applied to all metrics)
static_tags:
- tag: datacenter
value: "DC1"
- tag: environment
value: "production"
What this does:
Typical use cases:
Metric-level static tags apply to specific metrics only.
# Metric-specific static tags
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.2.2
name: ifTable
symbols:
- OID: 1.3.6.1.2.1.2.2.1.10
name: ifInOctets
static_tags:
- tag: "source"
value: "snmp"
- tag: "interface_type"
value: "physical"
What this does:
source=snmp and interface_type=physical only to the ifInOctets metric.Metric-level static tags are technically supported but rarely needed. In most cases, prefer profile-level
static_tagsfor consistency and simplicity.
Same-table tags extract values from columns in the same SNMP table as the metric.
They are the most common way to label per-row metrics with identifiers like interface names or indexes.
The collector:
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.2.2
name: ifTable
symbols:
- OID: 1.3.6.1.2.1.2.2.1.10
name: ifInOctets
metric_tags:
- tag: interface
symbol:
OID: 1.3.6.1.2.1.2.2.1.2
name: ifDescr
What this does:
ifInOctets (input bytes) for each row in ifTable.ifDescr column from the same table to label each row.ifInOctets{interface="eth0"} = 1000
ifInOctets{interface="eth1"} = 2000
Cross-table tags let you use data from another SNMP table as a tag source.
The collector:
table: instead of the current one.index_transform can modify the current table’s index to align it with the target.Two tables are said to have the same index when their row identifiers (OID suffixes after the base OID) are identical — meaning they describe the same entity.
In practice, this means that the row number (index) in one table corresponds directly to the same row in another.
For example:
ifTable.ifInOctets.2 = 123456
ifXTable.ifName.2 = "xe-0/0/1"
Both OIDs end with .2, so they refer to the same interface.
This allows you to use ifName (from ifXTable) as a tag for metrics collected from ifTable.
metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.2.2
name: ifTable
symbols:
- OID: 1.3.6.1.2.1.2.2.1.10
name: ifInOctets
metric_tags:
- tag: interface
table: ifXTable
symbol:
OID: 1.3.6.1.2.1.31.1.1.1.1
name: ifName
What this does:
ifInOctets from ifTable.ifXTable (e.g., .2).ifName as the interface tag.ifInOctets{interface="xe-0/0/1"} = 123456
Some tables describe related data but use different index structures — meaning their OID suffixes don’t line up directly.
For example, in ipIfStatsTable the index contains two parts:
ipIfStatsTable.ipIfStatsHCInOctets.2.1 = 38560
ipIfStatsTable.ipIfStatsHCInOctets.2.2 = 44408
Here:
2) is the IP version (e.g., 2 = IPv4, 3 = IPv6).1, 2, 3, …) is the interface index.ifXTable, on the other hand, uses only the interface index (1, 2, 3, …).Because the indexes differ, they can’t be matched directly.
To fix this, use index_transform to select only the relevant part of the index so it matches the target table’s format.
metrics:
- MIB: IP-MIB
table:
OID: 1.3.6.1.2.1.4.31.3
name: ipIfStatsTable
symbols:
- OID: 1.3.6.1.2.1.4.31.3.1.6
name: ipIfStatsHCInOctets
chart_meta:
description: Total inbound IP octets (including errors)
family: 'Network/Interface/IP/Traffic/Total/In'
unit: "bit/s"
scale_factor: 8
metric_tags:
- tag: _interface
table: ifXTable
symbol:
OID: 1.3.6.1.2.1.31.1.1.1.1
name: ifName
index_transform:
- start: 1
end: 1
What this does:
ipIfStatsTable.start: 1, end: 1) from 2.1 → becomes 1.ifXTable to find the corresponding ifName.ipIfStatsHCInOctets{_interface="xe-0/0/1"} = 38560
index_transform Worksindex_transform tells the collector which parts of the current table’s index to keep when matching rows across tables.
| Concept | Example |
|---|---|
| Original index | 2.1 (from ipIfStatsTable) → [ipVersion, ifIndex] |
| Target index | 1 (from ifXTable) |
| Transform | index_transform: [ { start: 1, end: 1 } ] |
| Result | The collector keeps only the second element (ifIndex = 1), which now matches ifXTable |
In short:
start and end positions are zero-based (0 = first index element).Index-based tags extract values directly from the OID index of the SNMP table rather than from a column.
This is useful when a table encodes identifiers (like method, code, or port number) as part of the OID itself instead of storing them in separate columns.
The collector:
index: rule, assigns a tag using the specified position in the index.metrics:
- MIB: SIP-COMMON-MIB
table:
name: sipCommonStatusCodeTable
OID: 1.3.6.1.2.1.149.1.5.1
symbols:
- OID: 1.3.6.1.2.1.149.1.5.1.1.3
name: sipCommonStatusCodeIns
chart_meta:
family: 'Network/VoIP/SIP/Response/StatusCode/In'
description: Total number of response messages received with the specified status code
unit: "{response}/s"
metric_tags:
- index: 1
tag: applIndex
- index: 2
tag: sipCommonStatusCodeMethod
- index: 3
tag: sipCommonStatusCodeValue
What this does:
1.3.6.1.2.1.149.1.5.1.1.3.1.6.200
applIndex=1
sipCommonStatusCodeMethod=6
sipCommonStatusCodeValue=200
sipCommonStatusCodeIns{applIndex="1", sipCommonStatusCodeMethod="6", sipCommonStatusCodeValue="200"} = 42
Tag transformations let you modify or extract parts of SNMP values to produce clear, human-readable tags.
They work the same in both places:
metadata (e.g., device model, OS name), andmetric_tags (e.g., per-row interface labels).Available Tag Transformations:
| Transformation | Purpose | Example Input → Output |
|---|---|---|
mapping | Replace numeric/string codes with names. | 1 → "ethernet", 161 → "lag" |
extract_value | Extract a substring via regex (first group). | "RouterOS CCR2004-16G-2S+" → "CCR2004-16G-2S+" |
match_pattern + match_value | Replace the value using regex groups or static. | "Palo Alto Networks VM-Series firewall" → "VM-Series firewall" |
match + tags (multiple tags) | Create several tags from one value. | "xe-0/0/1" → if_family=xe, fpc=0, pic=0, port=1 |
Combination & Behavior:
| Rule | Description |
|---|---|
| Where | Can be used inside metadata.*.fields.*.symbols[] and metric_tags[]. |
| Order of application | 1️⃣ match_pattern + match_value or extract_value (whichever is present) → 2️⃣ mapping → 3️⃣ match + tags (if defined). |
| No match behavior | • extract_value: keeps the original value. |
• match_pattern: skips the value (tag not emitted). | |
• match + tags: emits no tags. | |
| Multiple symbols | If multiple symbols are listed for the same tag, the first non-empty result is used. |
| Mapping key consistency | Keys in a mapping must all be the same type — all numeric or all string. |
| Safety | Keep regexes simple and, when possible, anchor them (e.g. ^pattern$) to prevent unwanted matches. |
Quick Syntax Recap:
mapping
mapping:
6: "ethernet"
161: "lag"
extract_value
extract_value: 'RouterOS ([A-Za-z0-9-+]+)' # first capture group is used
match_pattern + match_value
match_pattern: 'Palo Alto Networks\s+(PA-\d+ series firewall|VM-Series firewall)'
match_value: '$1' # or a static value like 'Router' when matched
match + tags (multiple tags)
match: '^([A-Za-z]+)[-_]?(\d+)\/(\d+)\/(\d+)$'
tags:
if_family: $1
fpc: $2
pic: $3
port: $4
Use mapping to replace raw tag values with human-readable text labels.
The collector:
metadata or metric_tags.metrics:
- MIB: IF-MIB
table:
OID: 1.3.6.1.2.1.2.2
name: ifTable
symbols:
- OID: 1.3.6.1.2.1.2.2.1.10
name: ifInOctets
metric_tags:
- tag: if_type
symbol:
OID: 1.3.6.1.2.1.2.2.1.3
name: ifType
mapping:
1: "other"
6: "ethernet"
24: "loopback"
131: "tunnel"
161: "lag"
What this does:
other, ethernet, loopback, tunnel, lag).metadata fields and metric_tags.Use extract_value to capture a part of a string using a regular expression.
The collector:
( … ).^ or $.symbols are defined.metadata:
device:
fields:
model:
symbols:
# Example: 'RouterOS CCR2004-16G-2S+' → 'CCR2004-16G-2S+'
- OID: 1.3.6.1.2.1.1.1.0
name: sysDescr
extract_value: 'RouterOS ([A-Za-z0-9-+]+)'
# Example: 'CSS326-24G-2S+ SwOS v2.13' → 'CSS326-24G-2S+'
- OID: 1.3.6.1.2.1.1.1.0
name: sysDescr
extract_value: '([A-Za-z0-9-+]+) SwOS'
Use match_pattern and match_value together to build a tag value using multiple regex capture groups.
The collector:
match_pattern.match_value.match_value, you can reference capture groups using $1, $2, $3, etc.Example 1 — Reformat using capture groups:
metadata:
device:
fields:
product_name:
symbol:
OID: 1.3.6.1.2.1.1.1.0
name: sysDescr
match_pattern: 'Palo Alto Networks\s+(PA-\d+ series firewall|WildFire Appliance|VM-Series firewall)'
match_value: "$1"
# Examples:
# - Palo Alto Networks VM-Series firewall → VM-Series firewall
# - Palo Alto Networks PA-3200 series firewall → PA-3200 series firewall
# - Palo Alto Networks WildFire Appliance → WildFire Appliance
Example 2 — Assign static value on match:
metadata:
device:
fields:
type:
symbols:
- OID: 1.3.6.1.2.1.1.1.0
name: sysDescr
# RouterOS devices
match_pattern: 'RouterOS (CCR.*)'
match_value: 'Router'
Use match and tags to create multiple tags from a single SNMP value using a regular expression with capture groups.
The collector:
matches, creates all tags listed under tags, substituting $1, $2, $3, etc. from the capture groups.Example 1 — Split OS name and model from sysDescr (metadata):
metadata:
device:
fields:
type:
symbols:
- OID: 1.3.6.1.2.1.1.1.0
name: sysDescr
match: '^(\S+)\s+(.*)$'
tags:
os_name: $1 # e.g. 'RouterOS'
model: $2 # e.g. 'CCR2004-16G-2S+'
Input like
RouterOS CCR2004-16G-2S+becomes:os_name=RouterOS,model=CCR2004-16G-2S+.
Example 2 — Derive multiple labels from interface names (metric_tags):
metric_tags:
- symbol:
OID: 1.3.6.1.2.1.2.2.1.2
name: ifDescr
match: '^([A-Za-z]+)[-_]?(\d+)\/(\d+)\/(\d+)$'
tags:
if_family: $1 # e.g. 'xe' or 'ge' or 'GigabitEthernet' → 'GigabitEthernet'
fpc: $2 # '0'
pic: $3 # '0'
port: $4 # '1'
xe-0/0/1, ge-0/0/0, or GigabitEthernet1/0/24.if_family=xe, fpc=0, pic=0, port=1.Value transformations let you process or normalize raw SNMP metric values before they are stored and charted.
They are applied per symbol (per OID) during SNMP data collection. They modify only metric values, not tags or metadata, and are not applied to virtual metrics.
These transformations are typically used to:
Available Value Transformations:
| Transformation | Purpose | Example Input → Output |
|---|---|---|
mapping | Convert numeric or string codes into state dimensions. | 1 → up, 2 → down, 3 → testing |
extract_value | Extract a numeric substring via regex. | "23.8 °C" → "23" |
scale_factor | Multiply values by a constant to adjust units. | "1.5" (MBps) × 8 → 12 (Mbps) |
match_pattern + match_value | Not applicable for metric values (use extract_value instead). | — |
Combination & Behavior:
| Rule | Description |
|---|---|
| Where | Value transformations are used inside metrics[*].symbol or metrics[*].symbols[]. |
| Order of application | 1️⃣ extract_value (if present) → 2️⃣ mapping → 3️⃣ scale_factor. |
| Scale factor position | scale_factor is always applied last, after all other transformations. |
| Data type handling | Transformations preserve numeric type (integer/float) unless the mapping converts it to a multi-value metric. |
| Error handling | If a transformation fails (e.g., regex doesn’t match), the collector keeps the original value. |
| Applicability | Transformations affect metric values only — not metadata or tags. |
| Mapping behavior | Always produces a multi-value metric where each mapped entry becomes a dimension; the active one reports 1, others 0. |
Quick Syntax Recap:
mapping
mapping:
1: up
2: down
3: testing
extract_value
extract_value: '(\d+)' # First capture group is used
scale_factor
scale_factor: 8 # Octets → bits
Use mapping to convert raw metric values into state dimensions.
Each mapping entry defines a dimension name and the numeric or string value that triggers it.
The collector:
1 if the current value matches the key, or 0 otherwise.0.metrics:
- OID: 1.3.6.1.2.1.2.2.1.7
name: ifAdminStatus
chart_meta:
description: Current administrative state of the interface
family: 'Network/Interface/Status/Admin'
unit: "{status}"
mapping:
1: up
2: down
3: testing
What this does:
up, down, and testing.1; all others report 0.Use extract_value to extract a numeric or string portion from the raw SNMP value using a regular expression.
This is often used when a metric is encoded as a string that contains numeric data (e.g. "23.8 °C").
The collector:
( … ) as the new metric value.symbols are defined, the first non-empty result is used.metrics:
- MIB: CORIANT-GROOVE-MIB
table:
OID: 1.3.6.1.4.1.42229.1.2.3.1.1
name: shelfTable
symbols:
- OID: 1.3.6.1.4.1.42229.1.2.3.1.1.1.3
name: coriant.groove.shelfInletTemperature
# Example: "23.8 °C" → "23"
extract_value: '(\d+)'
chart_meta:
description: Shelf inlet temperature
family: 'Hardware/Shelf/Temperature/Inlet'
unit: "Cel"
What this does:
(\d+) to the string "23.8 °C"."23" and uses it as the metric value.Use scale_factor to multiply collected metric values by a constant.
This transformation is typically used to convert between units (for example, bytes to bits).
The collector:
extract_value).metrics:
- MIB: IP-MIB
table:
OID: 1.3.6.1.2.1.4.31.1
name: ipSystemStatsTable
symbols:
- OID: 1.3.6.1.2.1.4.31.1.1.6
name: ipSystemStatsHCInOctets
chart_meta:
description: Octets received in input IP datagrams
family: 'Network/IP/Traffic/Total/In'
unit: "bit/s"
scale_factor: 8 # Octets → bits
- MIB: IF-MIB
symbol:
OID: 1.3.6.1.2.1.31.1.1.1.15
name: ifHighSpeed
chart_meta:
description: Estimate of the interface's current bandwidth
family: 'Network/Interface/Speed'
unit: "bit/s"
scale_factor: 1000000 # Megabits → bits
What this does:
8, reporting traffic in bits per second instead of bytes.ifHighSpeed from megabits to bits.Common use cases:
virtual_metrics:
- name: <string>
# Option 1 — Direct sources (no fallback)
sources:
- { metric: <metricName>, table: <tableName>, as: <dimensionName> }
# Option 2 — Alternatives (with fallback sets)
alternatives:
- sources: # Try this first (preferred)
- { metric: <metricNameA>, table: <tableName>, as: <dimensionName> }
- { metric: <metricNameB>, table: <tableName>, as: <dimensionName> }
- sources: # Fallback if the first set is missing
- { metric: <fallbackMetricA>, table: <tableName>, as: <dimensionName> }
- { metric: <fallbackMetricB>, table: <tableName>, as: <dimensionName> }
per_row: <true|false>
group_by: <label | [labels]>
chart_meta:
description: ...
family: ...
unit: ...
Sources vs. Alternatives:
sources: defines the primary or default input set — used when there is only one way to compute the metric.alternatives: defines ordered fallback sets, each containing its own sources: block.The collector evaluates alternatives in order and uses the first set that successfully produces data.
| Item | Field | Type | Required | Default | Applies to | Description |
|---|---|---|---|---|---|---|
| Virtual Metric | name | string | yes | — | all | Unique within the profile. Used as metric/chart base name. |
sources | array<Source> | no* | — | totals, per_row, grouped | Direct source set. Ignored if alternatives exist (alternatives take precedence). | |
alternatives | array<Alternative> | no* | — | totals, per_row, grouped | Ordered fallback sets. The first alternative whose sources produce data is used. | |
per_row | bool | no | false | per-row/grouped | When true, emits one output per input row; sources become dimensions; row tags attach. | |
group_by | string / array | no | — | per-row/grouped | Label(s) used as row-key hints (in order). Missing/empty hints fall back to a full-tag stable key. With per_row:false, this acts like PromQL’s sum by (...). | |
chart_meta | object | no | — | all | Presentation metadata (description, family, unit, type). | |
| Source | metric | string | yes | — | — | Name of an existing metric (scalar or table column metric). |
table | string | yes | — | — | Table name for the originating metric. Must match the metric’s table when used in per-row/grouped. | |
as | string | yes | — | — | Dimension name within the composite (e.g., in, out). | |
| Alternative | sources | array<Source> | yes | — | — | All sources in an alternative are evaluated together. If none produce data, the collector tries the next alternative. Per-row/group rules apply within the winning alternative. |
At least one of
sourcesoralternativesmust be defined.
| Rule | Description |
|---|---|
| Precedence | If both sources and alternatives exist, alternatives take precedence. |
| Same-table requirement | When per_row or group_by is used, all sources must originate from the same table. For alternatives, this rule applies within each alternative set. |
| per_row: true | One output per input row; multiple sources become chart dimensions (as); row tags attach automatically. |
| group_by (with per_row:true) | Acts as row-key hints (in order). Missing or empty hints fall back to a full-tag composite key. |
| group_by (with per_row:false) | Aggregates rows by the listed labels, similar to PromQL’s sum by (...). |
| Alternative evaluation | Alternatives are checked in order. The first whose sources produce data becomes the “winner”; others are ignored. |
| Parent metadata | The virtual metric emits charts using its own name and chart_meta, even when data comes from an alternative. |
| Dimensions | Each as value defines a dimension in the resulting chart (e.g., in, out, total). |
| Totals vs per-row | Omitting both per_row and group_by produces a single total chart across all rows (device-wide view). |
virtual_metrics:
- name: ifTotalTraffic
sources:
- { metric: _ifHCInOctets, table: ifXTable, as: in }
- { metric: _ifHCOutOctets, table: ifXTable, as: out }
per_row: true
group_by: ["interface"]
chart_meta:
description: Traffic per interface
family: 'Network/Interface/Traffic'
unit: "bit/s"
What this does:
ifXTable.in and out.group_by: ["interface"] provides key hints to keep per-interface charts stable.per_row or group_by requires all sources to come from the same table.virtual_metrics:
- name: ifTotalTraffic
sources:
- { metric: _ifHCInOctets, table: ifXTable, as: in }
- { metric: _ifHCOutOctets, table: ifXTable, as: out }
chart_meta:
description: Total traffic across all interfaces
family: 'Network/Total/Traffic'
unit: "bit/s"
What this does:
ifXTable into a single chart.in, out) representing the total interface traffic for the entire device.per_row or group_by fields → a single total chart (device-wide view).virtual_metrics:
- name: ifTypeTraffic
sources:
- { metric: _ifHCInOctets, table: ifXTable, as: in }
- { metric: _ifHCOutOctets, table: ifXTable, as: out }
per_row: false
group_by: ["ifType"]
chart_meta:
description: Traffic aggregated by interface type
family: 'Network/InterfaceType/Traffic'
unit: "bit/s"
What this does:
ifType label into grouped totals.in and out dimensions aggregated by interface type.virtual_metrics:
- name: ifTotalPacketsUcast
alternatives:
- sources:
- { metric: _ifHCInUcastPkts, table: ifXTable, as: in }
- { metric: _ifHCOutUcastPkts, table: ifXTable, as: out }
- sources:
- { metric: _ifInUcastPkts, table: ifTable, as: in }
- { metric: _ifOutUcastPkts, table: ifTable, as: out }
chart_meta:
description: Total unicast packets across all interfaces (in/out)
family: 'Network/Total/Packet/Unicast'
unit: "{packet}/s"
What this does:
name and chart_meta, sourcing values from the selected child.sources and alternatives are present, alternatives take precedence.virtual_metrics:
- name: ifTotalPacketsByKind
sources:
- { metric: _ifHCInUcastPkts, table: ifXTable, as: in_ucast }
- { metric: _ifHCOutUcastPkts, table: ifXTable, as: out_ucast }
- { metric: _ifHCInMulticastPkts, table: ifXTable, as: in_mcast }
- { metric: _ifHCOutMulticastPkts, table: ifXTable, as: out_mcast }
- { metric: _ifHCInBroadcastPkts, table: ifXTable, as: in_bcast }
- { metric: _ifHCOutBroadcastPkts, table: ifXTable, as: out_bcast }
chart_meta:
description: Total packets across all interfaces by kind (in/out)
family: 'Network/Total/Packet/ByKind'
unit: "{packet}/s"
What this does
as becomes a dimension (in_ucast, out_ucast, in_mcast, …).per_row/group_by → totals aggregated across all interfaces.