Monitoring as Code

Monitoring as Code

Monitoring as Code vous permet de définir votre configuration de monitoring LoadFocus sous forme de fichiers versionnés et de l'appliquer depuis la ligne de commande ou la CI — de la même façon que vous gérez votre infrastructure avec Terraform ou Pulumi. Vous décrivez les moniteurs, groupes, alertes, fenêtres de maintenance, tableaux de bord et pages de statut que vous voulez ; la CLI @loadfocus/monitoring calcule la différence par rapport à ce qui est en production et la réconcilie (création, mise à jour, suppression).

C'est déclaratif et idempotent : exécuter deploy deux fois ne change rien la seconde fois. Vos fichiers sont la source de vérité, donc les changements passent par des pull requests et l'historique de votre monitoring vit dans git.

Tout s'exécute dans votre compte et votre équipe active, avec les limites de votre offre appliquées par le backend LoadFocus exactement comme dans le tableau de bord. La CLI ne fait que ce que vous pourriez faire vous-même dans l'interface.

Comment ça marche

Vous conservez un dossier de petits fichiers YAML (ou JavaScript) — une ressource par fichier — plus un loadfocus.config.yaml qui pointe vers eux. La CLI envoie ces définitions à LoadFocus, qui les associe aux ressources en production, calcule le diff et renvoie un plan. Vous examinez le plan, puis vous l'appliquez.

  • Rédiger — décrivez les ressources sous forme de fichiers (constructs YAML ou JS).
  • Planifierdeploy --dry-run montre exactement ce qui sera créé, mis à jour, adopté ou supprimé.
  • Appliquerdeploy réconcilie votre compte pour qu'il corresponde aux fichiers.
  • Réconcilier l'identité — chaque ressource porte un logicalId stable que vous choisissez. C'est ainsi que la CLI suit une ressource à travers les renommages, de sorte que changer le nom d'affichage d'une vérification ne la recrée jamais.

Installation

La CLI est un package Node (Node 18+). Exécutez-la à la demande avec npx :

npx @loadfocus/monitoring --help

…ou installez-la globalement pour obtenir la commande loadfocus-monitoring :

npm install -g @loadfocus/monitoring
loadfocus-monitoring --help

Authentification

La CLI s'authentifie avec une clé d'API LoadFocus et un id d'équipe. Trouvez votre clé d'API dans le tableau de bord sous les paramètres de votre compte/API, et votre id d'équipe sur la page des équipes.

Connectez-vous une fois et les identifiants sont enregistrés dans ~/.loadfocus/config.json :

loadfocus-monitoring login
loadfocus-monitoring whoami # confirm who you are and which team you're targeting

Pour la CI, préférez les variables d'environnement (elles ont priorité sur la configuration enregistrée et ne touchent jamais le disque) :

export LOADFOCUS_API_KEY="apikey_xxxxxxxx"
export TEAM_ID="team_xxxxxxxx"
# optional: export API_URL="https://apimonitor.loadfocus.com"

Créer un projet

Générez un fichier de configuration et un moniteur d'exemple dans votre dépôt :

loadfocus-monitoring init

Cela écrit 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 délimite tout ce que la CLI gère. Les ressources d'un projet sont réconciliées ensemble ; tout ce qui est dans le projet et qui ne figure plus dans vos fichiers est supprimé au deploy. Utilisez des projets distincts pour gérer des ensembles de moniteurs indépendants.
  • checkMatch est le ou les globs de vos fichiers de rédaction.
  • defaults renseigne schedule, locations et alertChannels pour les vérifications qui les omettent.

Le workflow

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 <logicalId> # run a check now
loadfocus-monitoring destroy # delete everything managed in the project

deploy est sûr par défaut : il montre le plan et, lorsqu'il est exécuté de manière interactive, demande avant de supprimer quoi que ce soit. En CI (non interactif), il refuse de supprimer sans --yes et se termine avec un code clair plutôt que de rester bloqué sur une invite. Ajoutez --json aux commandes de lecture/résultat pour une sortie exploitable par machine.

Adopter des moniteurs existants

Vous avez déjà des moniteurs dans le tableau de bord ? Importez-les dans des fichiers au lieu de les recréer :

loadfocus-monitoring import --project my-project --out monitors

Cela écrit un fichier par ressource et un loadfocus.config.yaml. Examinez, validez (commit), puis exécutez deploy --dry-run — les ressources correspondantes sont adoptées sur place (prises en gestion) plutôt que dupliquées.

Ressources

