# Probado en

Los equipos, las versiones de RouterOS, las fechas y las condiciones que hay detrás de cada medida y cada comprobación de la documentación de mikroscope, lo que se encontró y lo que no se ha probado.

Source: https://docs.jmrp.io/mikroscope/es/about/status/

Dónde se ejecutó, se midió o se comprobó cada parte de mikroscope: el equipo, la versión de
RouterOS, la fecha y las condiciones, lo que encontró cada ejecución y lo que no se ha probado. Las
guías dicen lo que hace la herramienta y enlazan aquí la prueba. Los veredictos de las funciones se
contrastaron con el código de la 1.2.0 y de la 1.2.2 el 2026-09-24, los apartados que vinieron de
las guías con el código de la 1.3.1 el 2026-09-26, y lo que esta página dice del código posterior a
la 1.3.1, que es el que publica la 1.4.0, con ese código el 2026-09-27, y sus apartados sobre la
publicación en Grafana, `uninstall` y las baterías de pruebas con el código de la 1.5.0 el mismo día;
la versión actual es la [1.6.1](https://github.com/jmrplens/mikroscope/releases/tag/v1.6.1).

## Hardware de referencia

Todas las cifras medidas en hardware de router que aparecen en esta documentación salen de un único
MikroTik RB5009UG+S+: arm64, 4 × 1,4 GHz Cortex-A72 (r0p1), 1 GiB de RAM, Linux 5.6.3. Es el router de
producción del mantenedor del proyecto, José Manuel Requena Plens, así que nada que necesite un
reinicio se hace en él fuera de una ventana de mantenimiento, y no se le provoca ninguna tormenta de
conntrack, que puede dejar sin acceso el camino por el que se está trabajando. No hay un segundo
equipo físico. El único otro RouterOS que usa el proyecto es el
[laboratorio virtual](https://docs.jmrp.io/mikroscope/es/about/status/#virtual-lab). Qué RouterOS tenía en cada momento está en
[Equipos y versiones](https://docs.jmrp.io/mikroscope/es/about/status/#un-equipo-dos-versiones-de-routeros).

### Kernel y PMU

- **Ficheros de contabilidad** (campaña [`kernel-2026-09-11`](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-kernel-2026-09-11)):
  no hay `/proc/pressure` ni `/proc/schedstat`, y la columna `irq` de `/proc/stat` vale siempre 0,
  así que el tiempo de IRQ hardware se cuenta dentro de `system`. `USER_HZ` es 100, un tick de 10 ms.
- **Trazado**: un contenedor de descubrimiento privilegiado no encontró el 2026-09-12 ni eBPF, ni
  kprobes, ni ftrace: ni BTF, ni debugfs, ni tracefs, y los puntos de montaje no existen. Una nueva
  comprobación el 2026-09-14 encontró `/sys/fs/bpf` presente y vacío y `/proc/modules` con 238 módulos
  cargados, pero ni `/lib/modules`, ni cabeceras del kernel, ni compilador en el equipo.
- **PMU**, desde dentro de un contenedor privilegiado el 2026-09-12 (RouterOS 7.24.2): la prueba abrió
  `cycles`, `instructions`, `cache-misses`, `branch-misses` y `bus-cycles` a nivel de sistema en 4 de
  4 CPU. En los datos del propio agente de las 24 h que terminaron el 2026-09-12, seis de los siete
  contadores que pide informaron en 4 de 4 núcleos, `cache-references` entre ellos, y
  `branch-instructions` no produjo ninguna fila. Los eventos genéricos `stalled-frontend` y
  `stalled-backend` devuelven `ENOENT` en el A72.
- **El trabajo que el tick no ve**: en una muestra de 100,4 ms en la que `/proc/stat` no marcó ningún
  tick ocupado en ninguno de los cuatro núcleos, la PMU contó entre 2,2 y 4,6 millones de ciclos y
  entre 0,8 y 2,1 millones de instrucciones ejecutadas, con una tasa de fallos de caché del 3,8–5,7 %
  (registrado el 2026-09-12). Durante 2 s ese mismo día, las instrucciones por ciclo fueron de 0,381
  en cpu0 a 0,992 en cpu1.
- **Privilegios**: `perf_event_paranoid` vale 2 y no bloquea a un contenedor privilegiado, que conserva
  `CAP_SYS_ADMIN` efectiva frente al host (medido el 2026-09-12). Un contenedor sin privilegios ya
  tiene las 38 capacidades, y su root corresponde al uid 32768 del host, así que `/proc/slabinfo` y
  `/dev/kmsg` devuelven `EACCES` (RouterOS 7.24.2; la fecha de estas dos lecturas no consta). Con
  `privileged=yes`, el log del kernel, `/proc/slabinfo`, los contadores ECC de la MTD y la PMU se
  encontraron legibles el 2026-09-12 (RouterOS 7.24.2, kernel 5.6.3).

### Sensores y relojes

- `/sys/class/hwmon` está vacío, incluso con privilegios. Las dos zonas térmicas, `cpu-thermal` y
  `soc-thermal`, son todo el conjunto de sensores del modelo base, y las dos se leen sin privileged.
  El `/system/health` de RouterOS en esta placa informa de exactamente un sensor, `cpu-temperature`,
  que es la zona `soc-thermal` truncada a grados enteros: un desfase medio de +0,55 °C durante los 8
  minutos en que existieron las dos series (2026-09-14).
- Las dos zonas declaran un `polling_delay` de 1 000 ms y un `polling-delay-passive` de 250 ms (leído
  el 2026-09-14), así que el kernel vuelve a leer el sensor a 1 Hz. El punto de disparo crítico
  declarado es 105 °C, leído de `/sys` (la fecha no consta). El sensor cuantiza en escalones de
  unos 0,42 °C ([`floors-overnight`](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-floors-overnight)).
- El gobernador de cpufreq marcaba `userspace` el 2026-09-14, y los clusters de cpufreq, leídos de
  `related_cpus` y `affected_cpus` dentro del contenedor ese mismo día (RouterOS 7.24.2), son `{0,1}`
  y `{2,3}`.

### Vista desde el contenedor

- **Globales dentro del contenedor** (establecido el 2026-09-11, RouterOS 7.24.2, kernel 5.6.3): los
  ficheros de CPU, interrupciones, memoria y dispositivos de bloques, y `/proc/net/softnet_stat`. Un
  contenedor normal leyó además como del router, el 2026-09-12: las dos zonas térmicas,
  `scaling_cur_freq` por núcleo, `/proc/yaffs` y `/proc/buddyinfo`. `/proc/device-tree/model` dice
  `RB5009` incluso sin privilegios.
- **Los del propio contenedor** (campaña [`netns-2026-09-12`](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-netns-2026-09-12)):
  `/proc/net/dev`, `/proc/net/snmp`, `/proc/net/netstat` y `nf_conntrack_count` describían la veth del
  contenedor, 4 paquetes mientras el router reenviaba millones, y `privileged=yes` no cambió eso. El
  resto de esa frontera:

| Qué                                                                               | Lo que ve el contenedor                                                                             | Leído      |
| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ---------- |
| `/sys/class/net`                                                                  | solo `lo` y la veth; ningún dispositivo para ningún puerto frontal, privilegiado o no               | 2026-09-14 |
| `/sys/class/mdio_bus`, `/sys/class/phy`                                           | `mdio_bus` solo contiene `fixed-0`; `phy` está vacío                                                | 2026-09-14 |
| `netdev_budget`, `netdev_max_backlog` y las demás entradas globales de `net.core` | ausentes; las entradas por espacio de nombres, como `somaxconn`, están presentes                    | 2026-09-14 |
| ficheros de `/proc/net/*` creados por módulos                                     | los del propio contenedor: `fib_trie` muestra solo el `/30` de la veth, `snmp6` cuenta sus paquetes | 2026-09-15 |
| `nf_conntrack_max`                                                                | el techo real del router, 966 656, el mismo que RouterOS informa como `max-entries`                 | 2026-09-14 |
| tiempos de expiración de conntrack                                                | los valores por defecto de Linux (`tcp_timeout_established` 432 000 s frente al `1d` de RouterOS)   | 2026-09-14 |

- **Los montajes del host** no cruzan la frontera:
  ver [el hecho verificado](https://docs.jmrp.io/mikroscope/es/about/status/#verified-host-mounts) del 2026-09-15.
- El registro de datos del equipo lleva los techos propios de la placa, nunca un número sacado de
  otro sitio: el techo de conntrack de 966 656 y el límite de memoria de 64 MiB del contenedor.

### Almacenamiento

- `nbd0`–`nbd15` están presentes e inactivos y `mtdblock0`–`2` dan todo ceros (2026-09-12, RouterOS
  7.24.2, kernel 5.6.3; [`internal/dashboards/panels.go`](https://github.com/jmrplens/mikroscope/blob/main/internal/dashboards/panels.go), el panel de E/S en curso de
  disco). La fila de `/proc/yaffs` o de `/proc/diskstats` de un dispositivo solo se guarda cuando su
  delta no es cero, lo que aquí ocurre unas pocas veces por minuto. El almacén InfluxDB de referencia
  seguía sin tabla de dispositivos de bloques, y sin tabla de PSI, el 2026-09-25, con RouterOS 7.24.4.
- Los contadores ECC de la MTD están todos a cero tras años de servicio (la fecha de la lectura no
  consta).
- `/proc/slabinfo` ocupa 13 833 bytes y 129 líneas por lectura (2026-09-14), el mayor análisis por
  tick, un orden de magnitud por encima de cualquier otro.
- El log del router tenía 66 217 filas cuando `record` lo leyó, porque su tema `dns` registra a disco
  (la fecha no consta).
- Tiene un disco tmpfs, que usa `--ephemeral`. Su cortafuegos raw lleva las dos reglas de descarte
  `defconf:` de MikroTik en su forma de listas, `in-interface-list=!LAN` y `src-address-list=!LANs`
  ([Listas del firewall](https://docs.jmrp.io/mikroscope/es/install/firewall/)).

### Puertos e interfaces

- **Nombres del kernel frente a nombres de RouterOS**
  ([Nombres de puertos](https://docs.jmrp.io/mikroscope/es/reference/port-names/)): `eth1` = `ether2` por el bucle de capa
  2 del caso real (2026-09-13). `eth5` = `ether6` y `eth6` = `ether7` el 2026-09-15: los dos puertos
  están comentados como `Unused` y ninguno estaba `RUNNING`, así que cada uno se apagó y se volvió a
  encender por la API mientras el agente leía `/dev/kmsg`. El kernel registró
  `br0: port 7(eth5) entered disabled state` dentro de la ventana de `ether6` y `port 7(eth6)` dentro
  de la de `ether7`, con nueve segundos entre ellas, lo que descarta leer dos veces el mismo apagado.
  No se interrumpió ningún tráfico y los dos puertos estaban de vuelta en menos de cuatro segundos.
  Los seis pares deducidos y el switch se apoyan en un `/interface/ethernet/print` de solo lectura del
  2026-09-13: direcciones MAC consecutivas, de `…:55` para `ether1` a `…:5D` para `sfp-sfpplus1`, en el
  orden de enumeración de RouterOS, y los nueve puertos declarando `switch=switch1` frente al único
  `switch0` del kernel. El device tree, analizado el 2026-09-14, muestra el `ethernet@0` del SoC con
  tres MAC, solo `eth0` habilitada (el enlace de subida de 10 G) y `eth1`/`eth2` deshabilitadas; los
  nueve puertos del frontal son netdevs que el driver del switch crea en tiempo de ejecución. La tabla
  es la de esta placa, observada con RouterOS 7.24.2.
- **Las formas de registro del log del kernel** para cada clase de suceso de puerto se vieron entre el
  2026-09-12 y el 2026-09-15 (kernel 5.6.3).
- **Inventario** (2026-09-16, RouterOS 7.24.2): las tres lecturas de configuración devuelven 17
  interfaces. `ether1` es un `ether` de la lista `LAN`, puerto de `bridge`, etiquetado «TrueNAS - High
  Performance Storage», MTU 9000; `ether5` es un `ether` de `WAN` que no está en ningún bridge,
  etiquetado «DIGI ONT»; `PPPoE_DIGI` es `pppoe-out`, `WAN`, MTU 1480; `VLAN_DIGI` es `vlan`, `WAN`;
  `wg_devices` y `wg_trastero` son `wg` en `LAN,VPN`; `ether6` y `ether7` llevan el comentario
  «Unused».
- **Contadores**: 9 puertos × 45 contadores, y 15 en cada interfaz bridge, VLAN, PPPoE, WireGuard,
  veth o loopback, contados en las propias filas `mikroscope_api_ifcounters` del colector el
  2026-09-24. La versión de RouterOS no se leyó con ellas; el router tenía 7.24.4 ese día.

## Laboratorio virtual

El Cloud Hosted Router de MikroTik bajo QEMU, en un contenedor Docker, en la máquina en la que se
construyó el laboratorio (x86_64, 12 núcleos, 27 GB de RAM, Docker 29.8, QEMU 10.0.13), aprovisionado
en una instantánea limpia con el paquete `container` y `device-mode container=yes`. Medido el
2026-09-26 con RouterOS 7.24.4 y la CLI y la imagen del agente 1.3.1 publicadas:

- **CHR x86_64** con KVM: 2 núcleos, kernel `5.6.3-64`.
- **CHR arm64** con la emulación TCG de QEMU, `cortex-a72`, 2 vCPU, 1 GiB: kernel `5.6.3`, la
  arquitectura, la versión del kernel y el modelo de CPU del RB5009, a la velocidad del host.

**Lo que muestra**: corrección. Las órdenes de RouterOS que envía mikroscope y lo que responde
RouterOS, la lectura que hace `doctor` del router, que RouterOS elija y descargue la imagen de su
arquitectura, el arranque y la parada del contenedor, la detección de capacidades del agente, su
formato de muestra y su anillo. Las rutas de instalación que se ejecutaron allí están en
[Rutas de instalación probadas](https://docs.jmrp.io/mikroscope/es/about/status/#install-routes-tested).

**Cómo llega el laboratorio a sus agentes**: por una ruta estática. El lado LAN del laboratorio,
`192.168.88.10/24` dentro del contenedor del laboratorio, tiene su ruta por defecto por el puente de
Docker, no por el router, y llega a cada agente por `172.30.0.0/16 via 192.168.88.1`, el valor por
defecto de `LAB_AGENT_ROUTES`: el prefijo más amplio de
[Ruta estática](https://docs.jmrp.io/mikroscope/es/install/reaching-the-agent/#ruta-estática). El 2026-09-27, la
`172.30.10.0/30` por defecto y una instalación en `172.30.11.0/30` respondieron ambas a `/healthz` por
ella.

**Lo que no puede mostrar**:

- Una placa. No hay chip de switch, flash, sensores ni modelo en el device tree, así que no hay mapa
  de puertos. Las `/capabilities` del agente dan `cpufreq`, `mtd`, `psi`, `schedstat` y `thermal`
  ausentes en los dos, `perf` y `kmsg` presentes en los dos, y `yaffs` ausente en x86_64 y presente
  en arm64, un `/proc/yaffs` sin flash detrás.
- Cadencias por encima de 10 Hz. La licencia gratuita de CHR limita lo que envía el router a
  1 Mbit/s por interfaz: copiar 2 MiB desde el router por ether2 llevó 15,6 s, unos 1,07 Mbit/s,
  frente a 0,2 s hacia él. `/stream` midió 2 526 B por línea en el laboratorio, 0,21 Mbit/s a 10 Hz,
  así que 50 Hz está en el tope y 100 Hz por encima. No se midió ninguna de las dos.
- Ningún coste en arm64. Con TCG el reloj del invitado sigue al del host, así que ninguna duración,
  ninguna cifra de CPU (`cpu-load`, `self.cpu_us`, `read_ns`, `wake_ns`, la dispersión de `dt_ns`,
  `slipped`), ninguna tasa de interrupciones, softirqs o cambios de contexto y ninguna cuenta de la
  PMU del laboratorio arm64 mide un Cortex-A72. El agente aguantó allí a 10 Hz, 3 003 ticks en 300,1 s
  con 1 retrasado y 1 202 en 120,1 s sin ninguno, y su tamaño residente de 14–16 MiB (32 MiB
  cargados a su cgroup) es solo orientativo.

Un bucle de rutas del propio laboratorio, ya corregido, hacía que el router emulado se arrastrara
cada vez que algo sondeaba una dirección de agente sin veth detrás: antes de la corrección, `install`
en arm64 tardó 38,4, 11,8 y 34,1 s, y el primero y el tercero salieron con 1 en una instalación
completa. Las cifras de arm64 de aquí son de después de la corrección; las de x86_64 se tomaron
antes. Lo que encontró allí la 1.3.1 está en
[Problemas conocidos](https://docs.jmrp.io/mikroscope/es/about/status/#encontrado-en-el-laboratorio-virtual).

### Tiempos del laboratorio

En la máquina de arriba, desde la instantánea limpia. Cómo se ejecuta cada batería está en
[Baterías de pruebas](https://docs.jmrp.io/mikroscope/es/reference/testing/#el-laboratorio-virtual-de-routeros).

- **Un arranque desde la instantánea hasta que responde ssh**, 2026-09-26: 7 s en x86_64 (6,9, 7,2,
  7,4 y 7,4 s) y de 26 a 28 s en arm64 (25,7, 26,6, 27,0 y 27,5 s).
- **`make roundtrip`**, 2026-09-26: `doctor`, `install`, `status`, `upgrade` y `uninstall`, cada
  orden con `--ephemeral`, y el `/export` del router resumido con un hash antes y después. De 28 a
  34 s en x86_64 en tres ejecuciones y de 40 a 45 s en arm64 en cuatro, con el export idéntico byte a
  byte todas las veces. Con el código de la 1.4.0, que hace un solo intento de `uninstall`, el
  2026-09-27: 20 s en x86_64 y 35 s en arm64, una ejecución de cada una con los pasos de compilación
  de make incluidos, con el export idéntico byte a byte. Con el código de la 1.5.0 el mismo día:
  21 s en x86_64 y 30 s en arm64, medidos igual, con el export idéntico byte a byte.
- **`make test-lab` con los escenarios de la 1.3.1**, 2026-09-26: de 7 min 21 s a 9 min 49 s en
  x86_64 en seis ejecuciones y de 12 min 12 s a 16 min 48 s en arm64 en tres, las más lentas de cada
  una con las dos baterías en paralelo en un anfitrión ocupado. Ninguna instalación falló.
- **`make test-lab` con los escenarios de las opciones de instalación**, con el código posterior a
  la 1.3.1, 2026-09-27: 28 min 32 s en x86_64 sola, y después 28 min 17 s en x86_64 y 57 min 29 s en
  arm64 en paralelo. Tras las correcciones que pidió la revisión, 29 min 2 s y 57 min 13 s en
  paralelo, con todas las pruebas superadas; las veinte desinstalaciones de S9 con un cliente en
  `/stream`, diez por arquitectura, quedaron limpias al primer intento, en 8,0 a 12,6 s. Ese mismo
  día S17 se ejecutó en un laboratorio CHR x86_64 con RouterOS 7.23.7: a `doctor` le faltó
  `RouterOS 7.24 or later` y leyó todas las demás comprobaciones.
- **RouterOS 7.24.4 cambia su propio `/export`**: añade y quita por su cuenta una línea
  `/system keymat-provider … name=default`, así que la comparación de la batería deja esa línea fuera
  (2026-09-26).

### Corte de corriente tras instalar

El 2026-09-26, un corte de corriente hecho en cuanto una instalación recién hecha respondió no
devolvió ningún agente en 90 s en tres de cuatro intentos en el laboratorio arm64. Los dos
contenedores que se miraron no podían arrancar (`Exec format error`, `Segmentation fault`), muy
probablemente porque RouterOS aún no había escrito la instalación en su disco; eso no se examinó. En
x86_64 volvieron tres de tres. El escenario del arranque con el router, S7, espera 45 s entre la
instalación y su corte, y solo pregunta si ese arranque funciona. S6 corta la corriente bajo una
instalación `--ephemeral` en el disco tmpfs del laboratorio: después el contenedor sigue configurado y
detenido, su raíz, su imagen y el manifiesto se han ido con el contenido del disco, el disco sigue ahí
y vacío, y nada responde; `uninstall --ephemeral` no deja después nada en absoluto. Pasó en las dos
arquitecturas en las ejecuciones del 2026-09-27.

### Detecciones de reinicio

El 2026-10-05, en el laboratorio x86_64 (CHR, RouterOS 7.24.4, KVM), el colector del código
posterior a la 1.5.0 ejecutó `forward --api-mode off --stdout json` a través de un reinicio hecho
con el propio `/system/reboot` de RouterOS, con el agente 1.5.0 instalado por la descarga de Docker
Hub y arranque con el sistema. El agente volvió a responder unos 20 s después del reinicio; el
colector registró `agent restarted: its newest sample is 439 and the cursor was 1057; resuming from
1`, y `agent-restart` saltó con su resumen de los 30 s anteriores: 300 muestras, CPU ocupada al 0 %,
MemAvailable 767,5 MiB de 863,0 MiB, nf_conntrack 24 de 843 776, ninguna caída en softnet y después
16,2 s sin muestras. `reboot` no saltó: ningún registro del log del kernel tras volver el agente
tenía un tiempo desde el arranque menor que el último de antes del reinicio. Una sola ejecución, en
un router en reposo.

Más tarde ese mismo día, en el mismo laboratorio, el agente y el colector del código posterior a la
1.5.0 que lee el identificador de arranque del kernel (el agente del tar de la rama, con arranque con
el sistema) ejecutaron siete minutos de `forward --api-mode off --stdout json` a través de una parada
y un arranque del contenedor del agente y después un `/system/reboot`. El agente dentro del
contenedor de RouterOS leyó el identificador y lo sirvió en `/healthz`. Tras `/container/stop` y
`/container/start` (20,6 s sin muestras) el identificador era el mismo, y `agent-restart` lo dijo:
`the kernel's boot id did not change, so the router did not reboot`; ningún `reboot`. Tras
`/system/reboot` (16,5 s sin muestras) el identificador era nuevo: el colector registró `router
rebooted: the kernel's boot id went from 30b9831d-… to 8d4e19f2-…`, y `agent-restart` y `reboot`
saltaron con la primera muestra del agente con el mismo resumen (300 muestras, CPU ocupada al 0 %,
nf_conntrack 24 de 843 776, ninguna caída en softnet). El log del kernel del arranque nuevo no hizo
saltar un segundo `reboot`. Una ejecución de cada caso, en un router en reposo; el laboratorio arm64
no se ejecutó.

Lo que RouterOS escribe sobre un arranque se leyó esa misma tarde por la API, de `/log/print`, tras
cada forma de tumbar el laboratorio x86_64. Tras `/system/reboot` desde una sesión SSH su buffer de
memoria tenía `router rebooted by ssh-cmd:admin@192.168.88.10/reboot` (topics `system,info`); desde
un script, `…/script:rb/reboot`; tras `/system/shutdown` y un arranque, `…/shutdown`; tras quitar la
corriente (`power-cycle`), `router was rebooted without proper shutdown` (`system,error,critical`), y
lo mismo tras el `system_reset` de QEMU (`reset-button`). Con una acción de logging que mandaba
también el topic `system` a disco, un `/log/print` sin más devolvió además las líneas del arranque
anterior, y `/log/print ?buffer=memory` solo las de este.

Después el colector del código que lo lee (`forward --api-mode slow --stdout json`, con la capa de
API recibiendo las credenciales del laboratorio mediante `LAB_CLI_API=lab`) funcionó ocho minutos a
través de un `/system/reboot` y un `reset-button`. Las dos veces la lectura salió bien en la lectura
de salud que notó el identificador de arranque nuevo, antes de que la ronda propia de la capa de API
reconectara (la lectura reabrió la conexión), así que `reboot` saltó con la primera muestra del
agente, con `RouterOS logged at boot: "router rebooted by ssh-cmd:admin@192.168.88.10/reboot"` la
primera vez y `"router was rebooted without proper shutdown"` la segunda, 19,4 s y 22,1 s sin
muestras. Una ejecución de cada caso; la espera de dos minutos a una API que no ha vuelto no se
ejercitó en un router, solo en las pruebas unitarias.

En el RB5009 (RouterOS 7.24.4), el agente 1.6.0 instalado el 2026-10-06 sirvió el identificador de
arranque del kernel en `/healthz` desde dentro de su contenedor. El `agent-restart` de esa
actualización dijo `the kernel's boot id did not change, so the router did not reboot`, que era
cierto pero no se sabía: el agente 1.5.0 anterior no daba ningún identificador. En el código
posterior a la 1.6.0 el primer agente que da un identificador después de uno que no lo daba no
afirma nada sobre el kernel.

Un `power-cycle` del laboratorio no sirve para probar el colector: reinicia el contenedor del
laboratorio, y un colector lanzado antes con `mikroscope-lab cli` conserva el espacio de red del
contenedor viejo y no alcanzó nada tras el corte (`no route to host` hasta que terminó, el mismo
día). El reinicio desde dentro conserva la red del laboratorio.

### Avisos de exposición de doctor

El 2026-10-05, en el laboratorio x86_64 (CHR, RouterOS 7.24.4, KVM), el `doctor` del código
posterior a la 1.5.0 que añade los dos avisos se ejecutó contra el router del laboratorio preparado
de tres maneras. Con `allow-remote-requests=yes` y ninguna regla de cortafuegos, avisó `the router
does not answer DNS from its uplink (…, uplink ether1: no rule drops a query that comes in on it)`.
Con las dos reglas de input de la configuración por defecto (aceptar
`established,related,untracked`, descartar `in-interface-list=!LAN`) añadidas diez segundos antes,
pasó, nombrando el descarte `!LAN`; con solo `in-interface=ether1 protocol=udp dst-port=53
action=drop` también pasó. Con una regla de filter cuya lista de interfaces se había quitado y una
regla de raw cuya veth se había quitado, nombró las dos bajo `no firewall rule doctor reads is
invalid or names a deleted list`.

Lo que hace RouterOS con una regla cuya referencia desaparece se leyó por SSH el mismo día. Una lista
de interfaces quitada bajo una regla dejó la regla válida, con `in-interface-list=!*2000010`; crear
una lista con el mismo nombre no la cambió, y la regla contó paquetes como una regla que lo coge
todo puesta al lado. Un descarte `!LAN` que se quedó así en la cadena input cortó el SSH del propio
laboratorio desde la LAN hasta que se reinició el laboratorio. Una veth quitada bajo una regla dejó
la regla inválida (`in-interface=*4`, `about=vprobe not ready`), y no contó ningún paquete. Una
regla leída justo después de añadirla era inválida sin `about`, y válida cinco segundos después.
RouterOS no deja añadir una regla que nombra una lista que no existe (`input does not match any
value of interface-list`).

Para la colocación de la solución: `place-before=0` falló desde una sesión SSH de una sola orden
(`no such item`), y un place-before de la primera regla de la cadena input falló con la cadena vacía
y funcionó con una regla en ella. Sin probar: IPv6, y una consulta DNS enviada desde fuera del
laboratorio, cuyo enlace de subida es la red de usuario de QEMU; `doctor` lee las reglas y no envía
ningún paquete.

En el RB5009 (RouterOS 7.24.4, 2026-10-06), el `doctor` de la 1.6.0 leyó 80 reglas activas en raw
prerouting y en filter forward e input, ninguna inválida ni que nombrara una lista borrada, y dijo
que la comprobación de DNS no tenía enlace de subida que evaluar: la ruta por defecto activa del
router va por PPPoE, y su `immediate-gw` es la interfaz sola (`PPPoE_DIGI`), que la lectura del
enlace de subida no contemplaba; el enlace DHCP del laboratorio se lee `10.0.2.2%ether1`. Con esa
lectura corregida, el código posterior a la 1.6.0 encontró `PPPoE_DIGI` en la lista `WAN` y evaluó
las consultas como un quizá, porque la regla `accept to local loopback (for CAPsMAN)` de la
configuración por defecto, `dst-address=127.0.0.1`, va antes de su `drop all not coming from LAN` y
se leía como una aceptación posible. Tomando un destino de loopback como no coincidente para un
paquete que llega de Internet, nombró `defconf: drop all not coming from LAN` como la regla que
descarta las consultas. Cada una de las tres ejecuciones fue una sola conexión de lectura.

### RouterOS x86 desde la ISO

El laboratorio opcional que instala RouterOS x86 desde la ISO de MikroTik se ejecutó el 2026-09-26
con RouterOS 7.24.4. El router informó de la placa `x86 QEMU Standard PC (Q35 + ICH9, 2009)` y de
una licencia de prueba sin nivel y con 24 horas por delante. La CLI 1.3.1 y el agente de la rama del
laboratorio se comportaron como en CHR x86_64: a `doctor` le faltaron las mismas dos listas, una
instalación desde el tar respondió al momento, `status` reconoció todos los objetos y `uninstall`
verificó el router limpio, dejando el mismo directorio `mikroscope` vacío. Las `/capabilities` del
agente fueron las de CHR x86_64.

### Ejecuciones en la CI

El flujo se ejecutó por primera vez en los runners de GitHub el 2026-09-26, como el trabajo del
laboratorio de la CI en el pull request #69: cuatro ejecuciones x86_64 entre las 21:06 UTC de ese día
y las 00:45 UTC del 2026-09-27, cada una con las diez pruebas que tenía entonces la batería superadas
(de 471,7 a 485,8 s) en un trabajo de 10 min 30 s a 13 min 30 s. De las tres ejecuciones de abajo,
las dos primeras tenían la caché vacía, así que `make lab-up` descargó RouterOS y lo aprovisionó; la
tercera tomó las descargas de la caché y aprovisionó una instantánea nueva.

| Ejecución                          | Commit                                   | Runner                                                         | `make lab-up`                                                    | Batería                                                                                   | Trabajo       |
| ---------------------------------- | ---------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------- |
| arm64, a petición sobre main       | `e7efbbe`, el laboratorio tal como se fusionó | `ubuntu-latest`: 4 CPU, 15 989 MB, `/dev/kvm` presente     | 4 min 29 s: aprovisionamiento 83 s, un arranque de la instantánea 24 s | 638,6 s, las diez pruebas de ese commit superadas                                    | 16 min 24 s   |
| x86_64, pull request #70           | `3c34d9a`, las opciones de instalación   | `ubuntu-latest`: 4 CPU, 15 989 MB, `/dev/kvm` usado por KVM    | 4 min 28 s: aprovisionamiento 46 s, un arranque de la instantánea 8 s | 1 591,4 s (26 min 31 s), todas las pruebas superadas; S17 omitida, porque necesita un RouterOS anterior a 7.24 | 32 min 42 s   |
| x86_64, pull request #70           | `1826aa5`, con la credencial de registro | `ubuntu-latest`, `/dev/kvm` usado por KVM                      | 1 min 25 s: las descargas desde la caché, aprovisionamiento 76 s | 1 633,1 s (27 min 13 s), todas las pruebas superadas; S17 omitida. El router descargó como la cuenta de Docker Hub del repositorio, S2 incluida; S1, S18 y los scripts de Docker Hub y de GHCR de S5 arrancaron sin ella | 29 min 52 s   |

En las dos primeras de esas ejecuciones se cortó una descarga desde MikroTik
(`connection reset by peer`) y se reanudó al primer reintento. La sonda de KVM en el runner arm64 de
GitHub encontró `ubuntu-24.04-arm` con 4 CPU y sin `/dev/kvm`, así que el laboratorio arm64 sigue
emulado en un runner x86_64.

Las dos ejecuciones en el pull request #70 lo retuvieron 30 y 33 min, y por eso `lab.yml` se ejecuta ahora
solo cada semana y a petición, nunca en un pull request ni antes de una publicación.

En el commit de la publicación 1.4.0 (`79b7c2f`, una ejecución a petición el 2026-09-27, run
36329638066) la batería entera pasó en las dos arquitecturas: 1 517,2 s en x86_64 en un trabajo de
31 min 38 s, y 3 042,6 s en arm64, emulado, en un trabajo de 54 min 52 s. La imagen del agente 1.4.0
aún no estaba publicada, así que los trece casos de referencia que descargan su imagen descargaron la
de la 1.3.1, como hace S5 antes de una etiqueta y dice en su registro.

En el commit de la publicación 1.5.0 (`e61ffb6`, una ejecución a petición el 2026-09-27, run
36344788569) la batería entera volvió a pasar en las dos arquitecturas: 1 573,2 s en x86_64 en un
trabajo de 31 min 38 s, y 3 065,8 s en arm64, emulado, en un trabajo de 54 min 55 s. Los trece casos
de referencia que descargan su imagen descargaron la de la 1.4.0, porque la de la 1.5.0 aún no
estaba publicada, como registró S5.

## Equipos y versiones

| Equipo                         | Tipo                            | RouterOS | Cuándo                                               | Qué se ejecutó allí                                                                                                                            |
| ------------------------------ | ------------------------------- | -------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| RB5009UG+S+                    | hardware, arm64                 | 7.24.1   | hasta la actualización del 2026-09-10                | el coste de una conexión SSH, 2026-08-26                                                                                                       |
| RB5009UG+S+                    | hardware, arm64                 | 7.24.2   | del 2026-09-10 a más o menos el 2026-09-18 22:43 UTC | la mayoría de las campañas, del 2026-09-11 al 2026-09-18                                                                                       |
| RB5009UG+S+                    | hardware, arm64                 | 7.24.4   | desde más o menos el 2026-09-18 22:43 UTC           | la campaña de errores de puerto, los tiempos de `/stream`, las gráficas del almacén de referencia y las órdenes de despliegue desde el 2026-09-21; `upgrade` con la 1.5.0 y la 1.6.0, `doctor` con la 1.6.0 |
| CHR x86_64, laboratorio virtual | virtual (KVM), amd64            | 7.24.4   | 2026-09-26 y 2026-09-27                              | `doctor`, `plan`, tres rutas de instalación, `--expose`, `uninstall` con la 1.3.1; la batería entera del laboratorio con el código posterior y en el commit de la 1.4.0     |
| CHR arm64, laboratorio virtual  | emulado (TCG), arm64            | 7.24.4   | 2026-09-26 y 2026-09-27                              | `doctor`, `plan`, tres rutas de instalación, `uninstall` con la 1.3.1; la batería entera del laboratorio con el código posterior y en el commit de la 1.4.0                |
| CHR x86_64, laboratorio virtual | virtual (KVM), amd64            | 7.23.7   | 2026-09-27                                           | `doctor`, que rechaza un RouterOS anterior a 7.24 (S17)                                                                                         |
| RouterOS x86 desde la ISO, laboratorio virtual | virtual (KVM), amd64 | 7.24.4 | 2026-09-26                                    | `doctor`, una instalación desde el tar, `status` y `uninstall` con la 1.3.1                                                                    |

**Cuándo pasó el RB5009 a 7.24.4.** La actualización en sí no quedó anotada, pero está acotada: la
fecha de compilación de 7.24.4 es 2026-09-16 11:32:21; el 2026-09-24 el router informó de 7.24.4 con
un uptime de 5d15h49m12s, un arranque hacia el 2026-09-18 22:43 UTC; y una actualización de RouterOS
lo reinició a las 00:43:30 CEST del 2026-09-19, las 22:43:30 UTC del día anterior, tras lo cual la
capa del kernel se reanudó a las 00:45:03. El uptime de la capa de la API en el almacén de referencia
crece al ritmo del reloj desde el 2026-09-19 a las 11:13:35 UTC. Así que el router tiene 7.24.4 desde
ese arranque como tarde. Las campañas fechadas del 2026-09-16 al 2026-09-18 constan como 7.24.2; la
cota ni lo confirma ni lo desmiente. Ninguna de las medidas de 7.24.2 se ha repetido sobre 7.24.4.

**Lo que se ejecutó sobre 7.24.4.** `doctor`, `plan`, `install`, `status` y `uninstall` el
2026-09-21, con el agente instalado funcionando de forma continua desde el 2026-09-19. El 2026-09-23
se reprodujo en solo lectura la forma 1.2.x del aviso de registro de `doctor`, y su aviso de token
con una instalación desechable que se expuso, se actualizó sin token y se retiró, así que `upgrade`
también se ha ejecutado allí. Ese mismo día `doctor` leyó 600 muestras del anillo del agente en
marcha y no encontró nada. El 2026-09-24 se le dio a RouterOS la referencia del agente con su host de
registro dentro de `remote-image=`
(dos [hechos verificados](https://docs.jmrp.io/mikroscope/es/about/status/#verified-remote-image-host)). La capa de la API funciona sin
parar sobre 7.24.4 desde el 2026-09-19; sus lecturas de inventario y de claves de pérdidas y su
perfil de coste son de 7.24.2 (2026-09-15 y 16), y su prueba de reconexión y su A/B con 16
interfaces del 2026-09-19, tras la actualización de ese día, sin la versión anotada al lado.

**Los ajustes del contenedor** que escribe `install` se verificaron en el RB5009 con RouterOS 7.24.2
y se volvieron a ejercitar sobre 7.24.4; no se probó ninguna otra placa.

**El agente del RB5009** se actualizó a 1.0.9 el 2026-09-19, a 1.2.0 a las 08:08:54 UTC del
2026-09-24 y a 1.2.1 y 1.2.2 ese mismo día, a 1.5.0 el 2026-09-27 y a 1.6.0 a las 07:15 UTC del
2026-10-06, cada vez con `upgrade --remote-image`; la última tardó 11,8 s desde la orden hasta la
respuesta de la sonda. Los tiempos de `/stream` del 2026-09-21 son del agente 1.0.9.

### Plataformas

De las cuatro plataformas que publica una versión, `arm64` se ha ejecutado en hardware, el RB5009, y
emulada en el laboratorio. `amd64` solo se ha ejecutado en el laboratorio, en el CHR x86_64 y en
RouterOS x86 desde la ISO, ambos bajo KVM, nunca en hardware x86. `arm/v7` y `arm/v5` nunca se han
ejecutado en RouterOS: se compilan de forma cruzada, y la CI arranca cada imagen con `-version` bajo
la emulación de modo usuario de QEMU (`make agent-smoke`), que no es RouterOS. Qué publica cada
versión, y qué números de versión nunca llegaron a publicarse, está en
[Versiones](https://docs.jmrp.io/mikroscope/es/about/changelog/#lo-que-publica-cada-versión).

## Estado de las funciones

Todo lo siguiente se ejecutó contra el RB5009 salvo que diga la batería de contenedores o el
laboratorio: con RouterOS 7.24.2 si está fechado hasta el 2026-09-18, y con 7.24.4 si está fechado
desde el 2026-09-19 ([Equipos y versiones](https://docs.jmrp.io/mikroscope/es/about/status/#un-equipo-dos-versiones-de-routeros)). Cada parte
empieza por su veredicto y la fecha que lo respalda.

### Agente

**El agente funciona en el RB5009: el instalado estaba en marcha allí el 2026-09-23, cuando `doctor`
leyó 600 muestras de su anillo.** Lee `/proc`, `/sys`, `/dev/kmsg` y los contadores de
`perf_event_open` del kernel compartido con un temporizador fijo de 1 a 100 Hz (10 Hz por defecto;
10, 20, 50 y 100 Hz [medidos](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-rates-2026-09-18)), guarda las muestras en un
anillo y las sirve: `/healthz`, `/capabilities`, `/snapshot`, `/stream`, `/sampler`, y los endpoints
de captura por disparo `/captures` y `/capture`. No sirve ningún `/metrics`; la exposición es la del
colector.

### Órdenes de despliegue

**Las seis órdenes de despliegue se han ejecutado en el RB5009 con RouterOS 7.24.4, las seis a más
tardar el 2026-09-23, cada una con la CLI de su fecha. De la 1.4.0 en adelante solo se han
ejecutado allí `upgrade` (la 1.5.0 el 2026-09-27 y la 1.6.0 el 2026-10-06, la segunda leyendo el
manifiesto de instalación que escribió la primera) y `doctor` (1.6.0, 2026-10-06); el resto del
código posterior a la 1.3.1, que es el que publica la 1.4.0, solo se ha ejecutado en el laboratorio
virtual (2026-09-27). Según su código, la 1.5.0 no cambia ningún paso de las seis
órdenes en el router; su `uninstall` rechaza `--grafana-dry-run` y lista los objetivos de Grafana y
de los almacenes antes de tocar el router, ambas cosas comprobadas solo en pruebas unitarias
([`uninstall --targets`](https://docs.jmrp.io/mikroscope/es/about/status/#uninstall---targets)).** `doctor`, `plan`, `install`, `status`, `upgrade`
y `uninstall` instalan, actualizan y retiran el agente, listando cada escritura antes de hacerla y
verificando cada retirada por recuento de propiedad.

- **Ida y vuelta, 2026-09-12**: `doctor` → `install` → `status` → `upgrade` → `uninstall` dejó el
  `/export` del router idéntico byte a byte ([verificado](https://docs.jmrp.io/mikroscope/es/about/status/#verified-export-identical)).
  El agente respondió 3 s después de la instalación, con un tiempo de ida y vuelta de 5–7 ms: dos
  sondeos, 7 ms tras `install` y 5 ms tras `upgrade`, y el primero imprimió
  `direct transport ok: agent 4857d0a-dirty, 10 Hz, seq 29, 0 slipped, 7ms round trip`. Es una
  instalación en una red, no una cifra para otra. La ejecución pasó `--ephemeral` a `doctor`,
  `install` y `upgrade`, y es anterior a 1.1.0, desde la que `uninstall` solo retira con `--yes`.
  `scripts/roundtrip.sh` pasa ahora `--yes` a su desinstalación (hasta 1.2.0 no lo hacía, así que ahí
  solo listaba y su comprobación del export fallaba) y `--ephemeral` a todas las órdenes. En esa forma
  se ejecuta en el laboratorio como `make roundtrip` ([Tiempos del laboratorio](https://docs.jmrp.io/mikroscope/es/about/status/#lab-timings)), y no
  se ha ejecutado contra el RB5009, donde es `make roundtrip-device`.
- **Rutas de instalación**: cuatro rutas de principio a fin el 2026-09-17, y las del laboratorio el
  2026-09-26, en [Rutas de instalación probadas](https://docs.jmrp.io/mikroscope/es/about/status/#install-routes-tested).
- **`doctor` por sí solo** lee además una vez el anillo del agente en marcha y nombra cuatro fallos
  que las herramientas de RouterOS no muestran: un bucle de capa 2, cambios continuos de STP, un
  enlace que cae y vuelve y descartes de softnet. Si ningún agente responde en 3 s lo dice y lo
  omite, y lo que encuentra nunca cambia el código de salida. El 2026-09-23 leyó 600 muestras y no
  encontró nada; los cuatro fallos los cubren pruebas que reproducen el texto real de los registros y
  la cadencia de 2,0 s del bucle del RB5009, no un fallo en vivo. Su hallazgo de cambios de STP se
  apoya en cómo se ve un enlace sano al subir: en el ether7 del RB5009, cinco subidas de enlace el
  2026-09-21 registraron cada una tres pasos a learning a la vez y llegaron a forwarding entre 2,1 y
  2,8 s después, y en 30 días del almacén de ese router toda subida sana dejó learning menos
  forwarding en 0.
- **Sus comprobaciones `WARN`**, que no cambian ni el código de salida ni que `install` siga
  adelante. Dos son anteriores a la 1.4.0: con `--remote-image`, un usuario puesto en
  `/container/config` cuando `registry-url` está vacío o nombra un host distinto del que se descarga
  la imagen; y una instalación con el mismo `--name` publicada en la LAN sin `TOKEN` en su entorno.
  Lee si hay un usuario puesto y cuántas entradas `TOKEN` existen, nunca un valor. La forma 1.2.x del
  aviso de registro se reprodujo en solo lectura sobre 7.24.4 el 2026-09-23; la comparación de hosts
  que la sustituyó solo ha avisado contra respuestas de router falsas en los tests. La 1.4.0 añade un
  `WARN` para una descarga en un router ARM de 32 bits, para una descarga con menos de 16 MiB libres
  por encima del `memory-max` del contenedor, para el arranque con el router cuando la raíz está en un
  disco tmpfs, para una regla de cortafuegos que puede descartar las respuestas del agente, para un
  `--lan-address` en el enlace de subida, para objetos etiquetados para la instalación que las
  opciones no seleccionan, y para una tabla de rutas o un cortafuegos que no pudo leer. De ellos, los
  avisos del tmpfs y de los objetos etiquetados saltaron en el laboratorio en CHR x86_64, RouterOS
  7.24.4, el 2026-09-27; ninguno se ha ejecutado en el RB5009.
- **Extracción del tar**, 7.24.2, 2026-09-11: un tar de 1,8 MiB, una compilación de esa fecha
  anterior a 1.0.0, se extrajo en el mismo segundo que su `/container/add`. La CLI de entonces borraba
  el tar tras una espera fija; la 1.4.0 espera a que el contenedor marque `stopped`, con
  `--extract-timeout` como límite.
- **Una instalación expuesta actualizada sin su token**, 7.24.4, 2026-09-21: el upgrade pasó su
  comprobación, dejó las dos reglas en su sitio y escribió una envlist sin `TOKEN`, y `/snapshot` por
  la dirección LAN del router pasó de `401` a `200`. Desde 1.2.0 `doctor` señala ese estado, y el
  código posterior a la 1.3.1 rechaza un `upgrade` así (laboratorio, 2026-09-27).
- **Un `uninstall` sin más de una instalación expuesta**, 7.24.4, 2026-09-21: retiró todo lo demás,
  imprimió `verified: nothing mikroscope created remains on the router` y dejó el dst-nat apuntando a
  una dirección que ya no existía. El código posterior a la 1.3.1 lee del router la forma de la
  instalación, y un `uninstall` sin más retiró las dos reglas en el laboratorio (2026-09-27).

### `record`, `mark` y `plot`

**`record`, `mark` y `plot` funcionan de extremo a extremo, como muestra una grabación hecha en el
RB5009 el 2026-09-12:** 60 s a 10 Hz, exactamente 600 muestras, 0 huecos y −7 ms de desfase de
reloj. Lo que mostró está en [su campaña](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-record-2026-09-12).

En el laboratorio el 2026-09-27 (CHR x86_64, RouterOS 7.24.4, la imagen publicada del agente 1.3.1),
`record --for 60s` escribió 600 muestras, `seq` de 11 a 610, con 0 huecos. Tres notas de `mark`
desde una segunda shell llegaron al mismo `.markers.csv` mientras `record` corría, y el resumen de
`record` dijo `0 marker(s)`: solo cuenta las notas escritas en él. `mark --log-markers` por la API
del laboratorio añadió 7 marcadores del log del router en la ventana, y `plot` dibujó las 600
muestras y 10 marcadores.

### `forward`

**`forward` se ha ejecutado desde el RB5009 hacia tres de sus once destinos, fichero, Prometheus e
InfluxDB 3, los tres a la vez el 2026-09-15; los otros ocho solo se han vuelto a leer desde productos
reales en contenedores, desde el 2026-09-16.** `forward` une la capa del kernel con la capa de la API
de RouterOS y escribe en once destinos. Por Loki, OTLP, Graphite, Elasticsearch, SQL, PostgreSQL,
Telegraf y stdout no han pasado muestras del router; la batería de contenedores escribe en cada
producto real y lo vuelve a leer por su propia API ([Baterías de pruebas](https://docs.jmrp.io/mikroscope/es/about/status/#las-baterías-de-pruebas)).

- **2026-09-12, ocho minutos**: 4 800 muestras del kernel y 479 de la API reenviadas con 0 huecos y 0
  descartes, ejecutando
  `mikroscope forward --for 8m --prom :9124 --influx … --interfaces bridge,ether1,PPPoE_DIGI --conntrack-every 10s`.
- **2026-09-15, cinco ejecuciones de cadencia** a 10, 50 y 100 Hz hacia un fichero, una exposición
  Prometheus e InfluxDB 3 a la vez: todos los destinos informaron de 0 huecos y 0 descartes
  ([`rates-2026-09-15`](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-rates-2026-09-15)).
- **Prometheus**: un Prometheus 3.14 hizo scrape de la exposición del colector cada 5 s con el RB5009
  alimentando el colector, el 2026-09-12 y de nuevo el 2026-09-15. No consta ningún otro intervalo de
  scrape ni ninguna otra versión de Prometheus.
- **InfluxDB 3**: el primer destino real, el 2026-09-12, respondió
  `422: would exceed limit of 5 databases`, el límite por nodo que InfluxData documenta para Core. Las
  ejecuciones medidas usaron una instancia de InfluxDB 3 Core propia. El 2026-09-19 el colector pasó
  a InfluxDB 3 Enterprise 3.11.4 y escribió 44 820 filas en 36 tablas en sus primeros 19 minutos, 0
  descartadas y 0 errores. Todo lo anterior a esa fecha se midió contra Core.
- **El colector frente a un agente más rápido**, 2026-09-21: con el agente a 100 Hz y otra vez a
  50 Hz, `/healthz` daba `rate_hz` 100 y 50 y el propio registro del colector repetía esa misma
  cadencia, mientras que `mikroscope_info{rate_hz}` valía `10` en los dos casos;
  `mikroscope_cpu_busy_ticks` llevaba los cubos `le="0"` a `le="11"` más `+Inf` en los dos; y
  `window="1s"`, `window="10s"` y `window="60s"` estaban los tres presentes en los dos.
- **Detecciones en el almacén de referencia**, del 2026-09-19 a las 11:13 UTC al 2026-09-24 a las
  08:26 UTC: saltaron cuatro de las once reglas, `microburst` 116 veces, `ipc-collapse` 41 (en los
  cuatro núcleos), `link-flap` 11 y `agent-restart` una. Solo de `microburst` se ha medido el
  comportamiento contra las muestras
  ([`microburst-replay-2026-09-16`](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-microburst-replay-2026-09-16)); las otras
  tres se contaron, sin cotejarlas con lo que hacía el router. Las 11 filas de `link-flap` están en
  `ether1`, `ether2`, `ether4`, `ether6` y `ether7`, cada una con entre 2 y 6 registros de enlace en
  60 s, todas sin provocar; no se comprobó cuál se debió a un cable, a un equipo del otro lado o a
  otra cosa.
- **Reinicios**: el reinicio por la actualización de RouterOS del 2026-09-19 ejercitó de verdad la
  resincronización del colector (la capa del kernel se reanudó a las 00:45:03 CEST). No se comprobó
  si entonces se escribió una fila de `mikroscope_detection` para `agent-restart`, y el almacén que
  la habría guardado se sustituyó más tarde ese mismo día; el actual empieza a las 11:13 UTC. Guarda
  una fila de `agent-restart`, a las 08:08:54 UTC del 2026-09-24, con `value` 1 frente a `threshold`
  4 338 037, cuando se actualizó el agente a 1.2.0.
- **Datos del equipo**: enviados una sola vez al arrancar, los cuatro paneles del equipo muestran «No
  data» en toda ventana posterior: el 2026-09-17 la última fila de equipo del despliegue de
  referencia tenía 26 horas y esos paneles llevaban vacíos otro tanto. Repetidos cada cinco minutos,
  cuestan doce filas por envío en el RB5009.
- **La entrega durante 24 horas**, 2026-09-17, en el despliegue de referencia: la mayor interrupción
  fue de 114,5 s, y la provocamos nosotros, un cambio de contenedor más el minuto que tarda el colector
  en notar que el agente se ha reiniciado. En funcionamiento normal el colector nunca se quedó atrás.
  Por eso el anillo guarda 60 s por defecto: cubre un reinicio de cualquiera de los dos lados en una
  LAN.

### Capa de la API

**La capa de la API ha funcionado en una sola placa, el RB5009, sin parar sobre 7.24.4 desde el
2026-09-19.**

- **Reconexión**, 2026-09-19, tras la actualización de ese día, sin tocar el router: a un colector que
  ejecutaba `monitor-traffic` sobre 16 interfaces (todas salvo `lo`) a 1 Hz se le destruyó el socket
  de la API desde el host con `ss -K`, que es como se ve desde él el lado del router en un reinicio.
  La capa reabrió la conexión y reintentó dentro de la misma ronda: 0 comandos fallidos, 0 rondas
  perdidas, 16 interfaces en cada uno de los 108 segundos a ambos lados de la muerte del socket.
- **Lo que devuelve RouterOS**: [claves de pérdidas](https://docs.jmrp.io/mikroscope/es/about/status/#verified-monitor-traffic-keys),
  una [cuenta de `rx-overflow` que solo llevan los contadores de puerto](https://docs.jmrp.io/mikroscope/es/about/status/#verified-rx-overflow-port-counters),
  los [dos planos de cuenta](https://docs.jmrp.io/mikroscope/es/about/status/#verified-port-planes) de un puerto del switch y su bridge,
  y las [horas del log](https://docs.jmrp.io/mikroscope/es/about/status/#verified-log-time-full-date).
- **`cpu-load`** es una media móvil de más o menos un segundo, ajustada contra `/proc/stat`
  ([`cpu-load-window-2026-09-15`](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-cpu-load-window-2026-09-15)).
- **Lo que le cuesta al router**: [Coste de la capa API](https://docs.jmrp.io/mikroscope/es/cost/#api-tier-cost).

### Dashboards

**Todos los paneles de los cinco dashboards respondieron sin error en un Grafana real sobre los
almacenes de la batería de contenedores (2026-09-17), y los dashboards de InfluxDB y Prometheus
superaron `dashboards check` sobre los datos del propio RB5009 (2026-09-16).** Hay uno por almacén,
InfluxDB 3, Prometheus, PostgreSQL, Graphite y Elasticsearch, generados a partir de una sola lista de
paneles. Graphite y Elasticsearch llevan menos paneles a propósito
(39
y 28
frente a 177): Graphite no tiene etiquetas y
Elasticsearch no tiene documentos anidados. Los paneles de PostgreSQL son los de InfluxDB reescritos,
y la batería de contenedores hace que un PostgreSQL real planifique todas sus consultas. Las versiones
de Grafana usadas son la 12.3.2 el 2026-09-12; la 13.2.1 en las pasadas en el navegador del
2026-09-12 y el 2026-09-14, `check` y renderizado el 2026-09-15, `check` el 2026-09-16 y la batería
de contenedores; la 12.3.0 el 2026-09-21 y en los renderizados del 2026-09-25; y la 13.2.2 el
2026-09-24 y el 2026-09-25. No se ha probado ninguna otra versión.

- **2026-09-12.** En Grafana 12.3.2, el dashboard de InfluxDB contra un InfluxDB 3 Core aislado
  alimentado por `forward` desde el RB5009: todos los paneles devolvieron filas, entre 158 y 316 por
  panel en 10 minutos. El dashboard de Prometheus contra un Prometheus 3.14 haciendo scrape del
  colector cada 5 s: todos los paneles devolvieron filas, entre 228 y 2 052 en 5 minutos. Sin el
  campo `token` de la fuente de datos, los paneles fallaban con `flightsql: Unauthenticated`. Ese
  mismo día `dashboards check --store influxdb --window 12h` pasó en los 125 paneles que recorrió
  mientras unos 90 eran ilegibles en un navegador: leyendas que decían "value core 0", dos xycharts
  atascados en "Loading plugin panel…", una franja de continuidad que seguía en verde sobre 2 170
  ticks perdidos. Un Overview de ocho paneles se renderizó con 2 188 px de alto en una ventana de
  móvil de 844 px, y 900 puntos de datos es el ancho que envió el navegador para las gráficas.
- **2026-09-14.** Un Overview de once paneles midió 1 052 px de alto en una ventana de navegador de
  1 080 px, una pantalla de escritorio; un
  recorrido de renderizado contra una captura de 10,5 h del RB5009 renderizó 140 paneles de InfluxDB
  con 0 insignias de error y 0 "No data"; la fuente de datos de InfluxDB escapó `$__interval_ms` en
  cinco paneles, en el navegador, convirtiéndolo en un SQL que InfluxDB 3 no podía analizar; y una
  consulta que nombraba un campo que el almacén nunca había recibido falló al planificarse,
  `No field named limit. Valid fields are …`, a través del proxy de la fuente de datos.
- **2026-09-15, Grafana 13.2.1**: `check`, y un recorrido fila a fila sin interfaz de los dos
  dashboards en Chromium a 1600x1000, 0 insignias de error y 0 "No data" en 168 paneles de InfluxDB y
  130 de Prometheus. No se ha repetido para los tres paneles que no cubrió: los dos de eventos de
  puerto y "What each interface is: type, role, bridge and label". El mismo recorrido vio la
  proporción de fast path oscilar entre 0 y 100 % de una lectura a otra en interfaces que movían
  pocos paquetes. Regenerar ese día reprodujo byte a byte los ficheros del repositorio.
- **2026-09-16, Grafana 13.2.1**, contra el agente del RB5009 (RouterOS 7.24.2, privilegiado, los
  disparadores por defecto), `forward --prom :9124 --influx … --interfaces bridge,ether1,PPPoE_DIGI
  --counters-every 10s` durante 30 minutos hacia un InfluxDB 3 Core aislado, y un Prometheus 3.14
  haciendo scrape del colector cada 5 s y del agente directamente para las familias que el colector
  no podía recalcular entonces:

| Almacén    | Ventana    | Paneles | Fallan | Vacíos conocidos tolerados                                                                                                                                  |
| ---------- | ---------- | ------: | -----: | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| InfluxDB 3 | 30 minutos |     171 |      0 | 10 (los dos paneles de eventos de puerto, la consulta opcional de conntrack, los dos paneles de disparos, PSI, los cuatro dispositivos de bloques en reposo) |
| Prometheus | 30 minutos |     133 |      0 | 9 (los dos paneles de eventos de puerto, los dos paneles de conntrack de la API, PSI, los cuatro dispositivos de bloques)                                    |

Los 10 y 9 son ese despliegue sobre esa ventana. El SQL de los dos paneles de eventos de puerto se
validó ese mismo día contra una tabla sintética en ese mismo InfluxDB 3, porque el almacén en vivo no
tenía columna `kind` hasta que se le escribiera el primer registro de puerto clasificado; la tiene
desde el 2026-09-19, con las ocho clases. La página de dashboards de esa fecha registró además que
la exposición del propio agente llevaba la etiqueta `kind` solo cuando el propio agente clasificaba,
cosa que el del RB5009 no hacía entonces; hoy los agentes no sirven exposición.

- **2026-09-17, batería de contenedores**: los cinco dashboards importados en un Grafana real sobre
  los almacenes que llenó la batería, preguntando a cada panel: devolvieron datos 57, 98, 136, 35 y
  28 paneles, y no falló ninguno.
- **2026-09-21, Grafana 12.3.0**: `import` contra el almacén InfluxDB 3 en vivo y después `check` sobre
  una ventana de 15 min: 167 paneles devolvieron filas, los 9 vacíos conocidos salieron vacíos, y el
  indicador de detecciones del Overview salió vacío porque el almacén no tenía ninguna detección en
  esa ventana, que es el único caso que `check` señala y que un navegador lee como el «none» sano.
- **2026-09-24, el Grafana de producción**, cuyo endpoint de salud informaba de la 13.2.2 más tarde
  ese mismo día: el dashboard de InfluxDB importado y capturado a 390x844 y a 1600x1000 para comprobar
  el texto de 32 px de los paneles stat y la serie temporal de memoria. Con el tamaño automático de
  Grafana, un simple "0" se dibujaba de unos 60 px de alto a 390x844 y cada panel stat ocupaba cerca
  de un tercio de la pantalla; con el tamaño fijo, los números se leían a un tamaño normal en los dos.
  No se hizo recuento de insignias fila a fila, no se midió la altura del Overview y los otros cuatro
  dashboards no se capturaron.
- **2026-09-25, Grafana 12.3.0, 13.2.1 y 13.2.2 sobre un InfluxDB 3.11.2 Core desechable**:
  - La fila no disponible tal como estaba en 1.3.0 envió cinco consultas y pintó cinco insignias
    `table … not found` en 12.3.0 y 13.2.1; con sus consultas publicadas ocultas no envió ninguna ni
    pintó ninguna, y 13.2.2 hizo lo mismo en un segundo renderizado.
  - Una consulta de detecciones contra una tabla `mikroscope_detection` que falta no puede escribirse
    de forma que evite el error de planificación de InfluxDB 3: `WHERE false`, un `UNION ALL` y una
    guarda `EXISTS` sobre `information_schema` fallaron todas al planificar. En 13.2.1 la capa que
    falla no mostró nada en el dashboard y escribió en el log de Grafana una línea de nivel error
    `Partial data response error` por carga. 12.3.0 nunca envió la consulta de esa capa, con la tabla
    o sin ella ([problema conocido](https://docs.jmrp.io/mikroscope/es/about/status/#encontrado-y-sin-corregir)).
  - Un `import` con sondeo desde 1.3.0 quitaba las consultas de un panel que faltaba, y Grafana
    12.3.0 le da a un panel sin consultas una por defecto: el plugin de InfluxDB le respondió
    `No SQL statements were provided in the query string`, como una insignia roja. 13.2.1 no envió
    nada por ese mismo panel.
  - Elasticsearch 9.5.3: la búsqueda de la variable Host, escrita hasta 1.3.0 como un objeto JSON,
    salía de 13.2.1 y 13.2.2 como una consulta vacía respondida con 400
    `invalid query, missing metrics and aggregations`, y 12.3.0 no la enviaba; abierto sin
    `?var-host=`, seis paneles del Overview fallaban con `Failed to parse query [host.keyword:]`.
    Escrita como la cadena JSON que analiza la fuente de datos, Host se llenó desde el índice y ningún
    panel mostró insignia en ninguna de las tres.
  - Un panel de InfluxDB que agrupa con `$__dateBin` con un paso por debajo del segundo dibujó un bin
    de 0 segundos y volvió vacío, en `check` y en un navegador con el zoom en unos pocos minutos, en
    13.2.1 y 13.2.2.
- **2026-09-25, el Grafana 13.2.2 de producción contra el almacén InfluxDB 3 de referencia**, con una
  compilación que oculta las consultas de la fila no disponible: `dashboards check --window 1h`, con
  el sondeo y con `--no-probe`, dio 164 paneles con filas, 12 vacíos conocidos tolerados y 1 fallo,
  "Detections in the window", porque el almacén no tenía ninguna detección en esa hora. Sin el
  sondeo, los cinco paneles no disponibles salen como `none … rows=0 frames=0` sin texto de error,
  donde 1.3.0 imprimía `400 … table … not found`; los dos paneles de disparos respondieron
  `mikroscope_trigger not found`, porque ese almacén no tiene tabla de disparos. El SQL de la anotación
  de detecciones devolvió 44 filas en 6 horas. Repetido más tarde ese día, después de que los ficheros
  sin sondeo de los otros cuatro almacenes recuperaran sus consultas de la fila no disponible, dio los
  mismos recuentos, y la capa de detecciones 32 filas en 6 horas; el fichero de InfluxDB comprobado
  era idéntico byte a byte al de la primera vez.
- **2026-09-25, batería de contenedores** (Grafana 13.2.1, Prometheus 3.14.0, PostgreSQL 18.6,
  graphite-statsd 1.1.10-5, Elasticsearch 9.5.3): las consultas no disponibles de los ficheros del
  repositorio, contra almacenes que no tenían nada para ellas, respondieron todas 200 sin error, y en
  Elasticsearch todos los puntos fueron 0, tanto si otro router del mismo índice había mapeado el
  campo como si no. En PostgreSQL la consulta de la capa de detecciones respondió 200 sin filas sobre
  una ventana anterior a cualquier detección, y 10 filas sobre la de la propia ejecución. Las dos
  fueron consultas por la API de Grafana, no renderizados.
- **La continuidad** se deriva del número de secuencia de cada muestra, y encontró 4 493 ticks
  perdidos y un reinicio en la captura del 2026-09-11/12 de los que el registro de huecos del colector
  no decía nada.
- **El rango por defecto** es de 3 horas porque `now-15m` abría 108 paneles vacíos con el agente
  parado, y con el agente en marcha dibujaba muros de ruido ilegibles de muestras de 100 ms (la fecha
  no consta).

### Reglas de alerta

**Solo la forma de InfluxDB 3 de las reglas se ha cargado en Grafana y se ha visto evaluarse, el
2026-09-21 contra el almacén del mantenedor; las formas de Prometheus y PostgreSQL nunca.** Las reglas
son 14 para InfluxDB
3, 15 para Prometheus
y 10 para PostgreSQL.

- **La carga del 2026-09-21**, en Grafana 13.2.1 contra el almacén InfluxDB 3 en vivo, tenía las doce
  reglas de InfluxDB de esa fecha y destapó dos defectos, los dos corregidos en 1.1.0. `coalesce()`
  sobre el agregado sin signo que escribe el destino de InfluxDB devolvía HTTP 200 sin marcos, que
  Grafana lee como NoData y estas reglas como OK: siete de las doce no podían saltar nunca,
  `mikroscope-l2-loop` entre ellas, mientras el mismo SQL contra `/api/v3/query_sql` devolvía 109 con
  la firma del bucle en vivo. Y la regla de conntrack nombraba `limit_objs`, la columna del destino
  SQL, donde el destino de InfluxDB escribe `limit`; la página de reglas de alerta había predicho ese
  defecto antes de confirmarse. Tras la corrección las doce devolvieron un valor, y
  `mikroscope-l2-loop` pasó a Alerting a las 16:58:50Z con la firma `own-address` en vivo; la lista de
  instancias de Grafana para esa regla seguía llevando `Normal (NoData)` de las 16:56:50Z, de la
  ejecución anterior a la corrección.
- **Consultas ejecutadas a mano contra el almacén en vivo el 2026-09-21**: `mikroscope-l2-loop` dio
  109 en su propia ventana de cinco minutos, con la firma `own-address` en `ether2` corriendo sin
  parar a unos 0,5 registros/s desde el 2026-09-19; `mikroscope-port-link-down` dio 3 en la ventana que
  contiene una caída de enlace real en `ether7` a las 16:33:49 y 4 en el grupo de cuatro de `ether4`
  de las 09:19 del 2026-09-20. Las dos tienen umbral 0 con `gt`, así que las dos condiciones se
  cumplieron.
- **Las dos reglas que añadió 1.2.0** no estaban en esa carga, y ningún Grafana las ha evaluado
  desde entonces. Su SQL de InfluxDB se contrastó con datos pasados del almacén de referencia:
  `mikroscope-bridge-port-dark` devolvió 1 en tres ventanas dentro del bucle y 0 después, y marcó
  `sfp-sfpplus1` en 204 intervalos de diez minutos y `ether2` en 376 entre el 2026-09-19 11:13 y el
  2026-09-23 22:44 UTC, las dos fases del bucle de capa 2 de esa semana, y ningún otro puerto.
  `mikroscope-wakeup-storm` devolvió 0,94–0,95 en dos ventanas sanas, nunca pasó de 1,81 en 551
  ventanas de diez minutos con un día completo detrás (del 2026-09-20 al 23), y se abrió en 35,7 con la
  tormenta de despertares del 2026-09-23; se apagó cuando la nueva tasa pasó a ser la base, al cabo de
  unas cuatro horas. Su PromQL solo se comprobó en su sintaxis. De la forma PostgreSQL de la regla de
  despertares no consta ninguna ejecución, y la regla del puerto oscuro no tiene forma PostgreSQL: la
  1.2.1 la quitó, porque la tabla de contadores de interfaz del destino SQL no tiene las columnas que
  lee.
- **La regla de detecciones** ya no salta con `microburst` ni con `ipc-collapse`, que describen cómo
  lleva el tráfico un router sano: del 2026-09-23 10:30 al 2026-09-24 10:30 UTC en el RB5009 fueron 64
  de 71 detecciones, y con ellas la regla saltó en 43 de 288 ventanas de cinco minutos; sin ellas, en
  6.
- **La regla de salida**: un puerto de 1 GbE hacia un servidor perdió 3 337 paquetes en seis ráfagas
  de un segundo a lo largo de 6,5 h, con picos de 436 paquetes/s (2026-09-19), visible en el panel de
  cola de salida y, con razón, sin ser una alerta.
- **La regla térmica** lee el punto de disparo crítico de la propia zona, 105 °C en el RB5009.

### `forward --grafana`

**`forward --grafana` se ha ejecutado contra el Grafana del mantenedor (2026-09-19, InfluxDB 3) y
contra el de la batería de contenedores para los cinco almacenes (2026-09-20, y con el código de la
1.5.0 el 2026-09-27). `dashboards publish` solo se ha ejecutado allí, el 2026-09-27, sobre lo que
`forward --grafana` acababa de crear.** El 2026-09-20 se apuntó el colector a un Grafana real y a
cada uno de los cinco almacenes por turno, se le dejó crear la fuente de datos, y después
`dashboards check` pasó la consulta de cada panel por la API de Grafana contra la fuente de datos
que había construido el colector. Los cinco respondieron sin error de fuente de datos tal como lo
leía la prueba de esa fecha: buscaba `flightsql: Unauthenticated`, el error de TLS que se cita más
abajo y `err` con un espacio a cada lado, que no es ninguna marca que imprima `check`, así que un
error redactado de cualquier otra forma la pasaba. La misma ejecución encontró un defecto que
ninguna prueba unitaria tenía: un colector que escribía en un PostgreSQL vivo por `--postgres` y en
nada más no publicaba nada y decía «there is nothing to publish», porque la lista de almacenes solo
conocía `--sql`. Contra un almacén InfluxDB en HTTP plano, una fuente de datos sin `insecureGrpc`
respondía a todos los paneles
`tls: first record does not look like a TLS handshake` mientras el almacén estaba perfectamente
(medido el 2026-09-19).

El 2026-09-27 la prueba se ejecutó con el código de la 1.5.0 (el commit `ffb934e`, cuyo código Go es
el de la publicación; la ejecución 36344009521 de `e2e.yml`) contra Grafana 13.2.1, InfluxDB 3.11.2
Core, Elasticsearch 9.5.3, PostgreSQL 18.6, Prometheus 3.14.0 y graphite-statsd 1.1.10-5, y para
entonces fallaba con cualquier línea `FAIL` de `check` que llevara un error. Para cada almacén por
turno, `forward --grafana` creó la fuente de datos y publicó el dashboard, `check` pasó cada panel
contra esa fuente de datos sobre una ventana de 15 minutos, y `dashboards publish`, con las mismas
opciones de almacén y de Grafana, salió con código 0, dio la fuente de datos como `unchanged` e
imprimió la dirección del dashboard. Ningún panel que `check` cuenta como fallido llevaba un error;
un panel que se espera vacío se marca `none` cuando no devuelve filas o devuelve un error, y la
prueba solo lee esas líneas en busca de los dos errores de InfluxDB de arriba. La fuente de datos de
Elasticsearch fue la del colector, con `@timestamp` como campo de tiempo (la de la 1.4.0 nombraba
`time`, un campo que no lleva ningún documento), y su `check` salió con código 0; en InfluxDB,
PostgreSQL, Prometheus y Graphite, 5, 20, 33 y 4 paneles no devolvieron filas en la ventana, sin
error. No se ha probado en la batería: la cabecera `Authorization` que envía la fuente de datos de
Elasticsearch, porque su Elasticsearch funciona sin autenticación; una fuente de datos que lleve un
token o una contraseña, que ningún almacén de allí tiene; ni una ejecución que publique más de un
almacén, porque cada ejecución publicó uno.

### `uninstall --targets`

**`uninstall --targets` retiró solo lo que escribió este proyecto en la batería de contenedores
(2026-09-20, y `--targets data` de nuevo con el código de la 1.5.0 el 2026-09-27), y no se ha
ejecutado contra el almacén de producción del mantenedor.** La batería comprueba que una tabla que
este proyecto no escribió, en la misma base de datos y el mismo esquema, ni se lista ni se borra.
Ejecuta la orden solo con `--targets data`, contra PostgreSQL e InfluxDB 3, sin router y sin
Grafana. Lo que la 1.5.0 cambió en la orden fuera de ese camino solo tiene pruebas unitarias:
rechaza `--grafana-dry-run`, lista los objetivos de Grafana y de los almacenes antes de tocar el
router, se detiene ante un Grafana que no pudo leer, que la 1.4.0 contaba como uno sin nada que
retirar, y lee la dirección de Grafana de `GRAFANA_URL` cuando
`MIKROSCOPE_GRAFANA_URL` no está definida.

### Baterías de pruebas

**Cuatro baterías no necesitan router: la unitaria y la de extremo a extremo se ejecutan en la CI en
Linux, macOS y Windows contra árboles capturados y simulaciones, otra contra nueve almacenes reales
en docker compose, completa por primera vez el 2026-09-16, y otra ejecuta la CLI y el agente contra
un RouterOS virtual, en verde por primera vez el 2026-09-26 y ejecutada por primera vez en los
runners de GitHub el mismo día.** Qué demuestra cada una y cómo ejecutarla está en
[Baterías de pruebas](https://docs.jmrp.io/mikroscope/es/reference/testing/).

- **De extremo a extremo**: los dos binarios contra un árbol `/proc` capturado del RB5009 y un agente
  simulado, con un receptor por cada protocolo de destino que comprueba los bytes. No necesita router,
  ni Grafana, ni red, y se ejecuta en la CI tanto en macOS y Windows como en Linux, que es donde se
  notaría una diferencia en el nombre del ejecutable, en los ficheros que escriben los destinos de
  fichero y SQL, o en cómo se detiene un proceso hijo. Cada destino se prueba contra un receptor local
  desde el 2026-09-12, en el equipo de desarrollo amd64. La batería antes hacía scrape del agente y del
  colector, y ahora comprueba solo el colector.
- **Almacenes** (`make test-e2e-docker`): el colector, contra el mismo agente enlatado y con la capa
  de la API apagada, hacia Loki 3, el OpenTelemetry Collector, graphite-statsd, Elasticsearch 9,
  Telegraf 1.39 por HTTP, PostgreSQL 18 (con `--sql`, y con `--postgres` desde que ese destino llegó el
  2026-09-21), InfluxDB 3 y Prometheus, con el destino de fichero como el oráculo contra el que se
  comparan los demás. Cada almacén se vuelve a leer por su propia API, después se importan los cinco
  dashboards en Grafana y la consulta de cada panel pasa por la API de Grafana; la batería hace que
  `forward --grafana` publique las cinco fuentes de datos y comprueba sus dashboards contra ellas,
  después, desde el 2026-09-27, ejecuta `dashboards publish` con las mismas opciones de almacén y de
  Grafana, que tiene que salir con código 0 y nombrar la fuente de datos y el dashboard de cada
  almacén, y vuelve a vaciar los almacenes con `uninstall --targets data`. Necesita Docker y ningún
  router: las muestras son enlatadas, así que la
  ejecución es reproducible en cualquier máquina. La primera ejecución completa, el 2026-09-16,
  encontró un panel que nombraba dos columnas que el almacén solo tiene cuando se ejecutó la capa de la
  API: la tabla de eventos de puerto nombra `label` y `role`, que el destino escribe en una fila del
  registro del kernel solo desde el inventario de la capa de la API, y en InfluxDB 3 una columna que
  no está en la tabla hizo fallar la consulta con `Schema error: No field named label`, así que el
  panel no podía dibujarse. Las páginas de destinos registran el colector escribiendo en estos
  almacenes desde el 2026-09-17. En la máquina de desarrollo, el 2026-09-16, la pila se levantó en 55
  a 81 s con las imágenes ya descargadas, y la batería entera tardó de 75 a 100 s desde cero. La
  batería entró en la ruta de los pull requests el 2026-09-18. Hasta entonces se ejecutaba cada
  semana, a petición y antes de una publicación, y así llegó la 1.0.5 a `main` con dos pruebas de la
  batería leyendo todavía el `/metrics` del agente, que esa versión había quitado: todos los checks
  del pull request estaban en verde, y lo encontró la puerta de publicación. En la ejecución de
  publicación que falló tardó 2 min 37 s desde el inicio del trabajo hasta el resultado, contenedores
  incluidos; en el pull request #70, el 2026-09-27, 4 min 9 s. El OpenTelemetry Collector, que acepta JSON, es el único receptor OTLP real contra el que
  se ha ejecutado el destino. El 2026-09-20 los destinos SQL y PostgreSQL, ejecutados en paralelo
  hacia dos bases de datos, tenían 34 tablas coincidiendo byte a byte, cada columna de cada fila con
  un hash por fila sumado, más un `information_schema.columns` idéntico para todo el esquema.
- **Laboratorio virtual de RouterOS** (`make test-lab`): los verbos de despliegue de la CLI y el
  agente contra el Cloud Hosted Router 7.24.4 de MikroTik en QEMU, x86_64 y arm64 emulado:
  instalación por las dos vías de imagen, actualización, desinstalación, `--ephemeral` y
  `start-on-boot` a través de un corte de corriente, y cada escenario termina comparando el `/export`
  del router con el de su inicio. Prueba que el instalador es correcto; no es una placa, y ninguna
  cifra de [Coste del agente](https://docs.jmrp.io/mikroscope/es/about/status/#lo-que-cuesta-hoy-el-agente) ni de [Campañas](https://docs.jmrp.io/mikroscope/es/about/status/#campaigns) sale de él.
  El laboratorio, sus tiempos y sus primeras ejecuciones en los runners de GitHub están en
  [Laboratorio virtual](https://docs.jmrp.io/mikroscope/es/about/status/#virtual-lab), y sus escenarios en
  [Baterías de pruebas](https://docs.jmrp.io/mikroscope/es/reference/testing/#el-laboratorio-virtual-de-routeros).
- **Fixtures de los destinos**, no un router: los tamaños de SQL, OTLP, Graphite, Elasticsearch y
  Telegraf de [Otros destinos](https://docs.jmrp.io/mikroscope/es/sinks/other/) salen de fixtures de pruebas de dos
  núcleos del 2026-09-12. La cabecera SQL de las cuarenta y tres tablas, generada por el propio
  `header()` del destino el 2026-09-19, ocupa 10 482 B, 13 966 B con las sentencias de hypertable de
  TimescaleDB. Doce renderizados de un mapa de 8 nombres dieron 7 órdenes (2026-09-12), registrado
  en [`internal/sinks/telegraf.go`](https://github.com/jmrplens/mikroscope/blob/main/internal/sinks/telegraf.go).
- **El equipo de desarrollo** (amd64, kernel 6.12.107): `TestParsePressureReadsTheRunningKernel` y
  `TestParseSchedstatReadsTheRunningKernel` analizan el `/proc/pressure/{cpu,memory,io}` y el
  `/proc/schedstat` del propio equipo y los comparan con una segunda lectura de esos mismos bytes, y se
  saltan la prueba donde los ficheros no están, que es el caso del RB5009. En ese equipo pasan. Su
  `/proc/pressure/cpu` lleva línea `full`, toda a cero al volver a leerla el 2026-09-24: la
  documentación de PSI del kernel dice que el `full` de CPU no está definido para el sistema entero y
  que se publica desde la 5.13 a cero, así que un kernel más antiguo no tiene esa línea y el analizador
  acepta las dos formas. Su PMU, registrada el 2026-09-21,
  tiene seis contadores, `cycles`, `instructions`, `cache-references`, `cache-misses`,
  `branch-instructions` y `branch-misses`, multiplexados, cada uno funcionando en torno al 84 % del
  tiempo que estuvo habilitado. Un intervalo de 100,3 ms llevó allí 11 ticks (2026-09-11/12);
  `sample_test.go` comprueba que la fracción de ocupación está limitada a 1.
- **El rearme del filtro de cambios**, contra el árbol de fixtures el 2026-09-15: las familias de
  medidores con suelo y `mikroscope_slab_limit_objects` estaban presentes en 6 de 6 scrapes desde 5 s
  después del arranque. El comentario de `ProcSource.ReArm`
  en [`internal/agent/source.go`](https://github.com/jmrplens/mikroscope/blob/main/internal/agent/source.go) registra la misma comprobación como cuatro scrapes desde
  t+5 s, 0 antes de la corrección y 4 de 4 después; no consta de qué ejecución es cada cuenta.
- **El generador de scripts**, 2026-09-27: `pnpm run rsc:check` renderiza en JavaScript los 20 casos
  de referencia de la especificación de pasos y compara byte a byte con la salida de Go cada script,
  las órdenes de cada paso, el orden de retirada, los valores y la línea de órdenes; un cambio de una
  línea en el renderizador le hizo informar de 72 fallos. `pnpm test:generator` hizo 168
  comprobaciones en Chromium sin interfaz (Playwright 1.63) contra el sitio compilado: los 20 casos
  puestos con los propios controles del formulario, los errores, el token, copiar, el uso solo con
  teclado, ninguna petición de red, y las descargas `.rsc`, que funcionan bajo la CSP meta del sitio.
  Una comparación puntual con el código de Go sobre 304 juegos de opciones coincidió en 301; los
  otros tres son entradas que la página rechaza y Go acepta (un prefijo `/030`, un umbral
  `busy>=.5` y una dirección IPv6 con IPv4 mapeada).
- **El sitio**, 2026-09-25: Chromium 153 sin interfaz pidió solo `favicon.svg`, y resolvió un `id` de
  manifiesto `./` a la raíz del origen; en Chromium y WebKit sin interfaz, con los dos esquemas, tras
  elegir en el selector, tras una elección guardada y una recarga, tras el botón del teléfono y sin
  JavaScript, la etiqueta `theme-color` tuvo el color de la cabecera todas las veces, donde el par
  separado por `prefers-color-scheme` al que sustituye tenía el color del otro tema tras cada elección.

## Rutas de instalación probadas

| Ruta                                   | RB5009UG+S+                                                                                                                                                                                                                                         | CHR x86_64, laboratorio                                                                      | CHR arm64, laboratorio                                                                              |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| Descarga de Docker Hub, `--remote-image` | 2026-09-17, 7.24.2: `/healthz` a 2 ms; la imagen 1.0.1, enviada sin su host y descargada a través de `registry-url`. 2026-09-24, 7.24.4: la referencia con su host, con un `/container/add` escrito a mano, sin arrancar; ningún `install` completo | 2026-09-26: `install` en 9,6 s, descarga anónima con el `/container/config` de fábrica; 2026-09-27: S2, S4 y S5 | 2026-09-26: `install` en 10,3 y 10,2 s, descarga anónima; 2026-09-27: S2, S4 y S5 |
| Descarga de GHCR, `--remote-image`     | 2026-09-21, 7.24.4: **falló**, `auth error`                                                                                                                                                                                                         | 2026-09-26: descarga sin credencial de registro y con el host en `remote-image=`, `/healthz` 5 s después de empezar la instalación; 2026-09-27: S18 y S5 | 2026-09-27: S18 y S5 |
| `plan --rsc`, con `/import`            | 2026-09-17, 7.24.2: `/healthz` a 15 ms en sus primeras muestras, sin CLI en la instalación                                                                                                                                                          | 2026-09-26: `/healthz` 14 s después de empezar la subida; 2026-09-27: S4, y los quince guiones de referencia que el laboratorio puede ejecutar (S5); el script por defecto pegado en el indicador `] >`, y un script de tar sin su tar, que se detuvo antes de escribir nada | 2026-09-26: `/healthz` 9,1 y 9,5 s después de empezar la subida; el script era el de x86_64; 2026-09-27: S4 y S5 |
| Tar de la imagen, `--agent-tar`        | 2026-09-17, 7.24.2: el tar arm64 publicado, `/healthz` a 2 ms                                                                                                                                                                                       | 2026-09-26: el tar amd64 de la versión, 6 s; 2026-09-27: el tar de la rama, S3 y diez instalaciones seguidas; el tar amd64 de la versión comprobado con `sha256sum` y `cosign verify-blob`, y después instalado y actualizado | 2026-09-26: el tar arm64 de la versión, suma de comprobación como la publicada, 9,6 y 9,2 s; 2026-09-27: el tar de la rama, S3 y tres instalaciones seguidas |
| Generador de scripts                   | sin ejecutar | 2026-09-27: el script por defecto de la página, igual al de `plan --rsc`, y un script de tar con otros ajustes, cada uno descargado de la página compilada y pegado en el indicador `] >`; el agente respondió cada vez, y el `uninstall` de la CLI y el script de desinstalación de la página dejaron cada uno el `/export` como estaba | sin ejecutar |
| Instalación manual, terminal           | sin ejecutar | 2026-09-27: las órdenes de la página una a una, descarga del registro y tar; `/healthz` respondió, `status` reconoció la instalación por su manifiesto, y la retirada de la página no dejó nada; de nuevo con las dos reglas de `--expose`, y con las dos pertenencias omitidas | sin ejecutar |
| Instalación manual, WebFig             | sin ejecutar | 2026-09-27: las dos vías de imagen, cada formulario enviado; `/healthz` 200 cada vez; la descarga retirada por WebFig, el tar por `uninstall` leyendo el manifiesto que escribió WebFig; el `/export` como estaba tras cada una | sin ejecutar |
| Desde el repositorio                   | 2026-09-17, 7.24.2: `/healthz` a 2 ms; la ida y vuelta del 2026-09-12                                                                                                                                                                               | sin ejecutar                                                                                 | sin ejecutar                                                                                        |
| `--expose`                             | 2026-09-11: las dos reglas [verificadas](https://docs.jmrp.io/mikroscope/es/about/status/#verified-expose-rules); 2026-09-23, 7.24.4: una instalación desechable expuesta, actualizada sin token y retirada                                                                             | 2026-09-26: `/healthz` 200, `/capabilities` 401 sin el token y 200 con él; 2026-09-27: S8 y S14 | 2026-09-27: S8 y S14 |
| `uninstall`                            | 2026-09-17: verificado por recuento de propiedad tras cada ruta; el `/export` tras las cuatro, idéntico byte a byte al de antes                                                                                                                      | 2026-09-26, 1.3.1: fallaron 5 de 15 primeros intentos; un segundo lo limpió todo cada vez. 2026-09-27: cada primer intento limpio, tras cada ruta (F4) | 2026-09-26, 1.3.1: 8 de 8 primeros intentos limpiaron; con un cliente en `/stream` falló. 2026-09-27: cada primer intento limpio, tras cada ruta (F4) |

- **En el laboratorio, el 2026-09-27**, con el código posterior a la 1.3.1 (la sección 1.4.0
  del registro de cambios): la batería entera del laboratorio en las dos arquitecturas, con todas las
  pruebas superadas ([Tiempos del laboratorio](https://docs.jmrp.io/mikroscope/es/about/status/#lab-timings)). Tras cada ruta, las de descarga y tar
  de la CLI, una instalación desde el tar y después una actualización, un guion de `plan --rsc`
  importado, cada guion de referencia que el laboratorio puede ejecutar e instalaciones hechas por la
  CLI 1.3.1 publicada, `uninstall` dejó el `/export` igual al tomado antes de instalar y ninguna ruta
  de mikroscope en `/file`. La descarga de GHCR del 2026-09-26 registró `registry=ghcr.io`, una capa
  de 3 093 207 bytes y `download/extract done` 2 s después, con `/container/config` sin
  `registry-url` ni usuario.
- **Las ejecuciones de las páginas de instalación**, 2026-09-27, en el laboratorio x86_64, con el
  código posterior a la 1.3.1 y la imagen y el tar publicados del agente 1.3.1:
  - El script por defecto del generador respondió 8,8 s después de empezar a pegarlo. Su script de
    tar (nombre `gen2`, `172.30.11.0/30`, puerto 9200, las dos listas `none`, cadencia 20, disparos
    `busy>=0.9,oom`, un token generado en la página, `--expose` en 192.168.88.1,
    `--restart-max-count 3`, `--start-on-boot no`) era idéntico byte a byte al de `plan --rsc` para
    la línea de órdenes de la página, respondió en `172.30.11.2:9200` y borró su tar tras la
    extracción.
  - El script por defecto de `plan --rsc`, idéntico byte a byte a `pull-dockerhub.rsc`, instaló un
    agente en marcha tanto pegado como subido y después con `/import` (`Script file loaded and
    executed successfully`). El script de tar sin el tar se detuvo con
    `mikroscope: upload mikroscope.tar first` y no escribió nada.
  - Las órdenes de la página de instalación manual por terminal, cada una por separado: las dos vías
    respondieron, la espera de la vía del tar borró el tar tras la extracción, y una instalación
    manual con tar también la retiró `uninstall --yes` sin más. Un buscar y reemplazar de los
    marcadores que también reescribió las claves de la envlist hizo que la retirada dejara la envlist
    entera, sin avisar, y por eso la página dice que se reemplacen solo los valores.
  - La misma página otra vez, cuando ya escribía un manifiesto por vía de imagen y daba a `--expose`
    una sección: una descarga del registro expuesta en `192.168.88.1` con token, una instalación con
    tar y una descarga del registro con las dos pertenencias omitidas. Cada manifiesto que
    escribieron sus órdenes fue idéntico byte a byte al de la CLI con los mismos ajustes
    (`pull-dockerhub`, `expose-token`, `default-tar`, `lists-none`); `status` leyó cada uno de su
    manifiesto, el expuesto con sus dos reglas como de la instalación; `/capabilities` respondió 401
    sin el token y 200 con él; y la retirada de la página, primero las dos reglas, dejó la cuenta de
    sobrantes en 0 y `/export`, el residuo y `/file` iguales a la referencia.
  - Una instalación por WebFig dejó un `/export` igual al que dejó el `/import` del script de
    referencia, en las dos vías, salvo las dos direcciones MAC de la veth, que RouterOS elige al azar;
    `status` listó cada uno de sus objetos como de la instalación.
  - Las comprobaciones de la página sin conexión sobre los ficheros publicados de 1.3.1:
    `sha256sum --ignore-missing -c checksums.txt` OK y `cosign verify-blob` (cosign v3.1.3)
    `Verified OK`. Después `install` y `upgrade --agent-tar` con el tar amd64, 7 053 KiB subidos, y un
    `uninstall` limpio.
  - Instalaciones hechas por la CLI publicada 1.3.1: `status` leyó su forma de las etiquetas,
    `upgrade --remote-image` escribió un manifiesto, y `uninstall --yes` lo retiró todo, el directorio
    `mikroscope/` de 1.3.1 incluido.
  - `upgrade` sin `--remote-image` ni `--agent-tar` buscó Go para compilar el agente: no toma la
    imagen del manifiesto. Un segundo `install` en un router ya instalado no creó nada
    (`install done: 0 step(s) created`).
- **Las ejecuciones de las páginas de configuración**, 2026-09-27, laboratorio x86_64: `doctor` en
  un CHR de serie marcó MISSING solo la lista de interfaces `LAN`, con una solución que ofrece
  `--iface-list none`, y con las dos listas en `none` pasó cada comprobación. Las listas integradas se
  rechazaron antes de conectar. La comprobación de trampas contra los perfiles `advanced-firewall` y
  `advanced-firewall-range` nombró la regla que descarta las respuestas del agente, y su solución.
  Una lista de direcciones que no existía la creó la entrada de la instalación y ya no estaba tras
  `uninstall`. La primera ida y vuelta del sondeo marcó de 1,02 a 1,03 s en tres de seis
  instalaciones y 2 ms en las otras tres, y `status` un segundo después de 1 a 2 ms.
- **En el RB5009, el 2026-09-17**, las cuatro rutas se ejecutaron una tras otra, cada una con su
  propio nombre, su veth y su `/30` para no tocar nada de lo que ya había en el equipo, y cada una se
  retiró antes de la siguiente. `/healthz` se leyó desde el equipo del colector.
- **GHCR, el 2026-09-21**, una segunda instalación junto a la que estaba en marcha, con su propio
  `--name`, `--veth`, `--subnet` y `--port`. La CLI de esa fecha ponía en `remote-image=` solo el resto
  de la referencia, así que `registry-url` se apuntó a `https://ghcr.io` para la ejecución y se
  restauró después; `doctor` se negó primero con `MISSING registry-url is https://ghcr.io`. Con el
  registro apuntando a GHCR el router creó el contenedor y falló la descarga:
  `download/extract error: fetch manifest failed: getting https://ghcr.io/v2/jmrplens/mikroscope-agent/manifests/1.0.9 failed: auth error`.
  `/container/config` guarda un único usuario y contraseña para todos los registros, y el del RB5009
  es un login de Docker Hub. Desde el equipo del operador ese mismo día, contra el mismo paquete
  público, sin credencial devolvía 200 una vez obtenido el token anónimo, y con una credencial ajena
  403 en el endpoint del token. La ejecución encontró además que una instalación con `--remote-image`
  identificaba su contenedor por la referencia del registro, la misma cadena en cualquier
  instalación, así que una segunda instalación en un router se negaba como si la primera fuera de
  otro; ahora se identifica por su veth.
- **Los límites de Docker Hub**, leídos el 2026-09-24: 100 descargas anónimas cada 6 horas por
  dirección IPv4 o `/64` IPv6, y el token anónimo lleva las mismas 6 h (`pull_limit_interval` 21600),
  mientras que la cabecera `ratelimit-limit` del registro en un `HEAD` del manifiesto del agente decía
  `100;w=3600`. No se midió cuál de los dos aplica Docker. La cifra de una descarga por instalación
  sale de la regla de recuento de Docker y de una descarga hecha con `curl` desde el equipo del
  operador, no de una descarga de RouterOS.
- **Las fuentes de MikroTik sobre el registro por defecto**, leídas el 2026-09-24: el changelog de 7.18
  añade `registry-url=https://lscr.io`, el de 7.21.2 dice "changed default container registry to
  docker.io", ningún changelog de 7.21.3 a 7.24.4 menciona el registro, y la documentación de
  contenedores sigue dando `https://lscr.io/`. El CHR del laboratorio con 7.24.4 no tenía
  `registry-url` ni usuario e informaba `assumed-registry-url: docker.io`.

## Coste del agente

Con los valores por defecto de la instalación, 10 Hz, suelos por fuente por defecto y un anillo de
60 s, el agente cuesta **2,69 % de un núcleo y 13,2 MiB de
RSS**, leídos de su propio cgroup en régimen estacionario con el anillo lleno:

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-18 · ventanas de 300 s en régimen estacionario (con el anillo ya lleno), conjunto completo de fuentes, la configuración que se envía —anillo de 60 s, límite de memoria derivado de él y el tope de contenedor de serie de 64M— con el colector reenviando a InfluxDB 3

Las ejecuciones medidas:

| cadencia | suelos | CPU de un núcleo | µs/muestra | RSS | ticks retrasados | huecos / descartes |
| --- | --- | --- | --- | --- | --- | --- |
| 10 Hz (por defecto) | por defecto | **2,69 %** | 2 685 | 13,2 MiB | **0** | 0 / 0 |

Eso está por encima del presupuesto de 2 % de un núcleo y dentro
del de 16 MiB de RSS. La campaña del 2026-09-15 estaba por encima en los dos, con
un anillo de 300 s y un límite de memoria fijo, antes de que 1.0.6 trajera el anillo de 60 s y el
límite derivado. El presupuesto de imagen es 8 MiB; la imagen publicada de
1.2.1 para arm64 mide 6,38 MiB ([`image`](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-image)). El
presupuesto es orientativo, no un contrato: el coste depende del equipo, del conjunto de fuentes y
del tamaño del anillo.

Dos reglas mantienen honesta una cifra de coste. Espera primero a que se llene el anillo
(`BUFFER_S`): en el RB5009, con un límite blando de memoria de 14 MiB, una lectura tomada en el primer
minuto tras la instalación dio un 1,47 % de un núcleo frente a un 9,38 % en
régimen estacionario. Y lee el coste del `/metrics` del colector, o de `cpu_us` y `rss` en
`mikroscope_self` en el almacén que uses, en vez de un `/snapshot` grande, cuya respuesta de ~1,9 MB
tiene que serializar el agente. El procedimiento está en
[Coste del agente](https://docs.jmrp.io/mikroscope/es/cost/#medirlo-en-tu-propio-equipo).

### Coste por configuración

Todas las filas se midieron en el mismo RB5009 a 10 Hz, y cada una es una ventana sin dispersión
registrada.

| Configuración                                                            | CPU de un núcleo                                                       | RSS                            | Medido     | Nota                                                                                                          |
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------- | ------------------------------ | ---------- | ------------------------------------------------------------------------------------------------------------- |
| Cada fuente leída en cada tick                                           | 2,43 %                                                                 | no registrado                  | 2026-09-12 | por encima del presupuesto                                                                                    |
| Anillo lleno, `MEM_LIMIT_MB` 14                                          | 9,38 % (9 374 µs/muestra) | no registrado                  | 2026-09-12 | un anillo de 300 s de líneas de unos 2,4 kB, la línea de esa fecha, ocupa ~7,3 MB; el GC de Go corre sin pausa |
| Anillo lleno, `--mem-limit-mb 40`, `--memory-max 64M`                    | 1,39 % (1 388 µs/muestra) | 25,13 MiB                      | 2026-09-12 | 0 ticks retrasados                                                                                            |
| Contadores PMU activados, un `forward` en marcha escribiendo en InfluxDB | 1,72 %                                                                 | no registrado                  | 2026-09-12 | 0 ticks retrasados; 2 400 muestras reenviadas, 0 huecos, 0 descartes                                          |
| Los valores por defecto de la instalación                                | 2,69 %                                         | 13,2 MiB | 2026-09-18 | la cifra de arriba                                                                                            |

## Campañas

Cada campaña en una entrada: el equipo, la versión de RouterOS, la fecha y las condiciones, las
cifras que citan de ella las guías y lo que encontró. Una cifra de una guía enlaza aquí su campaña.

### Coste y cadencia

#### Cadencias con la configuración de serie

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-18 · ventanas de 300 s en régimen estacionario (con el anillo ya lleno), conjunto completo de fuentes, la configuración que se envía —anillo de 60 s, límite de memoria derivado de él y el tope de contenedor de serie de 64M— con el colector reenviando a InfluxDB 3

- `read.under2ms` 97,7 %
- `read.floorOver5ms` 1,45 %
- `read.100hz.meanMs` 1,2 ms
- `read.100hz.worstMs` 17,9 ms
- `load.ordinary` 19 Mbit/s
- `run.10hz.cpu` 2,69 %
- `run.10hz.rss` 13,2 MiB
- `run.10hz.usPerSample` 2 685 µs
- `run.10hz.slippedPct` 0,000 %
- `run.20hz.cpu` 4,61 %
- `run.20hz.rss` 15,4 MiB
- `run.20hz.usPerSample` 2 303 µs
- `run.20hz.slippedPct` 0,000 %
- `run.50hz.cpu` 9,63 %
- `run.50hz.rss` 23,3 MiB
- `run.50hz.usPerSample` 1 926 µs
- `run.50hz.slippedPct` 0,000 %
- `run.100hz.cpu` 16,83 %
- `run.100hz.rss` 45,7 MiB
- `run.100hz.usPerSample` 1 684 µs
- `run.100hz.slippedPct` 0,017 %
- `run.50hz-floor.cpu` 22,56 %
- `run.50hz-floor.rss` 25,1 MiB
- `run.50hz-floor.usPerSample` 4 511 µs
- `run.50hz-floor.slippedPct` 0,027 %
- `run.100hz-floor.cpu` 42,70 %
- `run.100hz-floor.rss` 49,5 MiB
- `run.100hz-floor.usPerSample` 4 270 µs
- `run.100hz-floor.slippedPct` 0,593 %

Seis ventanas de 300 s, a 10, 20, 50 y 100 Hz y a 50 y 100 Hz con `FLOOR_HZ`, ninguna de las cuales
perdió una muestra: [Techo de muestreo](https://docs.jmrp.io/mikroscope/es/cost/rate-ceiling/) tiene la tabla. La WAN
llevaba de media unos 19 Mbit/s durante los 44 minutos de la campaña, con picos
de 933 Mbit/s.

#### Cadencias hacia tres destinos

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-15 · ventanas de 60 s en régimen estacionario (con el anillo ya lleno), conjunto completo de fuentes, colector reenviando a la vez a fichero, a una exposición Prometheus y a InfluxDB 3

Cinco ejecuciones de cadencia a 10, 50 y 100 Hz con el colector escribiendo a la vez en un fichero,
en una exposición Prometheus y en InfluxDB 3; todos los destinos informaron de 0 huecos y 0
descartes. El valor por defecto de la instalación a 10 Hz de esa fecha costaba un 2,85 % de un núcleo
y 31,3 MiB de RSS, con un anillo de 300 s y un límite de memoria fijo de 40 MiB; 50 Hz necesitó
`--memory-max 96M` y 100 Hz `128M`. La WAN llevaba unos 30 Mbit/s, por la tarde. La cifra de la
instalación por defecto que citan las guías es de `rates-2026-09-18`, no de esta campaña.

#### Límite de memoria y recolector

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-12 · 10 Hz, anillo de 300 s lleno, las mismas fuentes en las dos ejecuciones; solo cambian los límites de memoria

- `gc.tight.cpu` 9,38 %
- `gc.tight.us` 9 374 µs
- `gc.roomy.cpu` 1,39 %
- `gc.roomy.us` 1 388 µs

El mismo agente, anillo y fuentes con un límite blando de 14 MiB y después con margen:
[Coste por configuración](https://docs.jmrp.io/mikroscope/es/about/status/#coste-a-10-hz-por-configuración) tiene las dos filas.

#### Línea del anillo con todas las fuentes

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-17 · una línea del anillo con todas las fuentes activas, privileged, 10 Hz, 4 núcleos, `IRQ_TOP_K=8` —incluidos el PMU y la propia temporización del muestreador, que la medición del 2026-09-12 no tenía

- `ring.lineKB` 3,5 kB
- `ring.lineBytes` 3 230 B
- `ring.lineChargedBytes` 3 456 B
- `relay.maxBatch` 13

3 230 B medidos, cobrados desde la clase de tamaño de 3 456 B de Go. Los 2 439 B del 2026-09-12
subestimaban el anillo un 35 %, y el agente funcionaba con 32,9 MiB de RSS donde bastaban 24,3. Una
línea sin PMU cuesta un 35 % menos. El tamaño de las líneas con los suelos por fuente actuales no se
ha medido.

#### Primera medición de la línea del anillo

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-12 · la línea media precodificada del anillo con todas las fuentes de esa fecha, las lentas refrescadas a 1 Hz, privileged, 10 Hz, 4 núcleos, `IRQ_TOP_K=8`

La línea media antes de que llevara la PMU y la temporización del propio muestreador, redondeada a
unos 2,4 kB en las guías de esa fecha.

#### Bucle de shell de busybox

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · 2026-09-11 · un bucle de shell de busybox leyendo a 10 Hz el conjunto de ficheros que leía entonces el agente, siete ficheros, con un fork por iteración, en un contenedor del router; dos ejecuciones de 60 s

- `busybox.cpu` 2,40–2,48 %
- `procread.ms` 0,77 ms

Dos ejecuciones de 60 s, 2,40 y 2,48 % de un núcleo, del `cpu.stat` del cgroup frente a
`/proc/uptime`; las lecturas en sí tardaban unos 0,77 ms por muestra. No se ha vuelto a medir con el
conjunto de fuentes actual del agente:
[Coste del agente](https://docs.jmrp.io/mikroscope/es/cost/#lo-que-cuesta-la-alternativa).

#### Coste de una conexión SSH

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.1 · 2026-08-26 · una conexión ssh, mientras dura

- `ssh.connectCpu` 20–27 %

Medido antes de que existiera el agente, con RouterOS 7.24.1. Con 7.24.2, el 2026-09-11, el mismo
coste apareció en `/tool profile` como un 17–33 % en una o dos instantáneas, no en una ventana medida:
[Coste de SSH](https://docs.jmrp.io/mikroscope/es/cost/#ssh-cost).

#### Perfil del router con la capa de la API

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-16 · `/tool profile duration=60s cpu=total`, una vez con el colector parado y otra con él en marcha con `--interfaces bridge,ether1,PPPoE_DIGI --counters-every 10s --api-every 1s`; descartadas las cinco primeras instantáneas de un segundo de cada perfil, porque llevan la conexión SSH que lo pidió

Un perfil de 60 s por condición, sin dispersión:
[Coste de la capa API](https://docs.jmrp.io/mikroscope/es/cost/#api-tier-cost).

#### Tamaño de la imagen publicada

2026-09-24 · tar de la imagen arm64 de la versión v1.2.1 publicada, el fichero que carga el router

- `image.size` 6,38 MiB

Medido con `ls -l` sobre el artefacto de la versión v1.2.1, con su suma de comprobación verificada
contra el `checksums.txt` firmado: 6 690 304 B, de los que el binario del agente ocupa 6 684 832 B.
Los tar de armv5 y armv7 miden 7 214 592 B y el de amd64 7 222 784 B. El trabajo `agent-size` de la CI
mantiene el binario del agente, que es todo lo que lleva la imagen, por debajo de 8 MiB en arm64,
armv7 y amd64.

#### Tamaño de la imagen en 1.0.0

fecha no registrada · tamaño de la imagen del agente de la versión 1.0.0

- `image.size.v100` 6,1 MiB

La cifra que dan las notas de la versión 1.0.0; la v1.0.0 se etiquetó el 2026-09-16. Las imágenes
entre ella y la 1.2.1 no tienen medida propia.

### Kernel y fuentes

#### Ficheros de contabilidad del kernel

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · 2026-09-11 · `/proc/pressure` y `/proc/schedstat` ausentes

La columna `irq` de `/proc/stat` vale siempre 0 en este kernel, así que el tiempo de IRQ hardware
está dentro de `system`. `USER_HZ` es 100, así que un tick son 10 ms y los escalones de ocupación de
las guías son aritmética a partir de él. Los ficheros que dentro del contenedor son del router se
establecieron ese mismo día ([Vista desde el contenedor](https://docs.jmrp.io/mikroscope/es/about/status/#vista-desde-el-contenedor)).

#### Contenedor de descubrimiento privilegiado

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · 2026-09-12 · un contenedor de descubrimiento privilegiado leyendo una vez el `/proc` del host, antes de que el agente leyera slabinfo

- `conntrack.slabDiscovery` 6 582

La ronda que no encontró ningún camino de trazado ([Kernel y PMU](https://docs.jmrp.io/mikroscope/es/about/status/#kernel-y-pmu)), y cuyo `slabinfo`
es el de `testdata/proc/rb5009`: `nf_conntrack` 6 582 activos de 8 075.

#### Espacio de red con privileged

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-12 · `privileged=yes` no cambia el espacio de nombres de red

Dentro del contenedor `/proc/net/dev` contaba la veth, 4 paquetes mientras el router reenviaba
millones, con `privileged=yes` y sin él.

#### Cadencias de las fuentes en una noche

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · 2026-09-13 · una captura de 10,5 h a 50 Hz durante una noche en reposo, con el reloj fijo

- `thermal.quantumC` 0,42 °C

La captura que fijó el suelo de 6 Hz al que se ralentiza `/proc/slabinfo`, la frecuencia a la que
cambiaba su caché más rápida, `nf_conntrack`. Los niveles de memoria se movían unas 24 veces por
segundo. Es una placa, una noche en reposo, con el reloj fijado en el ajuste del mantenedor: «cpufreq
nunca cambió» significa que no cambió esa noche.

#### Ventana de promedio de `cpu-load`

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · 2026-09-15 · `/system/resource` consultado a 1 Hz frente a la proporción de ocupación por núcleo del agente a 10 Hz, en dos horas distintas

- `cpuLoad.window1` 1,0 s
- `cpuLoad.delay1` 0,6 s
- `cpuLoad.r1` 0,9825
- `cpuLoad.samples1` 3 499
- `cpuLoad.window2` 1,1 s
- `cpuLoad.delay2` 0,1 s
- `cpuLoad.r2` 0,9734
- `cpuLoad.samples2` 3 594

El mejor ajuste de cada hora: una media móvil de 1,0 s que llegó a la
API con 0,6 s de retardo (r = 0,9825
sobre 3 499 muestras de la API), y una media
de 1,1 s que llegó con 0,1 s de retardo
(r = 0,9734 sobre 3 594). `/system/resource` publica
`cpu-load` como un porcentaje entero, y la serie de la API se correlacionó con la proporción de
ocupación por núcleo del agente, los mismos jiffies de `/proc/stat`, para una serie de longitudes de
ventana y retardos. Ensanchar la ventana solo empeoró el ajuste: 1,5 s dio 0,955; 2 s, 0,919; 5 s,
0,822; y 8 s, 0,791. Una media de sesenta segundos queda descartada dos veces: su correlación es
0,238, y en el mayor salto de carga del día el kernel pasó de 5 % a 27 % en un segundo y `cpu-load` de
5 a 26 en ese mismo segundo, y de 22 % a 6 % al bajar con la misma rapidez. La
[documentación de `/system/resource`](https://help.mikrotik.com/docs/spaces/ROS/pages/40992875/Resource)
de MikroTik define `cpu-load` como el porcentaje de recursos de CPU usados, sumando todas las CPU, y
no nombra ninguna ventana (leída el 2026-09-24).

### Grabación y transporte

#### Grabación de un bucle de script

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-12 · un `record` de 60 s a 10 Hz, 600 muestras en 59,9 s, un bucle de script de RouterOS lanzado por ssh y el log del router añadido como marcadores

Exactamente 600 muestras, 0 huecos y un desfase de reloj de −7 ms. Un bucle de RouterOS por script
(`:for … 400 000`) se vio como la carga de un núcleo entero al 100 % de t = 21,0 a 25,8 s, con la
muestra de 25,8 s marcando alrededor del 60 %, y el inicio y el final resueltos a 100 ms. Los
marcadores del log del router explicaron una meseta de 2 s entre 15 y 17 s que nadie había provocado:
el planificador `ensure-ipv6-nd-prefix`. Las horas del log llegaron por la API como fechas completas
([verificado](https://docs.jmrp.io/mikroscope/es/about/status/#verified-log-time-full-date)).

#### Grabación en reposo

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-16 · un `record` de 70 s a 10 Hz, 700 muestras en 69,9 s, el router por lo demás en reposo, tres notas escritas en el terminal de `record`

La grabación de la que sale el gráfico de
[Línea base en reposo](https://docs.jmrp.io/mikroscope/es/playbooks/idle/#gráfico-grabado).

#### Duración de una conexión `/stream`

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.4 · 2026-09-21 · tres conexiones `GET /stream` contra el agente instalado a 10 Hz, abiertas desde el equipo del operador en la LAN y mantenidas hasta que el servidor las cerró

- `stream.lifetime` 30,01–30,06 s
- `stream.lines` 304–306

Agente 1.0.9 a 10 Hz. Cada conexión terminó en el tiempo de escritura de 30 s del servidor, le
quedara lo que le quedara por enviar, así que quien consuma `/stream` reconecta con el último `seq`
que vio.

#### Límite del fetch del relay

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · 2026-09-11 · `/tool fetch output=user` llamado por la API binaria; cada llamada tardó o unos 3 ms o alrededor de 1 s, y más o menos la mitad tardó 1 s

- `relay.replyMaxBytes` 64 512 B

`/tool fetch output=user` truncó el cuerpo sin avisar en 64 512 B con cuerpos de 64 K, 256 K, 1 M y
4 M.

#### Tamaño de una muestra en protocolo de líneas

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · 2026-09-12 · una muestra del kernel a 10 Hz renderizada en protocolo de líneas de InfluxDB, con el conjunto de fuentes que tenía el agente en esa fecha

Unos 1,2 KiB por muestra, la cifra a partir de la cual los destinos de InfluxDB y Telegraf
dimensionan su presupuesto de bytes. No medido por encima de 10 Hz, ni vuelto a medir con el conjunto
de fuentes actual.

### Red y fallos

#### Lecturas de los casos reales

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · 2026-09-12 · agente a 10 Hz en un contenedor privilegiado efímero

- `loop.eventsBefore` 1,49 /s
- `loop.eventsAfter` 0,03 /s
- `loop.helloGap` 2,00–2,01 s
- `conntrack.slab` 6 287

Las lecturas sobre las que se construyen los [casos reales](https://docs.jmrp.io/mikroscope/es/playbooks/idle/), de un
kernel aarch64 en una placa con 1 GB de RAM; donde se provocó un fallo, el caso real dice cómo. Tres
casos llevan además un gráfico del almacén InfluxDB de referencia, cuyo historial empieza el
2026-09-19: la vuelta del bucle, la comprobación cruzada de conntrack y el puerto que pierde tramas.
El puerto que pierde tramas es una campaña aparte, una semana después, leída en los contadores de
puerto de la capa de la API y no en el agente. `time_squeeze` no era cero ni siquiera en reposo.
Mientras el reflejo de capa 2 estaba activo, el log del kernel iba
a 1,49 /s, y una pareja «blocking state» y luego «learning state» llegaba
dentro de un mismo tick de 100 ms con el mismo nivel, así que su orden dentro del tick es la señal. La
tabla de conntrack tenía 6 287 entradas, un 0,65 % del techo de 966 656
que el kernel informó el 2026-09-14.

#### Distribución de los squeezes de softnet

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-16 · 3 738 704 muestras por CPU en 24 h a 10 Hz, `time_squeeze` de softnet por muestra, 0 descartes en toda la ventana

- `squeeze.backgroundOne` 11,2 %
- `squeeze.backgroundTwo` 1,2 %
- `squeeze.exactlyThree` 0,21 %

Las 24 h terminaron a las 07:00 UTC del 2026-09-16. `time_squeeze` era 0 en el 87,3 % de las muestras
por CPU, y una ventana móvil de esa distribución tiene un percentil 90 de 1, así que «por encima de
p90» lo cumple cualquier 2. El 2026-09-15 una condición de disparo que salta ante cualquier squeeze
saltó 92 veces en veinte minutos (RouterOS 7.24.2), y por eso `squeeze` no es un disparador por
defecto.

#### Reejecución de la regla de microrráfagas

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-16 · la regla reejecutada sobre 6 h de muestras almacenadas, 863 944 filas, 4 CPU

- `microburst.firesPerHourAtTwo` 77,7 /h
- `microburst.firesPerHourAtThree` 0,5 /h

Con suelo 3 la regla siguió marcando 88 muestras para el contador de ráfagas y para `derived.burst`.

#### Cuenta de conntrack por la API

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · 2026-09-11 · la tabla de conexiones contada por la API binaria de RouterOS, `/ip/firewall/connection/print count-only`, diez llamadas

- `conntrack.api` 6 212
- `api.conntrackMs` 1,3 ms

La cuenta fue 6 212, el día antes de que el slab del agente marcara 6 287:
el mismo orden de magnitud, que no dice nada de si las dos se siguen. Las diez llamadas tardaron una
mediana de 1,3 ms, la más rápida 1,1 ms y la primera 71 ms, en frío; la hora no consta.

#### Contadores de puerto y de fast path

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · 2026-09-16 · contadores de puerto y de interfaz de RouterOS leídos por la API, acumulados desde el arranque o desde el último reinicio del contador de cada puerto

`ether1`, 2,5 GbE hacia un NAS, había recibido 255,8 GB por el cable (`rx-bytes`) y había entregado
29,7 GB de ellos a la CPU (`driver-rx-byte`) desde el último reinicio del contador del puerto; el
resto lo reenvió el chip de conmutación en hardware. Todos los puertos del switch daban una
proporción de fast path de alrededor del 100 %, con `fp-rx-byte` igual a `driver-rx-byte` con unos
pocos kB de diferencia. `bridge` había pasado por el fast path 211,9 GB de los 663,0 GB que llevó a la
CPU desde el arranque (32 %), y `PPPoE_DIGI` el 99,97 %. `fp-tx-byte` estaba a 0 en todas las
interfaces tras cientos de GB transmitidos ([verificado](https://docs.jmrp.io/mikroscope/es/about/status/#verified-fp-tx-zero)).

#### Desbordamiento del puerto antes y después

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.4 · 2026-09-19 · ether1, el puerto de 2,5 GbE del NAS, en intervalos de contador de 10 s; las cifras de antes son las tres horas previas al arreglo y las de después los 39 minutos siguientes, con la misma carga

- `overflow.shareBefore` 0,502 %
- `overflow.perHourBefore` 5 399
- `overflow.occupancy` 0,36 %
- `overflow.burstRate` 8,96 Mbit/s

El caso real es [Puerto que pierde tramas](https://docs.jmrp.io/mikroscope/es/playbooks/port-errors/).

Medido sin campaña propia: el 2026-09-15 una ráfaga tuvo un pico de 736 paquetes en una muestra de
20 ms, una muestra a 50 Hz, frente a una mediana de 28.

## Comportamiento de RouterOS verificado

Hechos de sí o no sobre RouterOS en los que se apoyan las guías, cada uno comprobado una vez, con
dónde y cuándo.

### Un usuario read ve las envlists

Por la API binaria, `/container/print` devolvió todas las propiedades de todos los contenedores, `cmd` y `envlist` incluidas, a un usuario con solo `read,api`, el usuario `mikroscope`; solo se imprimieron los nombres de las propiedades, y no se comprobó si ese usuario lee los valores de `/container/envs` (RB5009UG+S+, RouterOS 7.24.2, 2026-09-11).

### Política test para fetch y profile

`/tool fetch` y `/tool profile` exigen ambos la política `test` (RB5009UG+S+, RouterOS 7.24.2, 2026-09-11).

### Valores entre comillas en find

En un `find` de RouterOS, los atributos de dirección y de puerto solo coinciden cuando su valor va entre comillas, y una palabra suelta se lee como nombre de variable: sobre las mismas 15 reglas dstnat (RouterOS 7.24.4, 2026-09-21), `protocol=tcp` encontró 0 y `protocol="tcp"` encontró 10 (RB5009UG+S+, RouterOS 7.24.2, 2026-09-11).

### Las reglas de exposición llegan al agente

Una regla `dst-nat` más una regla `accept` en forward llegan al agente desde la LAN, y las dos se retiran por su etiqueta (RB5009UG+S+, RouterOS 7.24.2, 2026-09-11).

### La LAN llega a la veth

La LAN llega a la veth en cuanto la veth entra en la lista de interfaces `LAN` y el /30 en la lista de direcciones `LANs` (RB5009UG+S+, RouterOS 7.24.2, 2026-09-11).

### El borrado del contenedor vuelve antes

`/container/remove` vuelve antes de que el contenedor haya desaparecido, y un `/file/remove` lanzado mientras tanto no hace nada, sin avisar (RB5009UG+S+, RouterOS 7.24.2, 2026-09-11).

### Borrar el tar vuelve a extraer

Con `ignore-remote-image-change=no`, borrar el tar de la imagen hace que RouterOS detenga y elimine el contenedor y lo vuelva a extraer minutos después (RB5009UG+S+, RouterOS 7.24.2, 2026-09-11).

### La ida y vuelta deja /export intacto

`doctor`, `install`, `status`, `upgrade` y `uninstall`, en ese orden, dejaron el `/export` del router idéntico byte a byte, salvo sus líneas de cabecera `#`, comparado por hash en memoria y sin escribirlo nunca a disco (RB5009UG+S+, RouterOS 7.24.2, 2026-09-12).

### Instalar en tmpfs no escribe en la NAND

Un disco tmpfs aloja el tar de la imagen y la raíz del contenedor sin escribir en la NAND: `write-sect-since-reboot` se quedó en 58 279 durante la instalación, el funcionamiento y la retirada (RB5009UG+S+, RouterOS 7.24.2, 2026-09-11).

### Privileged conserva red y PID

`privileged=yes` quita el espacio de nombres de usuario del contenedor, pero no el de red ni el de PID (RB5009UG+S+, RouterOS 7.24.2, 2026-09-12).

### Host del registro en la referencia

Un host de registro dentro de `remote-image=` manda sobre `/container/config registry-url`, y `docker.io` se descarga como `registry-1.docker.io`: con `registry-url=https://registry-1.docker.io`, una referencia en `registry.invalid` quedó registrada como `registry=registry.invalid` y falló con `resolving error`, mientras que la imagen 1.2.2 del agente escrita como `docker.io/…` y como `registry-1.docker.io/…` quedó registrada como `registry=registry-1.docker.io` y terminó en `download/extract done`, con su capa arm64 de 2 799 648 bytes; `/container/config` quedó igual que antes. Los contenedores se crearon en una veth temporal, nunca se arrancaron y se retiraron después (RB5009UG+S+, RouterOS 7.24.4, 2026-09-24).

### Descarga de Docker Hub sin login

Con el usuario y la contraseña de `/container/config` borrados, RouterOS descargó de Docker Hub la imagen 1.2.2 del agente de forma anónima, tanto como `remote-image=registry-1.docker.io/…` como sin host a través de `registry-url=https://registry-1.docker.io`, y las dos terminaron en `download/extract done` 5 s después del alta; después se restauró la configuración y se comprobó que era idéntica (RB5009UG+S+, RouterOS 7.24.4, 2026-09-24).

### Horas del log por la API

Por la API, `/log/print` devuelve el `time` de una entrada como fecha y hora completas y sin zona, `2026-09-12 02:21:24`, y acepta ese formato en una consulta `?>time=` (RB5009UG+S+, RouterOS 7.24.2, 2026-09-12).

### Claves de pérdidas de monitor-traffic

`/interface/monitor-traffic` devuelve `rx-drops`, `tx-drops` y `tx-queue-drops` por segundo y ninguna clave de errores (RB5009UG+S+, RouterOS 7.24.2, 2026-09-15).

### rx-overflow solo en los contadores de puerto

`ether1` llevaba 652 364 sucesos `rx-overflow`, en aumento, en sus contadores de puerto mientras `monitor-traffic` no devolvía ninguna clave de errores para ese puerto: esa cuenta solo llega a un consumidor por los contadores de puerto (RB5009UG+S+, RouterOS 7.24.2, 2026-09-15).

### Planos del puerto y del bridge

Un puerto `ether` de un bridge cuenta su cable, incluidas las tramas que el chip de conmutación reenvió por hardware, y el `bridge` cuenta su lado de CPU, así que ninguno es un subconjunto del otro: desde el último reinicio del contador del puerto, `ether1` había recibido 255,8 GB por el cable (`rx-bytes`) y había entregado 29,7 GB de ellos a la CPU (`driver-rx-byte`) (RB5009UG+S+, RouterOS 7.24.2, 2026-09-16).

### fp-tx-byte se queda a cero

`fp-tx-byte` marcaba 0 en todas las interfaces tras cientos de GB transmitidos, mientras `fp-rx-byte` sí contaba; no está establecido por qué RouterOS lo deja a 0 (RB5009UG+S+, RouterOS 7.24.2, 2026-09-16).

### Rutas del host en un contenedor privilegiado

Un contenedor privilegiado con `/proc`, `/sys` y `/` del host montados leyó cero PID en el `/proc` del host y no encontró `class/net` en su `/sys`, así que los espacios de nombres aguantaron; el `/` del host sí se montó, y expuso el sistema de ficheros de la flash de RouterOS, configuración y ficheros, secretos incluidos. Se hizo con el consentimiento del mantenedor (RB5009UG+S+, RouterOS 7.24.2, 2026-09-15).

### La credencial va si el host coincide

RouterOS presenta el usuario y la contraseña de `/container/config` para una referencia cuyo host es `registry-url` tal como está escrito: con una credencial errónea a propósito, la imagen del agente 1.3.1 nombrada como `registry-1.docker.io/jmrplens/mikroscope-agent` falló con `auth error` con `registry-url=registry-1.docker.io`, y se descargó de forma anónima con `https://registry-1.docker.io`, el valor de los ejemplos de MikroTik, y con el mismo terminado en barra. Un router al que se dio una credencial no volvió a intentar la descarga de forma anónima (CHR x86_64, RouterOS 7.24.4, 2026-09-27).

### WebFig no tiene campo para ignore-remote-image-change

Los formularios New Container y de edición del contenedor de WebFig no muestran campo para `ignore-remote-image-change`, con File o Remote Image puestos o no; lo pone el terminal (CHR x86_64, RouterOS 7.24.4, 2026-09-27).

### Un set del contenedor reinicia restart-policy

Un `/container/set` que no nombra `restart-policy` (de `ignore-remote-image-change`, de `comment`, de `logging`) la devolvió de `on-failure` a `always` sin cambiar nada más de lo que muestra `/container/print detail`; un set que la nombra la conservó, igual que Apply u OK en el formulario de edición de WebFig. La CLI nunca ejecuta `/container/set` (CHR x86_64, RouterOS 7.24.4, 2026-09-27).

### WebFig muestra los valores de env

WebFig muestra en claro el valor de una entrada de `/container/envs`, en la lista Envs y en su formulario, también con la clave `TOKEN` (CHR x86_64, RouterOS 7.24.4, 2026-09-27).

### WebFig no tiene página Device Mode

El menú System de WebFig no tiene página Device Mode, así que el modo de dispositivo se pone desde el terminal (CHR x86_64, RouterOS 7.24.4, 2026-09-26).

### fetch as-value devuelve el cuerpo

`:put ([/tool/fetch url="http://172.30.10.2:9123/healthz" output=user as-value]->"data")`, ejecutado en el router, imprimió el JSON de `/healthz` del agente, en una sesión ssh, en el terminal de WebFig y al final de un script pegado (CHR x86_64, RouterOS 7.24.4, 2026-09-27).

### La pregunta de la licencia se lleva las primeras líneas

El primer inicio de sesión interactivo tras un reinicio pregunta `Do you want to see the software license? [Y/n]:` antes del indicador `] >`. Un script pegado en esa pregunta perdió sus primeras líneas: una o dos líneas de comentario de la cabecera, y después un fragmento ejecutado como orden (`bad command name .` o `syntax error`); el bloque `{ … }` del script de instalación se ejecutó igualmente e instaló, y el script de desinstalación retiró igualmente todo (CHR x86_64, RouterOS 7.24.4, 2026-09-27).

## Sin probar

Lo que no cubre aquí ninguna ejecución, medida ni comprobación. Una guía que afirma una de estas cosas
como comportamiento esperado enlaza esta lista.

### Hardware y versiones

- Una segunda placa de cualquier tipo. El hEX S (2025), RouterOS de 32 bits sobre un chip ARM64, que
  es para lo que existe la compilación `linux/arm/v5` del agente, no ha llegado, así que ni la ruta
  del desbordamiento de contadores de 32 bits ni ninguna de las dos imágenes ARM de 32 bits se han
  ejecutado en RouterOS. Un
  [informe de placa](https://github.com/jmrplens/mikroscope/issues/new?template=2-board-report.yml)
  desde otra placa es lo que cambia esto.
- RouterOS x86 en hardware: la imagen amd64 solo se ha ejecutado en QEMU, en el CHR x86_64 del
  laboratorio y en RouterOS x86 instalado desde la ISO de MikroTik.
- Ningún RouterOS anterior a 7.24 más allá de la comprobación de versión de `doctor`, que S17 ejecutó
  en un CHR con 7.23.7, y ninguna de las cifras de 7.24.2 vuelta a medir sobre 7.24.4.
- Nada que necesite un reinicio del RB5009, que espera a una ventana de mantenimiento. Así que no está
  probado en hardware que una instalación persistente sobreviva a un reinicio con
  `start-on-boot=yes`. En el CHR del laboratorio volvió a responder en menos de 90 s tras un corte de
  corriente (S7, en las dos arquitecturas).
- Qué ficheros están en un espacio de nombres en otra versión de RouterOS u otra placa: cada fila de
  [Vista desde el contenedor](https://docs.jmrp.io/mikroscope/es/about/status/#vista-desde-el-contenedor) se leyó en un único RB5009 con 7.24.2.
- Una placa con sensores hwmon, o un RouterOS posterior que construya los contenedores de otra
  manera: el conjunto de sensores, las 38 capacidades y la correspondencia de uid se leyeron en un
  único RB5009 con 7.24.2.
- La correspondencia de puertos en otra placa: el desplazamiento de uno, la posición de la jaula
  SFP+ y la reutilización de `port 7` se observaron en un RB5009UG+S+ con 7.24.2, y el agente no los
  aplica a ninguna otra placa.
- Los caminos de PSI y `schedstat` en un router: el kernel del RB5009 no tiene ninguno de los dos. El
  conjunto de contadores de la PMU solo se conoce en el Cortex-A72 del RB5009 y en el equipo de
  desarrollo amd64.
- Cualquier cadencia de las fuentes en otro equipo o con otra carga: las cadencias son las del RB5009,
  con 7.24.2. Vuelve a medirlas con `FLOOR_HZ` igual a la cadencia del muestreador.
- Qué claves de pérdidas y qué contadores devuelve otra versión de RouterOS u otra placa.
- Lo que ahorra `--goarm 7` frente a la compilación ARMv5: ningún hardware ARM ha ejecutado ninguna.
- Las entradas de la envlist en un RouterOS anterior a 7.24: mikroscope escribe `key=`, porque
  `name=` falló en el RB5009 con 7.24.2, y no se probó cómo toma una u otra una 7.x anterior.
- Un tráfico mayor que la carga corriente del RB5009: unos 19 Mbit/s en la WAN
  durante la campaña del 2026-09-18. No se afirma ninguna cadencia en otra placa.

### Instalación y actualización

- En el RB5009, una descarga de GHCR sin credencial de registro, y cualquier descarga de GHCR con el
  host dentro de `remote-image=`: su única ejecución contra GHCR tomó el host de `registry-url`. El
  CHR del laboratorio hizo las dos con 7.24.4 ([Rutas de instalación probadas](https://docs.jmrp.io/mikroscope/es/about/status/#install-routes-tested)).
- Qué credencial presenta RouterOS a un host que solo se nombra en `remote-image=` cuando
  `registry-url` nombra otro. La única ejecución con un host distinto del de `registry-url`, el
  2026-09-24, nombraba `registry.invalid`, que nunca se resolvió. Con el mismo host, el laboratorio
  mostró que RouterOS solo la presenta cuando `registry-url` se escribe como el host a secas
  ([verificado](https://docs.jmrp.io/mikroscope/es/about/status/#verified-registry-url-host-match)).
- En el RB5009: un `install` o un `upgrade` completo que envíe la referencia completa, un
  `registry-url` con su valor de fábrica y la referencia completa en cualquier RouterOS que no sea
  7.24.4. El CHR del laboratorio ejecutó las dos cosas con la 1.3.1 sobre 7.24.4.
- Una descarga a través de un espejo o una caché intermedia nombrados en la referencia.
- `install`, `status` y `uninstall` de la 1.4.0 en adelante en cualquier hardware, y el script con
  sus guardas: solo se han ejecutado en los CHR del laboratorio. En el RB5009, el `upgrade` de la
  1.6.0 leyó del router el manifiesto de instalación y la arquitectura (`--arch auto`), y su
  `doctor` ejecutó todas las comprobaciones.
- `--ssh-option` y `MIKROSCOPE_SSH_OPTIONS` contra cualquier router: la CLI del laboratorio se conecta
  con el `ssh_config` propio del laboratorio, y solo las pruebas unitarias pasan la opción.
- Que `--extract-timeout` se agote, lo que conserva el tar, en cualquier router.
- La comparación de hosts de registro de `doctor` contra un router real: solo se ha ejecutado contra
  respuestas de router falsas en los tests.
- Si un usuario `read,api` puede leer los valores de la envlist en `/container/envs`.
- La ida y vuelta idéntica byte a byte en hardware: en cualquier placa que no sea el RB5009, en el
  RB5009 con cualquier RouterOS salvo 7.24.2, con `install` y `upgrade` sin `--ephemeral`, o con los
  ajustes actuales del contenedor (`privileged=yes`, `memory-max=64M`, las entradas de la envlist
  `MEM_LIMIT_MB`, `CAPTURE_MB`, `TRIGGERS` y `FLOOR_HZ`): en el RB5009 se hizo con `memory-max=32M`.
  Desde entonces `install`, `status` y `uninstall` se han ejecutado allí en 7.24.4. En el CHR 7.24.4
  del laboratorio, `make roundtrip` la ejecuta con `--ephemeral` (2026-09-26); S2 y S3 ejecutan
  `install`, `upgrade` y `uninstall` sin él, con `privileged=yes`, `memory-max=64M`, `MEM_LIMIT_MB` y
  `CAPTURE_MB`, y S5 importa un script que además escribe `TRIGGERS` y `FLOOR_HZ`; cada uno termina
  con el `/export` igual al de su inicio, salvo la línea `keymat-provider` de RouterOS (las dos
  arquitecturas, 2026-09-27).
- Cortafuegos distintos del del RB5009, donde el 2026-09-11 bastaron las dos pertenencias a listas, y
  de los perfiles del laboratorio. Un cortafuegos con otras reglas de descarte en `raw`, `input` o
  `forward` puede descartar el tráfico del contenedor en otro punto, e `install` no añade nada para
  eso más allá de las dos pertenencias. No se comprobó si la configuración de fábrica de un router
  lleva las dos reglas raw.
- `--expose` desde fuera de la LAN: solo se probó una máquina de la LAN llegando a la dirección LAN
  del router. Si algo de fuera de la LAN llega a esa dirección depende del resto del cortafuegos, y no
  se probó ningún camino así.
- Winbox: la página de instalación por WebFig dice que Winbox tiene los mismos menús y campos, y no se
  ejecutó ningún Winbox. Las reglas de `--expose` por los formularios NAT y Filter Rules de WebFig, un
  script entero pegado en el terminal de WebFig o de Winbox, y WebFig en cualquier RouterOS salvo
  7.24.4.
- Los scripts del generador, la instalación manual por terminal y la instalación por WebFig en el
  laboratorio arm64 o en el RB5009.

### Grabación y captura

- Una grabación por encima de 10 Hz: las ejecuciones sin pérdidas a 20, 50 y 100 Hz fueron del
  colector, que usa el mismo tamaño de lote. Una grabación a través del relay, a cualquier cadencia.
- El rendimiento del relay. Con idas y vueltas de `/tool fetch` de cerca de 1 s en la mitad de las
  llamadas y unos 3 ms en el resto ([medido](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-relay-fetch) en el RB5009 con
  7.24.2), la aritmética da del orden de 26 muestras por segundo, menos cuando
  las llamadas lentas se agrupan. El límite del relay y el aviso de arranque están leídos del código
  (2026-09-15), no medidos en un equipo. El límite del relay y su fracción de 1 s en cualquier
  RouterOS salvo 7.24.2.
- El coste de un disparo en el equipo; 3 µs para una ventana de 10 s a 10 Hz es la estimación del
  diseño. Cómo se comporta el agente bajo una tormenta sostenida de disparos. Cualquier captura a 50 o
  100 Hz. Los tamaños de captura de [Captura por disparo](https://docs.jmrp.io/mikroscope/es/record/triggers/) son
  aritmética a partir del tamaño de línea, no tamaños de capturas tomadas en el RB5009.

### Colector y destinos

- Destinos alimentados desde el RB5009 hacia un backend en marcha: solo fichero, Prometheus e
  InfluxDB 3. Loki, un receptor OTLP, carbon, Elasticsearch, OpenSearch, Telegraf, PostgreSQL y
  TimescaleDB no han recibido muestras del router en ninguna ejecución registrada. OpenSearch, las
  hypertables de TimescaleDB y la salida estándar nunca se han probado contra un almacén real; solo
  los cubren las pruebas de contrato de bytes.
- Un Elasticsearch u OpenSearch que exija autenticación. El Elasticsearch de la batería de
  contenedores funciona con la seguridad desactivada, así que la cabecera `Authorization` que se
  construye a partir de `MIKROSCOPE_ELASTIC_AUTH`, autenticación básica para `user:password` y
  `ApiKey` en otro caso, no tiene ninguna ejecución registrada contra uno: ni desde el destino ni
  desde la fuente de datos de Elasticsearch que construyen `--grafana` y `dashboards publish`, que
  envía la misma cabecera desde la 1.5.0. Las pruebas unitarias fijan ambas formas, y la batería de
  extremo a extremo el `ApiKey` del destino contra un receptor simulado. Esa fuente de datos tampoco
  se ha ejecutado contra un OpenSearch, con autenticación o sin ella.
- Un TimescaleDB real: las llamadas a `create_hypertable` siguen la firma documentada de TimescaleDB
  2.x y no están verificadas.
- El tamaño del destino SQL en un router. Las cifras del fixture (1 375 B de SQL para un evento del
  kernel frente a 716 B de protocolo de líneas, 1 138 B para un evento de la API frente a 608 B, unos
  14 KiB/s a 10 Hz más la capa de la API a 1 Hz tras una cabecera de 5,6 KiB, 2 749 B con las fuentes
  privilegiadas) cubren dieciocho de las cuarenta y tres tablas que escribe el destino: once se
  añadieron después del fixture, y `load`, `stat`, `buddy`, `mtd`, `api_ifcounter`, `api_ifinfo`,
  `trigger`, `derived`, `derived_iface`, `detection` y las cuatro tablas `device` no se ejercitaron.
  Son anteriores a las columnas `port` y `kind` de `mikroscope_event`.
- `--sql - | psql` con un `psql` que se queda atrás frente a un agente a 10 Hz, que bloquea el bucle de
  peticiones.
- El presupuesto de la salida estándar para `json`, cuyas líneas son más grandes que las del
  protocolo de líneas.
- Un renderizado OTLP de una muestra de cuatro núcleos con un top-K real de interrupciones, una
  muestra de cuatro núcleos en el formato de Elasticsearch, y el presupuesto de Graphite por encima de
  10 Hz.
- Una escritura en el `/api/v2/write` de InfluxDB 2. El tamaño en protocolo de líneas por encima de
  10 Hz o con el conjunto de fuentes actual. Si desactivar el reenvío propio del cliente HTTP evita
  los duplicados del 2026-09-13.
- La entrega de Loki durante una tormenta del log del kernel.
- Cualquier intervalo de scrape de Prometheus que no sea 5 s, y cualquier Prometheus que no sea 3.14.
- Los 10 Hz constantes del colector frente a un agente más rápido: la referencia de ráfagas y la poda
  del top-K están leídas del código; el peso EWMA de 1/600 y el desalojo a las 36 000 muestras no se
  han visto ocurrir nunca, porque ninguna ejecución hizo que una línea de interrupción cayera del
  top-K y siguiera fuera.
- Los deltas a cero que se escriben junto a una proporción de fast path ausente (leído
  en [`internal/derive/derive.go`](https://github.com/jmrplens/mikroscope/blob/main/internal/derive/derive.go)), y un cambio de techo o de cadencia sin cambio de hash
  que llega a los destinos en la siguiente repetición de cinco minutos (leído en `capsHash`).
- El coste de PMU por paquete comparado entre dos configuraciones del router. Si los diez segundos de
  la referencia de ráfagas sirven en otra placa u otra mezcla de tráfico: se ajustó contra un RB5009
  en un solo día. Una proporción de fast path de tx a partir de contadores en vivo.
- Detecciones provocadas con las reglas en marcha: ningún OOM kill en el contenedor, reinicio, flap de
  enlace, vaciado o tormenta de conntrack, excursión térmica ni colapso de IPC. Si `reboot` saltó en el
  reinicio del 2026-09-19. Un flap provocado con `link-flap` en marcha; los flaps del 2026-09-15 no lo
  estaban.
- Si RouterOS calcula la ventana de un segundo de `cpu-load` sobre un reloj de pared o sobre jiffies.
  Si la cuenta de conntrack de la API y la del slab se siguen la una a la otra.

### Otras herramientas

- Ninguna de las seis herramientas de [Comparado con alternativas](https://docs.jmrp.io/mikroscope/es/start/compared/) se
  ejecutó para esa página. Cada celda de sus filas es lo que dice su propia documentación o su
  código, leído el 2026-09-24: mktxp en el commit `1e4412a` (fechado el 2026-09-21),
  mikrotik-exporter en `428dbfc` (fechado el 2026-07-03), y el fichero MIB que MikroTik publica para
  RouterOS 7.24.4. No se midió lo que le cuesta a un router el sondeo SNMP, The Dude, Graphing, el
  Profiler, mktxp o mikrotik-exporter, con qué frecuencia puede sondearlo cada uno con utilidad, ni
  qué pone RouterOS en `hrProcessorLoad`.

### Dashboards y alertas

- Cualquier Grafana que no sea 12.3.0, 12.3.2, 13.2.1 o 13.2.2. En 12.3.0 los únicos renderizados son
  los del 2026-09-25; el resto del dashboard se comprobó allí solo por consulta.
- `dashboards publish` contra cualquier Grafana que no sea 13.2.1, y sobre algo que no sea lo que
  `forward --grafana` acababa de crear allí: en la batería de contenedores, el 2026-09-27, se ejecutó
  una vez por almacén, después del colector, sin credenciales en ninguna fuente de datos, y encontró
  la carpeta y cada fuente de datos tal como las había dejado el colector, y las dio como
  `unchanged`. Con `dashboards publish`, una ejecución de más de un almacén, un almacén que falla
  mientras los demás siguen, una fuente de datos que lleva un token o una contraseña (se escribe de
  nuevo en cada ejecución y se da como `updated`) y `--grafana-dry-run` solo se han ejecutado en las
  pruebas unitarias, contra Grafanas simulados.
- La altura del Overview de trece paneles en un navegador; el JSON del repositorio le da 31 unidades
  de cuadrícula.
- La regeneración byte a byte de los ficheros de dashboard añadidos después del 2026-09-15.
- Las anotaciones y capas de detecciones de Elasticsearch y Graphite en Grafana: solo se comprueba su
  JSON generado, con pruebas unitarias.
- Una pasada de renderizado sobre los dos paneles de eventos de puerto y la tabla de inventario de
  interfaces.
- Que una regla se resuelva: el bucle del RB5009 terminó el 2026-09-23, pero no se ha comprobado en el
  historial de estados de Grafana la vuelta de `mikroscope-l2-loop` a Normal. No se ha visto a
  `mikroscope-l2-loop` ni a `mikroscope-port-link-down` pasar a pendiente, saltar y resolverse.
- Las dos reglas que añadió 1.2.0 dentro de cualquier Grafana, su PromQL más allá de la sintaxis y el
  SQL de PostgreSQL de la regla de despertares.
- Los ficheros de alertas de Prometheus y PostgreSQL en cualquier Grafana, y cualquier consulta de
  alerta de PostgreSQL contra un PostgreSQL real: una prueba unitaria lee el esquema, no una base de
  datos.
- La entrega de avisos: no se configuró ningún punto de contacto, así que lo que se observó es el
  estado de cada regla.
- Un almacén al que le falta una tabla o una columna que lee una regla: se espera que la consulta
  falle y que se aplique `execErrState: Error` en lugar de OK. Lo que hace entonces Grafana es su
  comportamiento de Error y No Data, no probado aquí.

## Problemas conocidos

Contrastado con el código el 2026-09-24, y el flujo del resumen final otra vez con la 1.3.1 el
2026-09-26:

- **El resumen final de `forward` va a stdout**, el mismo flujo en el que el destino `--stdout`
  escribe los registros, así que `forward --stdout=lp | telegraf` termina cada ejecución con líneas que
  el consumidor no puede analizar.
- **Un `--token` erróneo no hace fallar la ejecución.** Cada petición queda registrada como
  `401 Unauthorized`, y la ejecución termina en el plazo de `--for` con código de salida 0 y
  `forwarded 0 kernel samples`. La comprobación de salud que hace `forward` antes de empezar a pedir
  datos lee `/healthz`, que no necesita token, así que la supera. El mensaje es correcto; el código de
  salida no le dice nada a un fichero de unidad.
- **Números de secuencia duplicados en la ejecución nocturna del 2026-09-13.** La ejecución a 50 Hz
  escribió valores de `seq` repetidos en InfluxDB; los paneles llaman a esas filas "duplicate sample
  (seq repeated)". La explicación más probable, sin verificar, es que el cliente HTTP de Go reenviaba
  un POST por una conexión reutilizada ya muerta después de que el servidor lo hubiera confirmado. Los
  destinos InfluxDB, Loki, OTLP, Elasticsearch y Telegraf rechazan ese reenvío, así que una conexión
  muerta es un error que el destino reintenta y contabiliza. Ninguna ejecución posterior a esa noche
  muestra si los duplicados han desaparecido.
- **Un tag negado dentro de un OR no devuelve nada, en silencio, en InfluxDB 3.** El 2026-09-23, en el
  almacén de referencia (InfluxDB 3 Enterprise desde el 2026-09-19; la versión no se anotó con la
  consulta), `NOT (port='ether2' AND kind IN (…))` sobre `mikroscope_kmsg` devolvió 0 filas donde
  coincidían 14, y lo mismo su forma de De Morgan y el OR explícito. Devolvió 14 en cuanto se filtró
  también `port='ether2'` fuera del OR. Los paneles y las reglas que se distribuyen no usan ese patrón.
- **Grafana 12.3.0 nunca envía la consulta de la capa de detecciones de InfluxDB**, con la tabla o sin
  ella: su interruptor se quedó con un indicador de carga, apagarlo, encenderlo y refrescar no envió
  nada, y no se dibujó ninguna marca, ni en el dashboard completo ni en una copia de un solo panel
  (2026-09-25). Grafana 13.2.1 la envió en el acto sobre el mismo almacén. Por qué, y si 12.3.2 hace
  lo mismo, no se ha investigado.

### Encontrado en el laboratorio virtual

Lo que encontraron la CLI y la imagen del agente 1.3.1 publicadas en el CHR del laboratorio, RouterOS
7.24.4, el 2026-09-26. Cada punto termina con lo que hace el código posterior a la 1.3.1, comprobado
en el laboratorio el 2026-09-27; la 1.4.0 publica ese código, y la sección 1.4.0 del registro de
cambios recoge cada cambio.

- **`doctor` con sus valores por defecto falla tres comprobaciones en un CHR.** `--arch` vale arm64
  por defecto, lo que falla solo en x86_64; la lista de interfaces `LAN` no existe; y la comprobación
  «has entries» de la lista de direcciones `LANs` falla con una lista vacía o inexistente, aunque su
  propio arreglo dice que una lista vacía está bien si no existe esa regla. Un router sin esa regla solo
  pasa dándole una entrada a la lista, o con `--no-doctor`, que se salta todas las demás comprobaciones.
  **Tras la 1.3.1**: `--arch` vale `auto` por defecto y lee la arquitectura del router, una lista de
  direcciones vacía ya no es un fallo, y una lista de interfaces que falta, todavía MISSING con los
  valores por defecto, tiene un arreglo que ofrece `--iface-list none` (S1).
- **Una lista de interfaces integrada** como `static`, `all` o `dynamic` pasa la comprobación de
  existencia de doctor, y RouterOS se niega a añadirle un miembro. **Tras la 1.3.1**: `--iface-list`
  rechaza `all`, `dynamic` y `static`; RouterOS responde `cannot add to builtin list`.
- **`--ephemeral` necesita un disco tmpfs**, y un CHR no lista ningún disco. El arreglo de doctor,
  `/disk/add type=tmpfs tmpfs-max-size=64M slot=tmpfs`, funcionó, y la instalación fue a
  `tmpfs/mikroscope/mikroscope` con `start-on-boot=no`. **Tras la 1.3.1**: igual, y `doctor` avisa
  además cuando se fuerza el arranque con el router sobre una raíz en un disco tmpfs, que un reinicio
  vacía.
- **`uninstall` compite con la parada del contenedor.** Detiene el contenedor, espera 4 s fijos y lo
  elimina, y el agente tardó 0 s en pararse seis veces, 4 s cuatro veces y 5 s una (log de RouterOS,
  resolución de 1 s): 5 de 15 primeros intentos en x86_64 fallaron con
  `failure: cannot remove running`. Con un cliente en `/stream` falló siempre en las dos arquitecturas,
  porque el cierre HTTP del agente lo espera hasta 5 s. Los pasos siguientes se ejecutaron igualmente,
  y un segundo `uninstall` lo limpió todo cada vez. **Tras la 1.3.1**: la retirada espera hasta 30 s
  mientras el contenedor está `running` o `stopping`, y cada primer intento quedó limpio
  ([Tiempos del laboratorio](https://docs.jmrp.io/mikroscope/es/about/status/#lab-timings)).
- **Un directorio `mikroscope` vacío se queda en `/file` después de cada `uninstall`**: el padre del
  root-dir del contenedor, que el recuento de propiedad no incluye. **Tras la 1.3.1**: cada vía de
  instalación escribe un manifiesto de instalación, y `uninstall` quita lo que lista, y después el
  manifiesto y el directorio `mikroscope/` cuando no queda nada más en él; tras ninguna vía quedó una
  ruta de mikroscope en `/file` (F4).
- **El sondeo posterior a `install` lee mal un contenedor en marcha** sobre 7.24.4. Pregunta
  `/container/find … status="running"`, y `status` no es una propiedad de `/container` allí
  (`/container/find status=running` responde `bad parameter status`), mientras que la marca `running`
  vale 1. Así que cuando falló el sondeo, la CLI dijo "the container is not running on the router" con
  el agente en marcha y a punto de responder. Visto dos veces en arm64. **Tras la 1.3.1**: el sondeo
  lee la marca `running`.
- **El listado del plan nombraba un tar con `--remote-image`**: `image=mikroscope.tar`, un fichero
  que `install` nunca sube, e imprimía la subida o la descarga como un paso propio con el número del
  paso del contenedor, así que dos pasos compartían número. **Tras la 1.3.1**: `image=` nombra la
  referencia que descarga el router, y la descarga o la subida es una línea del paso del contenedor.
- **El token del agente viajaba en la línea de órdenes de ssh**, donde la tabla de procesos del
  anfitrión lo mostraba mientras la orden se ejecutaba: el código de la 1.3.1 lo mostró en dos líneas
  de órdenes. **Tras la 1.3.1** una orden que lo lleva va a ssh por la entrada estándar; leer la
  tabla de procesos cada 2 ms durante una instalación y una actualización con `--expose` no lo
  encontró en ninguna, en las dos arquitecturas.
- **Las palabras de RouterOS se perdían cuando su ssh salía con 1**: el error decía
  `ssh "<script>": exit status 1`, y el mensaje de RouterOS, en las líneas siguientes, lo descartaba
  la línea de omisión de uninstall. El ssh de RouterOS salió con 1 o con 0 ante el mismo fallo, más o
  menos a partes iguales. **Tras la 1.3.1** el error empieza con lo que imprimió RouterOS.

## Fuentes sin recoger

Dos ficheros legibles del RB5009, leídos allí el 2026-09-15, no se recogen: `/proc/cmdline`, que lleva
`board=5009 ver=7.24.1`, una segunda identidad del equipo sin la API, y el watchdog hardware en
`/sys/class/watchdog/watchdog0`.

## Véase también

- [Coste del agente](https://docs.jmrp.io/mikroscope/es/cost/): el presupuesto, los costes de SSH y de la capa de la API,
  y cómo medir el agente en tu propio router.
- [Techo de muestreo](https://docs.jmrp.io/mikroscope/es/cost/rate-ceiling/): las seis ejecuciones medidas a 10, 20, 50 y
  100 Hz.
- [Límites de la evidencia](https://docs.jmrp.io/mikroscope/es/cost/limits/): lo que estas medidas no pueden decirte
  sobre otro equipo u otra carga.
- [Casos reales](https://docs.jmrp.io/mikroscope/es/playbooks/idle/): los fallos leídos en el RB5009, con las órdenes que
  los reproducen.
- [Versiones](https://docs.jmrp.io/mikroscope/es/about/changelog/): la versión actual, su fecha y lo que publica cada
  versión.
