Aller au contenu

DevOps — SLO, chaîne d'approvisionnement, observabilité LLM

1. SLO + error budget par application

Dans le tableau de bord

  1. Sidebar → Apps → cliquer votre application → onglet SLO
  2. Bouton ‘Define SLO’ → target 0.999 + fenêtre 30 jours
  3. Sparkline burn-down apparaît dans le même onglet
  4. Bouton ‘Embed badge’ copie markdown pour README

Définissez une application et liez-y des metrics :

Ou via API (avancé — pour automatisation)

Fenêtre de terminal
curl -X POST https://app.monsys.ai/api/v1/apps \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "checkout-api",
"type": "http",
"agent_id": "<agent_uuid_of_web_lb>",
"endpoint": "https://checkout.example.com/healthz",
"interval_seconds": 30
}'

Définissez SLO + fenêtre :

Fenêtre de terminal
curl -X POST https://app.monsys.ai/api/v1/apps/<app_id>/slo \
-H "Authorization: Bearer $TOKEN" \
-d '{
"target": 0.999,
"window_days": 30,
"minimum_data": 0.95
}'

/operations/mttr affiche par application :

  • Uptime rolling 30j actuel (% et minutes-down)
  • Error budget restant (en minutes)
  • Sparkline burn-down (taux actuel vs cible)
  • “Jours avant épuisement du budget” si vous continuez à brûler au rythme de cette semaine

Pour votre sprint review : récupérez le CSV SLO via /api/v1/apps/<id>/slo/history?days=90. Pour votre deploy-gate, vérifiez que le burn rate était < 2.0 dans la dernière heure.


2. Alerte Slack/ntfy quand un conteneur redémarre > 3× en une heure

Dans le tableau de bord

  1. Sidebar → Settings → Alert rules → ‘Nouvelle règle’
  2. Metric : container_restart_count, opérateur >, seuil 3, window 1h
  3. Champ webhook URL : https://hooks.slack.com/services/T0/B0/xxx
  4. WebhookDispatchWorker fait retries + ne lâche jamais secrets

monsys.ai ne poste pas directement sur Slack — il poste sur ntfy (self-host) ou via un webhook. Exemple webhook Slack :

Ou via API (avancé — pour automatisation)

Fenêtre de terminal
curl -X POST https://app.monsys.ai/api/v1/alert-rules \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "Container flapping",
"metric": "container_restart_count",
"operator": ">",
"threshold": 3,
"window": "1h",
"severity": "warning",
"group_by": ["agent_id", "container_name"],
"webhook_url": "https://hooks.slack.com/services/T0/B0/xxx"
}'

WebhookDispatchWorker fait le POST sortant avec un body JSON minimal ({title, severity, agent, link}) — pas de contenu de prompts ni de secrets. Retries 3× avec backoff. Logs dans /audit-log event_type webhook_delivery.


3. Auto-update des deps npm vulnérables, mais pinner notre driver DB

Dans le tableau de bord

  1. Sidebar → Recommandations → onglet ‘Application CVEs’
  2. Par package vulnérable : bouton ‘Auto-update’ ou ‘3-points → Suppress this fix’
  3. Sur suppression : saisir expires_at + raison
  4. Future Auto-update-all montre skip avec raison dans les preuves mensuelles

Le scanning CVE des dépendances applicatives tourne toutes les heures. Ouvrez /recommendations → “Application CVEs” → mettons que vous voyez 12 paquets avec des fixes disponibles.

Cliquez “Auto-update all” — conditions :

  • TOTP requis
  • Plafonné à 25 EATs par clic (évite un blast sur toute la flotte)
  • Par (project, ecosystem) chaque hôte reçoit un EAT avec la liste combinée

Pour pinner un paquet (par ex. mysql2@2.3.0 car 2.4.x a un ABI break) ? Ajoutez une suppression :

Ou via API (avancé — pour automatisation)