Chaque ressource est un fichier avec un kind, un logicalId (votre identifiant stable) et les champs propres à ce kind. Les références entre ressources utilisent des logicalId (ou des noms pour les canaux d'alerte) — le serveur les résout, et l'ordre de déploiement est géré pour vous.

Vérifications

Un seul kind Monitor couvre chaque type de vérification via type : api, browser, multistep, tcp, heartbeat.

kind: check
type: api
logicalId: home
name: Home API
schedule: "300" # seconds between runs
locations: [us-east-1, eu-west-1]
request:
url: "https://example.com/health"
method: GET
assertions:
- { type: statusCode, comparison: equals, value: 200 }
- { type: responseTime, comparison: lessThan, value: 1000 }
  • api — requête HTTP avec des assertions sur le statut, le corps, les en-têtes, le temps de réponse, l'expiration SSL.
  • browser — un script de parcours utilisateur Playwright avec captures d'écran et chronométrages par étape (payant).
  • multistep — une séquence ordonnée de requêtes API qui passent des données entre les étapes.
  • tcp — une vérification de port/joignabilité depuis plusieurs régions.
  • heartbeat — un dispositif d'homme mort : un job externe ping une URL selon une planification, et LoadFocus alerte si un ping est manqué.

Groupes

Partagez les régions, les canaux d'alerte, la fréquence et l'activation entre plusieurs vérifications. Une vérification rejoint un groupe avec group: <logicalId>.

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

Règles d'alerte

Alerter quand une métrique d'une vérification franchit un seuil.

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

Canaux d'alerte

Gérez les canaux de notification en tant que code et référencez-les par leur nom depuis une vérification, un groupe ou une règle d'alerte. Types (type) pris en charge : email, slack, microsoftteams, webhook, discord, pagerduty, opsgenie. Les champs secrets (webhookUrl, routingKey, apiKey) acceptent une référence {{secrets.NAME}} — la valeur est stockée avec env set-secret et résolue lors de l'envoi d'une alerte, jamais versionnée dans vos fichiers.

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

Fenêtres de maintenance

Supprimer les alertes pendant des travaux planifiés. Les horaires sont en UTC. startsAt / endsAt acceptent une chaîne ISO-8601 (par ex. "2026-07-01T00:00:00Z") ou des millisecondes 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=Sun6=Sat
targets:
allChecks: false
checkIds: [home] # by logicalId

Tableaux de bord

Une vue partagée de vérifications sélectionnées, éventuellement publique via un slug.

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

Pages de statut

Une page de statut publique à <slug>.loadfoc.us, éventuellement sur votre propre domaine personnalisé.

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 domaine personnalisé est mis en service une fois que vous créez le CNAME et que le certificat est émis — deploy le déclare ; la vérification se fait hors bande.

Variables

Valeurs non secrètes (URLs de base, identifiants) que les vérifications référencent au moment de l'exécution via {{vars.NAME}}. Le logicalId est la clé de la variable. (Pour les secrets, utilisez env set-secret — ne les placez jamais dans des fichiers.)

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

Rédiger en JavaScript ou TypeScript

Si vous préférez le code au YAML, construisez les mêmes définitions de manière programmatique et exportez-les — les constructs produisent des ressources identiques :

const { Monitor, Group, AlertRule, Maintenance, Dashboard, StatusPage, AlertChannel, Variable } = require('@loadfocus/monitoring');
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'] });

Pointez checkMatch vers vos fichiers .js et la CLI les charge comme n'importe quelle autre ressource.

Secrets et variables

Référencez des valeurs depuis vos vérifications sans les versionner. Les secrets (jetons, mots de passe) sont gérés uniquement de manière impérative et référencés via {{secrets.NAME}} dans les champs de vérification et les champs secrets des canaux d'alerte. Les variables (non secrètes) peuvent être déclarées sous forme de fichiers (kind: variable, ci-dessus) ou définies de manière impérative, et sont référencées via {{vars.NAME}}.

loadfocus-monitoring env set-secret API_TOKEN "s3cr3t"
loadfocus-monitoring env set-variable BASE_URL "https://example.com"
loadfocus-monitoring env ls # list secret + variable keys (values never shown)

L'exécuter en CI

Un pipeline typique valide à chaque pull request et déploie à la fusion sur la branche principale.

# .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 }}
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

Bon à savoir

  • logicalId est l'identité. Gardez-le stable. Vous pouvez renommer librement le name ou le title d'une vérification ; changer son logicalId est traité comme la suppression d'une ressource et la création d'une autre.
  • Les suppressions sont limitées au projet. deploy ne retire que les ressources du project courant qui ne figurent plus dans vos fichiers — jamais quoi que ce soit dans un autre projet ou créé en dehors de Monitoring as Code (jusqu'à ce que vous l'adoptiez).
  • Les slugs de page de statut sont globaux. slug devient un sous-domaine, il doit donc être unique parmi tous les clients LoadFocus.
  • Les fonctionnalités payantes échouent bruyamment. Une équipe gratuite qui déclare un champ réservé aux offres payantes (un domaine personnalisé de page de statut, la suppression du badge « Powered by ») reçoit une erreur claire au deploy plutôt qu'un résultat partiel silencieux.
  • Les limites d'offre s'appliquent. Créer des ressources via la CLI est soumis aux mêmes quotas d'offre que le tableau de bord.

Associés