Ir al contenido

Monitoring as Code

Monitoring as Code te permite definir tu configuración de monitoreo de LoadFocus como archivos versionados y aplicarla desde la línea de comandos o CI, igual que gestionas la infraestructura con Terraform o Pulumi. Describes los monitores, grupos, alertas, ventanas de mantenimiento, paneles y páginas de estado que quieres; la CLI @loadfocus/monitoring calcula la diferencia con lo que está en producción y la reconcilia (crear, actualizar, eliminar).

Es declarativa e idempotente: ejecutar deploy dos veces no cambia nada la segunda vez. Tus archivos son la fuente de verdad, así que los cambios pasan por pull requests y el historial de tu monitoreo vive en git.

Todo se ejecuta dentro de tu cuenta y tu equipo activo, con los límites de tu plan aplicados por el backend de LoadFocus exactamente igual que en el panel. La CLI solo hace lo que tú mismo podrías hacer en la interfaz.

Mantienes una carpeta de archivos YAML (o JavaScript) pequeños (un recurso por archivo) más un loadfocus.config.yaml que apunta a ellos. La CLI envía esas definiciones a LoadFocus, que las mapea a recursos en producción, las compara y devuelve un plan. Revisas el plan y luego lo aplicas.

  • Escribe: describe los recursos como archivos (constructos YAML o JS).
  • Planifica: deploy --dry-run muestra exactamente qué se va a crear, actualizar, adoptar o eliminar.
  • Aplica: deploy reconcilia tu cuenta para que coincida con los archivos.
  • Reconcilia la identidad: cada recurso lleva un logicalId estable que tú eliges. Así es como la CLI rastrea un recurso a través de los cambios de nombre, de modo que cambiar el nombre visible de una comprobación nunca la recrea.

La CLI es un paquete de Node (Node 18+). Ejecútala bajo demanda con npx:

Ventana de terminal
npx @loadfocus/monitoring --help

…o instálala globalmente para obtener el comando loadfocus-monitoring:

Ventana de terminal
npm install -g @loadfocus/monitoring
loadfocus-monitoring --help

La CLI se autentica con una clave de API de LoadFocus y un id de equipo. Encontrarás ambos en la página de desarrolladores, que muestra tu clave de API y tu id de equipo juntos, junto con la configuración de MCP.

Inicia sesión una vez y las credenciales se guardan en ~/.loadfocus/config.json:

Ventana de terminal
loadfocus-monitoring login --apikey <your-api-key> --teamid <your-team-id>
loadfocus-monitoring whoami # confirm who you are and which team you're targeting

Para CI, prefiere las variables de entorno (anulan la configuración guardada y nunca tocan el disco):

Ventana de terminal
export LOADFOCUS_API_KEY="apikey_xxxxxxxx"
export LOADFOCUS_TEAM_ID="team_xxxxxxxx"
# optional: export LOADFOCUS_API_URL="https://apimonitor.loadfocus.com"

Para cambiar más tarde un valor guardado, usa config set con --apikey, --teamid o --api-url. config show muestra las credenciales que la CLI usa realmente, incluidas las variables de entorno, con la clave de API enmascarada salvo sus cuatro últimos caracteres. logout elimina de ~/.loadfocus/config.json la clave de API y el id de equipo guardados.

Ventana de terminal
loadfocus-monitoring config set --teamid <your-team-id> # change one saved value
loadfocus-monitoring config show # credentials in use, API key masked
loadfocus-monitoring logout # remove the saved API key and team id

Genera un archivo de configuración y un monitor de ejemplo en tu repositorio:

Ventana de terminal
loadfocus-monitoring init

Esto escribe loadfocus.config.yaml:

