Skip to main content

SNMP Profile Format

Overview

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:

  • which OIDs to query
  • how to interpret the returned values
  • how to transform them into metrics, dimensions, tags, and metadata

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.

How Profiles Work

When Netdata connects to an SNMP device, the collector:

  1. Reads the device’s sysObjectID and sysDescr.
  2. Evaluates all available profiles.
  3. Applies all profiles whose selectors match (multiple profiles can apply simultaneously).
  4. Uses the combined configuration to:

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: Complete SNMP Profile

# 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"

Profile Structure

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>
SectionPurpose
selectorDefines which devices the profile applies to.
extendsInherits and merges other base profiles.
metadataCollects device-level information (host labels).
metricsDefines which OIDs to collect and how to chart them.
metric_tagsDefines global dynamic tags collected once per device and attached to all metrics.
static_tagsDefines fixed tags applied to all metrics.
virtual_metricsDefines calculated or aggregated metrics based on others.

1. selector

You use the selector to:

  • Target specific device families (e.g., Cisco, Juniper, HP)
  • Match devices supporting specific MIBs
  • Exclude unwanted devices

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:

  • Each selector rule is a set of conditions (sysobjectid, sysdescr, etc.).
  • For a rule to match, all its conditions must pass.
  • A profile is applied if at least one rule in the selector list matches the device.
  • If both sysobjectid and sysdescr are defined within the same rule, both must succeed.

Supported conditions:

KeyWhat It ChecksMatch Criteria (Pass)Fails When...
sysobjectid.includeDevice sysObjectIDMatches at least one pattern in the list.No items match.
sysobjectid.excludeDevice sysObjectIDMatches none of the listed patterns.Any item matches.
sysdescr.includeDevice sysDescr (case-insensitive)Contains at least one substring in the list.No listed substrings are found.
sysdescr.excludeDevice sysDescr (case-insensitive)Contains none of the listed substrings.Any listed substring is found.

2. extends

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:

  1. Order matters — profiles are loaded in the order listed.
  2. Metrics are merged — all metrics from all referenced profiles are included.
  3. Later overrides earlier — if the same field is defined multiple times, the last one wins.

Metric override identity depends on metric type:

  • Scalar metrics use symbol.name + symbol.OID. This preserves same-name scalar fallback definitions that try alternative OIDs.
  • Table metrics use logical table identity (table.name when set, otherwise table.OID) + symbol.name. If two inherited profiles define the same table metric name, the later profile wins even when the table or symbol OID differs. If the same logical table name is inherited with a different table OID, the later table definition replaces the earlier table definition; symbols from the earlier table OID are not merged into the later table. Different metric names can still read from the same column OID when separate transformations are needed.

Common base profiles

ProfileProvidesTypical Use
_system-base.yamlBasic system info (uptime, name, contact)All devices
_std-if-mib.yamlInterface statistics (IF-MIB)Network devices
_std-ip-mib.yamlIP-level statistics (IP-MIB)Routers, switches
_std-tcp-mib.yamlTCP statisticsServers, firewalls
_std-udp-mib.yamlUDP statisticsServers, firewalls
_std-ups-mib.yamlPower and UPS metricsUPS devices

3. metadata

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:

  • Staticvalue: is a fixed string.
  • Dynamic — the value is read from one or more SNMP OIDs using either:
    • 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.
  • These values appear as device (virtual node) host labels in the Netdata UI.
  • They are not per-metric tags and are applied to the device itself, not individual charts.
tip

See Tag Transformation for supported transformations and syntax examples.

4. metrics

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:

  • Scalars — single values that apply to the entire device (for example, uptime).
  • Tables — repeating rows of related values (for example, interfaces, disks, sensors).
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:

  • Each entry defines a metric or table of metrics to collect via SNMP.
  • Scalars use a single symbol, while tables define a table and one or more symbols.
  • Metrics can include transformations (extract_value, scale_factor, etc.) and chart metadata.
  • Table metrics can include tags (metric_tags) to identify rows by interface, disk, or other attributes.
tip

See also

Underscore-prefixed metrics

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, while preserving them in the internal hidden metric set for collector-level consumers.

# 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 }

Scalar symbol fallbacks

You can express “try this OID, otherwise try that OID” by declaring multiple scalar 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"

5. metric_tags

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:

  • Attach device-wide metadata such as serial number, firmware version, or model.
  • Enable grouping and filtering by hardware, OS, or vendor attributes.
  • Complement per-metric tags (for example, per-interface or per-sensor tags in tables).
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:

  • Each tag is collected once per device, not per metric or per table row.
  • The resulting tag values are attached to all metrics collected by the profile.
  • Tags can be transformed (for example, reformatted or mapped) using the same rules as per-metric tags.
