Ir al contenido

Grabar, marcar y dibujar

Usa record cuando vayas a cambiar algo en el router y quieras ver qué hace el cambio. Trae las muestras del agente a tu máquina a cadencia completa; mark añade notas y el propio log del router; plot dibuja el resultado.

Ventana de terminal
mikroscope record --for 5m --out cap # cap.jsonl, cap.csv, cap.markers.csv, cap.meta.json; escribe líneas para marcar
mikroscope mark --out cap "queue tree applied" # una nota sellada con la hora actual (ver abajo)
mikroscope mark --out cap --log-markers # las líneas del propio log del router, por la API
mikroscope plot --in cap # cap.svg, determinista

Las tres órdenes comparten un mismo juego de opciones: cada una acepta todas las de abajo, y la tabla dice sobre qué orden actúa cada una.

Opción Por defecto Qué hace
--out capture-<UTC time> Prefijo de salida: <out>.jsonl, .csv, .markers.csv, .meta.json. mark necesita el prefijo de una grabación existente.
--for 0 record: para tras este tiempo. 0 graba hasta Ctrl-C.
--from-start desactivada record: rellena todo lo que guarda el anillo del agente antes de pasar a directo.
--poll 500ms Cada cuánto se tira del anillo del agente.
--batch 0 Muestras por petición. 0 es el doble de lo que produce un intervalo de --poll a la cadencia del agente, con un mínimo de 20; el relay limita una petición a 13.
--transport auto auto, direct (HTTP a la veth) o relay (/tool fetch por la API de RouterOS).
--log-markers desactivada record: añade las líneas del log del router de la ventana cuando termina la grabación. mark: añade las líneas del log de la ventana de la grabación.
--topics system,interface,container Temas del log que se conservan como marcadores; añade firewall o script cuando sus líneas son la historia.
--router-tz Local Zona IANA que muestra el reloj del router. Las horas del log de RouterOS no llevan zona.
--api MIKROSCOPE_API_ADDR host:port de la API de RouterOS, para el relay y para --log-markers.
--api-user MIKROSCOPE_API_USER El usuario de la API. La contraseña solo se lee de MIKROSCOPE_API_PASSWORD; no hay opción para ella.
--token MIKROSCOPE_TOKEN El token bearer del agente.
--port 9123 El puerto HTTP del agente.
--subnet MIKROSCOPE_SUBNET, si no 172.30.10.0/30 La /30 del agente; su dirección es la .2.
--in ninguno plot: un prefijo de grabación, o la ruta de un fichero .jsonl.
--svg <in>.svg plot: el fichero de salida.
--title el prefijo plot: el título del gráfico.

Primera grabación recorre las tres órdenes de principio a fin. Una grabación medida, con su número de muestras, sus huecos y su desfase de reloj, está en la página de pruebas. Las grabaciones por encima de 10 Hz y a través del relay no se han medido.

--transport Camino Si falla
auto (por defecto) direct si responde un GET /healthz a http://<.2 de --subnet>:<--port>, si no relay un error, abajo
direct HTTP plano de tu máquina a la veth, con --token como token bearer falla, sin alternativa
relay /tool fetch output=user en el router, por la API binaria; el usuario de la API necesita las políticas read,api,test falla, sin alternativa
  • Cuando auto tiene que recurrir al relay y falta --api o --api-user, record se detiene con un error que nombra --api, --api-user y MIKROSCOPE_API_PASSWORD y sugiere install --expose. Si falta la contraseña, aparece en su lugar un error de inicio de sesión, api <host:port>: ….
  • La sugerencia de --expose es para otros clientes HTTP. record siempre llama a la .2 de --subnet y no tiene opción para la dirección LAN del router.
  • La petición desde el router no lleva cabecera, así que un agente instalado con token solo se puede grabar por direct.
  • Cada llamada por relay tarda o unos 3 ms o alrededor de 1 s. Una respuesta está limitada a 64 512 B, así que una petición por relay pide como mucho 13 muestras, y una respuesta que llega al límite se rechaza en vez de analizarse truncada.

