Skip to content

Referencia de API — MiniObserv

Base URL: http://<host>:<puerto> (predeterminado :8080)


1. Autenticación

Las rutas de métricas requieren un token JWT en el encabezado Authorization:

Authorization: Bearer <jwt>

Cómo funciona:

  1. El secreto AGENT_TOKEN (mínimo 16 caracteres) es compartido entre el agente y el servidor.
  2. El agente firma un JWT HS256 con exp = now + 24h usando ese secreto.
  3. El servidor valida la firma, el algoritmo (solo HS256 es aceptado) y la expiración en cada petición.
  4. Si el token es inválido, expirado o ausente, el servidor devuelve 401 Unauthorized.

Las rutas /healthz y /readyz no requieren autenticación.


2. POST /api/v1/metrics

Ingesta un batch de métricas recolectadas por el agente.

Autenticación

Requerida (Bearer JWT).

Cuerpo de la petición

Content-Type: application/json

json
{
  "host": "string",
  "metrics": [
    {
      "time":   "RFC3339",
      "host":   "string",
      "name":   "string",
      "value":  "number",
      "labels": { "clave": "valor" }
    }
  ]
}
CampoTipoObligatorioDescripción
hoststringNombre lógico del host origen del batch
metricsarrayLista de mediciones (1 – 1000 elementos)
metrics[].timeRFC3339Instante de la medición (con zona horaria)
metrics[].hoststringNombre del host (debe coincidir con el campo raíz)
metrics[].namestringNombre canónico de la métrica (ver sección 6)
metrics[].valuefloat64Valor numérico finito (no NaN, no ±Inf)
metrics[].labelsobjectnoMetadatos adicionales como pares clave-valor

Respuesta exitosa

HTTP 202 Accepted

json
{ "ingested": 7 }

Ejemplo

bash
TOKEN="TU_JWT_AQUI"

curl -s -X POST http://localhost:8080/api/v1/metrics \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "host": "servidor-prod-01",
    "metrics": [
      {
        "time": "2026-06-05T12:00:00Z",
        "host": "servidor-prod-01",
        "name": "cpu.usage_pct",
        "value": 45.2,
        "labels": { "core": "total" }
      },
      {
        "time": "2026-06-05T12:00:00Z",
        "host": "servidor-prod-01",
        "name": "mem.used_pct",
        "value": 68.1
      }
    ]
  }'

Respuesta:

json
{ "ingested": 2 }

Validaciones

  • metrics no puede estar vacío.
  • El batch no puede superar 1000 métricas.
  • Cada name debe ser uno de los nueve nombres canónicos (ver sección 6).
  • time no puede ser el instante cero.
  • value debe ser un número finito.
  • Las claves y valores de labels no pueden estar vacíos.

3. GET /api/v1/metrics/query

Consulta una serie temporal con agregación por bucket de tiempo.

Autenticación

Requerida (Bearer JWT).

Parámetros de consulta

ParámetroTipoObligatorioPredeterminadoDescripción
hoststringNombre exacto del host a consultar
namestringNombre canónico de la métrica (ver sección 6)
fromRFC3339Inicio del rango temporal (inclusive)
toRFC3339Fin del rango temporal (inclusive)
bucketstringno1mGranularidad del bucket: 1m, 5m, 15m, 1h, 1d
aggstringnoavgFunción de agregación: avg, max, min

Respuesta exitosa

HTTP 200 OK

json
{
  "host":   "servidor-prod-01",
  "name":   "cpu.usage_pct",
  "bucket": "1m",
  "agg":    "avg",
  "points": [
    { "time": "2026-06-05T12:04:00Z", "value": 45.2 },
    { "time": "2026-06-05T12:03:00Z", "value": 42.8 },
    { "time": "2026-06-05T12:02:00Z", "value": 39.1 }
  ]
}

Los puntos se devuelven en orden descendente (más reciente primero). Si no hay datos en el rango, points es [].

Ejemplos

Uso de CPU en los últimos 5 minutos, bucket de 1 minuto:

bash
TOKEN="TU_JWT_AQUI"