tip

See Tag Transformation for supported transformations and syntax examples.

Underscore-prefixed tags

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"

Tag fallback (first non-empty wins)

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

6. static_tags

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:

  • Add environment or deployment identifiers (for example, environment, region, or service).
  • Simplify filtering, grouping, and alerting across metrics from multiple devices.
  • Provide consistent context (for example, datacenter or team ownership).
static_tags:
- tag: environment
value: production
- tag: region
value: us-east-1
- tag: service
value: network

How it works:

  • Each tag is added to all metrics collected by the profile.
  • Static tags are merged with any dynamic tags defined in metric_tags.
  • Device-specific or dynamic tags always take precedence if they overlap.

7. virtual_metrics

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:

  • Combine related counters (for example, in + out traffic or errors).
  • Create fallbacks (prefer 64-bit counters, fall back to 32-bit if missing).
  • Aggregate or group metrics per tag (for example, total per interface or per type).
  - 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:

  • Defines a new virtual metric named ifTotalTraffic.
  • Uses existing metrics (ifHCInOctets, ifHCOutOctets) as sources.
  • The as field names the resulting dimensions (in, out).
  • The resulting chart behaves like a regular metric — visible in dashboards, alertable, and included in exports.

Collecting Metrics

This section explains how SNMP data is structured and how it maps to metrics in a Netdata profile.

Understanding SNMP Data

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 (Single Values)

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:

  • Collects the sysUpTime value once per device.
  • The .0 at the end indicates there is only one instance of this value.
  • Common scalar metrics: device uptime, total memory, or overall temperature.

Table Metrics (Multiple Rows)

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).
  • Each column (symbol) in the table has its own OID pattern but shares the same row indexes.

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:

  1. The collector reads both columns (ifHCInOctets and ifName) from the same table.
  2. It aligns rows using their shared SNMP index (1, 2, …).
  3. Each metric is emitted with its corresponding tag from the same row.

What this does:

  • Collects traffic (ifHCInOctets) from each interface.
  • Tags each row with its name (ifName) from the same index.
  • Produces metrics like:
    ifHCInOctets{interface="eth0"} = 1024
    ifHCInOctets{interface="eth1"} = 2048

Metric Types

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 TypeDefault Netdata TypeTypical Use
Counter32, Counter64rateNetwork traffic, packet counters
Gauge32, IntegergaugeTemperatures, usage levels, statuses
TimeTicksgaugeUptime, 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:

  • Forces ifInOctets to be treated as a gauge (instantaneous value) instead of a rate.
  • Normally, Counter types are automatically converted to per-second rates.

Chart Metadata

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"
FieldTypeRequiredDescription
descriptionstringnoHuman-readable description shown in dashboards and alerts.
familystringnoChart grouping path (slashes / define hierarchy). Helps organize charts by system or subsystem.
unitstringnoDisplay unit, e.g. "bit/s", "%", "{status}", "Cel".
typestringnoOptional chart style override: line, area, or stacked. Defaults depend on metric type.

Adding Tags to Metrics

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:

  • Attaches tags to each metric as labels.
  • Uses tags to differentiate rows when building charts.
  • Requires at least one tag for every table metric (to identify each row).

Key Concepts:

ConceptDescription
Table metrics must have tagsEach 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 for identityScalars represent one value for the entire device, so tags are not part of their normal public identity contract.
Static tagsFixed values that never change (for example, datacenter, environment).
Dynamic tagsExtracted from SNMP data — from table columns, related tables, or row indexes.
Global tagsDefined in the profile’s top-level metric_tags section and applied to all metrics.

Tag Types and Available Transformations:

Tag TypeDescriptionSupported Transformations
StaticFixed tags with constant values.None (value is fixed).
Same-TableValues from columns in the same table as the metric.mapping, extract_value, match_pattern + match_value, match + tags
Cross-TableValues from another table.mapping, extract_value, match_pattern + match_value, match + tags
Index-BasedValues derived from the OID index of each row.mapping (optional)
Index TransformAdjusts multi-part indexes so cross-table tags align correctly.— (structural, not a transformation)