Fenêtre de terminal
curl -X POST https://app.monsys.ai/api/v1/cve-suppressions \
-H "Authorization: Bearer $TOKEN" \
-d '{
"package_name": "mysql2",
"ecosystem": "npm",
"version_range": ">=2.4.0",
"reason": "ABI break — see PROD-123 ticket",
"expires_at": "2026-09-01"
}'

Les futurs auto-update-all sautent cet upgrade ET notent dans les preuves qu’il a été sauté avec la raison fournie.


4. Détecter un changement de mainteneur npm (indicateur d’attaque chaîne d’approvisionnement)

Dans le tableau de bord

  1. Sidebar → Inventaire → onglet Dependencies → filtre ‘Maintainer changed (7d)’
  2. Par package : maintainer set actuel + précédent
  3. Cliquer package suspect → ‘Pin version’ ou ‘Investigate’
  4. Hit déclenche automatiquement webhook vers outillage incident

Depuis schema 076 monsys trace l’ensemble des publish-emails par paquet npm dont vous dépendez. Changement = alerte.

Ou via API (avancé — pour automatisation)

SELECT package_name,
ecosystem,
maintainers,
deprecated,
last_maintainer_change_at,
seen_at
FROM supply_chain_maintainer_cache
WHERE tenant_id = $1::UUID
AND last_maintainer_change_at >= NOW() - INTERVAL '7 days'
ORDER BY last_maintainer_change_at DESC;

Workflow sur un hit :

  1. Vérifier si le nouveau mainteneur est un collaborateur d’org légitime (souvent oui → accepter le changement dans l’UI)
  2. Sinon : pinner la version actuelle via cve_suppressions + ouvrir un ticket upstream
  3. Optionnel : déclencher un EAT IsolateNetwork sur les hôtes staging qui ont déjà installé le paquet

5. Config Terraform-managed vs drift detection

Dans le tableau de bord

  1. Sidebar → Settings → API tokens → générer token scoped readonly
  2. Sidebar → AI Insights → ‘Deploy gate template’ → copier snippet bash
  3. Coller dans CI yaml avant l’étape deploy
  4. Tester avec —dry-run — affiche Trust Score + alertes critiques ouvertes

On suppose que Terraform est la source de vérité pour /etc/ssh/sshd_config. Drift = quelqu’un a fait une modification manuelle.

Ou via API (avancé — pour automatisation)

Fenêtre de terminal
# Après chaque terraform apply réussi : bumper la baseline
curl -X POST https://app.monsys.ai/api/v1/agents/<id>/config-hashes/rebase \
-H "Authorization: Bearer $TOKEN" \
-d '{
"paths": ["/etc/ssh/sshd_config", "/etc/nginx/nginx.conf"],
"reason": "terraform apply commit 7a3c…"
}'

Drift dans les 7 jours après un rebase baseline par quelqu’un d’autre que le service-user Terraform = ticket automatique dans votre issue tracker via WebhookDispatch.


6. Coût LLM par équipe via SDK

Dans le tableau de bord

  1. Sidebar → AI → onglet ‘Par équipe’
  2. Groupement par défaut sur tag ‘team’ du SDK
  3. Filtre descending sur coût OU latence p95
  4. Bouton ‘Export CSV mois’ pour cross-charge financière

Ou via API (avancé — pour automatisation)

# Dans votre service Python
from monsys_ai import MonsysClient
client = MonsysClient(
hub_url="https://hub.monsys.ai",
api_key=os.environ["MONSYS_AI_TOKEN"],
tenant="acme",
team="checkout", # → tag sur chaque trace
)
with client.trace("price-lookup") as t:
resp = openai.chat.completions.create(...)
t.add_llm_call(
model=resp.model,
prompt_tokens=resp.usage.prompt_tokens,
completion_tokens=resp.usage.completion_tokens,
)

Dans /ai/quadrant vous voyez par équipe : coût, latence p95, top 3 modèles, taux de refus. Export CSV pour la cross-charge mensuelle.

La redaction PII se fait dans le SDK, pas au hub. L’agent ne voit jamais le prompt brut — uniquement les compteurs de tokens et un hash SHA256 du prompt pour le dédup.


