Skip to content

How it works

mikroscope is two programs. An agent runs in a container on the router and samples the kernel it shares with RouterOS; a CLI on your machine installs it, records from it and runs the collector that writes to your stores.

  • mikroscope-agent is a static Go binary in a scratch container. It samples on a fixed ticker at 1 to 100 Hz, 10 Hz by default, keeps the last 60 s in a ring, and serves them over HTTP on its veth address. It opens no outbound connection and holds one secret at most: the token it asks of whoever reads it, which sits in the container’s envlist.
  • mikroscope, the CLI, runs on your machine. It installs, upgrades and removes the agent over ssh; records a window with markers and plots it as an SVG; and runs forward, the collector.
  • The router’s own objects: a veth with a /30, the router’s address on it, two list memberships, an envlist, the container, and an install manifest that lists them. Every one carries the tag mikroscope:<name> (managed by mikroscope), and uninstall removes them all.

The release publishes the CLI as an archive per platform (Linux and FreeBSD on amd64, arm64 and arm; macOS and Windows on amd64 and arm64), and the agent as one image tar per architecture and as a registry image, jmrplens/mikroscope-agent on Docker Hub and ghcr.io/jmrplens/mikroscope-agent on GHCR. The collector is also an image, jmrplens/mikroscope and ghcr.io/jmrplens/mikroscope (linux/amd64, linux/arm64), and the directory deploy/ has two compose stacks that pair it with InfluxDB 3 or Prometheus and Grafana. That image’s default command is forward, and dashboards runs in it too; the install commands need ssh and scp, which it leaves out. Both programs are under the MIT licence, in LICENSE.

Where the data comes from and where it goes The router runs the agent in a container that reads the shared kernel and serves it over a veth. The collector on your machine pulls that, merges the RouterOS API tier into it, derives, and writes to every sink you named. THE ROUTER Shared kernel /proc · /sys · /dev/kmsg · PMU mikroscope-agent 1–100 Hz · 300 s ring · HTTP RouterOS API 1 Hz, what the kernel cannot see YOUR MACHINE mikroscope forward pull · merge · derive · fan out veth /30 SINKS InfluxDB 3 Prometheus file · SQL Loki · OTLP Graphite · Elastic Telegraf · stdout pull every 500 ms
Where the data comes from and where it goes The router runs the agent in a container that reads the shared kernel and serves it over a veth. The collector on your machine pulls that, merges the RouterOS API tier into it, derives, and writes to every sink you named. THE ROUTER Shared kernel /proc · /sys · /dev/kmsg · PMU mikroscope-agent 1–100 Hz · 300 s ring · HTTP RouterOS API veth /30 mikroscope forward pull · merge · derive · fan out SINKS InfluxDB 3 Prometheus file · SQL Loki · OTLP Graphite · Elastic Telegraf · stdout
  1. The agent reads the kernel on each tick and appends a sample to its ring.
  2. forward, or record, pulls new samples from the agent over HTTP: directly to the veth address through the router, through the RouterOS API relay, or on the router’s LAN address with --expose (Network access).
  3. The collector asks the RouterOS API, once a second, for what the kernel cannot show the container, and stamps both tiers in the agent’s clock.
  4. It derives ratios, rates and detections from the merged samples and writes them to every sink you name (Run the collector).

ssh is never on this path. The CLI uses it to install and check, and batches each read into one connect, because each connect costs the router CPU for its duration (SSH cost).

A RouterOS container shares the router’s kernel, so /proc inside it is the router’s own:

  • /proc/stat per core, /proc/interrupts, /proc/softirqs and /proc/net/softnet_stat;
  • /proc/meminfo, /proc/vmstat, /proc/diskstats and /proc/loadavg;
  • with the container privileged: /dev/kmsg, the kernel log; /proc/slabinfo, which holds the router’s real connection count; the flash’s ECC counters; and the CPU’s PMU counters, system-wide, through perf_event_open.

The container runs privileged by default; Privileged mode lists what each setting gives. The agent ships raw counter deltas, CPU time as ticks, never a percentage, so the reader chooses the window. It reports at start which sources this kernel has, and a source the kernel lacks is absent from the output rather than zero. Prometheus metrics lists every series.

  • The RouterOS API tier: per-interface traffic and error counters, cpu-load per core, /system/health, and what each interface is (its comment, type, lists, bridge and MTU). The container cannot read these: its network namespace is its own. RouterOS API tier has the modes.
  • One clock: every record is stamped in the agent’s clock, so kernel and API samples line up.
  • Derived values: busy ratios, rates and shares, computed from the raw deltas (Derived values).
  • Detections: a layer-2 loop, a link flap, a microburst and the other rules, each written as an event (Detection rules).
  • Sinks: file, Prometheus, InfluxDB 3, Loki, OTLP, Graphite, Elasticsearch and OpenSearch, SQL, PostgreSQL, Telegraf and standard output.
  • RouterOS 7.24 or later, with a container. The agent needs the container package and device-mode container=yes, which takes a button press or a power cycle at the router. MIPS, TILE and PPC routers have no container package.
  • The kernel’s resolution, not the tool’s. /proc/stat counts CPU time in USER_HZ ticks, 100 a second, so a 100 ms window resolves one core in steps of 10 % (Resolution limits).
  • PSI and schedstat only where the kernel has them. The agent reads both when they exist; a RouterOS kernel may be built without them.
  • The container’s network is its own. /proc/net/dev, /proc/net/snmp and nf_conntrack_count describe the container, not the router; the conntrack count from the slab, when privileged, is the exception. Interface counters come from the RouterOS API and are merged, never estimated (Container visibility).
  • It merges with the RouterOS API and does not replace it. Without an API user the kernel tier still runs, and the interface panels stay empty.
  • No percentages from the agent. It never computes one, so it never decides what a percentage means; the collector and the dashboards derive them.
  • The observer has a cost. At 10 Hz the agent takes 2.69 % of one core; Agent cost has the table and how to measure it on your router.