Summary:

  • Each table metric must define at least one tag source (metric_tags) to distinguish rows.
  • Tags can come from the same table, another table, or the row index itself.
  • Scalar metrics do not use tags for identity. Internal bundled profiles may attach sidecar scalar values to hidden carrier metrics, but that is not a stable public authoring contract.
  • Tag transformations (mapping, extract_value, match_pattern, match + tags) can modify or extract parts of raw values.
  • Static tags apply globally and are not transformed.
  • Index transformations are a special mechanism used only for aligning multi-part indexes between tables.
  • Avoid reusing built-in device label names such as sysName, address, vendor, model, and device_type for row tags. Those keys are reserved for collector-provided device metadata labels.

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:

  1. The collector walks the table and collects both columns: ifInOctets (value) and ifDescr (tag source).
  2. It aligns them by their shared SNMP index (1, 2, …).
  3. Each metric row is tagged with the corresponding column value from the same index.

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:

  • The collector collects metrics from ifTable but fetches tag values from ifXTable.
  • It matches rows from both tables using their shared index (.1, .2, …).
  • The interface tag is populated from ifXTable.ifName for each matching row

Static

Static 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

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:

  • These tags are injected into every metric reported by the profile.

Typical use cases:

  • Identify the datacenter, region, or cluster where the device belongs.
  • Mark metrics from staging or production environments.
  • Add organization-wide context that doesn’t depend on SNMP data.

Metric-level Static Tags

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:

  • Adds the tags source=snmp and interface_type=physical only to the ifInOctets metric.
  • Does not affect other metrics in the same profile.

Metric-level static tags are technically supported but rarely needed. In most cases, prefer profile-level static_tags for consistency and simplicity.

Same-Table

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:

  • Retrieves both the metric value and the tag column from the same table row.
  • Automatically aligns rows by their shared index.
  • Adds the tag to every metric collected from that row.
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:

  • Collects ifInOctets (input bytes) for each row in ifTable.
  • Reads the ifDescr column from the same table to label each row.
  • Produces metrics like:
    ifInOctets{interface="eth0"} = 1000
    ifInOctets{interface="eth1"} = 2000

Cross-Table

Cross-table tags let you use data from another SNMP table as a tag source.

The collector:

  • Reads tag values from the specified table: instead of the current one.
  • Matches rows between tables by their index.
  • When index structures differ, an optional index_transform can modify the current table’s index to align it with the target.
  • When the target table is keyed differently, an optional lookup_symbol can match a transformed index value against a column in the target table and then read tags from the matched row.

Same Index

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:

  • Collects ifInOctets from ifTable.
  • Finds the row with the same index in ifXTable (e.g., .2).
  • Uses ifName as the interface tag.
  • Produces metrics like:
    ifInOctets{interface="xe-0/0/1"} = 123456

With Index Transformation

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:

  • The first component (2) is the IP version (e.g., 2 = IPv4, 3 = IPv6).
  • The second component (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:

  • Collects IP traffic metrics from ipIfStatsTable.
  • Keeps only the second index element (start: 1, end: 1) from 2.1 → becomes 1.
  • Looks up that interface index in ifXTable to find the corresponding ifName.
  • Produces:
    ipIfStatsHCInOctets{_interface="xe-0/0/1"} = 38560
How index_transform Works

index_transform tells the collector which parts of the current table’s index to keep when matching rows across tables.

ConceptExample
Original index2.1 (from ipIfStatsTable) → [ipVersion, ifIndex]
Target index1 (from ifXTable)
Transformindex_transform: [ { start: 1, end: 1 } ]
ResultThe 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).
  • Each range defines which parts of the index to keep.
  • You can list multiple ranges to combine non-contiguous parts.
  • drop_right can be used instead of end when you need to keep a variable-length prefix of the index and trim a fixed number of trailing elements.
  • The goal is to make the current table’s index match the target table’s index so tags align correctly.

Example with drop_right:

metric_tags:
- tag: peer_index
table: peerTable
symbol:
OID: 1.2.3.4.5
name: peerRemoteAs
index_transform:
- start: 0
drop_right: 2

If the current row index is 1.192.0.2.1.1.128, the transform keeps 1.192.0.2.1 and drops the trailing AFI / SAFI pair.

With Value Lookup (lookup_symbol)

Some vendor MIBs split related data across tables that do not share the same row index.

For example:

  • a prefix-counter table may be indexed by peerIndex.afi.safi
  • the peer table may be indexed by routingInstance.localAddr.remoteAddr
  • but the peer table still contains a peerIndex column

In that case, index_transform alone is not enough:

  • it can extract the current row's peerIndex
  • but it cannot guess which peer-table row owns that peerIndex

Use lookup_symbol to tell the collector:

  1. Extract a lookup value from the current row index
  2. Find the row in the target table whose lookup_symbol column matches that value
  3. Read the requested symbol from that matched row
