Recettes

Surveiller une page et être alerté

Vérifiez une page toutes les 15 minutes et n'alertez Slack que lorsque son état change.

Vérifiez une page ou une API publique toutes les 15 minutes, demandez à l'agent de rapporter ce qu'il trouve en JSON, et publiez sur Slack uniquement lorsque l'état change. Ephemeral exécute la vérification selon une planification ; un petit script de votre côté lit le résultat et décide s'il faut alerter.

Une vérification qui récupère une page prend environ 20 secondes. L'essentiel du coût est le calcul, facturé 0,0002 $ par seconde, plus 0,001 $ pour la récupération de la page. La part du modèle dépend du modèle que vous choisissez : lisez donc cost_micros sur les premières exécutions, puis ajustez la planification ou le modèle.

  1. Rassembler ce qu'il vous faut

    • Une clé API avec le rôle administrateur, car seuls les propriétaires et les administrateurs peuvent créer des planifications. Voir rôles et clés.
    • La page ou l'API à surveiller, sur un seul domaine, ici https://status.example.com.
    • L'URL d'un webhook entrant Slack, ou l'adresse de votre propre service d'alerte.
    • Un endroit où exécuter un script toutes les quelques minutes : cron, une tâche CI planifiée ou un minuteur serverless.
  2. Enregistrer le workflow

    Le workflow récupère la page et répond dans un format JSON fixe. Ephemeral n'impose pas de schéma de sortie : le résultat de l'exécution est du texte libre. Le prompt demande donc uniquement du JSON, et votre script l'analyse avec prudence à l'étape 4.

    curl -X PUT $EPHEMERAL_URL/v1/workflows/check-status-page \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "prompt": "Fetch the page at input.url with web_fetch. Reply with one JSON object and nothing else: {\"ok\": boolean, \"http_status\": number, \"summary\": string}. Set ok to true only when the response status is 200 and the page reports no ongoing incident, outage or degraded service; resolved past incidents do not count. summary is one sentence of at most 200 characters.",
        "web": { "allow": ["status.example.com"], "search": false },
        "shell": false,
        "timeout_seconds": 90
      }'

    L'accès web est limité à status.example.com et la recherche est désactivée : la vérification peut donc lire ce site et rien d'autre. L'URL à vérifier arrive en entrée, si bien que le même workflow peut servir plusieurs planifications sur ce domaine.

  3. Créer la planification

    Prévisualisez d'abord le calendrier. Il renvoie les cinq prochaines heures de lancement et n'enregistre rien.

    curl -X POST $EPHEMERAL_URL/v1/schedules/preview \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "cron": "*/15 * * * *", "timezone": "UTC" }'

    Créez-la ensuite. L'entrée et le budget sont les mêmes pour chaque exécution.

    curl -X POST $EPHEMERAL_URL/v1/schedules \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "workflow": "check-status-page",
        "name": "Status page, every 15 minutes",
        "cron": "*/15 * * * *",
        "input": { "url": "https://status.example.com" },
        "max_cost_micros": 100000
      }'

    Conservez l'id de la planification. Le budget de 100 000 micros (0,10 $) est réservé sur vos crédits à chaque lancement et libéré lorsque l'exécution est réglée ; il doit couvrir le calcul pour toute la durée du délai d'expiration, ici 90 secondes, soit 0,018 $. Si une vérification est encore en cours lorsque le lancement suivant est dû, ce lancement est ignoré, car skip_if_running vaut true par défaut.

  4. En lancer une maintenant et lire la réponse

    N'attendez pas le calendrier. POST /v1/schedules/{id}/run lance le workflow immédiatement avec l'entrée et le budget de la planification et répond 202 avec une exécution qui porte l'ID de la planification. Listez ensuite les exécutions de la planification, de la plus récente à la plus ancienne :

    curl -X POST $EPHEMERAL_URL/v1/schedules/$SCHEDULE_ID/run \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY"
    
    curl "$EPHEMERAL_URL/v1/runs?schedule=$SCHEDULE_ID&limit=1" \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY"

    output est une chaîne qui contient le JSON. Les modèles l'entourent parfois d'un bloc de code ou ajoutent une phrase malgré la consigne : le script ci-dessous prend donc tout ce qui se trouve entre le premier { et le dernier }, et l'analyse.

  5. Alerter uniquement en cas de changement

    Les exécutions planifiées n'envoient pas de callbacks ; votre script demande donc la dernière exécution de la planification. Il mémorise dans un fichier la dernière exécution et le dernier état, ignore les exécutions déjà vues ou encore en cours, et ne publie sur Slack que lorsque l'état diffère du précédent. Une vérification qui échoue ou renvoie quelque chose d'illisible compte comme un état à part, unknown, afin qu'une surveillance en panne ne ressemble pas à une page en bonne santé.

    monitor.mjs (Node.js 18 ou version ultérieure)
    import { readFile, writeFile } from "node:fs/promises";
    
    const { EPHEMERAL_URL, EPHEMERAL_API_KEY, SCHEDULE_ID, SLACK_WEBHOOK_URL } = process.env;
    const ACTIVE = new Set(["reserving", "queued", "starting", "running"]);
    const stateFile = "monitor-state.json";
    const state = JSON.parse(await readFile(stateFile, "utf8").catch(() => "{}"));
    
    const response = await fetch(`${EPHEMERAL_URL}/v1/runs?schedule=${SCHEDULE_ID}&limit=1`, {
      headers: { Authorization: `Bearer ${EPHEMERAL_API_KEY}` },
    });
    if (!response.ok) throw new Error(`Ephemeral returned ${response.status}`);
    const [run] = (await response.json()).items;
    if (!run || ACTIVE.has(run.status) || run.id === state.run) process.exit(0); // nothing new to judge
    
    let label = "unknown"; // the check itself did not produce an answer
    let summary = run.error ?? `The run ${run.status}.`;
    if (run.status === "succeeded") {
      try {
        const result = JSON.parse(run.output.match(/\{[\s\S]*\}/)[0]); // tolerate text or a code fence around the JSON
        label = result.ok === true ? "ok" : "down";
        summary = result.summary;
      } catch {
        summary = "The check did not return valid JSON.";
      }
    }
    
    if (label !== (state.label ?? "ok")) {
      await fetch(SLACK_WEBHOOK_URL, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ text: `Status page: ${label}. ${summary} (${run.id})` }),
      });
    }
    await writeFile(stateFile, JSON.stringify({ run: run.id, label }));

    Exécutez-le toutes les cinq minutes, par exemple avec */5 * * * * dans cron, avec les quatre variables définies. La première vérification reste silencieuse lorsque la page est saine ; chaque changement ultérieur, y compris le retour de down à ok, publie une seule fois.