Acceso por red explica qué camino permite una red, y Usuario de la API el usuario de RouterOS que necesita el relay.

  1. record lee /healthz. El reloj de pared del agente menos el de tu máquina es el desfase de reloj. Lo imprime por stderr junto con la versión del agente, la cadencia, el número de secuencia más reciente, el más antiguo que aún guarda el anillo y el transporte.
  2. La grabación empieza en directo desde la muestra más reciente, o desde la más antigua que guarda el anillo con --from-start.
  3. Cada --poll, pide /snapshot?since=<last seq>&max=<batch>. Mientras una petición vuelve llena, vuelve a pedir, hasta 100 veces por intervalo, así que un anillo que se ha adelantado se vacía en vez de seguirse a ritmo fijo.
  4. Una petición que falla se registra como pull: … y la grabación continúa; la siguiente pide desde el mismo número de secuencia.
  5. Cuando vence --for o pulsas Ctrl-C, una última petición recoge lo que llegó entretanto. record imprime cuántas muestras conservó, su rango de secuencia, los huecos, los marcadores, el transporte y los ficheros.

Cada fichero se crea con modo 0600. Un fichero existente con el mismo prefijo se sobrescribe.

Fichero Contenido
<out>.jsonl Cada línea de muestra tal como la envió el agente: deltas crudos de ticks y contadores, con todas las fuentes que tiene el agente. Esta es la grabación; los demás ficheros son vistas de ella.
<out>.csv Una fila ancha por muestra, para una hoja de cálculo. El conjunto de columnas se dimensiona a partir de la primera muestra: un grupo por núcleo y uno por cola softnet.
<out>.markers.csv wall_ns,wall_utc,seq,kind,label, una fila por marcador.
<out>.meta.json Se escribe al principio, para que mark y plot puedan ejecutarse después: started_utc, skew_ns (reloj de pared del agente menos el del anfitrión), agent (su versión), rate_hz, transport y capabilities cuando el transporte pudo obtenerlas.

El CSV guarda un subconjunto fijo de cada muestra. Todo lo demás que lleva una muestra — eventos del log del kernel, contadores PMU, temperaturas, interrupciones por línea y el resto — está solo en el .jsonl.

Columnas Contenido
seq, wall_ns, wall_utc, dt_ns El número de secuencia de la muestra, el reloj de pared del agente y el intervalo real.
busy_total La media de las proporciones de ocupación por núcleo, con tres decimales, calculada por la CLI a partir de los ticks.
c<N>_busy, c<N>_user, c<N>_nice, c<N>_system, c<N>_idle, c<N>_iowait, c<N>_irq, c<N>_softirq Por núcleo: la proporción de ocupación y después los deltas crudos de ticks.
ctxt, intr, irq_total Cambios de contexto e interrupciones de /proc/stat, y el delta sumado sobre todas las filas de /proc/interrupts.
softnet<N>_processed, softnet<N>_dropped, softnet<N>_time_squeeze Por cola softnet, los deltas del camino de recepción.
mem_free_kb, mem_available_kb, mem_cached_kb, mem_slab_kb Niveles de memoria, en kB.
load1, threads_running, threads_total Carga media y recuento de hilos.
pgfault, pgmajfault Deltas de fallos de página.
self_cpu_us, self_rss_bytes El tiempo de CPU propio del agente durante la muestra, en µs, y su memoria residente en ese momento, en bytes.

La proporción de ocupación es el único número que calcula la CLI, y hereda el suelo del kernel: un tick dura 10 ms, así que en una muestra de 100 ms un núcleo se resuelve en escalones del 10 %. Límites de resolución explica por qué, y por qué la proporción está limitada a 1.

Un marcador es una fila de <out>.markers.csv, de uno de tres tipos:

kind Se escribe cuando
note Escribes una línea no vacía mientras record corre en un terminal (imprime type a line and press Enter to add a marker; Ctrl-C stops), o ejecutas mark --out <prefix> "text". No se lee nada cuando la entrada estándar no es un terminal.
gap El agente informa de que unas muestras ya no estaban en su anillo. La etiqueta es samples <from>..<to> lost, y el resumen que imprime record lista los mismos huecos.
log --log-markers añade una línea del propio log del router (abajo).

Las notas y los huecos llevan la hora de tu máquina más el desfase medido al principio, así que quedan sobre el eje de tiempo del agente. mark --out cap "text" hace lo mismo con el desfase guardado en cap.meta.json: sella la hora actual en el reloj del agente, y ninguna opción fija otra. mark necesita ese fichero y un cap.markers.csv existente, y su fila lleva seq 0.

--log-markers convierte las líneas del log del router de la ventana de la grabación en marcadores log, con la etiqueta <topics>: <message>. Úsalo cuando haya que explicar un transitorio que no provocaste tú: ejecuciones del planificador, errores, eventos de interfaz.

