--- name: fn_monitoring description: "Monitoreo y visualizacion del estado del fn_registry. API HTTP read-only sobre las bases de datos SQLite y dashboard ImGui que consume la API." tags: [monitoring, api, dashboard, sqlite, visualization] repo_url: "" --- ## Apps | App | Lang | Descripcion | |-----|------|-------------| | [sqlite_api](apps/sqlite_api/app.md) | Go | API REST HTTP read-only sobre `registry.db` y todas las `operations.db`. Puerto `8484`. | | [registry_dashboard](apps/registry_dashboard/app.md) | C++ / ImGui | Dashboard con KPIs, charts y tablas del registry. Consume `sqlite_api` (HTTP) con fallback a SQLite directo. | Cada `app.md` es la referencia canonica del binario — endpoints completos, flags, dependencias. Este documento cubre **como operar el proyecto como un todo**: arranque, service, flujo de datos, troubleshooting. --- ## Arquitectura ``` registry.db (raiz) apps/*/operations.db projects/*/apps/*/operations.db │ (read-only, mode=ro) ▼ ┌──────────────────────────────────────────────┐ │ sqlite_api (Go net/http, :8484) │ │ /health │ │ /api/databases │ │ /api/databases/:db/tables │ │ /api/databases/:db/schema │ │ /api/databases/:db/query (POST, SELECT) │ │ /api/databases/:db/fts │ └──────────────────────────────────────────────┘ ▲ │ HTTP GET/POST │ (cpp-httplib + nlohmann/json) │ ┌──────────────────────────────────────────────┐ │ registry_dashboard (C++ / ImGui + ImPlot) │ │ main.cpp → reload_data() │ │ data_http.cpp (primario, HTTP) │ │ data.cpp (fallback, SQLite C API) │ │ views.cpp → KPI row, charts, tables │ └──────────────────────────────────────────────┘ ``` **Separacion de responsabilidades:** - `sqlite_api` **no conoce el dashboard**. Es una API generica: expone cualquier DB SQLite de `fn_registry/` read-only con FTS5. - `registry_dashboard` **no conoce la estructura de registry.db directamente**, solo a traves del JSON que devuelve la API. El modo SQLite directo es fallback para entornos sin red. **Puerto `8484`** — elegido para no colisionar con Metabase (3000), Jupyter (8888) ni deploy_server (9090). --- ## Servicio sqlite_api ### Modos de arranque | Modo | Comando | Cuando usarlo | |------|---------|---------------| | Dev (foreground, `go run`) | `cd projects/fn_monitoring/apps/sqlite_api && go run -tags fts5 .` | Iteracion rapida, ver logs en la terminal | | Dev (background) | `./start.sh` (dentro de `apps/sqlite_api/`) | Probar el dashboard rapido sin systemd. Escribe PID en `sqlite_api.pid` y log en `sqlite_api.log` | | Production (systemd) | `sudo systemctl start sqlite_api` | Arranque en boot, restart on failure, logs en journal | ### Variables de entorno | Var | Valor | Proposito | |-----|-------|-----------| | `FN_REGISTRY_ROOT` | ruta absoluta a la raiz del registry | Evita que el binario busque `registry.db` subiendo por el cwd. Obligatoria bajo systemd. | ### Instalar como servicio systemd (local) Usar el pipeline del registry `install_systemd_service_bash_pipelines`: ```bash cd /home/lucas/fn_registry # 1. Build del binario CGO_ENABLED=1 go build -tags fts5 \ -o projects/fn_monitoring/apps/sqlite_api/sqlite_api \ ./projects/fn_monitoring/apps/sqlite_api/ # 2. Instalar unit + enable + start (requiere sudo sin password para systemctl) source bash/functions/pipelines/install_systemd_service.sh install_systemd_service \ --name sqlite_api \ --exec "$(pwd)/projects/fn_monitoring/apps/sqlite_api/sqlite_api" \ --workdir "$(pwd)" \ --env "FN_REGISTRY_ROOT=$(pwd)" \ --description "fn_registry SQLite HTTP API" \ --after network.target \ --restart on-failure ``` ### Operacion ```bash sudo systemctl status sqlite_api # estado + ultimas lineas del journal sudo systemctl restart sqlite_api # tras rebuild del binario sudo systemctl stop sqlite_api # parar journalctl -u sqlite_api -f # logs en vivo curl http://127.0.0.1:8484/health # health check ``` ### Redeploy tras cambios en el codigo Go ```bash cd /home/lucas/fn_registry CGO_ENABLED=1 go build -tags fts5 \ -o projects/fn_monitoring/apps/sqlite_api/sqlite_api \ ./projects/fn_monitoring/apps/sqlite_api/ sudo systemctl restart sqlite_api ``` No hace falta reinstalar el unit — solo recompilar y reiniciar. --- ## Dashboard registry_dashboard ### Build ```bash cd cpp cmake -B build/linux -S . cmake --build build/linux --target registry_dashboard -j$(nproc) ``` El binario queda en `cpp/build/linux/registry_dashboard` (o `projects/fn_monitoring/apps/registry_dashboard/registry_dashboard.exe` en Windows). ### Ejecucion ```bash # Modo API (por defecto, intenta localhost:8484) ./registry_dashboard # API remoto ./registry_dashboard --api http://192.168.1.10:8484 # API + fallback SQLite ./registry_dashboard --api http://127.0.0.1:8484 /home/lucas/fn_registry/registry.db # Solo SQLite (sin API) ./registry_dashboard /home/lucas/fn_registry/registry.db ``` La UI muestra en la cabecera de donde vienen los datos (HTTP vs SQLite). `F5` recarga. ### Flujo de datos 1. `main.cpp::reload_data()` intenta HTTP primero via `load_registry_data_http()`. 2. Si la API responde `200` y el JSON parsea, los datos pueblan `RegistryData`. 3. Si falla la API (timeout, 5xx, JSON invalido) y hay `--db`, cae a `load_registry_data()` (SQLite directo). 4. Si ninguno funciona, la UI muestra un mensaje de error y no hay reintento automatico — hay que pulsar reload. ### Vistas | Seccion | Datos | Query subyacente | |---------|-------|------------------| | KPI row (8 cards) | totales y porcentajes | `SELECT COUNT(*)` sobre functions, types, apps, analysis, unit_tests, proposals + agregados tested/pure | | Charts (bar + pie) | funciones por lang/domain, reparto pure/impure, kind | `GROUP BY lang`, `GROUP BY domain`, `GROUP BY purity`, `GROUP BY kind` | | Tablas | ultimas 20 functions, apps, analysis, types | `ORDER BY updated_at DESC LIMIT 20` | Detalle de composicion de componentes viz en `apps/registry_dashboard/app.md`. --- ## Troubleshooting | Sintoma | Causa probable | Verificacion / Fix | |---------|----------------|--------------------| | Dashboard dice "HTTP API failed, falling back to SQLite" | `sqlite_api` no esta corriendo | `curl http://127.0.0.1:8484/health` — si falla, `systemctl status sqlite_api` o `./start.sh` | | `sqlite_api` arranca y muere inmediatamente | No encuentra `registry.db` | Exportar `FN_REGISTRY_ROOT=/home/lucas/fn_registry` o correr desde la raiz del registry | | `systemctl start sqlite_api` pide password | Falta sudoers para systemctl | Ver `.claude/rules/deploy.md` — el usuario necesita `NOPASSWD` para `systemctl`, `mv` a `/etc/systemd/system/` | | Dashboard abre pero todas las cifras son 0 | API conecta pero devuelve DB vacia | `curl -X POST http://127.0.0.1:8484/api/databases/registry/query -d '{"sql":"SELECT COUNT(*) FROM functions"}'` | | API responde lento / timeout | Query pesada sobre FTS5 | Timeout hardcoded a 5s en `handlers.go`. Revisar la query en journal. | | Bind rechazado (`address already in use`) | Otro proceso en `8484` | `ss -tlnp | grep 8484` — matar el huerfano o cambiar `--bind` | ### Logs ```bash # systemd journalctl -u sqlite_api -n 100 --no-pager journalctl -u sqlite_api -f # start.sh tail -f projects/fn_monitoring/apps/sqlite_api/sqlite_api.log ``` --- ## Como extender ### Anadir un endpoint a sqlite_api 1. Registrar la ruta en `Server.Routes()` (`handlers.go`). 2. Handler lee `r.URL.Path` / `r.Body`, delega en `DBPool` para resolver la DB, ejecuta SQL read-only. 3. Test en `handlers_test.go` (patron: tabla de casos HTTP). 4. Rebuild + `systemctl restart sqlite_api`. 5. Documentar en `apps/sqlite_api/app.md` (tabla de endpoints). ### Anadir una vista al dashboard 1. Nuevo campo en `RegistryData` (`data.h`) + su equivalente en la respuesta JSON. 2. Parseo en `data_http.cpp` y carga SQL en `data.cpp` (ambos paths, para mantener el fallback). 3. Renderizado en `views.cpp` usando componentes del dominio `viz` (`kpi_card`, `bar_chart`, etc.) — ver regla `frontend_theming` analoga para C++: usar primitivos del registry antes que ImGui crudo. 4. Rebuild con CMake. ### Anadir una DB nueva La descubre automaticamente `DiscoverDatabases()` escaneando `apps/*/operations.db` y `projects/*/apps/*/operations.db`. No hay que registrar nada — al reiniciar `sqlite_api` aparecen con alias `ops:{app_name}`. --- ## Deploy en otros PCs Este proyecto se instala identico en cualquier maquina con el registry clonado: 1. `fn sync` para traer los metadatos del proyecto. 2. Build + systemd install (seccion "Instalar como servicio systemd" arriba). 3. Build del dashboard. Los datos son los `.db` locales — cada PC ve su propio estado del registry y sus propias `operations.db`. No hay sincronizacion remota de datos en este servicio: para eso existe `fn sync` contra `registry_api` (proyecto diferente, ver memoria `project_registry_api`).