À savoir

SujetComportement
Vérifications qui se chevauchentAvec skip_if_running activé, un lancement est ignoré tant que l'exécution précédente est en cours, et la planification le consigne dans last_error. Ne le définissez sur false que si le chevauchement est sans danger.
Une planification qui s'arrêteAprès cinq échecs de lancement consécutifs, par exemple parce que les crédits sont épuisés, la planification se désactive d'elle-même et aucune nouvelle exécution n'apparaît. Vérifiez de temps en temps enabled et last_error avec GET /v1/schedules/{id}, ou rechargez des crédits et définissez enabled sur true.
Modifier l'intervallePATCH /v1/schedules/{id} avec un nouveau cron ; le prochain lancement est calculé à partir de maintenant.
Mettre en pauseephemeral schedules pause ID et resume, ou enabled dans un PATCH.
Gardez la vérification en lecture seule
Ce workflow n'a ni connexion ni shell, et l'accès web ne couvre qu'un seul domaine. Comme c'est l'exécution qui décide de ce qu'elle rapporte, considérez sa réponse comme un signal à examiner, pas comme une commande à exécuter automatiquement.
Vous préférez un callback ?
Si vous préférez recevoir un callback signé plutôt que d'interroger, lancez les exécutions depuis votre propre planificateur avec POST /v1/runs, le même workflow et un callback. Le récepteur est celui de la recette d'investigation de paiement. Vous renoncez alors à la protection contre le chevauchement et au calendrier d'Ephemeral : gardez donc les planifications pour le travail que vous n'avez pas besoin de pousser.
© 2026 EphemeralRéalisé par erni.works
esc

Aucun résultat pour « ».