# En qué punto está

Qué funciona de extremo a extremo, cuánto cuesta en el único equipo donde se ha ejecutado, qué se encontró y no se ha corregido, y qué publica la versión.

Source: https://jmrplens.github.io/mikroscope/es/about/status/

Esta página responde a lo que necesita saber primero quien está decidiendo si
probar mikroscope: qué partes funcionan de extremo a extremo, en qué hardware
se demostró, cuánto cuesta hoy el observador, qué defectos se conocen y siguen
abiertos, y si hay algo que descargar. Está contrastada con el código a fecha
del 2026-09-16.

## Qué funciona de extremo a extremo

Todo lo siguiente, salvo las baterías de pruebas y los siete destinos señalados
como tales, se ha ejecutado contra el RB5009 de referencia (RouterOS 7.24.2), y
no solo contra simulaciones:

- **El agente** 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; medidos 10, 50 y 100 Hz), guarda las muestras en
  un anillo y las sirve:
  `/healthz`, `/capabilities`, `/snapshot`, `/stream`, `/metrics`, y los
  endpoints de captura por disparo `/captures` y `/capture`.
- **La CLI de despliegue** lo instala, lo actualiza y lo retira — `doctor`,
  `plan`, `install`, `status`, `upgrade`, `uninstall` — listando cada escritura
  antes de hacerla y verificando cada retirada por recuento de propiedad. El
  2026-09-12, `doctor` → `install` → `status` → `upgrade` → `uninstall` dejó el
  `/export` del router idéntico byte a byte, comparado por hash en memoria y sin
  escribirlo nunca a disco. El agente respondió 3 s después de la instalación,
  con un tiempo de ida y vuelta de 5–7 ms. El 2026-09-17 se ejecutaron las
  cuatro rutas de instalación contra el mismo equipo, una tras otra y cada una
  retirada antes de la siguiente: la compilación desde el checkout, el tar del
  agente publicado, la descarga que el propio router hizo desde Docker Hub y el
  script de `plan --rsc` importado en el router sin CLI ninguna en la
  instalación misma. El agente respondió en todas, y el `/export` posterior a
  las cuatro era idéntico byte a byte al anterior a ellas.
- **`record`, `mark` y `plot`** funcionan de extremo a extremo. Una grabación de
  60 s a 10 Hz el 2026-09-12 dio exactamente 600 muestras, 0 huecos y −7 ms de
  desfase de reloj.
- **`forward`**, el colector, une la capa del kernel con la capa de la API de
  RouterOS y escribe en diez destinos. Fichero, Prometheus e InfluxDB 3 se han
  ejecutado desde el RB5009; por Loki, OTLP, Graphite, Elasticsearch, SQL,
  Telegraf y stdout todavía no han pasado muestras del router, pero todos ellos
  escriben ya en el producto real — InfluxDB 3, PostgreSQL, Elasticsearch,
  Graphite, Loki, un OpenTelemetry Collector, Telegraf y Prometheus en
  contenedores — y la batería vuelve a leer cada uno por su propia API
  (2026-09-16). Su etapa de derivación añade valores derivados y eventos de
  detección junto a las filas en bruto, y emite un flujo de datos del equipo
  una vez por cada hash de capacidades.
- **Cinco dashboards de Grafana**, uno por almacén —InfluxDB 3, Prometheus,
  PostgreSQL, Graphite y Elasticsearch—, generados a partir de una sola lista de
  paneles, con reglas de alerta para los tres cuyo lenguaje de consulta es el de
  las reglas. A los dos almacenes SQL se les hace la misma pregunta en dos
  dialectos: los paneles de PostgreSQL son los de InfluxDB reescritos, y las 209
  consultas las planifica un PostgreSQL real en la batería de contenedores.
  Graphite y Elasticsearch llevan menos paneles a propósito (41 y 30 frente a
  171): Graphite no tiene etiquetas y Elasticsearch no tiene documentos
  anidados, así que lo que no pueden expresar está ausente en vez de
  equivocado. Los cinco se importan en un Grafana real sobre los almacenes que
  llenó la batería, y se le pregunta a cada panel: el 2026-09-17 devolvieron
  datos 57, 98, 136, 35 y 28 paneles, y no falló ninguno.
  El 2026-09-16, en Grafana 13.2.1,
  contra el RB5009 con los disparadores por defecto y un `forward` de 30 minutos
  hacia los dos almacenes, `dashboards check` dio por buenos 171 paneles de
  InfluxDB (0 fallidos, 10 vacíos conocidos tolerados) y 133 paneles de
  Prometheus (0 fallidos, 9 vacíos conocidos tolerados). El recorrido sin
  interfaz, fila a fila, de los dos dashboards — 0 insignias de error y 0 "No
  data" — es del 2026-09-15 y cubre 168 y 130 paneles; no se ha repetido para
  los dos paneles de eventos de puerto ni para la tabla de inventario de
  interfaces, que no cubre. Un recorrido del 2026-09-14, contra una captura de
  10,5 h del mismo equipo, renderizó 140 paneles de InfluxDB con el mismo
  resultado.
- **Una batería de extremo a extremo** compila los dos binarios y los ejecuta
  contra un árbol `/proc` capturado del equipo de referencia y contra 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.
- **Una segunda batería contra los almacenes mismos** (`make test-e2e-docker`)
  levanta nueve de ellos con docker compose, ejecuta el mismo colector contra
  el mismo agente simulado con todos los destinos apuntando a ellos y luego
  le pregunta a cada almacén por su propia API: SQL contra InfluxDB 3, `psql`
  contra el guion que escribió el destino SQL, una búsqueda contra
  Elasticsearch, `query_range` contra Loki, `render` contra Graphite, el OTLP
  que el colector decodificó, el protocolo de línea que Telegraf analizó y un
  scrape del exportador almacenado en Prometheus. Después importa los dos
  dashboards en Grafana y pasa la consulta de cada panel por la propia API de
  Grafana. Necesita Docker y ningún router: las muestras son las mismas
  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.

