
monitor v0.44.0
Monitoreo en tiempo real y análisis de slowlog para bases de datos Valkey y Redis con detección de anomalías, auditoría de ACL y exportación de métricas de Prometheus.
BetterDB Monitor
La capa de monitorización que Valkey merece.
BetterDB persiste lo que Valkey descarta: slowlogs, patrones de comandos, actividad de clientes, señales de anomalías, para que puedas depurar lo que ocurrió a las 3 de la madrugada, no solo lo que está pasando ahora. Diseñado para Valkey 8.x con soporte nativo para COMMANDLOG, CLUSTER SLOT-STATS y métricas de E/S por hilo. Compatible con Redis 6+ para todo lo demás.
Website | Docker Hub | npm | Documentation | Blog
BetterDB está desarrollado por BetterDB Inc., una empresa de beneficio público que opera bajo la OCV Open Charter.

Inicio rápido (Docker)```bash
docker run -d --name betterdb -p 3001:3001 betterdb/monitor:latest
Apunta tu navegador a `http://localhost:3001`. Para monitorear una instancia específica:```bash
docker run -d \
--name betterdb \
-p 3001:3001 \
-e DB_HOST=your-valkey-host \
-e DB_PORT=6379 \
-e DB_PASSWORD=your-password \
betterdb/monitor:latest
¿Te conectas a una base de datos en tu máquina host? Dentro del contenedor
localhostes el propio contenedor, no tu host — así que usahost.docker.internalcomo host de la base de datos. En Docker Desktop (macOS/Windows) funciona directamente; en Linux añade--add-host=host.docker.internal:host-gatewayal comandodocker runpara que el nombre se resuelva. El botón de "conectar a instancia local" con un solo clic del dashboard lo detecta automáticamente y rellena el host correcto por ti.
Se publican dos variantes de imagen, ambas multi-arquitectura (linux/amd64, linux/arm64):
| Etiqueta | Qué es |
|---|---|
latest, X.Y.Z-no-ai | Imagen por defecto - incluye todas las funciones de monitorización, sin las dependencias del experimental AI Helper de LLM local |
X.Y.Z | Añade el experimental AI Helper (trae tu propio Ollama; deshabilitado por defecto mediante AI_ENABLED) |
Consulta Docker Production Deployment para almacenamiento persistente, puertos personalizados, licencias y configuraciones air-gapped.
Quick Start (Kubernetes / Helm)```bash
helm repo add betterdb https://docs.betterdb.com/charts
helm repo update
helm install betterdb-monitor betterdb/betterdb-monitor
--namespace betterdb --create-namespace
--set db.host=my-valkey.default.svc.cluster.local
--set db.password=yourpassword
Luego `kubectl port-forward -n betterdb svc/betterdb-monitor 3001:3001` y abre `http://localhost:3001`, o habilita el ingress del chart. El historial respaldado por PostgreSQL, el uso de tus propios Secrets y las licencias en entornos aislados se cubren en la [guía de Kubernetes](https://docs.betterdb.com/kubernetes) y el [README del chart](https://github.com/betterdb-inc/monitor/blob/master/charts/betterdb-monitor/README.md).
## Inicio rápido (CLI)
Ejecuta BetterDB Monitor sin Docker:```bash
npx @betterdb/monitor
En la primera ejecución, un asistente de configuración interactivo te guía a través de la conexión a la base de datos, el backend de almacenamiento (SQLite, PostgreSQL o en memoria) y la configuración del servidor. La configuración se guarda en ~/.betterdb/config.json.```bash
npm install -g @betterdb/monitor # global install
betterdb --setup # re-run setup wizard
betterdb --port 8080 # override server port
betterdb --db-host 1.2.3.4 # override database host
betterdb --help # all options
Requiere Node.js >= 20.0.0 y una instancia de Valkey o Redis que monitorizar. Para almacenamiento SQLite, también `npm install -g better-sqlite3`.
## Lo que obtienes
### Verlo todo, conservarlo todo
- **Analíticas históricas** - consulta slowlogs, patrones de comandos, actividad de clientes y latencia en cualquier rango temporal. Los datos que solían desaparecer tras una rotación de logs.
- **Soporte de COMMANDLOG** - exclusivo de Valkey 8.1+. Solicitudes y respuestas grandes, no solo las lentas.
- **Sesiones de captura MONITOR** - graba tráfico real bajo demanda: tail en vivo, filtrado, replay, exportación a JSON/CSV y referencias cruzadas con el historial de conexiones.
- **Seguimiento de hot keys** - claves más accedidas por frecuencia con movimiento de ranking a lo largo del tiempo. Key Analytics (Pro, gratis en acceso anticipado) añade distribuciones de tipo, TTL y tamaño a partir de muestreo en vivo.
- **Visibilidad de clúster** - grafos de topología, mapas de calor de SLOT-STATS, CPU por slot y distribución de claves.
- **Métricas de hilos de CPU y E/S** - visibilidad por hilo que ninguna herramienta de Redis puede ofrecer.
- **Analíticas de clientes** - ve exactamente qué servicio es responsable de qué, atribuido por nombre y patrón de cliente.
- **Registro de auditoría de ACL** - rastrea quién accedió a qué, persistido para cumplimiento y depuración posterior a incidentes.
### Comprender y actuar
- **Detección de anomalías** (Pro, gratis en acceso anticipado) - aprendizaje automático de líneas base con eventos correlacionados y diagnósticos en lenguaje natural. Más de 20 detectores, sin umbrales manuales.
- **Previsión de capacidad** - tiempo proyectado hasta el límite para memoria, ops/seg, CPU y fragmentación.
- **Webhooks** - entregas de alertas firmadas con HMAC con reintentos y un registro completo de entregas.
- **Migración en vivo** - muévete entre Redis y Valkey con un flujo de trabajo de tres fases: análisis, ejecución y validación.
### Diseñado para la era de la IA
- **Observabilidad de búsqueda vectorial** - ops/seg y latencia de FT.SEARCH con salud por índice para [valkey-search](https://github.com/valkey-io/valkey-search) y RediSearch. Consulta [docs/vector-ai](https://github.com/betterdb-inc/monitor/blob/master/docs/vector-ai/README.md).
- **Latencia de inferencia** - p50/p95/p99 por índice, con alertas de incumplimiento de SLA (Pro, gratis en acceso anticipado).
- **Inteligencia de caché semántica** (Pro, gratis en acceso anticipado) - salud de la tasa de aciertos, recomendaciones de umbral de similitud y un flujo de trabajo de propuestas de aprobación/rechazo. Incluye observabilidad de memoria de agentes.
- **Trazas de IA** - cascadas de spans OTLP desde tu aplicación de IA, correlacionadas con el estado en vivo de Valkey subyacente a cada solicitud. Consulta [docs/opentelemetry.md](https://github.com/betterdb-inc/monitor/blob/master/docs/opentelemetry.md).
### Se conecta con todo
- **Servidor MCP** - 60 herramientas para Claude Code, Cursor o cualquier cliente MCP mediante [`@betterdb/mcp`](https://github.com/betterdb-inc/monitor/blob/master/packages/mcp).
- **Endpoint de Prometheus** - más de 100 métricas `betterdb_*`. Consulta [docs/prometheus-metrics.md](https://github.com/betterdb-inc/monitor/blob/master/docs/prometheus-metrics.md).
- **OpenTelemetry** - ingiere trazas OTLP y replica métricas y eventos a cualquier backend OTLP. Consulta [docs/opentelemetry.md](https://github.com/betterdb-inc/monitor/blob/master/docs/opentelemetry.md).
- **API REST** - todo en la interfaz de usuario es una llamada a la API, documentada mediante OpenAPI.
## Accede a tus datos a tu manera
| Interfaz | Detalles |
|-----------|---------|
| Interfaz web | `http://localhost:3001` |
| Servidor MCP | `npx @betterdb/mcp` (stdio) - crea un token en Settings → MCP Tokens |
| Prometheus | `http://localhost:3001/api/prometheus/metrics` |
| API REST (OpenAPI) | `http://localhost:3001/docs` |
| Comprobación de estado | `http://localhost:3001/api/health` |
> **Nota**: En compilaciones de producción (Docker, CLI) las rutas de la API se sirven bajo el prefijo `/api`. En desarrollo local (`pnpm dev`) no hay prefijo - por ejemplo, `http://localhost:3001/health`.
## Bases de datos compatibles
| Base de datos | Versión mínima | Funciones compatibles |
|----------|----------------|-------------------|
| **Valkey** | 8.0+ | Todas las funciones, incluidos COMMANDLOG (8.1+) y CLUSTER SLOT-STATS |
| **Redis** | 6+ | Todas las funciones excepto COMMANDLOG y CLUSTER SLOT-STATS, exclusivos de Valkey |
El backend utiliza un adaptador unificado sobre el cliente `iovalkey` compatible a nivel de protocolo y detecta automáticamente Valkey frente a Redis a partir de la respuesta de `INFO` (`DB_TYPE=auto`). Capacidades como COMMANDLOG y SLOT-STATS se detectan por versión, y la interfaz de usuario se degrada de forma elegante cuando una función no está disponible.
También se admiten servicios gestionados: las guías para AWS ElastiCache, MemoryDB, Redis Cloud y Upstash están en [docs/providers](https://github.com/betterdb-inc/monitor/blob/master/docs/providers), y [`@betterdb/agent`](https://github.com/betterdb-inc/monitor/blob/master/packages/agent) llega a instancias solo accesibles desde VPC mediante un WebSocket saliente.
## Despliegue de producción con Docker
La imagen de Docker contiene la aplicación de monitorización (backend + frontend). Requiere:
1. Una instancia de Valkey/Redis que monitorizar
2. Una instancia de PostgreSQL para la persistencia de datos (o usar almacenamiento en memoria)
### Ejecutar con almacenamiento PostgreSQL```bash
docker run -d \
--name betterdb-monitor \
-p 3001:3001 \
-e DB_HOST=your-valkey-host \
-e DB_PORT=6379 \
-e DB_PASSWORD=your-password \
-e STORAGE_TYPE=postgres \
-e STORAGE_URL=postgresql://user:pass@postgres-host:5432/dbname \
betterdb/monitor
Ejecutar en un puerto personalizado
Establezca la variable de entorno PORT y haga coincidir el mapeo -p:```bash
docker run -d
--name betterdb-monitor
-p 8080:8080
-e PORT=8080
-e DB_HOST=your-valkey-host
betterdb/monitor
### Ejecutar con red del host (acceder a servicios de localhost)
Si tu Valkey y PostgreSQL se ejecutan en el mismo host:```bash
docker run -d \
--name betterdb-monitor \
--network host \
-e DB_HOST=localhost \
-e DB_PORT=6380 \
-e DB_PASSWORD=devpassword \
-e STORAGE_TYPE=postgres \
-e STORAGE_URL=postgresql://dev:devpass@localhost:5432/postgres \
betterdb/monitor
Variables de Entorno
| Variable | Requerida | Predeterminado | Descripción |
|---|---|---|---|
DB_HOST | Sí | localhost | Host de Valkey/Redis a monitorear |
DB_PORT | No | 6379 | Puerto de Valkey/Redis |
DB_PASSWORD | No | - | Contraseña de Valkey/Redis |
DB_USERNAME | No | default | Nombre de usuario ACL de Valkey/Redis |
DB_TYPE | No | auto | Tipo de base de datos: auto, valkey, o redis |
STORAGE_TYPE | No | memory | Backend de almacenamiento: memory o postgres |
STORAGE_URL | Condicional | - | URL de conexión a PostgreSQL (requerida si STORAGE_TYPE=postgres) |
PORT | No | 3001 | Puerto HTTP de la aplicación |
NODE_ENV | No | production | Entorno de Node |
ANOMALY_DETECTION_ENABLED | No | true | Habilitar detección de anomalías |
ANOMALY_PROMETHEUS_INTERVAL_MS | No | 30000 | Intervalo de actualización del resumen de Prometheus (ms) |
BETTERDB_LICENSE_KEY | No | - | Clave de licencia en línea (Pro/Enterprise), validada a través de la red |
BETTERDB_OFFLINE_LICENSE_FILE | No | - | Ruta a una licencia offline firmada .jwt para hosts air-gapped (ver abajo) |
BETTERDB_OFFLINE_LICENSE | No | - | Token de licencia offline como cadena JWT en línea |
BETTERDB_DATA_DIR | No | /app/data | Directorio para el estado de licencia persistido (montar un volumen con permisos de escritura) |
ENCRYPTION_KEY | No | - | Clave (mín. 16 caracteres) utilizada para cifrar con envelope encryption las contraseñas de conexión almacenadas y los secretos de túneles SSH en reposo. Sin ella, los secretos se almacenan en texto plano |
BETTERDB_SSH_KEY_DIR | No | - | Directorio en el que deben residir las claves privadas SSH del lado del servidor. Habilita la fuente de clave "ruta de archivo del servidor" para túneles SSH; la ruta de clave de una conexión debe resolverse dentro de él. Sin establecer, deshabilita las claves basadas en archivos (las claves pegadas en línea siguen funcionando) |
BETTERDB_TELEMETRY | No | true | Establecer false para deshabilitar la telemetría anónima |
Referencia completa, incluyendo IA, ajuste de webhooks y umbrales de health-gate: docs/configuration.md. Para la ingesta de trazas OTLP y la exportación de métricas/eventos, ver docs/opentelemetry.md.
Túneles SSH
Las conexiones pueden alcanzar una base de datos a través de un host bastión/salto SSH en lugar de conectarse directamente — útil para Valkey/Redis en una subred privada, ElastiCache o MemoryDB. Habilite Connect via SSH tunnel al agregar una conexión y proporcione el host, puerto y nombre de usuario SSH. Se admite un solo salto.
La autenticación es mediante contraseña o clave privada. Las claves privadas provienen de una de dos fuentes:
- Paste key (en línea): el contenido de la clave PEM se envía con la conexión. Se almacena cifrada en reposo solo cuando
ENCRYPTION_KEYestá establecida (envelope encryption); sin esa clave se almacena en texto plano, al igual que las contraseñas de conexión. Funciona en todas partes, incluyendo despliegues gestionados/en la nube. - Server file path: la clave ya reside en el sistema de archivos del servidor de monitoreo y se referencia por ruta. Esto requiere establecer la variable de entorno
BETTERDB_SSH_KEY_DIRal directorio que contiene las claves permitidas, y la ruta referenciada debe resolverse dentro de él, de modo que la API nunca pueda ser forzada a leer archivos arbitrarios. DejeBETTERDB_SSH_KEY_DIRsin establecer para deshabilitar esta opción.
Opcionalmente, fije la huella digital de la clave de host del servidor SSH (SHA256:...) en la conexión; cuando se establece, el túnel se rechaza a menos que el servidor presente una clave coincidente, previniendo ataques de man-in-the-middle en la ruta del bastión. Si se deja en blanco, la identidad del servidor no se verifica (se registra una advertencia).
El túnel reenvía a la base de datos a través de 127.0.0.1; cuando TLS está habilitado, el certificado aún se valida contra el nombre de host real de la base de datos. Establezca ENCRYPTION_KEY para que las contraseñas SSH, las frases de contraseña de claves y las claves en línea se cifren en reposo.
Limitación conocida — topologías de clúster/Sentinel: solo la conexión que configura se tuneliza. El monitoreo de clúster y Sentinel se distribuye a los otros nodos utilizando las direcciones que esos nodos anuncian (CLUSTER NODES / Sentinel), y esas conexiones por nodo se realizan directamente, no a través del túnel. Si los otros nodos solo son accesibles a través del bastión (por ejemplo, ElastiCache/MemoryDB en una subred privada), las vistas por nodo no estarán disponibles. Utilice túneles SSH para monitoreo de nodo único/primario, o coloque el monitor donde pueda alcanzar los nodos del clúster directamente.
Licenciamiento y Soporte Air-Gapped
BetterDB Monitor desbloquea las funciones Pro/Enterprise de una de dos maneras, dependiendo de si el host tiene acceso a internet:
- Clave de licencia en línea - establezca
BETTERDB_LICENSE_KEY. El monitor la valida contrabetterdb.comy almacena en caché un token firmado verificado localmente, para que su nivel siga funcionando durante interrupciones breves y reinicios. - Token de licencia offline / air-gapped - para hosts sin acceso a internet en absoluto (ver abajo).
Cómo funciona el licenciamiento air-gapped
Cada derecho es un JWT RS256 firmado. El monitor lo verifica localmente contra claves públicas incrustadas en la imagen - nunca tiene que alcanzar un servidor de licencias para confiar en un token. Así, un host air-gapped puede ejecutar niveles de pago con conectividad cero:
- En una máquina conectada a internet, inicie sesión en
betterdb.com/account/licenses y
descargue su token de licencia offline (
.jwt, Pro/Enterprise). No contiene secretos y no puede ser manipulado - cualquier edición rompe la firma. - Transfiera el token al host air-gapped como desee (USB, gestión de configuración, un montaje de secreto de Docker/Kubernetes).
- Proporciónelo mediante
BETTERDB_OFFLINE_LICENSE_FILE(ruta),BETTERDB_OFFLINE_LICENSE(cadena en línea), o péguelo en la UI bajo Settings → License → "Air-gapped environment? Activate an offline license."
Cuando se configura un token offline y no se establece BETTERDB_LICENSE_KEY, el
monitor realiza cero solicitudes salientes - las verificaciones de licencia, la telemetría y los pings de actualización
están todos deshabilitados. Ejecuta el nivel otorgado hasta que el token expire (las licencias
perpetuas se vuelven a descargar anualmente), luego revierte a Community.```bash
fully offline - no network required
docker volume create betterdb-data docker run --rm -v betterdb-data:/d alpine chown 1001:1001 /d # volume writable by UID 1001 (one-time)
docker run -d --name betterdb-monitor -p 3001:3001
-e DB_HOST=your-valkey-host -e DB_PORT=6379 -e DB_PASSWORD=your-password
-v /path/to/betterdb-license.jwt:/run/secrets/betterdb-license.jwt:ro
-e BETTERDB_OFFLINE_LICENSE_FILE=/run/secrets/betterdb-license.jwt
-v betterdb-data:/app/data
betterdb/monitor
Verificar con `GET /api/license/status` → `source: offline-token`, `mode: offline`,
`airGapped: true`.
> **Persistencia:** monta un volumen con permisos de escritura en `/app/data` para que la licencia offline y
> el token de gracia por interrupción online sobrevivan a los reinicios. El contenedor se ejecuta como **UID 1001**,
> por lo que un volumen recién creado debe recibir `chown` a ese UID (como se muestra arriba); de lo contrario,
> la persistencia falla con `EACCES … license.jwt`.
Para el flujo completo, la precedencia de verificación y el runbook de rotación de claves, consulta
**[Licencias Offline y Air-Gapped](https://github.com/betterdb-inc/monitor/blob/master/docs/offline-licenses.md)** y la
**[Referencia de configuración](https://github.com/betterdb-inc/monitor/blob/master/docs/configuration.md#license-configuration)**.
### Detalles de la Imagen Docker
- **Imagen base**: `node:20-alpine`
- **Tamaño comprimido**: ~360MB (`latest` / `-no-ai`) / ~640MB (imagen versionada con las dependencias de LLM local del AI Helper experimental)
- **Plataformas**: `linux/amd64`, `linux/arm64`
- **Contiene**: API de backend + archivos estáticos del frontend (servidos por Fastify)
- **Excluido**: Soporte de SQLite (usa PostgreSQL o almacenamiento en memoria)
### Operaciones del Contenedor```bash
docker logs -f betterdb-monitor # follow logs
docker stop betterdb-monitor # stop
docker rm betterdb-monitor # remove
Backends de almacenamiento
BetterDB Monitor persiste el registro de auditoría, las analíticas, las capturas y los datos de anomalías en uno de los cuatro backends:
| Backend | Caso de uso | Notas |
|---|---|---|
memory | Pruebas, entornos efímeros | Predeterminado en Docker; todos los datos se pierden al reiniciar |
postgres | Producción | STORAGE_TYPE=postgres + STORAGE_URL=postgresql://user:pass@host:port/db |
turso | Producción / SQLite serverless | STORAGE_TYPE=turso + STORAGE_URL=libsql://... + STORAGE_AUTH_TOKEN; funciona en Docker |
sqlite | Desarrollo local / CLI | Módulo nativo eliminado de la imagen Docker latest; STORAGE_SQLITE_FILEPATH opcional |
Métricas de Prometheus
Las métricas se exponen en GET /api/prometheus/metrics en formato de texto de Prometheus: auditoría de ACL, conexiones de clientes, patrones de slowlog/commandlog, memoria, rendimiento, keyspace, replicación, estadísticas de slots de clúster y métricas de runtime de Node.js - todas con el prefijo betterdb_.```yaml
scrape_configs:
- job_name: 'betterdb-monitor'
metrics_path: '/api/prometheus/metrics'
static_configs:
- targets: ['your-monitor-host:3001']
Referencia completa de métricas: [docs/prometheus-metrics.md](https://github.com/betterdb-inc/monitor/blob/master/docs/prometheus-metrics.md) y [docs/prometheus-integration.md](https://github.com/betterdb-inc/monitor/blob/master/docs/prometheus-integration.md).
## Desarrollo
### Estructura del proyecto```
betterdb-monitor/
├── apps/
│ ├── api/ # NestJS backend (Fastify)
│ └── web/ # React frontend (Vite)
├── packages/ # Published packages (see below)
├── docs/ # Documentation site (Jekyll)
├── docker-compose.yml # Local Valkey (port 6380) and Redis (port 6382) for testing
└── package.json # Workspace root
Paquetes
Este monorepo incluye varios paquetes independientes. Consulta packages/ para ver la lista completa.
| Paquete | Lenguaje | Registro |
|---|---|---|
@betterdb/monitor | TypeScript | npm |
@betterdb/mcp | TypeScript | npm |
@betterdb/agent | TypeScript | npm |
@betterdb/semantic-cache | TypeScript | npm |
betterdb-semantic-cache | Python | PyPI |
@betterdb/agent-cache | TypeScript | npm |
betterdb-agent-cache | Python | PyPI |
cache-benchmark | Python | Replay harness for benchmarking semantic caches |
Stack Tecnológico
- Backend: NestJS con adaptador Fastify,
iovalkeypara conexiones Valkey/Redis, TypeScript en modo estricto. Puerto 3001. - Frontend: React + TypeScript, Vite, TailwindCSS, Recharts. Servidor de desarrollo en el puerto 5173.
- Monorepo: pnpm workspaces + Turborepo.
Configuración Local
Requisitos previos: Node.js >= 20.0.0, pnpm >= 9.0.0, Docker.```bash pnpm install cp .env.example .env pnpm docker:dev # local Valkey (6380) and Redis (6382) pnpm dev # web on :5173, api on :3001
Para conectarse a Redis en lugar de Valkey, establezca `DB_PORT=6382` en `.env`.```bash
pnpm dev:api # API only
pnpm dev:web # frontend only
pnpm docker:dev:down # stop local databases
pnpm build # production build
pnpm test # API tests
Compilaciones de imágenes Docker:```bash pnpm docker:build # local build pnpm docker:publish # multi-arch build & push (requires buildx)
### Agregar nuevas funcionalidades
1. Agrega nuevos endpoints en `apps/api/src/`
2. Agrega las llamadas API correspondientes en `apps/web/src/api/`
3. Agrega tipos compartidos en `packages/shared/src/types/`
### Estilo de código
- Modo estricto de TypeScript, tipos de retorno explícitos, sin `any`
- ESLint + Prettier configurados
## Licencia
- El contenido bajo `docs/` está licenciado bajo CC BY-SA 4.0.
- El contenido bajo `proprietary/` está cubierto por una licencia comercial (ver `proprietary/LICENSE`). Estas funcionalidades son gratuitas durante el acceso anticipado.
- Todo lo demás está bajo [MIT](https://github.com/betterdb-inc/monitor/blob/master/LICENSE).