metrics:
- MIB: BGP4-V2-MIB-JUNIPER
table:
OID: 1.3.6.1.4.1.2636.5.1.1.2.6.2
name: jnxBgpM2PrefixCountersTable
symbols:
- OID: 1.3.6.1.4.1.2636.5.1.1.2.6.2.1.8
name: bgpPeerPrefixesAccepted
metric_tags:
- tag: neighbor
table: jnxBgpM2PeerTable
symbol:
OID: 1.3.6.1.4.1.2636.5.1.1.2.1.1.1.11
name: jnxBgpM2PeerRemoteAddr
lookup_symbol:
OID: 1.3.6.1.4.1.2636.5.1.1.2.1.1.1.14
name: jnxBgpM2PeerIndex
index_transform:
- start: 0
end: 0

What this does:

  • Collects accepted-prefix counters from the Juniper prefix table
  • Takes the first index element from the current row (peerIndex)
  • Scans jnxBgpM2PeerTable.jnxBgpM2PeerIndex for a matching value
  • Reads jnxBgpM2PeerRemoteAddr from the matched peer-table row
  • Produces metrics like:
    bgpPeerPrefixesAccepted{neighbor="192.0.2.1"} = 1234

Important behavior:

  • lookup_symbol is used only for cross-table tags
  • it works together with index_transform, not instead of it
  • if no row matches, the tag lookup fails for that row
  • if one row matches, the collector reads the requested tag from that row
  • if multiple rows match, the lookup succeeds only when all matched rows resolve to the same final tag value; conflicting values fail the lookup

Index-Based

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:

  • Splits the table’s row index into numbered parts (1-based).
  • For each index: rule, assigns a tag using the specified position in the index.
  • Converts numeric index components to strings automatically.
  • Attaches all resulting tags to the metric collected from that row.
  • Can also derive tags from the full row index using index_transform plus symbol.format, symbol.extract_value, symbol.match_pattern, or mapping, even when there is no column OID for that tag.
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:

  • Extracts the first three components of each row’s OID index and uses them as tags.
  • For example, if the full OID is:
    1.3.6.1.2.1.149.1.5.1.1.3.1.6.200
    The collector interprets:
    applIndex=1
    sipCommonStatusCodeMethod=6
    sipCommonStatusCodeValue=200
  • Produces metrics like:
    sipCommonStatusCodeIns{applIndex="1", sipCommonStatusCodeMethod="6", sipCommonStatusCodeValue="200"} = 42

Derived tag example from a transformed index:

metric_tags:
- tag: neighbor
symbol:
name: peerRemoteAddrIndex
format: ip_address
index_transform:
- start: 1
drop_right: 2

If the current row index is 1.192.0.2.1.1.128, the collector:

  • keeps the peer-address part only: 192.0.2.1
  • formats it as an IP address
  • emits neighbor="192.0.2.1"

Tag Transformation

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), and
  • metric_tags (e.g., per-row interface labels).

Available Tag Transformations:

TransformationPurposeExample Input → Output
formatConvert the raw SNMP value before tag parsing.0x18fd74331a9c → "18fd74331a9c"
mappingReplace numeric/string codes with names.1 → "ethernet", 161 → "lag"
extract_valueExtract a substring via regex (first group)."RouterOS CCR2004-16G-2S+" → "CCR2004-16G-2S+"
match_pattern + match_valueReplace 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:

RuleDescription
WhereCan be used inside metadata.*.fields.*.symbols[] and metric_tags[].
Order of application1️⃣ match_pattern + match_value or extract_value (whichever is present) → 2️⃣ mapping → 3️⃣ match + tags (if defined).
No match behaviorextract_value: keeps the original value.
match_pattern: skips the value (tag not emitted).
match + tags: emits no tags.
Multiple symbolsIf multiple symbols are listed for the same tag, the first non-empty result is used.
Mapping key consistencyKeys in a mapping must all be the same type — all numeric or all string.
Mapping modesTags and metadata support only exact-match mapping. Use mapping.items; mapping.mode is optional and defaults to exact.
SafetyKeep regexes simple and, when possible, anchor them (e.g. ^pattern$) to prevent unwanted matches.

Quick Syntax Recap:

  • mapping

    mapping:
    items:
    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
  • format

    symbol:
    OID: 1.3.6.1.2.1.17.1.1
    name: dot1dBaseBridgeAddress
    format: hex

Format

Use format when the raw SNMP value must be converted before tag or metadata processing.

The collector:

  • Applies format when converting the raw SNMP value to a string.
  • Then applies the configured tag or metadata transformations to that formatted string.
  • Supports the same format values accepted by symbol definitions elsewhere in the profile.

