# Compared with alternatives

What SNMP, The Dude, Graphing, the Profiler, mktxp and mikrotik-exporter read on a MikroTik router, beside mikroscope, and when to use them instead.

Source: https://jmrplens.github.io/mikroscope/start/compared/

mikroscope reads a MikroTik router's Linux kernel from inside a RouterOS container, at 1 to
100 Hz. SNMP, The Dude, RouterOS's own Graphing and Profiler, mktxp and mikrotik-exporter read
what RouterOS itself reports. The table sets the seven side by side; the sections after it say
where each cell comes from and when one of the other six is the better choice.

## Comparison table

| Tool | Where it runs | What it reads | Finest CPU view | Per-core softirq and softnet | Kernel log | Interface counters | Needs on the router |
| ---- | ------------- | ------------- | --------------- | ---------------------------- | ---------- | ------------------ | ------------------- |
| mikroscope | an agent in a RouterOS container; the CLI and the collector on your host | the router's kernel: `/proc`, `/sys`, `/dev/kmsg`, `perf_event_open` | per core, raw `/proc/stat` ticks at 1–100 Hz; a 100 ms sample resolves one core to 10 % steps | yes, per CPU, every tick | yes, `/dev/kmsg`, with `privileged=yes` | from the RouterOS API, merged: the container's network namespace hides the router's | RouterOS 7.24 or later, the `container` package, `device-mode container=yes`; arm64, arm or x86_64 |
| [SNMP](https://help.mikrotik.com/docs/spaces/ROS/pages/8978519/SNMP) | an agent built into RouterOS; the poller on another host | MIBs: MIB-2, HOST-RESOURCES-MIB, IF-MIB, MIKROTIK-MIB and others | `hrProcessorLoad` per processor, defined as a one-minute average ([RFC 2790](https://datatracker.ietf.org/doc/html/rfc2790)) | no object for either in [MIKROTIK-MIB](https://download.mikrotik.com/routeros/7.24.4/mikrotik.mib) | no; traps report interface changes, the SNMP service starting, and a temperature threshold (`temp-exception`) | yes, IF-MIB | `/snmp set enabled=yes` (off by default) and a community or an SNMPv3 user |
| [The Dude](https://help.mikrotik.com/docs/spaces/ROS/pages/377225250/Dude) | the `dude` package (arm, arm64, mmips, tile, x86, CHR); MikroTik calls it discontinued | not stated in MikroTik's current pages | not stated in MikroTik's current pages | not stated in MikroTik's current pages | not stated | not stated in MikroTik's current pages | the `dude` package; nothing else is stated in MikroTik's current pages |
| [Graphing](https://help.mikrotik.com/docs/spaces/ROS/pages/22773810/Graphing) | inside RouterOS; graphs in WebFig and WinBox | RouterOS's own resource and traffic figures | not stated; `store-every`, 5 min by default, is how often it writes to disk | no: it graphs resources, interfaces and simple queues | no | traffic per interface | `/tool graphing` entries; off by default |
| [Profiler](https://help.mikrotik.com/docs/spaces/ROS/pages/8323153/Profiler) | inside RouterOS, `/tool/profile`, run by hand | RouterOS's CPU accounting per process | per core and per process class; one-second snapshots ([API tier cost](https://jmrplens.github.io/mikroscope/cost/#api-tier-cost)) | no: CPU by process class | no | no | nothing: it is built in |
| [mktxp](https://github.com/akpw/mktxp) | your host: Python 3.9 or later on Linux, macOS or FreeBSD, or Docker | the RouterOS API | `cpu-load` from `/system/resource`: one figure for the whole router | no collector for either (source at `1e4412a`) | no; RouterOS's syslog goes to the separate [MKTXP Stack](https://github.com/akpw/mktxp-stack) | yes, over the API | an API user with `api,read` |
| [mikrotik-exporter](https://github.com/nshttpd/mikrotik-exporter) | your host | the RouterOS API | `cpu-load` from `/system/resource/print`: one figure for the whole router | no collector for either (source at `428dbfc`) | no | yes, `/interface/print` | an API user with `api,read,winbox` |

The six other rows are what each tool's own documentation or source says, with "not stated" where
it says nothing. None of the six was run for this table, so no cell in their rows is a measurement.
The sources are MikroTik's pages on [Packages](https://help.mikrotik.com/docs/spaces/ROS/pages/40992872/Packages)
and [`/system/resource`](https://help.mikrotik.com/docs/spaces/ROS/pages/40992875/Resource) besides
the four linked in the table; the [MIKROTIK-MIB file](https://download.mikrotik.com/routeros/7.24.4/mikrotik.mib),
none of whose objects is named or described as a softirq, softnet, interrupt or log counter; mktxp's
[exporter guide](https://github.com/akpw/mktxp/blob/1e4412a3349db95f59281c81d3b3bc65f2f7f963/docs/exporter.md) and
[resource collector](https://github.com/akpw/mktxp/blob/1e4412a3349db95f59281c81d3b3bc65f2f7f963/mktxp/collector/resource_collector.py)
at commit `1e4412a`; and mikrotik-exporter's
[resource collector](https://github.com/nshttpd/mikrotik-exporter/blob/428dbfcc37d05d52ee6a326fa45719a375a89d02/collector/resource_collector.go)
at commit `428dbfc`. Third-party tools change: check their pages before relying on a
cell.

The row for mikroscope comes from this site: [How it works](https://jmrplens.github.io/mikroscope/how-it-works/),
[Resolution limits](https://jmrplens.github.io/mikroscope/limits/), [Privileged mode](https://jmrplens.github.io/mikroscope/limits/privileged/),
[Container visibility](https://jmrplens.github.io/mikroscope/limits/namespaces/) and
[Requirements](https://jmrplens.github.io/mikroscope/install/prerequisites/). The resolution in its CPU cell is arithmetic
from the kernel's tick, not a reading.

## cpu-load in exporters

mktxp and mikrotik-exporter both read `cpu-load`, which MikroTik defines as the percentage of used
CPU resources with all CPUs combined. It is [a trailing mean of about one
second](https://jmrplens.github.io/mikroscope/sinks/api-tier/#how-many-seconds-does-routeros-cpu-load-average-over), so a burst
shorter than that second is averaged into it. Per-core figures exist in RouterOS's
`/system/resource/cpu`, which mikroscope's API tier reads and neither exporter's source asks for.

## Kernel-only signals

A layer-2 loop can leave RouterOS's log and port monitor reporting a healthy device while the
kernel log carries the router's own address coming back into the bridge every STP hello.
mikroscope reads that log through `/dev/kmsg`, and none of the other six is documented as reading
it. [Layer-2 loop](https://jmrplens.github.io/mikroscope/playbooks/loop/) is a real case, diagnosed.

It does not replace the RouterOS API either: per-interface bytes and packets come from that API,
and the collector merges them with the kernel's samples on the agent's clock.

## Router cost

At the install default, 10 Hz, the agent costs 2.69 % of one core
and 13.2 MiB RSS, from its own cgroup ([Agent cost](https://jmrplens.github.io/mikroscope/cost/)). Its
API tier, asking RouterOS a round every second, has a cost of its own:
[API tier cost](https://jmrplens.github.io/mikroscope/cost/#api-tier-cost). That figure is mikroscope's own client asking its
own commands, not an exporter's.

What SNMP polling, The Dude, Graphing, the Profiler, mktxp or mikrotik-exporter costs a router, how
often each can usefully poll one, and what RouterOS puts in `hrProcessorLoad` have not been
measured ([Not tested](https://jmrplens.github.io/mikroscope/about/status/#not-tested)).

## When to use another tool

- **A MIPS, TILE or PPC router.** The agent is nothing without a container, and MikroTik ships the
  `container` package for arm, arm64, x86 and CHR only. `/system/resource/print` names your
  router's `architecture-name`. SNMP, or an API exporter such as mktxp, reads what RouterOS reports
  on any of them.
- **RouterOS older than 7.24.** The container step writes `privileged=`, an attribute RouterOS added
  in 7.24, so `doctor` and the install script stop on an earlier release before writing anything.
  Upgrade RouterOS, or use SNMP or mktxp, neither of which needs a container.
- **No `container` package, or nobody to press the button.** `device-mode container=yes` takes a
  press of the reset or mode button, or a cold reboot, within five minutes of the command.
  [MikroTik's device-mode page](https://help.mikrotik.com/docs/spaces/ROS/pages/93749258/Device-mode)
  requires physical access on purpose, so no remote session can grant it. SNMP needs a service
  turned on, and an exporter an API user.
- **Interface traffic at a scrape interval is all you want.** mikroscope takes per-interface bytes
  and packets from the same RouterOS API an exporter reads, because the container cannot see them.
  An exporter gets them without putting anything on the router.
- **You need it proven on your board first.** [Tested on](https://jmrplens.github.io/mikroscope/about/status/) lists the
  boards and RouterOS versions it has run on. A
  [board report](https://github.com/jmrplens/mikroscope/issues/new?template=2-board-report.yml)
  adds yours.

## See also

- [How it works](https://jmrplens.github.io/mikroscope/how-it-works/): the agent, the collector and the limits that cannot
  be engineered away.
- [FAQ](https://jmrplens.github.io/mikroscope/start/questions/): MIPS, 7.24, the cost, a production router, in a paragraph
  each.
- [RouterOS API tier](https://jmrplens.github.io/mikroscope/sinks/api-tier/): what the collector still asks RouterOS.
- [Requirements](https://jmrplens.github.io/mikroscope/install/prerequisites/): the architecture, the package and the
  device-mode step.