project: my-project # a namespace for this set of resources
checkMatch:
- "monitors/**/*.{check,group,alertRule,maintenanceWindow,dashboard,statusPage,alertChannel,variable}.{yaml,yml,js}"
defaults:
schedule: "300" # applied to checks that omit a schedule
locations: [us-east-1]
  • project delimita todo lo que la CLI gestiona. Los recursos de un proyecto se reconcilian juntos; cualquier cosa del proyecto que ya no esté en tus archivos se elimina en deploy. Usa proyectos separados para gestionar conjuntos independientes de monitores.
  • checkMatch es el glob (o los globs) de tus archivos de autoría.
  • defaults rellenan schedule, locations y alertChannels para las comprobaciones que los omiten.

init omite los archivos que ya existen. Añade --force para sobrescribirlos.

Ventana de terminal
loadfocus-monitoring validate # compile locally + server-side dry-run; great as a PR gate
loadfocus-monitoring deploy --dry-run # show the plan (created / updated / adopted / deleted)
loadfocus-monitoring deploy # apply it
loadfocus-monitoring list # inventory of what's deployed in the project
loadfocus-monitoring list --status # …with each check's latest up/down/degraded status
loadfocus-monitoring get <logicalId> # show one deployed resource
loadfocus-monitoring trigger --id <logicalId> # run a check now (no --id runs every deployed check)
loadfocus-monitoring destroy # delete everything managed in the project

deploy es seguro por defecto: muestra el plan y, cuando se ejecuta de forma interactiva, pregunta antes de eliminar nada. En CI (no interactivo), se niega a eliminar sin --yes y termina con un código claro en lugar de quedarse colgado en un prompt. Añade --json a los comandos de lectura/resultado para una salida legible por máquina.

validate --no-server solo compila tus archivos en local: no necesita credenciales y omite la simulación en el servidor, así que sirve como hook de pre-commit. Además, deploy se niega a aplicar un proyecto cuyo checkMatch no carga ningún archivo, porque ese plan eliminaría todos los recursos que gestiona el proyecto; casi siempre se debe a una carpeta equivocada o a una errata en checkMatch. deploy --dry-run sigue mostrando ese plan. Para eliminarlo todo a propósito, ejecuta destroy o pasa --allow-empty a deploy.

Ventana de terminal
loadfocus-monitoring test
loadfocus-monitoring test --json # machine-readable results

test ejecuta una vez cada comprobación de tus archivos, directamente desde ellos, e indica si cada una pasa o falla. No se guarda nada: no se crea ni se modifica ninguna comprobación en tu cuenta. Termina con el código 1 cuando alguna comprobación falla o da error, de modo que un job de CI puede bloquear un pull request hasta que las comprobaciones pasen contra los endpoints reales; un resultado degradado no hace fallar la ejecución. Los proyectos con muchas comprobaciones se envían en lotes de 20.

¿Ya tienes monitores en el panel? Impórtalos a archivos en lugar de recrearlos:

Ventana de terminal
loadfocus-monitoring import --project my-project --out monitors

Esto escribe un archivo por recurso y un loadfocus.config.yaml. Revisa, haz commit y luego ejecuta deploy --dry-run: los recursos coincidentes se adoptan en su lugar (quedan bajo gestión) en vez de duplicarse.

import omite los archivos que ya existen en la carpeta de salida. Añade --force para sobrescribirlos con la versión del servidor.

Cada recurso es un archivo con un kind, un logicalId (tu identificador estable) y los campos de ese kind. Las referencias entre recursos usan logicalIds (o nombres para los canales de alerta); el servidor las resuelve y el orden de despliegue se gestiona por ti.

Un único kind check cubre todos los tipos de comprobación mediante type: api, browser, multistep, tcp, heartbeat (en JavaScript, el constructo Monitor hace lo mismo).

