# Capa de la API de RouterOS

Qué pregunta el colector a la API binaria de RouterOS, los preajustes que preguntan menos, qué promedia cpu-load y qué significa un valor que falta.

Source: https://docs.jmrp.io/mikroscope/es/sinks/api-tier/

`forward` puede mantener una sesión persistente con la [API binaria de
RouterOS](https://help.mikrotik.com/docs/spaces/ROS/pages/47579160/API) (una segunda
cuando la propia capa del kernel llega por el relay) para leer lo que el contenedor no
ve: el tráfico y los contadores por interfaz. Elige cuánto pregunta con `--api-mode`.

## Agente frente a la API

Casi todo lo que la capa de la API puede obtener lo lee el propio agente:

- `/system/resource` y `/system/resource/cpu` son la media de un segundo que hace
  RouterOS de los mismos jiffies de `/proc/stat` que el agente diferencia a 10 Hz.
- La temperatura de `/system/health` es `/sys/class/thermal`, legible desde el contenedor.
- El número de conexiones es la caché slab global `nf_conntrack`, que el agente lee con
  `privileged=yes`; consulta [Conntrack sin la API](https://docs.jmrp.io/mikroscope/es/playbooks/conntrack/).

Lo que queda son **los bytes y paquetes por interfaz**. Viven en el espacio de nombres de
red del router y quedan fuera de alcance se le dé lo que se le dé al contenedor; consulta
[Visibilidad del contenedor](https://docs.jmrp.io/mikroscope/es/limits/namespaces/).

## Ventana de cpu-load

El `cpu-load` de RouterOS es una media móvil de más o menos un segundo del tiempo
ocupado de `/proc/stat` del kernel, y llega a la API con una fracción de segundo de
retardo ([medido](https://docs.jmrp.io/mikroscope/es/about/status/#campaign-cpu-load-window-2026-09-15)). 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. No puede resolver nada más corto que su propio
segundo, que es la razón por la que mikroscope lee el kernel.

## Modos de la API

`--api-mode` elige un preajuste. Es `full` salvo que digas otra cosa, y un `--api-every`,
`--no-health` o `--conntrack-every` explícito sigue mandando sobre él.

| Modo   | Lo que hace                                                                                                                                                                 | Úsalo cuando                                                         |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| `off`  | sin capa de la API: `--api-every 0`                                                                                                                                         | en producción, cuando el tráfico por interfaz ya viene de otro sitio |
| `slow` | una ronda cada 10 s, sin `/system/health` y sin el número de conexiones; `/system/resource`, `monitor-traffic` y los contadores de puerto siguen ejecutándose en cada ronda | en producción, cuando también quieres las tasas de las interfaces    |
| `full` | una ronda por segundo, con `/system/health`; contadores de puerto cada 10 s; el número de conexiones solo si `--conntrack-every` lo pide                                    | experimentos y ejecuciones cortas de `forward`                       |

`off` renuncia al tráfico por interfaz; `slow` lo conserva a bajo coste. Con `slow` hay
dos paneles vacíos por configuración y no por el equipo — `/system/health` y el número
de conexiones de RouterOS — y nombran la opción que los rellena.

> **El preajuste off para la capa de la API, no toda sesión de API**
>
> El transporte por relay extrae el anillo del agente a través de `/tool fetch` sobre la misma API
> binaria. Con `--transport auto`, un colector que no puede llegar directamente al agente recurre al
> relay y abre una sesión de API para ello diga lo que diga `--api-mode`. `--transport direct` nunca
> lo hace.

## Órdenes por ronda

Cada orden de la capa de la API se ejecuta en la única sesión de esa capa, de una en una, con un tiempo de espera de 15 s
cada una. Las cadencias más lentas se comprueban en cada ronda, así que ninguna se ejecuta
más a menudo que `--api-every`.

| Orden                                                                        | Pide                                                                                                      | Se ejecuta                                                                                    | Apagada cuando                              |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------- |
| `/system/resource/print`                                                     | `cpu-load`, `free-memory`, `total-memory`, `free-hdd-space`, `uptime`, `version`                          | en cada ronda                                                                                 | la capa está apagada                        |
| `/system/resource/cpu/print`                                                 | `cpu`, `load`, `irq`, `disk`                                                                              | en cada ronda                                                                                 | la capa está apagada                        |
| `/system/health/print`                                                       | `name`, `value`                                                                                           | en cada ronda                                                                                 | `--no-health`, o `slow`                     |
| `/interface/monitor-traffic` con `interface=<list>` y `once`                 | las cuatro tasas de tráfico y las tasas de pérdidas que devuelva el router                                | en cada ronda, una llamada para todas las interfaces                                          | `--interfaces` está vacío                   |
| `/interface/print` con `.proplist=name,default-name,type,comment,actual-mtu` | qué es cada interfaz: su nombre actual, el nombre de fábrica de la placa, su tipo, su comentario y su MTU | al arrancar, antes de la primera extracción del kernel, y luego cada `--labels-every` (5 min) | la capa está apagada                        |
| `/interface/list/member/print` con `.proplist=list,interface`                | qué listas de interfaces nombran cada interfaz, que es su rol                                             | con la lectura de arriba                                                                      | la capa está apagada                        |
| `/interface/bridge/port/print` con `.proplist=interface,bridge`              | a qué bridge pertenece cada puerto                                                                        | con la lectura de arriba                                                                      | la capa está apagada                        |
| `/interface/ethernet/print stats` y `/interface/print stats-detail`          | cada contador numérico de **todas** las interfaces                                                        | cada `--counters-every` (10 s)                                                                | `--counters-every 0`                        |
| `/ip/firewall/connection/print count-only`                                   | el número de conexiones                                                                                   | cada `--conntrack-every`                                                                      | `--conntrack-every 0`, el valor por defecto |
| `/log/print` con `.proplist=topics,message` y `?buffer=memory`               | las líneas que RouterOS escribió sobre el arranque en el que está ([Log de arranque](https://docs.jmrp.io/mikroscope/es/sinks/api-tier/#el-log-de-arranque)) | una vez por reinicio, cuando cambió el identificador de arranque del kernel que da el agente | la capa está apagada                        |

- Una orden que falla deja vacía su parte de la muestra y registra por qué; el
  resto de la ronda sigue en pie. Los fallos se registran en la salida de error
  como `api tier: …`, se escriben como líneas en Loki y filas en SQL, y se cuentan
  en OTLP — nunca se convierten en un valor.
- Una lectura de `/interface` que falla conserva el inventario que ya tenía, así
  que un error transitorio no deja en blanco la etiqueta de todos los paneles, y
  se informa como `inventory: …`. Las lecturas de listas y de bridges son de mejor
  esfuerzo; sin ellas el inventario sigue llevando nombres, tipos y comentarios.
- La muestra de la capa de la API se marca con el reloj del colector más el
  desfase medido frente al agente, así que cae en la línea temporal del agente.

## Inventario de interfaces

Las tres lecturas del inventario dicen a qué pertenecen los números. De cada interfaz
dan:

| Campo                | Origen                                        | Ejemplo                                                                                 |
| -------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------- |
| nombre               | `/interface/print`                            | el nombre actual                                                                        |
| nombre por defecto   | `/interface/print`                            | el `ether5` de fábrica de un puerto físico; vacío en un bridge, una VLAN o un túnel     |
| tipo                 | `/interface/print`                            | `ether`, `bridge`, `vlan`, `pppoe-out`, `wg`, `veth`, `loopback`                        |
| comentario           | `/interface/print`                            | la etiqueta que muestra un panel                                                        |
| MTU                  | `/interface/print` (`actual-mtu`)             | `9000`                                                                                  |
| rol                  | `/interface/list/member/print`                | las listas de interfaces, ordenadas y unidas por comas: `WAN`, `LAN,VPN`                |
| bridge               | `/interface/bridge/port/print`                | el bridge del que es puerto                                                             |

- Un miembro de un bridge que no está en ninguna lista propia hereda las de su
  bridge, porque así es como lo empareja una regla de firewall de RouterOS. Un
  puerto de bridge que nombra una lista de interfaces en vez de una interfaz no se
  etiqueta.
- Esto es configuración, no telemetría, así que se lee una vez al arrancar —
  antes de la primera extracción del kernel, para que un registro del log del
  kernel lleve etiqueta desde la primera línea — y luego con la cadencia lenta de
  `--labels-every`, nunca en cada sondeo. Un comentario editado, o un puerto que
  cambia de lista, llega al dashboard en minutos, y un comentario borrado en
  RouterOS desaparece también aquí: la lectura sustituye el inventario entero.
  Ninguna de las cinco propiedades que pide puede llevar un secreto.
- Cada fila de tasas de `monitor-traffic` y cada fila de contadores por puerto
  llevan `label` (el comentario), `type`, `role` y `bridge`, para que un panel
  diga lo que hay enchufado en vez de un número de puerto, y qué números se pueden
  comparar.

Prometheus es la excepción a propósito: un comentario lo edita una persona, y una
etiqueta que cambia crearía una serie nueva en cada edición, así que el `/metrics` del
colector lleva una serie informativa por interfaz —
`mikroscope_api_interface_info{interface,label,type,role,bridge,default_name} 1`, para
cada interfaz tenga o no comentario — y una consulta las une:

```text
mikroscope_api_interface_counter_total * on(interface) group_left(label, type, role) mikroscope_api_interface_info
```

El inventario también le da sus nombres al log del kernel. Un registro del kernel nombra
un puerto como `eth1`, la tabla de puertos de la placa lo traduce al nombre por defecto
de RouterOS y el inventario traduce ese nombre por defecto al actual, así que quien haya
renombrado `ether5` a `WAN` lee `WAN` en el panel, con la etiqueta y el rol del puerto
al lado. Sin la capa de la API un registro del kernel conserva el nombre por defecto de
la placa y no recibe etiqueta.

## Opciones

| Opción              | Por defecto                    | Significado                                                                                                                  |
| ------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| `--api host:port`   | `MIKROSCOPE_API_ADDR`          | la API binaria de RouterOS, p. ej. `192.168.88.1:8728`                                                                       |
| `--api-user`        | `MIKROSCOPE_API_USER`          | el usuario de la API; su contraseña solo desde `MIKROSCOPE_API_PASSWORD`                                                     |
| `--api-mode`        | `full`                         | `off`, `slow` o `full`, como arriba                                                                                          |
| `--api-every`       | `1s`                           | la cadencia de la ronda; `0` desactiva la capa                                                                               |
| `--interfaces`      | `MIKROSCOPE_INTERFACES`, vacío | interfaces separadas por comas para `monitor-traffic`, p. ej. `bridge,ether1`                                                |
| `--counters-every`  | `10s`                          | cada cuánto leer los contadores acumulados de cada puerto; `0` nunca                                                         |
| `--labels-every`    | `5m`                           | cada cuánto releer qué es cada interfaz — comentario, tipo, listas de interfaces, bridge; `0` significa el valor por defecto |
| `--conntrack-every` | `0`                            | cada cuánto pedir el número de conexiones; `0` nunca, porque es un recorrido de tabla                                        |
| `--no-health`       | desactivada                    | omite `/system/health`                                                                                                       |

Sin `--api`, `--api-user` y `MIKROSCOPE_API_PASSWORD`, `forward` ejecuta solo la capa del
kernel. Si se dan pero la sesión no se puede abrir en 10 s, registra `api tier: not connected
yet, will keep trying: …` y engancha el lector igualmente: una primera marcación fallida es
un aviso, no una capa deshabilitada para toda la vida del proceso.

## Usuario de la API

En cualquier modo las órdenes de la capa de la API son lecturas: basta un usuario con las
políticas `read` y `api`. `test` solo hace falta para `/tool fetch`, que usa el transporte
por relay y nada más de la capa de la API. El grupo, la restricción de dirección y por qué
la credencial nunca vive en el router están en [Usuario de la
API](https://docs.jmrp.io/mikroscope/es/security/api-user/).

## Valores ausentes

La capa de la API guarda exactamente lo que devolvió el router y no se inventa nada para
lo que no devolvió.

- **Tasas de pérdidas.** `monitor-traffic` puede devolver `rx-drops`, `tx-drops`,
  `tx-queue-drops`, `rx-errors` y `tx-errors` por segundo, y un destino escribe cada
  una solo cuando volvió. Un router puede devolver las tres tasas de descartes y
  **ninguna clave de errores** ([verificado](https://docs.jmrp.io/mikroscope/es/about/status/#verified-monitor-traffic-keys)).
- **Contadores de puerto.** Los contadores por puerto son un mapa con los nombres de
  campo del propio RouterOS, no un conjunto fijo de campos, y solo se conservan los
  enteros sin signo simples que cuentan algo. `mtu`, `actual-mtu`, `l2mtu`,
  `max-l2mtu` y `sfp-shutdown-temperature` se leen como enteros pero son tamaños y
  configuración, y todo destino representa este mapa como una familia de
  contadores, así que se descartan aquí en vez de dejar que cada consumidor lo sepa;
  el MTU viaja en el inventario.
- **Dos órdenes, fusionadas por interfaz.** `/interface/ethernet/print stats` aporta
  los errores tipados de la MAC, la familia de colisiones, los intervalos de tamaño
  de trama y los contadores del driver; `/interface/print stats-detail` aporta los
  contadores `fp-*` del fast path, `link-downs`, `tx-queue-drop` y los totales del
  lado del kernel. Una placa sin contadores de colisiones no produce entradas de
  colisiones en vez de una fila de ceros que se lee como «sin colisiones».
- **Errores que solo llevan los contadores.** Un puerto puede contar `rx-overflow`
  mientras `monitor-traffic` no devuelve ninguna clave de errores para él, así que
  esa cuenta solo llega a un consumidor por los contadores de puerto
  ([verificado](https://docs.jmrp.io/mikroscope/es/about/status/#verified-rx-overflow-port-counters)).
- **Todas las interfaces.** Los contadores cubren todas las interfaces que lista el
  router, no solo `--interfaces`: el puerto en el que vive una avería suele ser uno
  que nadie pensó en vigilar.
- **Acumulados.** Los contadores van desde el arranque o desde el último reinicio
  del puerto, así que un consumidor los diferencia. Separan lo que un puerto de
  switch recibió en el cable (`rx-bytes`) de lo que llegó a la CPU
  (`driver-rx-byte`); el resto lo reenvió el chip de conmutación en hardware, y
  ningún contador de dentro del contenedor tiene un número para eso. El colector
  convierte los contadores del fast path que van al lado en [una proporción del
  tráfico que cada interfaz entrega a la
  CPU](https://docs.jmrp.io/mikroscope/es/sinks/derive/#junto-a-cada-lectura-de-contadores).
- **Un puerto de switch y un bridge cuentan cosas distintas**, y por eso el tipo
  viaja con cada fila. Un `ether` dentro de un bridge cuenta su cable, incluidas las
  tramas que el chip de conmutación reenvió sin la CPU; el `bridge` cuenta su
  propio lado de CPU; una VLAN o un enlace PPPoE cuentan lo que la CPU envió y
  recibió. Un puerto y su bridge son dos planos, ninguno subconjunto del otro:
  dibujados uno al lado del otro sin su tipo parecen iguales, y sumados cuentan dos
  veces. No los sumes nunca.
- **Etiquetas de interfaz.** Con qué se etiqueta cada fila — el comentario, el tipo,
  el rol y el bridge — es el inventario de arriba, y una interfaz que el inventario
  no lista no lleva ninguna de ellas en vez de una identidad en blanco inventada.

## rx-overflow

La capa del kernel no puede ver el `rx-overflow` por construcción. Una trama que el
chip de conmutación reenvía en hardware nunca llega a la CPU, así que ningún fichero
de `/proc` del router tiene un número para ella; hacen falta los contadores por
puerto, y solo la API los tiene. [Puerto que pierde
tramas](https://docs.jmrp.io/mikroscope/es/playbooks/port-errors/) recorre uno de esos puertos, desde el
indicador del dashboard hasta el arreglo.

## Coste para el router

El proceso de la API hace de intermediario de cada orden hacia el subsistema que la
responde (`interface-mgmt`, `config-db`), y ahí es donde se ve su coste. Los perfiles
y el A/B de una ronda por segundo están en [Coste del agente](https://docs.jmrp.io/mikroscope/es/cost/#api-tier-cost).

La API sigue siendo el camino caro. Los datos por puerto salen del contenedor siempre
que el contenedor pueda verlos, y la configuración se lee al arrancar y con la cadencia
lenta de las etiquetas, nunca en cada sondeo.

## Reconexión

La capa mantiene un solo socket, así que cualquier cosa que se lleve al router se la
lleva a ella: un reinicio, una actualización de RouterOS, un operador reiniciando el
servicio de API. La capa reabre la conexión ella sola.

| Fallo                                                                                  | Reabre la conexión                                        | Por qué                                                                                                   |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| error de transporte: EOF, una tubería rota, una conexión reiniciada, un tiempo de espera agotado | sí, y reintenta ese comando sobre la conexión nueva | el socket está acabado                                                                    |
| `!trap`                                                                                | no                                                        | el router está vivo y rechaza el comando; repetirlo solo gastaría su CPU                                  |
| `!fatal`                                                                               | sí                                                        | RouterOS lo envía al cerrar la sesión, como dice la [documentación de la API de MikroTik](https://help.mikrotik.com/docs/spaces/ROS/pages/47579160/API) |

- Los intentos van espaciados cinco segundos. Una ronda lanza cuatro o cinco
  comandos, así que a un router caído se le marcaría si no varias veces por segundo,
  y cada marcación lleva un inicio de sesión.
- El inventario se descarta y se vuelve a leer tras una reconexión: una
  actualización es justo cuando una interfaz puede cambiar de nombre, tipo o puente,
  y etiquetas viejas sobre tasas nuevas serían peor que un hueco de un momento.
- Un colector que arranca con el router caído es el mismo caso visto desde el otro
  lado: conecta en la primera ronda que el router responda.

Un socket destruido bajo un colector en marcha se reabre y el comando se reintenta
dentro de la misma ronda ([probado](https://docs.jmrp.io/mikroscope/es/about/status/#capa-de-la-api)). El colector
lo dice una vez por suceso y no una vez por comando fallido:

```text
api tier: reconnected (1 since start)
api tier: recovered after 137 failed round(s)
```

y el informe por minuto lleva `api: N failed round(s), N reconnect(s)` mientras alguno
no sea cero. `api` cuenta rondas _intentadas_, así que esas dos cuentas son lo que
muestra una capa en la que fallan todos los comandos. [Resolución de
problemas](https://docs.jmrp.io/mikroscope/es/reference/troubleshooting/#los-paneles-de-api-están-vacíos-y-los-de-kernel-bien)
cuenta cómo se ve eso en los dashboards.

## Log de arranque

Cuando cambia el identificador de arranque del kernel que da el agente, el router se reinició, y el
colector pregunta una vez a RouterOS qué escribió sobre el arranque en el que está. Lee solo el
buffer de memoria, que RouterOS vacía en cada arranque: en un router que también escribe el log a
disco, `/log/print` devuelve además las líneas de arranques anteriores. Se queda con las líneas de
`system` que empiezan por `router rebooted` o `router was rebooted`, y con cualquier línea que
mencione el arranque anterior.

| Cómo cayó                                      | La línea                                                 | Topics                   |
| ---------------------------------------------- | -------------------------------------------------------- | ------------------------ |
| `/system/reboot` desde una sesión              | `router rebooted by ssh-cmd:admin@192.168.88.10/reboot`  | `system,info`            |
| `/system/reboot` desde un script               | `router rebooted by ssh-cmd:admin@…/script:rb/reboot`    | `system,info`            |
| `/system/shutdown` y después encendido         | `router rebooted by ssh-cmd:admin@…/shutdown`            | `system,info`            |
| un corte de corriente, o un botón de reset     | `router was rebooted without proper shutdown`            | `system,error,critical`  |

La línea nombra la sesión y el usuario, o el script, que reinició el router, o dice que cayó sin
apagarse ([Probado en](https://docs.jmrp.io/mikroscope/es/about/status/#reboot-detections)). La detección
[`reboot`](https://docs.jmrp.io/mikroscope/es/sinks/detections/#reboot) la lleva, y el colector la registra:

```text
router's boot log: "router was rebooted without proper shutdown"
```

La conexión murió con el router, así que la lectura se intenta al notar el reinicio y otra vez
después de cada ronda hasta que la capa vuelve, durante un máximo de dos minutos; la detección
`reboot` la espera ese tiempo. A un router que responde con un error no se le vuelve a preguntar:
la detección dice entonces `RouterOS's log could not be read (…)`. Cuando el buffer de memoria no
tiene ninguna línea así, porque dio la vuelta o ninguna regla de logging manda el topic `system` a
memoria, dice `RouterOS's memory log holds no line about the boot`.

## Cuenta de conntrack

`--conntrack-every 10s` pregunta `/ip/firewall/connection/print count-only` con esa
cadencia; una llamada tardó 1,3 ms con 6 212
entradas. Está apagado por defecto porque es un recorrido de tabla sobre una sesión de
API, y con `privileged=yes` la cuenta slab `nf_conntrack` del agente es la misma
población leída de un fichero a la cadencia del muestreador. Las dos no coincidirán
exactamente — se muestrean en instantes distintos, y el slab cuenta objetos que el
asignador todavía retiene. Si se siguen [no se ha medido](https://docs.jmrp.io/mikroscope/es/about/status/#not-tested):
pide la cuenta y lee el slab en el mismo minuto en tu propio equipo para compararlas.

Las placas y versiones de RouterOS en las que ha funcionado la capa están en [Equipos y versiones](https://docs.jmrp.io/mikroscope/es/about/status/#un-equipo-dos-versiones-de-routeros).
Qué claves de pérdidas y qué contadores devuelve otra versión u otra placa lo tiene que
decir ese router; los destinos llevan lo que vuelva y nada más.

## Véase también

- [Usuario de la API](https://docs.jmrp.io/mikroscope/es/security/api-user/): el grupo de RouterOS y la restricción
  de dirección que necesita el usuario de la capa.
- [Ejecutar el colector](https://docs.jmrp.io/mikroscope/es/sinks/): dónde se une la muestra de la capa de la API a la línea
  temporal del kernel.
- [Nombres de puertos](https://docs.jmrp.io/mikroscope/es/reference/port-names/): cómo emparejar
  el `ether2` de la API con el `eth1` del kernel.
- [Conntrack sin la API](https://docs.jmrp.io/mikroscope/es/playbooks/conntrack/): leer el número de conexiones del slab
  en su lugar.
- [Comparado con alternativas](https://docs.jmrp.io/mikroscope/es/start/compared/): lo que leen SNMP, la API de RouterOS
  y las demás herramientas en un router MikroTik, junto a lo que lee el agente.