7. Deploy gate : bloquer la release si une alerte critique est ouverte

Dans le tableau de bord

  1. Sidebar → Webhooks → ‘Register endpoint’
  2. URL + HMAC secret partagé + events filter (alert.created, alert.resolved)
  3. Min severity = warning + agent_filter sur tag
  4. Retries 3× avec backoff ; failures atterrissent dans audit_log

Pour votre pipeline CI :

Ou via API (avancé — pour automatisation)

#!/usr/bin/env bash
# Avant `helm upgrade` / `kubectl apply` etc.
OPEN_CRITICAL=$(curl -s \
"https://app.monsys.ai/api/v1/alerts?severity=critical&is_resolved=false&tag=production" \
-H "Authorization: Bearer $MONSYS_TOKEN" | jq '. | length')
if [[ "$OPEN_CRITICAL" -gt 0 ]]; then
echo "✗ refusing deploy: $OPEN_CRITICAL critical alerts open on production"
exit 1
fi
# Gate Trust Score
SCORE=$(curl -s "https://app.monsys.ai/api/v1/trust-score/v12/tenant" \
-H "Authorization: Bearer $MONSYS_TOKEN" | jq '.final_score')
if [[ "$SCORE" -lt 70 ]]; then
echo "✗ refusing deploy: Trust Score $SCORE/100 below threshold 70"
exit 1
fi
echo "✓ Trust Score $SCORE, no open critical alerts — proceeding"

Évite l’anti-pattern “deploy maintenant, regarder les alertes plus tard”.


8. Intégration webhook avec votre propre outillage incident-response

Dans le tableau de bord

  1. Sidebar → Settings → ‘Embed badge’ (panneau Trust Score)
  2. Copier URL SVG avec votre tenant_id
  3. Coller markdown dans README ou status-page interne
  4. Mise à jour toutes les 30 min, pas de JS, pas de tracking

WebhookDispatchWorker fait un POST sur chaque alerte avec severity ≥ warning. Enregistrez un endpoint custom :

Ou via API (avancé — pour automatisation)

Fenêtre de terminal
curl -X POST https://app.monsys.ai/api/v1/webhooks \
-H "Authorization: Bearer $TOKEN" \
-d '{
"url": "https://incidents.acme.com/api/v1/intake",
"secret": "shared-hmac-secret",
"events": ["alert.created","alert.resolved"],
"min_severity": "warning",
"agent_filter": {"tag":"production"}
}'

Forme du body :

{
"event": "alert.created",
"alert": {
"id": "",
"severity": "critical",
"category": "cpu",
"title": "Host CPU > 95% sustained 10min",
"agent": { "id": "", "hostname": "web-03", "tags": ["production"] }
},
"tenant_id": "",
"timestamp": "2026-05-19T20:34:00Z"
}

Headers :

  • X-Monsys-Signature: sha256=… (HMAC sur body avec secret)
  • X-Monsys-Delivery: <uuid> (clé d’idempotence)
  • X-Monsys-Event: alert.created

Retries : 3× avec backoff exponentiel (10s / 60s / 5min). L’échec final atterrit dans /audit-log comme webhook_delivery_failed et votre endpoint passe en cooldown 10 min pour éviter les hot loops.


9. Badge Trust Score dans votre README/dashboard

Ou via API (avancé — pour automatisation)

![Trust Score](https://badge.monsys.ai/tenant/<tenant_id>/trust-score.svg)

SVG server-rendered. Mise à jour toutes les 30 minutes (cycle worker Trust Score). Le badge colorie par bande : <50 rouge, 50-70 orange, 70-85 vert, >85 vert foncé. Pas de JavaScript, pas de tracking — rendu directement depuis TimescaleDB.

Tip pour orgs multi-tenant : par repo, utilisez le tenant id du projet (DEV, STG, PROD séparés) et mettez 3 badges côte à côte — visible immédiatement si staging diffère de production.