kind: check
type: api
logicalId: home
name: Home API
schedule: "300" # seconds between runs
locations: [us-east-1, eu-west-1]
tags: [production, payments] # optional labels
request:
url: "https://example.com/health"
method: GET
assertions:
- { type: statusCode, comparison: equals, value: 200 }
- { type: responseTime, comparison: less-than, value: 1000 }
  • api: petición HTTP con aserciones sobre código de estado, tiempo de respuesta y cuerpo. Las comparaciones son equals, not-equals, greater-than, less-than, equals-or-greater-than, equals-or-less-than, contains y not-contains.
  • browser: un script de flujo de usuario de Playwright con capturas de pantalla y tiempos por paso (de pago).
  • multistep: una secuencia ordenada de peticiones de API que pasan datos entre pasos (de pago).
  • tcp: una comprobación de puerto/alcanzabilidad desde varias regiones (de pago).
  • heartbeat: un interruptor de hombre muerto: un trabajo externo hace ping a una URL según una programación, y LoadFocus alerta si falta un ping.

Una comprobación también puede llevar tags, las mismas etiquetas que pones junto al nombre de la verificación en la aplicación (consulta etiquetas de las verificaciones). Si despliegas un archivo de comprobación sin tags, esa comprobación pierde sus etiquetas. En JavaScript, el constructo Monitor conserva tags desde la versión 1.0.2 de la CLI; las versiones anteriores las descartaban.

Comparte ubicaciones, canales de alerta, frecuencia y activación entre muchas comprobaciones. Una comprobación se une a un grupo con group: <logicalId>.

kind: group
logicalId: web
name: Web services
locations: [us-east-1, eu-west-1]

Alerta cuando la métrica de una comprobación cruza un umbral.

kind: alertRule
logicalId: home-latency
name: Home API latency
check: home # reference a check by logicalId
metric: responseTime # responseTime | statusCode | duration
condition: above
conditionValue: 1500 # milliseconds

Gestiona los canales de notificación como código y referéncialos por nombre desde una comprobación, grupo o regla de alerta. Tipos (type) admitidos: email, slack, microsoftteams, webhook, discord, pagerduty, opsgenie. Los canales de email, Slack, Teams y webhook están en todos los planes; Discord, PagerDuty y Opsgenie son solo de pago. Los campos secretos (webhookUrl, routingKey, apiKey) toman una referencia {{secrets.NAME}}: el valor se almacena con env set-secret y se resuelve al enviar una alerta, nunca se incluye en tus archivos.

kind: alertChannel
logicalId: oncall # the name checks / groups / alert rules reference
type: pagerduty
routingKey: "{{secrets.PAGERDUTY_KEY}}"

Suprime las alertas durante el trabajo planificado. Las horas son UTC. startsAt / endsAt aceptan una cadena ISO-8601 (por ejemplo, "2026-07-01T00:00:00Z") o milisegundos unix.

kind: maintenanceWindow
logicalId: weekly-deploy
name: Weekly deploy window
enabled: true
startsAt: "2026-07-01T00:00:00Z" # ISO-8601 or unix ms
endsAt: "2026-07-01T02:00:00Z"
repeat: weekly # none | daily | weekly | monthly
weekdays: [2] # 0=Sun … 6=Sat
targets:
allChecks: false
checkIds: [home] # by logicalId

Una vista compartida de comprobaciones seleccionadas, opcionalmente publica mediante un slug.

kind: dashboard
logicalId: status-overview
name: Status overview
visibility: private # private | public
checks: [home] # by logicalId
window: 24h # 24h | 7d | 30d

Una página de estado publica en <slug>.loadfoc.us, opcionalmente en tu propio dominio personalizado.

kind: statusPage
logicalId: public-status
title: Acme Status
slug: acme # -> acme.loadfoc.us (globally unique)
enabled: true
customDomain: status.acme.com # optional, paid; point a CNAME at cname.loadfoc.us
groups:
- { id: core, name: Core Services, order: 0 }
components:
- id: api
name: API
groupId: core
monitors: [home] # checks shown on this component, by logicalId
branding:
brandColor: "#5353a4"
colorTheme: dark

Un dominio personalizado entra en funcionamiento una vez que creas el CNAME y se emite el certificado: deploy lo declara; la verificación ocurre fuera de banda.