## Lo que cuesta hoy el agente

Con los valores por defecto de la instalación — 10 Hz, suelos por fuente por
defecto, un anillo de 300 s — el agente cuesta **2,85 % de un núcleo y 31,3 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-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

Las ejecuciones medidas:

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

Eso está por encima del presupuesto de 2 % de un núcleo y 16 MiB de RSS. El
presupuesto es orientativo, no un contrato: el coste depende del equipo, del
conjunto de fuentes y del tamaño del anillo. El presupuesto de imagen es 8 MiB;
el único tamaño de imagen registrado es 6,1 MiB, y no lleva fecha.

Dos reglas mantienen honesta la cifra de coste: esperar a que se llene el
anillo (`BUFFER_S`) antes de citar una cifra de régimen estacionario — 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 leer el coste de `/metrics` en vez de un `/snapshot`
grande, cuya respuesta de ~1,5 MB tiene que serializar el agente.

### Coste a 10 Hz, 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. Son los ajustes que un lector puede elegir, así que la
tabla dice lo que cuesta cada uno, no lo que valía el número en algún momento
anterior.

| 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 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,85 %                                         | 31,3 MiB | 2026-09-15 | la cifra de arriba                                                                                            |

## Un equipo, una versión de RouterOS

Todas las cifras tomadas en el equipo que aparecen en esta documentación vienen
de un único RB5009UG+S+ con RouterOS 7.24.2, el router de producción del
propietario. No hay equipo de laboratorio.

> **Sin probar**
>
> 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` del agente — no ha llegado, así que ni la
> ruta del desbordamiento de contadores de 32 bits ni la imagen `linux/arm` se han ejecutado en
> hardware. Ningún host RouterOS x86_64. Ninguna versión de RouterOS distinta de 7.24.2. Nada que
> necesite un reinicio, que espera a una ventana de mantenimiento. La batería de extremo a extremo
> solo se ha ejecutado en Linux; no se ha ejecutado en macOS ni en Windows.

## Encontrado y sin corregir

Contrastado con el código a fecha de esta página:

- **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.
- **Graphite nombra las zonas térmicas por índice.** El índice es deliberado —
  la cadena `type` de una zona no es única entre zonas — pero la lista de rutas
  al principio de `internal/sinks/graphite.go` dice `thermal.<zone>`.

### Encontrado en el equipo y sin recoger

Dos ficheros legibles del equipo de referencia, 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`.

## Qué publica la versión

La versión actual es la **v1.0.0** — la que hay en `VERSION`, compilada en los
dos binarios y que devuelve `mikroscope version`. Una etiqueta `v*` lanza la
configuración de GoReleaser, que publica:

- **Archivos de la CLI** para linux, darwin, windows y freebsd en amd64, arm64 y
  arm: `.tar.gz`, y `.zip` en Windows, cada uno con `LICENSE` y `README.md`.
- **Archivos del agente** para linux en esas mismas tres arquitecturas, para
  quien quiera el binario pelado en lugar de una imagen.
- **Tar de imagen del agente para cargar a mano**, uno por arquitectura —
  `mikroscope-agent-arm64.tar`, `mikroscope-agent-arm.tar`,
  `mikroscope-agent-amd64.tar` —, que es lo que `install --agent-tar` sube al
  router.
- **La imagen del agente en dos registros**, `jmrplens/mikroscope-agent:1.0.0`
  en Docker Hub y `ghcr.io/jmrplens/mikroscope-agent:1.0.0` en GHCR, cada una un
  único manifiesto sobre `linux/amd64`, `linux/arm64` y `linux/arm/v7`, que
  `install --remote-image` hace descargar al router. RouterOS toma el host del
  registro del ajuste global `/container/config registry-url`, que viene puesto
  en `https://registry-1.docker.io`, así que la referencia de Docker Hub no
  necesita fijar nada en el equipo y la de GHCR necesita cambiar antes ese
  ajuste.
- **`checksums.txt`**, que cubre todos los archivos y todos los tar de imagen,
  una firma cosign sin claves sobre él y un SBOM SPDX por archivo, firmado a su
  vez.

Instalar desde una versión publicada no necesita ni toolchain de Go ni copia del
repositorio. Con una copia del repositorio y Go 1.27 se instala en cambio un
agente compilado desde tu propio árbol: `make build` para la CLI y
`make build-agent` para el agente, que `install` e `image` compilan también por
su cuenta. Las cuatro maneras de llevar el agente a un router, y lo que necesita
cada una, están en [Instalar el agente](/mikroscope/es/install/).

Lo que la versión publica para `linux/arm` y `linux/amd64` está compilado de
forma cruzada y comprobado en CI. De las tres arquitecturas, solo `arm64` se ha
ejecutado en hardware: en el único RB5009 de arriba.

## Véase también

- [El coste del observador](/mikroscope/es/cost/): el presupuesto, la cifra actual y cómo medirla
  en tu propio equipo.
- [El techo de muestreo](/mikroscope/es/cost/rate-ceiling/): las cinco ejecuciones medidas a 10, 50 y
  100 Hz.
- [El fichero y los demás destinos](/mikroscope/es/sinks/other/): los diez destinos en los que
  escribe `forward`.
- [Linaje y licencia](/mikroscope/es/about/lineage/): de dónde vienen el código de despliegue y el
  cliente de la API.