Where it can be used:

  • metadata.device.fields.<field>.symbol
  • metadata.device.fields.<field>.symbols[]
  • metric_tags[].symbol

Currently used by this profile set:

  • format: hex for octet-string values such as:
    • MAC addresses
    • binary management-address values
    • capability bitmaps

Example:

metadata:
device:
fields:
bridge_base_address:
symbol:
OID: 1.3.6.1.2.1.17.1.1
name: dot1dBaseBridgeAddress
format: hex

Mapping

Use mapping to replace raw tag values with human-readable text labels.

mapping.mode is optional here and defaults to exact. bitmask mode is not supported for tags or metadata.

The collector:

  • Looks up the raw value in the mapping table.
  • Replaces it with the corresponding string.
  • If the value is not found in the mapping, the original value is kept.
  • Keys can be numeric or string, but must be consistent in type.
  • Mapping is applied to tag values from 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:
items:
1: "other"
6: "ethernet"
24: "loopback"
131: "tunnel"
161: "lag"

What this does:

  • Replaces numeric interface type codes (1, 6, 24, 131, 161) with readable names (other, ethernet, loopback, tunnel, lag).
  • If a device reports an unknown type, the original numeric value is used.
  • Works identically for metadata fields and metric_tags.
  • Legacy flat-map syntax remains supported for backward compatibility: mapping: { 6: "ethernet", 161: "lag" }

Extract Value

Use extract_value to capture a part of a string using a regular expression.

The collector:

  • Applies the pattern to the raw value.
  • Replaces the value with the first capture group ( … ).
  • Keeps the original value if no match is found.
  • Searches anywhere in the string unless you anchor the pattern with ^ or $.
  • Uses the first non-empty result when multiple 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'

Match Pattern

Use match_pattern and match_value together to build a tag value using multiple regex capture groups.

The collector:

  • Tests the value against the regular expression in match_pattern.
  • If it matches, replaces the value with match_value.
  • Within match_value, you can reference capture groups using $1, $2, $3, etc.
  • If the value does not match, it is skipped (ignored).
  • Works both for reformatting captured text and for assigning a static replacement when matched.

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'

Match (Multiple Tags)

Use match and tags to create multiple tags from a single SNMP value using a regular expression with capture groups.

The collector:

  • Applies the regex in match to the raw value.
  • If it matches, creates all tags listed under tags, substituting $1, $2, $3, etc. from the capture groups.
  • If it doesn’t match, none of those tags are added.
  • Tags that resolve to an empty capture are not added.

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'
  • Handles common patterns like xe-0/0/1, ge-0/0/0, or GigabitEthernet1/0/24.
  • Output tags might be: if_family=xe, fpc=0, pic=0, port=1.

Value Transformation

Value transformations let you decode, process, or normalize raw SNMP symbol values before they are stored and charted.

For metrics, they are applied per symbol (per OID) during SNMP data collection and are not applied to virtual metrics.

format is the exception to the "metric values only" rule: it is symbol decoding, so it also applies when the same symbol is used for metric tags or device metadata. After decoding, metric tags and device metadata follow their own supported transformation rules.

These transformations are typically used to:

  • Extract numeric substrings from mixed strings.
  • Scale or convert units (bytes → bits, megabits → bits).
  • Map discrete states (1 = up, 2 = down, etc.) into named dimensions.

Available Value Transformations:

TransformationPurposeExample Input → Output
mappingConvert numeric or string codes into state dimensions.1 → up, 2 → down, 3 → testing
extract_valueExtract a numeric substring via regex."23.8 °C" → "23"
formatDecode raw SNMP data into a value shape before other processing.DateAndTime bytes → unix timestamp
scale_factorMultiply values by a constant to adjust units."1.5" (MBps) × 8 → 12 (Mbps)
match_pattern + match_valueReplace string metric values using regex groups or static text before numeric parsing."state=2" → "2"

Combination & Behavior:

RuleDescription
WhereMetric value transformations are used inside metrics[*].symbol or metrics[*].symbols[]; format also applies when symbols are used for metric tags or device metadata.
Order of applicationFor string-decoded metric values: 1️⃣ format (if present) → 2️⃣ extract_value (if present) → 3️⃣ match_pattern + match_value (if present) → 4️⃣ mapping → 5️⃣ numeric parsing → 6️⃣ scale_factor. Ordinary numeric PDUs skip the string-only extract_value and match_pattern steps and use numeric parsing → mappingscale_factor.
Scale factor positionscale_factor is always applied last, after all other metric value transformations. It cannot be combined with mapping.mode: bitmask.
String base parsingString-like values are parsed as base-10 by default. If format: hex is set, extracted values are parsed as base-16.
Data type handlingTransformations preserve numeric type (integer/float) unless the mapping converts it to a multi-value metric.
Error handlingextract_value keeps the original value when it does not match; match_pattern fails the metric value when it does not match; no-value format sentinels are treated as missing.
ApplicabilityMetric value transformations affect metric values only; format also decodes tag and metadata symbol values.
Mapping syntaxmapping.items defines the lookup table. mapping.mode is optional and defaults to exact. Legacy flat-map syntax remains supported for backward compatibility.
Mapping behaviorExact mode preserves the legacy exact-match/remap behavior. bitmask mode is metric-value only: every mapped bit becomes a dimension, the raw numeric value is preserved, key 0 matches only raw value 0, and unknown bits are ignored.

Quick Syntax Recap:

  • mapping

    mapping:
    items:
    1: up
    2: down
    3: testing
  • mapping (bitmask mode)

    mapping:
    mode: bitmask
    items:
    1: internalError
    128: processorPresent
    1024: processorThrottled
  • extract_value

    extract_value: '(\d+)'   # First capture group is used
  • format: hex

    format: hex
    extract_value: '^([0-9a-f]{2})' # First byte of an OCTET STRING
  • format: snmp_dateandtime

    format: snmp_dateandtime   # SNMPv2-TC DateAndTime OCTET STRING -> unix timestamp
  • format: text_date

    format: text_date   # Textual dates such as "2026-12-31" -> unix timestamp
  • scale_factor

    scale_factor: 8   # Octets → bits

Mapping

Use mapping to convert raw metric values into state dimensions or decoded bitmask dimensions.

mapping.mode defaults to exact. Use mapping.mode: bitmask when the raw metric value is a flag field where multiple bits may be set at the same time.

In exact mode, the emitted dimension names come from the string side of the mapping:

  • Numeric key -> string value (1: up) emits dimensions named after the mapped string values (up, down, ...).
  • String key -> numeric value (OK: 0) first normalizes the value to the numeric target, then emits dimensions named after the original string keys (OK, WARNING, ...).
  • Numeric key -> numeric value is treated as value normalization only and does not emit multi-value dimensions.

The collector:

  • Evaluates the value against mapping.items.
  • In exact mode, creates dimensions using the mapping's string labels, following the rules above.
  • Sets that dimension to 1 if the current value matches the key, or 0 otherwise.
  • In bitmask mode, sets every mapped dimension whose bit is active to 1, and inactive mapped bits to 0.
  • If the value doesn’t match any exact key, all exact-mode dimensions are 0.
  • mapping.mode: bitmask works only for metric values, not for tags or metadata.
  • mapping.mode: bitmask keys must be 0 or a single power-of-two bit (1, 2, 4, 8, ...).
  • scale_factor cannot be combined with mapping.mode: bitmask.
  • If multiple bit keys map to the same dimension, that dimension is active when any mapped bit is active.
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:
items:
1: up
2: down
3: testing

What this does:

  • Converts SNMP integer values (1, 2, 3) into a multi-value metric with dimensions up, down, and testing.
  • The dimension corresponding to the current value reports 1; all others report 0.
  • Legacy flat-map syntax remains supported and is equivalent to exact mode.
  • For string -> numeric exact mappings, the emitted dimensions use the original string keys instead of the normalized numeric values.

Bitmask example:

metrics:
- table:
OID: 1.3.6.1.4.1.674.10892.1.1100.32
name: processorDeviceStatusTable
symbols:
- OID: 1.3.6.1.4.1.674.10892.1.1100.32.1.6
name: processorDeviceStatusReading
mapping:
mode: bitmask
items:
1: internalError
2: thermalTrip
32: configurationError
128: processorPresent
256: processorDisabled
512: terminatorPresent
1024: processorThrottled

What this does:

  • Treats the raw value as a bitmask where multiple bits can be active at once.
  • Emits a multi-value metric with one dimension per mapped bit.
  • Requires each declared key to represent either 0 or exactly one bit.
  • Preserves the raw numeric metric value alongside the decoded dimensions.
  • Ignores active bits that are not declared in mapping.items.

Extract Value

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:

  • Applies the regular expression to the raw SNMP value.
  • Uses the first capture group ( … ) as the new metric value.
  • If the pattern doesn’t match, the original value is kept.
  • Works for any metric type (string or numeric).
  • When multiple 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:

  • Applies the regex (\d+) to the string "23.8 °C".
  • Extracts only the numeric part "23" and uses it as the metric value.
  • If the value doesn’t match, the original string is retained.
  • Ideal for string metrics that embed numbers, units, or labels.
  • If format: hex is also set, the extracted value is interpreted as hexadecimal before being stored as a metric.

