Prometheus metric families
This page lists every metric family mikroscope exposes in Prometheus text
format: its name, its type, its labels, what it counts, and when it is not
there. It is read from internal/, internal/
and internal/. A family is listed under the source it
comes from, because that is what decides whether a given board has it.
Two expositions, one renderer
Section titled “Two expositions, one renderer”The agent serves /metrics on the router, and forward --prom :9124 serves
one on the collector host. Both are written by the same Totals code: the
collector feeds it the samples it pulled, so a deployment reached only through
the relay still gets scrape-independent families. They are not identical.
| Families | Agent :9123/metrics |
Collector --prom |
|---|---|---|
| everything recomputed from samples: CPU, windows, runs, receive path, memory, PMU, sensors, flash, disk, kernel log, observer counters | yes | yes |
device facts (mikroscope_device_info, ceilings, cadences) |
yes | yes, once the collector has fetched /capabilities |
the sampler’s timing histograms and mikroscope_slipped_total |
yes | no |
| trigger and capture families | yes, while CAPTURE_MB is above 0 |
no |
mikroscope_collector_*, mikroscope_derived_* |
no | yes |
mikroscope_api_* |
no | yes, once the API tier has delivered a sample |
Scroll sideways to see every column
The collector leaves mikroscope_slipped_total out rather than writing 0,
because a 0 there would be a claim about a sampler it never ran. To have both
sets in one Prometheus, scrape the collector for everything and the agent only
for what the collector cannot produce. Scraping the agent without the keep
list doubles every counter the collector also exposes:
- job_name: "mikroscope" scrape_interval: 5s static_configs: [{ targets: ["<collector host>:9124"] }]- job_name: "mikroscope-agent" scrape_interval: 5s static_configs: [{ targets: ["172.30.10.2:9123"] }] metric_relabel_configs: - source_labels: [__name__] regex: "mikroscope_(tick_.*|trigger_.*|capture.*|captures_held|slipped_total)" action: keepWhat the collector’s copy does differently
Section titled “What the collector’s copy does differently”The collector’s sink is built for a nominal 10 Hz whatever rate the agent runs
at (promHistogramRateHz in cmd/), so that its
bucket layout does not change when it reconnects to a differently configured
agent. Five things follow from that constant, read from the code:
mikroscope_info{rate_hz}on the collector reads10, not the agent’s rate./healthzhas the agent’s.mikroscope_has the bucketscpu_ busy_ ticks le="0"tole="11", sized for a 100 ms sample. An agent below 10 Hz puts its busier samples in+Inf.- The ring behind the trailing windows holds 60 s of the connected agent’s
samples: the collector reads the agent’s rate from its health check and sizes
the ring from it, so
window="60s"is 60 s at any rate. - The trailing mean behind
mikroscope_has a weight of 1/600, which is a 60 s memory at 10 Hz and shorter above it.softnet_ burst_ samples_ total - An interrupt line leaves
mikroscope_irq_totalafter 36 000 samples out of every top-K, which is one hour only at 10 Hz: 12 min at 50 Hz, 6 min at 100 Hz. The check runs every 1 000 samples, so a line can stay up to that much longer.
The counters on the collector count from the collector’s start, and
mikroscope_ and mikroscope_info{version} describe the
collector. mikroscope_self_* still describe the agent: they come from the
agent’s samples.
Conventions
Section titled “Conventions”- Counters count since the exporter started and never reset on a scrape.
The ring carries deltas;
/metricsaccumulates them.rate()over any range is then correct, and two scrapers see the same values. - Gauges are the newest sample. A floored source (thermal, cpufreq, slab,
buddyinfo, MTD) is absent from most samples by design, so its gauge holds
the last reading between emissions, and
mikroscope_says how old that reading is.source_ age_ seconds - Absent is not zero, with five exceptions. Most families for a source the kernel does
not have, or the deployment cannot read, are not rendered at all. The
exceptions are
mikroscope_,meminfo_ kbytes mikroscope_load,mikroscope_threads,mikroscope_andself_ rss_ bytes mikroscope_: they are written from the first sample and read 0 when their file cannot be read orirq_ errors_ total SOURCESleaves it out.mikroscope_also reads 0 on a kernel whoseirq_ errors_ total /proc/interruptshas noErrrow. - One dimension, one name. A processor is the label
cpueverywhere. Which cores, zones, interrupt lines, caches and counters exist is a property of the board; read the label, never assume a set. - No ratio in the samples. The busy-ratio gauges are window statistics
computed at scrape, and the collector’s
mikroscope_derived_*gauges are divisions it made beside their inputs. Every other ratio is yours to divide.
CPU ticks and /proc/stat
Section titled “CPU ticks and /proc/stat”| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_ |
counter | cpu, mode: user, nice, system, idle, iowait, irq, softirq, steal |
USER_HZ ticks per core and mode |
mikroscope_ |
counter | mode |
the same, from /proc/stat’s own cpu summary line; a separate name so summing the per-core series cannot double-count it |
mikroscope_ |
histogram | cpu, le |
busy ticks per sample, one bucket per achievable integer, 0 up to one more than a period holds, plus +Inf. _sum is the exact busy total. Recovers time above a threshold to one sample, not contiguity |
mikroscope_ |
counter | none | ctxt |
mikroscope_ |
counter | none | intr, every source |
mikroscope_forks_total |
counter | none | the processes line: RouterOS spawning scripts, fetches and containers, although the PID namespace hides the processes |
mikroscope_procs_blocked |
gauge | none | tasks in uninterruptible sleep; on a kernel without PSI the only direct stall signal |
Scroll sideways to see every column
A tick is busy when it is user, nice, system, irq, softirq or
steal. On the RB5009 with RouterOS 7.24.2 the irq column is always 0
(measured 2026-09-11), so hard-IRQ time is inside system: read the irq mode
as absent there, not as a router with no interrupt load.
Trailing windows and busy runs
Section titled “Trailing windows and busy runs”Computed at scrape from the ring over fixed wall-clock windows, so a scraper at any interval up to 60 s sees a transient’s peak whoever scraped last.
| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_ |
gauge | cpu, window: 1s, 10s, 60s; stat: max, min, p95 |
busy ratio statistics over the trailing window |
mikroscope_ |
gauge | window, stat |
the sampler’s measured interval over the trailing window; its max says whether the rate was delivered |
mikroscope_ |
histogram | cpu, threshold: 0.5, 0.9; le: 0.1, 0.2, 0.5, 1, 2, 5, 10, 30, 60, +Inf |
length of each run of consecutive samples at or above the busy ratio, in seconds of the samples’ own intervals, observed when the run ends |
mikroscope_ |
gauge | cpu, threshold |
how long the run in progress has lasted; 0 below the threshold |
Scroll sideways to see every column
A 2 s plateau is one observation of 2 in mikroscope_ and
twenty scattered 100 ms spikes are twenty of 0.1; the busy-tick histogram
cannot tell those apart.
The sampler’s own timing
Section titled “The sampler’s own timing”Agent only. A sample is read over a stretch of time, not at an instant, and these families measure that stretch.
| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_ |
histogram | le |
measured interval between samples; buckets at 0.5, 0.9, 0.95, 0.99, 1.01, 1.05, 1.1, 1.25, 1.5, 2 and 5 times the nominal period |
mikroscope_ |
histogram | le |
how late the loop ran after its ticker fired; buckets 0.1 ms, 0.25, 0.5, 1, 2, 5, 10, 20, 50, 100 ms |
mikroscope_ |
histogram | le |
how long reading every due source took; same buckets |
mikroscope_slipped_total |
counter | none | ticks whose read finished after the next tick was due |
Scroll sideways to see every column
A slipped tick is not a lost sample: the sample is still produced with its real
dt_ns. If mikroscope_slipped_total moves, distrust the sampler’s own
accounting before the router’s.
Receive path and interrupts
Section titled “Receive path and interrupts”/proc/net/softnet_stat, /proc/softirqs and /proc/interrupts are global
inside the container, unlike /proc/net/dev.
| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_softnet_total |
counter | cpu, kind: processed, dropped, time_squeeze |
per-CPU softnet counters |
mikroscope_ |
counter | cpu |
samples in which that CPU had any squeeze or drop; its rate is a duty cycle |
mikroscope_ |
counter | cpu |
the squeezed samples whose packet count was at or below that CPU’s trailing mean (EWMA with a one-minute memory); evidence of bursts shorter than a sample, not a count of them |
mikroscope_softirq_total |
counter | cpu, kind |
softirq counts; which kinds exist is the kernel’s list. NET_RX carries a router’s forwarding load |
mikroscope_irq_total |
counter | irq, name, cpu |
lines that appeared in any sample’s top-K. A line out of every top-K for an hour leaves the family, and restarts from 0 if it returns; on the collector the hour holds only at 10 Hz (above) |
mikroscope_ |
counter | none | every interrupt line summed, including those outside the top-K: the denominator for mikroscope_irq_total |
mikroscope_ |
counter | none | the Err row of /proc/interrupts, which the top-K never shows while it sits at zero |
Scroll sideways to see every column
Match an interrupt on its name label or on its rate, never on a hardcoded
name: which lines a NIC raises is a property of the board and its driver.
Scheduler, load and PSI
Section titled “Scheduler, load and PSI”| Family | Type | Labels | Absent when | Meaning |
|---|---|---|---|---|
mikroscope_load |
gauge | period: 1m, 5m, 15m |
no sample yet | load averages |
mikroscope_threads |
gauge | state: running, total |
no sample yet | from /proc/loadavg |
mikroscope_ |
counter | resource, kind: cpu/some, memory/some, memory/full, io/some, io/full |
the kernel has no /proc/pressure |
PSI stall microseconds |
mikroscope_ |
counter | cpu |
the kernel has no /proc/schedstat |
time tasks spent on each CPU |
mikroscope_ |
counter | cpu |
the same | time runnable tasks waited for each CPU |
Scroll sideways to see every column
Both PSI and schedstat families are absent on the RB5009, whose RouterOS 7.24.2 kernel has neither file:
Measured on RB5009UG+S+ · 4 × 1.4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · · /proc/pressure and /proc/schedstat absent
Memory
Section titled “Memory”| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_ |
gauge | field |
/proc/meminfo in kB: MemTotal, MemFree, MemAvailable, Buffers, Cached, Dirty, Writeback, Shmem, Slab, SReclaimable, SUnreclaim, AnonPages, Mapped, KernelStack, PageTables, Active, Inactive, Committed_AS, CommitLimit |
mikroscope_ |
counter | event |
/proc/vmstat events: pgfault, pgmajfault, pgscan_kswapd, pgscan_direct, pgsteal_kswapd, pgsteal_direct, pgalloc, pgfree, allocstall, compact_stall, oom_kill, pswpin, pswpout. pgalloc and allocstall are summed over zones |
mikroscope_vm_pages |
gauge | field |
/proc/vmstat levels in pages: nr_free_pages, nr_dirty, nr_writeback, nr_slab_reclaimable, nr_slab_unreclaimable |
mikroscope_ |
gauge | node, zone, order |
free blocks of 2^order pages from /proc/buddyinfo: fragmentation that MemFree cannot show |
Scroll sideways to see every column
The events and the levels are separate families on purpose: nr_dirty falling
is pages being written back, not a negative event count. MemFree in kB
divided by nr_free_pages gives the page size from the data rather than from
an assumption. The vmstat families are absent until a sample shows a fault or
a free-page level, because an unreadable /proc/vmstat and a quiet tick both
arrive as zeros.
PMU and CPU frequency
Section titled “PMU and CPU frequency”| Family | Type | Labels | Absent when | Meaning |
|---|---|---|---|---|
mikroscope_ |
counter | counter, cpu |
not privileged, or no reachable PMU | hardware counter events from perf_event_open; a counter the CPU does not implement is absent |
mikroscope_ |
counter | counter, cpu |
the same | seconds each counter was enabled |
mikroscope_ |
counter | counter, cpu |
the same | seconds it was actually counting; below enabled the PMU is multiplexed and the counts are scaled down by running over enabled |
mikroscope_ |
counter | cpu |
no cpufreq | the governor’s frequency integrated over each sample’s interval: nominal cycles offered, not cycles retired. rate() of it is the mean frequency over any window |
mikroscope_ |
gauge | cpu |
no cpufreq | the governor’s frequency at the newest emission |
Scroll sideways to see every column
Instructions per cycle is rate(mikroscope_
over rate(…{counter="cycles"}); the agent ships the counts and never the
ratio.
Temperature and slab caches
Section titled “Temperature and slab caches”| Family | Type | Labels | Absent when | Meaning |
|---|---|---|---|---|
mikroscope_ |
gauge | zone |
no thermal zone | temperature under the kernel’s own zone name, for example cpu-thermal, soc-thermal on the RB5009 |
mikroscope_ |
gauge | cache |
not privileged | active objects per slab cache; nf_conntrack is the router’s real connection count, although the container’s namespace reports zero |
mikroscope_ |
gauge | cache |
not privileged, or no ceiling published | the ceiling for caches that have one, today nf_conntrack from nf_conntrack_max; read once at agent start |
Scroll sideways to see every column
Connection-table occupancy is
mikroscope_.
A change to nf_conntrack_max shows after the agent restarts.
Flash and block devices
Section titled “Flash and block devices”| Family | Type | Labels | Absent when | Meaning |
|---|---|---|---|---|
mikroscope_ |
counter | device, kind: page_writes, page_reads, erasures, gc_copies, gcs |
no /proc/yaffs |
YAFFS NAND operations; erasures maps to flash lifetime, gc_copies over page_writes is write amplification |
mikroscope_ |
gauge | device |
no /proc/yaffs, and on any scrape whose newest sample carried no flash row (no operation, free chunks unchanged); not held between emissions |
blocks the NAND has retired; a rise is the flash wearing out |
mikroscope_ |
gauge | device |
the same as mikroscope_ |
chunks still free |
mikroscope_ |
counter | device, partition |
not privileged | bits the ECC corrected since boot, the kernel’s own count; climbs before a block is retired |
mikroscope_ |
counter | device, partition |
not privileged | reads the ECC could not correct since boot: data loss |
mikroscope_mtd_blocks |
gauge | device, partition, kind: bad, bbt |
not privileged | bad blocks, and blocks the bad-block table occupies |
mikroscope_ |
gauge | device, partition |
not published | corrected bits per ECC step at which the kernel moves a block’s data |
mikroscope_ |
gauge | device, partition |
not published | most bits per ECC step the code can correct |
mikroscope_ |
counter | device, op: read, write |
no device has done I/O | requests completed |
mikroscope_ |
counter | device, op |
the same | sectors transferred; the conversion to bytes is left to the reader |
mikroscope_ |
counter | device |
the same | time the device had I/O in flight |
mikroscope_disk_inflight |
gauge | device |
no I/O on that device in the newest sample; not held between emissions | requests in flight |
Scroll sideways to see every column
A block device that did nothing is not in the sample and so not here either;
a comment in internal/, undated and with no RouterOS
version, says the RB5009 lists sixteen idle nbd devices. Unlike the floored
sources in the conventions above, the flash levels and mikroscope_disk_inflight
are not carried forward, so they are missing from most scrapes of a quiet
board.
Kernel log
Section titled “Kernel log”/dev/kmsg is root-only, so these families need a privileged container. The
record text is never a label.
| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_ |
counter | level: emerg, alert, crit, err, warn, notice, info, debug |
records per syslog severity |
mikroscope_ |
counter | none | loss events, not records: one per tick that hit the cap of 64 records, one per kernel ring overrun (which can stand for many records); while it moves, the per-level counts above are a lower bound |
mikroscope_ |
counter | port, kind, level |
records whose text named a port: a subset of the family above. kind is link-up, link-down, stp-<state> (blocking, listening, learning, forwarding, disabled), own-address — the bridge received a frame carrying its own MAC as source address, the layer-2 loop signature — or other; only non-zero triples are written |
Scroll sideways to see every column
Both mikroscope_ and mikroscope_ are
rendered from the start, at 0, on both expositions when the capabilities list
kmsg as a source, so a quiet router reads as silent and not as unreadable.
Without that, they appear with the first record. The port family appears with
the first record that names a port.
On the agent, port is the RouterOS default name on a board in the port table
and the kernel name otherwise. On the collector’s copy the API tier’s interface
inventory puts the port’s current RouterOS name there, so a port renamed from
ether5 to WAN is counted under WAN; without an API tier the record keeps
the board’s default name. The collector classifies any record that reaches it
without a kind of its own, so its exposition carries the label even when the
agent’s does not — which is how the reference RB5009 stands on 2026-09-16, with
an agent whose /metrics has no kind.
A port coming up writes four records on a bridge, not four faults: link-up,
then stp-blocking, stp-learning and stp-forwarding on its bridge port.
own-address is the one kind that is a fault on its own.
The observer itself
Section titled “The observer itself”| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_ |
counter | none | CPU microseconds the agent’s container used: from cgroup2 when mounted, else /proc/self/stat ticks |
mikroscope_ |
gauge | none | the agent’s resident set |
mikroscope_ |
gauge | none | the container cgroup’s memory.current, RSS plus page cache charged to it; absent without cgroup2 |
mikroscope_ |
counter | none | periods the container’s cpu.max quota stopped it; absent without cgroup2 |
mikroscope_ |
counter | none | seconds it spent stopped; absent without cgroup2 |
mikroscope_ |
counter | none | processes OOM-killed inside the agent’s own cgroup; not the router’s, which is mikroscope_ |
mikroscope_samples_total |
counter | none | samples folded into these counters |
mikroscope_ |
counter | none | sequence number of the newest sample; increase() of it against increase(mikroscope_ is exactly the ticks produced and not folded in |
mikroscope_ |
counter | none | the samples’ own intervals summed; rate() of it is the wall-clock time covered per second, 1 while no tick slipped. The denominator for derived ratios |
mikroscope_ |
counter | none | monotonic counters that went backwards without a 32-bit wrap; a rate across such a tick is a lower bound |
mikroscope_info |
gauge | version, rate_hz |
always 1 |
mikroscope_ |
gauge | none | seconds since this exporter started |
Scroll sideways to see every column
The agent’s cost is two reads of mikroscope_ 60 s apart at
steady state, divided by 60 000 000. The cost of the
observer has the procedure and the measured figures.
Device facts
Section titled “Device facts”What the agent established about the board at start, with no RouterOS API. Each family is absent when the device does not publish that fact.
| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_device_info |
gauge | board, kernel, cores, privileged, cgroup, ports_from, hash |
always 1; hash changes when the source set does |
mikroscope_ |
gauge | zone |
the lowest critical trip point the zone declares; passive and active trips are not included |
mikroscope_ |
gauge | zone |
the zone’s polling_delay: reads faster than this see the same value |
mikroscope_ |
gauge | cpu, bound: min, max |
the hardware clock range |
mikroscope_ |
gauge | cpu, step |
every frequency the driver uses; step counts from the slowest |
mikroscope_ |
gauge | cpu, governor |
always 1; userspace is a pinned clock, ondemand or schedutil one that scales |
mikroscope_ |
gauge | cpu |
the lowest-numbered core that changes frequency with this one; {0,1} and {2,3} on the RB5009 |
mikroscope_ |
gauge | none | the container’s own memory.max, as the operator set it |
mikroscope_ |
gauge | source, reason |
the rate each level source is read and stored at, and why: declared, policy, budget, change, override or rate |
mikroscope_ |
gauge | source |
seconds since each floored source (thermal, cpufreq, slabinfo, buddyinfo, mtd) was last actually read |
Scroll sideways to see every column
All but the last are read once at agent start; a ceiling changed while the agent runs shows after it restarts.
Triggers and captures
Section titled “Triggers and captures”Agent only, and only while CAPTURE_MB is above 0. Every
condition-and-reason pair is written from the start at 0.
| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_ |
counter | condition |
times each configured condition armed a capture; condition="manual" appears after the first POST /capture |
mikroscope_ |
counter | condition, reason: refractory, pending |
times a condition was true and nothing was armed: how much of a burst was not seen |
mikroscope_ |
counter | reason: budget, empty |
captures collected and not kept: the budget was full, or the ring no longer held the window |
mikroscope_captures_held |
gauge | none | captures retained |
mikroscope_capture_bytes |
gauge | none | ring bytes the retained captures pin |
mikroscope_ |
gauge | none | the budget |
mikroscope_ |
counter | none | bytes handed out over /captures/{id}, which runs on the sampler’s core |
Scroll sideways to see every column
Collector only: the derive stage
Section titled “Collector only: the derive stage”| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_ |
counter | none | ring gaps the collector saw: samples lost between pulls |
mikroscope_ |
counter | cause |
capture triggers the collector saw the agent fire; absent until the first. The windows stay on the agent under /captures |
mikroscope_ |
counter | rule |
detection events per rule, every rule at 0 from the first scrape: counter-reset, agent-restart, agent-oom, microburst, reboot, link-flap, conntrack-cliff, conntrack-high, thermal-high, thermal-rising, ipc-collapse |
mikroscope_ |
counter | none | samples flagged as a sub-sample burst |
mikroscope_ |
gauge | none | the allocator’s ladder at the newest sample: 0 none, 1 kswapd scanned, 2 direct reclaim, 3 an allocation stalled or a page swapped out, 4 the OOM killer ran |
mikroscope_ |
gauge | none | PMU cycles per packet, summed over cores; absent without a PMU, in a sample with no packets, and in one with a counter reset |
mikroscope_ |
gauge | none | the same, instructions |
mikroscope_ |
gauge | none | the same, cache misses |
mikroscope_ |
gauge | none | packets per device interrupt, the NAPI coalescing depth; absent when the timer row was not in the sample’s top-K |
mikroscope_ |
gauge | interface, direction: rx, tx |
the fast-path share of the traffic the interface hands the CPU, between the last two counter polls: fp-rx-byte over driver-rx-byte on a switch port, over rx-byte on a software interface. Absent for a direction that moved no bytes |
Scroll sideways to see every column
The fast-path share is not a share of the wire: a frame the switch chip
forwards in hardware is in neither of its two numbers. On a switch port the two
are close together — measured 2026-09-16 on the reference RB5009, fp-rx-byte
equals driver-rx-byte within a few kB, so every port reads about 100 %. The
software interfaces are where the number moves: the bridge fast-pathed 211.9 GB
of the 663.0 GB it took to the CPU since boot (32 %), PPPoE_DIGI 99.97 %.
fp-tx-byte reads 0 on every interface of that router after hundreds of GB
transmitted, so direction="tx" is withheld while the cumulative fp-tx-byte
is 0 rather than published as a fabricated 0 %.
The rules and what each may not claim are on detections; the derived values on what the collector derives.
Collector only: the RouterOS API tier
Section titled “Collector only: the RouterOS API tier”Absent until the API tier has delivered a sample, and absent entirely with
--api-mode off unless --api-every is also given explicitly.
| Family | Type | Labels | Meaning |
|---|---|---|---|
mikroscope_api_up |
gauge | none | 1 once the API tier has delivered a sample. It does not go back to 0 if the tier stops later, although its HELP line says “while” |
mikroscope_api_cpu_load |
gauge | none | cpu-load as /system/resource reports it, a one-second average |
mikroscope_ |
gauge | kind: free, total |
from /system/resource |
mikroscope_ |
gauge | none | the router’s uptime |
mikroscope_ |
gauge | cpu, kind: load, irq, disk |
/system/resource/cpu |
mikroscope_api_health |
gauge | name |
/system/health readings, by RouterOS’s name |
mikroscope_api_interface |
gauge | interface, kind: rx_bps, tx_bps, rx_pps, tx_pps, and rx_drops, tx_drops, tx_queue_drops, rx_errors, tx_errors only when the router returned them |
instantaneous rates from monitor-traffic |
mikroscope_ |
gauge | interface, label, type, role, bridge, default_name |
always 1, one series per interface: label is its RouterOS comment, type RouterOS’s own interface type, role its interface lists, bridge the bridge it is a port of, default_name the factory name of a physical port. An empty value is how the exposition spells “none” |
mikroscope_ |
counter | interface, counter |
every numeric per-port counter RouterOS keeps, under its own name (rx-overflow, fp-rx-byte, link-downs …), for every interface |
mikroscope_ |
gauge | none | /ip/firewall/connection count, held between polls; only with --conntrack-every |
Scroll sideways to see every column
What each interface is — comment, type, interface lists, bridge — is an info
family and not a set of labels on every rate and counter, because a human edits
those and a changed label starts a new series. The collector reads the
configuration once at start and again every --labels-every (5 minutes by
default), and the family holds one series per interface, with or without a
comment. Join it in a query:
mikroscope_api_interface_counter_total * on(interface) group_left(label, type, role) mikroscope_api_interface_infoThe join is worth making because RouterOS counts different things on different
types, and type is what says which: an ether port in a bridge counts its
wire, including the frames the switch chip forwarded in hardware, while the
bridge counts its CPU side. Measured 2026-09-16 on the reference RB5009,
ether1 had received 255.8 GB on the wire and 29.7 GB at the driver. The two
are different planes and neither is a subset of the other: never sum a port and
its bridge.
Sizes and configuration that happen to parse as integers — mtu, actual-mtu,
l2mtu, max-l2mtu and sfp-shutdown-temperature — are not in
mikroscope_, because a rate() of an MTU counts
nothing. The MTU travels with the interface inventory instead, which the row
sinks write as a field.
On the RB5009 with RouterOS 7.24.2, monitor-traffic returned rx-drops,
tx-drops and tx-queue-drops per second and no error keys at all
(2026-09-15), so the rx_errors and tx_errors kinds are absent there;
mikroscope_ carries the port’s typed errors
instead.