Ventana de terminal
export MIKROSCOPE_API_ADDR=192.168.88.1:8728 MIKROSCOPE_API_USER=mikroscope MIKROSCOPE_API_PASSWORD=…
mikroscope record --for 60s --out burst
mikroscope mark --out burst --log-markers --router-tz Europe/Madrid
  • mark --log-markers usa la ventana desde started_utc del fichero meta, desplazado por su skew_ns al reloj del agente, hasta la última muestra del .jsonl, e imprime cuántas líneas añadió, la ventana y los temas. started_utc se guarda al segundo. Añade sin comprobar lo que ya hay: ejecutarlo dos veces vuelve a añadir las mismas líneas.
  • record --log-markers pide el log cuando la grabación se ha detenido, para la ventana desde su inicio hasta su final en el reloj del agente, y añade las líneas por el mismo camino que usa mark, así que el total de marcadores del resumen cuenta lo que contiene el fichero. Si la petición del log falla, record imprime log markers: … y conserva la grabación.

La CLI pide al router solo la ventana, con una consulta ?>time= que empieza un segundo antes, y solo los campos time, topics y message, porque un router que registra un tema con mucho tráfico en disco puede tener decenas de miles de filas. Después conserva las líneas dentro de la ventana cuyos temas incluyen alguno de --topics. Un evento registrado por varias acciones de registro sobre un mismo tema llega una vez por acción, precedido del nombre de la acción ([INFO]: …, [SYSTEM]: …); el prefijo se elimina y los duplicados se conservan una sola vez.

Las horas del log no llevan zona:

  • Por la API, RouterOS imprime la fecha y la hora completas (verificado). El analizador acepta también las formas más cortas, sin año o sin fecha, y las completa a partir del final de la ventana.
  • Las horas se leen en --router-tz y se sellan como reloj de pared del agente, que es el propio reloj del router, así que no se les aplica desfase. El valor por defecto Local es la zona de tu máquina: si la del router es distinta, pásala, o cada marcador de log caerá desplazado en esa diferencia.
  • Las horas del log tienen resolución de un segundo, así que un marcador de log sitúa su evento al segundo, no a la muestra.

plot --in cap lee cap.jsonl, y cap.markers.csv cuando existe, y escribe cap.svg (o --svg). Imprime el nombre del fichero con sus recuentos de muestras y marcadores. La misma entrada produce siempre los mismos bytes.

El gráfico mide 1 200 unidades de ancho, con un título (--title, o el prefijo) y una línea con el número de muestras, la duración y el número de núcleos. Tres paneles comparten un eje de tiempo, en segundos desde que empezó la grabación:

  1. CPU busy per core, % — de 0 a 100, una línea por núcleo, cada una etiquetada en su extremo. La paleta tiene ocho colores, así que se dibujan los ocho primeros núcleos.
  2. softnet per second, all CPUs — dropped y time_squeeze, sumados sobre todas las colas y agrupados en segundos enteros. Los descartes se dibujan en rojo.
  3. memory available, MiB — MemAvailable por muestra, con el eje y ajustado a los datos.

Marcadores en el gráfico:

  • Cada marcador es una línea vertical discontinua que cruza los tres paneles, gris para notas y líneas de log y roja para huecos, con una etiqueta encima del primer panel.
  • Las etiquetas se reparten en hasta seis filas. Una etiqueta de más de 40 caracteres se acorta; cuando no cabe en ninguna fila se sigue acortando hasta que cabe, y una que quedaría por debajo de 12 caracteres se descarta. Su línea discontinua sigue marcando el instante.
  • Los marcadores de log consecutivos, en orden de tiempo, que caen en el mismo segundo se pliegan en una sola etiqueta, <count>× <topics>: <first message>. Una nota o un hueco entre ellos corta el pliegue, y las notas y los huecos nunca se pliegan.
  • Los marcadores fuera del intervalo de tiempo de la grabación no se dibujan.

Con una sola muestra, el SVG dice not enough samples to draw; sin ninguna, plot se detiene con record: no samples y no escribe SVG. La paleta es propia del gráfico, validada para su fondo claro: ΔE entre pares adyacentes con deficiencia de visión del color 9,1, con visión normal 22,9. No hay variante oscura.

plot también lee una captura que el agente guardó por un disparo: guarda GET /captures/<id> en un fichero .jsonl y pásalo a --in. La línea de cabecera de la captura no lleva número de secuencia y se salta.

Cuando salta un disparador en el agente, una línea {"trigger":{…}} viaja en la misma petición que las muestras, justo antes de la muestra en la que saltó. El colector la reconoce; record no.

Captura por disparo explica qué salta y cómo traer la ventana a cadencia completa que el agente guardó a su alrededor.