Valores no secretos (URLs base, IDs) que las verificaciones de API referencian en tiempo de ejecución como ${{NAME}} en la URL, los encabezados, los parámetros de consulta y el cuerpo, con el mismo marcador que los secretos. El logicalId es la clave de la variable. (Para los secretos, usa env set-secret: nunca los pongas en archivos.)

kind: variable
logicalId: BASE_URL
value: "https://api.example.com"

Si prefieres código en lugar de YAML, construye las mismas definiciones de forma programática y expórtalas: los constructos producen recursos idénticos:

const { Monitor, Group, AlertRule, Maintenance, Dashboard, StatusPage, AlertChannel, Variable } = require('@loadfocus/monitoring');
module.exports = [
new Monitor({
type: 'api', logicalId: 'home', name: 'Home API', schedule: '300',
locations: ['us-east-1'],
request: { url: 'https://example.com/health', method: 'GET' },
assertions: [{ type: 'statusCode', comparison: 'equals', value: 200 }],
}),
new Group({ logicalId: 'web', name: 'Web services', locations: ['us-east-1'] }),
];

Exporta los constructos desde el archivo (un array, como arriba) y nómbralo de modo que checkMatch lo recoja, por ejemplo monitors/home.check.js. La CLI lo carga como cualquier otro recurso.

Referencia valores desde tus comprobaciones sin incluirlos en el repositorio. Los secretos (tokens, contraseñas) se gestionan únicamente de forma imperativa y se referencian como ${{NAME}} en los campos de las comprobaciones (URL, encabezados, cuerpo) y como {{secrets.NAME}} en los campos secretos de los canales de alerta. Las variables (no secretas) pueden declararse como archivos (kind: variable, arriba) o establecerse de forma imperativa, y se referencian igual en los campos de una verificación de API, como ${{NAME}}; en esos campos, un marcador sin el signo de dólar, como {{NAME}}, se envía como texto literal. Una verificación multipaso pasa los valores entre pasos de otra forma: su script de configuración lee la variable como ${{NAME}} y la guarda en ctx.vars, y los pasos la usan como {{name}} (consulta Scripts de configuración y limpieza).

Ventana de terminal
loadfocus-monitoring env set-secret API_TOKEN "s3cr3t"
loadfocus-monitoring env set-var BASE_URL "https://example.com"
loadfocus-monitoring env ls # list secret + variable keys (values never shown)
loadfocus-monitoring env rm-secret API_TOKEN # delete a secret
loadfocus-monitoring env rm-var BASE_URL # delete a variable

Un pipeline típico valida en cada pull request y despliega al hacer merge a la rama principal.

.github/workflows/monitoring.yml
name: monitoring
on:
pull_request:
push:
branches: [main]
jobs:
monitoring:
runs-on: ubuntu-latest
env:
LOADFOCUS_API_KEY: ${{ secrets.LOADFOCUS_API_KEY }}
LOADFOCUS_TEAM_ID: ${{ secrets.LOADFOCUS_TEAM_ID }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npx @loadfocus/monitoring validate
- if: github.ref == 'refs/heads/main'
run: npx @loadfocus/monitoring deploy --yes
  • logicalId es la identidad. Mantenlo estable. Puedes renombrar libremente el name o el title de una comprobación; cambiar su logicalId se trata como eliminar un recurso y crear otro.
  • Las eliminaciones se limitan al proyecto. deploy solo retira recursos del project actual que ya no están en tus archivos, nunca nada de otro proyecto ni creado fuera de Monitoring as Code (hasta que lo adoptes).
  • Los slugs de las páginas de estado son globales. El slug se convierte en un subdominio, así que debe ser único entre todos los clientes de LoadFocus.
  • Las funciones de pago necesitan un plan de pago. Un equipo gratuito que declare un dominio personalizado en una página de estado recibe un error claro en deploy. Quitar la insignia "Powered by" no se aplica en un plan gratuito: el campo sigue desactivado.
  • Se aplican los límites del plan. Crear recursos mediante la CLI está sujeto a las mismas cuotas de plan que el panel. Un recurso que superaría una cuota se informa como rechazado y el resto del deploy continúa.