Format

Use format to decode raw SNMP values as a symbol is converted into its textual or numeric representation.

For metric values, format runs before the rest of the value-processing pipeline. For metric tags and device metadata, format runs before their own supported extraction, match, and mapping rules. scale_factor remains metric-value-only. Ordinary numeric PDUs do not pass through string-only processing such as extract_value or match_pattern unless an explicit string-decoding format routes them through the string processor first.

If a format yields no value (for example, text_date encounters a vendor sentinel such as 0, 4294967295, never, or n/a), the result is treated as missing. For metrics, no metric value is produced from that symbol. For metric tags and device metadata, no tag or metadata value is produced from that symbol.

Supported formats:

  • hex: decodes OCTET STRING bytes to lowercase hexadecimal text.
  • ip_address: decodes IP address values.
  • mac_address: decodes MAC address values.
  • snmp_dateandtime: decodes SNMPv2-TC DateAndTime OCTET STRING values into unix timestamps. The 11-octet form uses its embedded UTC offset. The 8-octet form has no timezone fields, so the collector interprets it as UTC because the device timezone is unavailable.
  • text_date: parses common textual date strings and epoch strings into unix timestamps. Vendor no-value sentinels such as 0, 4294967295, never, and n/a are treated as missing values.
  • uint32: interprets integer values as unsigned 32-bit values.
metrics:
- MIB: EXAMPLE-MIB
symbol:
OID: 1.3.6.1.4.1.99999.1.1.0
name: example.expiry_timestamp
format: snmp_dateandtime

The decoded value becomes the metric value seen by later processing steps, such as extract_value, mapping, scale_factor, or transform.