curl -s \
  -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8080/api/v1/metrics/query?host=servidor-prod-01&name=cpu.usage_pct&from=2026-06-05T12:00:00Z&to=2026-06-05T12:05:00Z&bucket=1m&agg=avg"

Uso de memoria máximo en la última hora:

bash
curl -s \
  -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8080/api/v1/metrics/query?host=servidor-prod-01&name=mem.used_pct&from=2026-06-05T11:00:00Z&to=2026-06-05T12:00:00Z&bucket=1h&agg=max"

Bytes de red recibidos, bucket de 5 minutos:

bash
curl -s \
  -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8080/api/v1/metrics/query?host=servidor-prod-01&name=net.bytes_in&from=2026-06-05T11:00:00Z&to=2026-06-05T12:00:00Z&bucket=5m&agg=avg"

Restricciones

  • El rango fromto no puede superar 30 días.
  • from debe ser anterior a to.
  • bucket debe ser uno de: 1m, 5m, 15m, 1h, 1d.
  • agg debe ser uno de: avg, max, min.

4. GET /api/v1/hosts

Devuelve el estado de salud actual de todos los hosts conocidos por el servidor. No requiere autenticación.

El servidor registra la última vez que cada host envió métricas. El estado se deriva del tiempo transcurrido desde entonces:

EstadoCondición
okEl host reportó métricas dentro del período HOST_STALE_AFTER (predeterminado 20 s)
staleSilencioso durante más de HOST_STALE_AFTER pero menos de HOST_DOWN_AFTER
downSilencioso durante más de HOST_DOWN_AFTER (predeterminado 50 s); se ha disparado el webhook host.down

Autenticación

No requerida.

Ejemplo

bash
curl -s http://localhost:8080/api/v1/hosts | jq .

Respuesta exitosa

HTTP 200 OK

json
{
  "hosts": [
    {
      "host": "web-01",
      "status": "ok",
      "last_seen": "2026-06-05T16:42:23Z"
    },
    {
      "host": "web-02",
      "status": "stale",
      "last_seen": "2026-06-05T16:41:58Z"
    },
    {
      "host": "api-01",
      "status": "down",
      "last_seen": "2026-06-05T16:40:10Z"
    }
  ]
}

hosts es un array vacío si ningún agente ha reportado todavía.

Variables de entorno relacionadas

VariablePredeterminadoDescripción
HOST_STALE_AFTER20sTiempo tras el cual un host silencioso se considera stale. Acepta duraciones Go.
HOST_DOWN_AFTER50sTiempo tras el cual un host silencioso se considera down y se dispara el webhook host.down.
ALERT_NOTIFICATIONSArray JSON de objetos webhook que reciben los eventos host.down. Ver getting-started.

6. GET /healthz

Sonda de liveness. Verifica que el proceso del servidor está en ejecución.

Autenticación

No requerida.

Respuesta

HTTP 200 OK — siempre, sin consultar la base de datos.

ok

Cuándo usarla

  • Configuración de sondas de liveness en Kubernetes (livenessProbe).
  • Verificación rápida de que el proceso arrancó correctamente.
  • No indica si la base de datos está disponible (para eso, use /readyz).

Ejemplo

bash
curl -s http://localhost:8080/healthz
# ok

7. GET /readyz

Sonda de readiness. Verifica que el servidor puede atender peticiones y que la conexión con la base de datos funciona.

Autenticación

No requerida.

Respuesta exitosa

HTTP 200 OK

ok

Respuesta en caso de error

HTTP 503 Service Unavailable

json
{ "error": "db unavailable" }

Cuándo usarla

  • Configuración de sondas de readiness en Kubernetes (readinessProbe).
  • Verificación post-arranque antes de dirigir tráfico al servidor.
  • Diagnóstico de problemas de conectividad con TimescaleDB.

Ejemplo

bash
curl -s http://localhost:8080/readyz
# ok

# Verificar el código de estado HTTP:
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/readyz
# 200

8. GET /metrics

Pública — no requiere autenticación. Compatible con cualquier scraper de Prometheus.