Scale Factor

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:

  • Multiplies the raw SNMP value by the specified factor.
  • Applies to both integer and floating-point values.
  • Keeps the result in the same numeric type (integer or float).
  • Works for metric values only (not for tags or metadata).
  • Applies after all other transformations on the same metric (such as 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:

  • Multiplies octet counters by 8, reporting traffic in bits per second instead of bytes.
  • Converts ifHighSpeed from megabits to bits.
  • Ensures scaling happens after other transformations, such as value extraction or regex processing.

Virtual Metrics

  • Virtual metrics are calculated metrics built from other metrics in your profile (or inherited ones).
  • They don’t query SNMP; they reuse existing metric values to create totals, fallbacks, or per-row aggregations.
  • Once computed, they behave like normal metrics: charted, tagged, and alertable.

Common use cases:

  • Fallbacks: prefer 64-bit counters, fall back to 32-bit if missing.
  • Sums/Combines: add related metrics (e.g., in + out traffic).
  • Per-row totals: aggregate multiple columns into one per-interface metric.

Structure

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: [<labels>]
emit_tags:
- { tag: <outputTag>, from: <sourceTag> }
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.

Config reference

ItemFieldTypeRequiredDefaultApplies toDescription
Virtual MetricnamestringyesallUnique within the profile. Used as metric/chart base name.
sourcesarray<Source>no*totals, per_row, groupedDirect source set. Ignored if alternatives exist (alternatives take precedence).
alternativesarray<Alternative>no*totals, per_row, groupedOrdered fallback sets. The first alternative whose sources produce data is used.
per_rowboolnofalseper-row/groupedWhen true, emits one output per input row; sources become dimensions; row tags attach.
group_byarray<string>noper-row/groupedLabel(s) used as row-key hints (in order). With per_row:true, missing/empty hints fall back to a stable key built from all non-underscore tags. With per_row:false, this acts like PromQL’s sum by (...).
emit_tagsarray<EmitTag>noper-row/groupedRenames or selects which source tags are emitted on the resulting virtual metric. Useful when grouping by private tags such as _neighbor but exporting standard tags such as neighbor.
chart_metaobjectnoallPresentation metadata (description, family, unit, type).
SourcemetricstringyesName of an existing metric (scalar or table column metric).
tablestringno*Table name for the originating metric. Required for table-derived grouped/per-row virtual metrics. Scalar sources may omit it.
asstringnoOptional dimension name within a composite (e.g., in, out). Single-source virtual metrics do not need it.
dimstringnoSelects one dimension from a MultiValue source metric (for example start or established) before aggregation. Useful when composing virtual metrics from mapped status charts.
EmitTagtagstringyesOutput tag name to emit on the virtual metric.
fromstringyesExisting source-tag name to copy from the grouped source rows.
Alternativesourcesarray<Source>yesAll 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 sources or alternatives must be defined.

Rules & Constraints

RuleDescription
PrecedenceIf both sources and alternatives exist, alternatives take precedence.
Same-table requirementWhen 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: trueOne 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 stable key built from all non-underscore tags.
group_by (with per_row:false)Aggregates rows by the listed labels, similar to PromQL’s sum by (...).
emit_tagsIf omitted, per_row:true emits the winning row tags as-is. Grouped non-per_row metrics emit the group_by labels by default. When set, only the listed tags are emitted, using the from source-tag names.
Alternative evaluationAlternatives are checked in order. The first whose sources produce data becomes the “winner”; others are ignored.
Parent metadataThe virtual metric emits charts using its own name and chart_meta, even when data comes from an alternative.
DimensionsEach as value defines a dimension in the resulting chart (e.g., in, out, total).
Selected source dimensionWhen dim is set on a source, the collector reads only that MultiValue dimension from the source metric and ignores the rest.
Totals vs per-rowOmitting both per_row and group_by produces a single total chart across all rows (device-wide view).

Examples

Per-row aggregation from one table (in + out traffic)

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:

  • Creates one output per input row in ifXTable.
  • Each chart represents one interface with two dimensions: in and out.
  • group_by: ["interface"] provides key hints to keep per-interface charts stable.
  • If a hint is missing or empty, a stable key built from all non-underscore tags is used instead.
  • Constraint: per_row or group_by requires all sources to come from the same table.

Total aggregation (sum across all interfaces)

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:

  • Aggregates data from all rows in ifXTable into a single chart.
  • Produces two dimensions (in, out) representing the total interface traffic for the entire device.
  • No per_row or group_by fields → a single total chart (device-wide view).

Grouped aggregation (sum by label)

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"

Per-row availability from mapped status charts

virtual_metrics:
- name: bgpPeerAvailability
per_row: true
sources:
- { metric: bgpPeerAdminStatus, table: bgpPeerTable, as: admin_enabled, dim: start }
- { metric: bgpPeerState, table: bgpPeerTable, as: established, dim: established }
chart_meta:
description: BGP peer administrative and established availability
family: 'Network/Routing/BGP/Peer/Availability'
unit: "{status}"

What this does:

  • Reuses mapped one-hot status charts instead of adding duplicate raw-code metrics.
  • Reads only the start dimension from bgpPeerAdminStatus.
  • Reads only the established dimension from bgpPeerState.
  • Emits one per-peer chart row with stable dimensions admin_enabled and established.

Per-row grouping by private tags, but emitting normalized tags

virtual_metrics:
- name: bgpPeerAvailability
per_row: true
group_by: ["_neighbor", "_address_family", "_subsequent_address_family"]
emit_tags:
- { tag: neighbor, from: _neighbor }
- { tag: address_family, from: _address_family }
- { tag: subsequent_address_family, from: _subsequent_address_family }
sources:
- { metric: hwBgpPeerAdminStatus, table: hwBgpPeerRouteTable, as: admin_enabled, dim: start }
- { metric: hwBgpPeerState, table: hwBgpPeerRouteTable, as: established, dim: established }
chart_meta:
description: BGP peer availability
family: 'Network/Routing/BGP/Peer/Availability'
unit: "{status}"

What this does:

  • Groups rows using private helper tags that are not meant to appear in the final chart labels.
  • Emits standard operator-facing tags on the virtual metric (neighbor, address_family, subsequent_address_family).
  • Avoids collapsing multiple AFI/SAFI rows for the same peer into one output row.

What this does:

  • Performs PromQL-like “sum by (ifType)” aggregation.
  • Combines all rows sharing the same ifType label into grouped totals.
  • Result: one chart with in and out dimensions aggregated by interface type.
  • Constraint: all sources must come from the same table.

Alternatives (total; prefer 64-bit, fallback to 32-bit)

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:

  • Defines two alternatives, each as a list of sources.
  • At runtime, the collector evaluates alternatives in order and uses the first one where all source metrics exist and contain data (HC first).
  • Once a winner is found, later alternatives are ignored.
  • The parent emits metrics using its own name and chart_meta, sourcing values from the selected child.
  • If both sources and alternatives are present, alternatives take precedence.

Composite (multi-source total: unicast/multicast/broadcast

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

  • Builds a single total chart combining multiple related packet counters.
  • Each as becomes a dimension (in_ucast, out_ucast, in_mcast, …).
  • No per_row/group_by → totals aggregated across all interfaces.

Do you have any feedback for this page? If so, you can open a new issue on our netdata/learn repository.