Devuelve los valores actuales de todas las métricas de todos los hosts en formato de texto Prometheus (versión 0.0.4). Los nombres de métricas llevan el prefijo miniobserv_ y los puntos se reemplazan por guiones bajos.

Autenticación

No requerida.

Petición

GET /metrics

Respuesta

Content-Type: text/plain; version=0.0.4

# HELP miniobserv_cpu_usage_pct MiniObserv metric: cpu.usage_pct
# TYPE miniobserv_cpu_usage_pct gauge
miniobserv_cpu_usage_pct{host="web-01"} 42.5 1717600943000
miniobserv_cpu_usage_pct{host="web-02"} 71.2 1717600943000

Ejemplo

bash
curl http://localhost:8080/metrics

Uso con Prometheus

yaml
scrape_configs:
  - job_name: miniobserv
    static_configs:
      - targets: ['tu-host:8080']
    metrics_path: /metrics

Códigos de respuesta

CódigoCuerpoSignificado
200 OKFormato texto PrometheusMétricas devueltas para todos los hosts conocidos.

9. Respuestas de error

Todas las respuestas de error siguen este formato JSON:

json
{ "error": "descripción del error" }

Códigos de estado

CódigoSignificadoCausas típicas
400 Bad RequestPetición mal formadaJSON inválido, campo faltante, nombre de métrica desconocido, batch vacío, batch > 1000, parámetro de query inválido, rango > 30 días
401 UnauthorizedToken ausente o inválidoSin encabezado Authorization, token expirado, firma incorrecta, algoritmo distinto de HS256
500 Internal Server ErrorError interno del servidorFallo en la base de datos al insertar o consultar
503 Service UnavailableBase de datos no disponibleSolo en /readyz; la base de datos no responde al ping

Ejemplos de respuestas de error

400 — Nombre de métrica desconocido:

json
{ "error": "metric[0]: unknown metric name \"cpu.load\"" }

400 — Batch excede el límite:

json
{ "error": "batch exceeds maximum size of 1000" }

400 — Parámetro de bucket inválido:

json
{ "error": "invalid bucket \"2m\": must be one of 1m,5m,15m,1h,1d" }

401 — Token ausente:

json
{ "error": "unauthorized" }

400 — Rango temporal inválido:

json
{ "error": "time range must not exceed 30 days" }

10. Referencia de métricas

Tabla de nombres canónicos

NombreUnidadLabelsEmitido desde
cpu.usage_pct% (0–100)core=total|0|1|…Primer tick
mem.used_pct% (0–100)Primer tick
mem.used_bytesbytesPrimer tick
mem.total_bytesbytesPrimer tick
disk.used_pct% (0–100)mount=/Primer tick
disk.used_bytesbytesmount=/Primer tick
disk.total_bytesbytesmount=/Primer tick
net.bytes_inbytes (delta)iface=eth0Segundo tick
net.bytes_outbytes (delta)iface=eth0Segundo tick

Notas sobre labels

  • cpu.usage_pct: core=total representa el promedio de todos los núcleos; core=0, core=1, etc. representan cada núcleo físico.
  • disk.*: mount contiene el punto de montaje exacto del sistema de archivos (p. ej. /, /data, /home).
  • net.*: iface contiene el nombre de la interfaz de red (p. ej. eth0, ens3, enp3s0). El loopback (lo) siempre se excluye.
  • Las métricas de memoria no tienen labels porque representan el estado global del sistema.

Semántica de net.bytes_in / net.bytes_out

Estos valores representan el delta de bytes desde el tick anterior, no el total acumulado. Por eso no se emiten en el primer tick del agente: el primer tick solo registra el estado inicial de los contadores del sistema operativo como referencia para el cálculo siguiente.


11. Límites

LímiteValor
Tamaño máximo de batch (POST /api/v1/metrics)1000 métricas
Rango máximo de consulta (GET /api/v1/metrics/query)30 días
Granularidades de bucket disponibles1m, 5m, 15m, 1h, 1d
Funciones de agregación disponiblesavg, max, min
Duración del JWT generado por el agente24 horas
Longitud mínima de AGENT_TOKEN16 caracteres
Algoritmo JWT aceptadoHS256 únicamente

Released under the MIT License.