Monitoring as Code
Mit Monitoring as Code definieren Sie Ihr LoadFocus-Monitoring-Setup als versionierte Dateien und wenden es von der Kommandozeile oder aus CI an, genauso, wie Sie Infrastruktur mit Terraform oder Pulumi verwalten. Sie beschreiben die Monitore, Gruppen, Benachrichtigungen, Wartungsfenster, Dashboards und Statusseiten, die Sie haben möchten; die @loadfocus/monitoring CLI ermittelt den Unterschied zum Live-Zustand und gleicht ihn ab (erstellen, aktualisieren, löschen).
Es ist deklarativ und idempotent: Wenn Sie deploy zweimal ausführen, ändert sich beim zweiten Mal nichts. Ihre Dateien sind die einzige Quelle der Wahrheit, sodass Änderungen über Pull Requests laufen und Ihr Monitoring-Verlauf in Git lebt.
Alles läuft in Ihrem Konto und Ihrem aktiven Team, wobei Ihre Plan-Limits vom LoadFocus-Backend genauso durchgesetzt werden wie im Dashboard. Die CLI tut nur, was Sie auch selbst in der Oberfläche tun könnten.
Wie es funktioniert
Abschnitt betitelt „Wie es funktioniert“Sie pflegen einen Ordner mit kleinen YAML- (oder JavaScript-) Dateien, eine Ressource pro Datei, sowie eine loadfocus.config.yaml, die auf sie verweist. Die CLI sendet diese Definitionen an LoadFocus, das sie auf Live-Ressourcen abbildet, vergleicht und einen Plan zurückgibt. Sie prüfen den Plan und wenden ihn dann an.
- Verfassen: Beschreiben Sie Ressourcen als Dateien (YAML- oder JS-Konstrukte).
- Planen:
deploy --dry-runzeigt genau, was erstellt, aktualisiert, übernommen oder gelöscht wird. - Anwenden:
deploygleicht Ihr Konto so ab, dass es den Dateien entspricht. - Identität abgleichen: jede Ressource trägt eine stabile, von Ihnen gewählte
logicalId. So verfolgt die CLI eine Ressource über Umbenennungen hinweg, sodass das Ändern des Anzeigenamens eines Checks ihn nie neu erstellt.
Installation
Abschnitt betitelt „Installation“Die CLI ist ein Node-Paket (Node 18+). Führen Sie es bei Bedarf mit npx aus:
npx @loadfocus/monitoring --help…oder installieren Sie es global, um den Befehl loadfocus-monitoring zu erhalten:
npm install -g @loadfocus/monitoringloadfocus-monitoring --helpAuthentifizierung
Abschnitt betitelt „Authentifizierung“Die CLI authentifiziert sich mit einem LoadFocus-API-Schlüssel und einer Team-ID. Beides finden Sie auf der Entwicklerseite, die Ihren API-Schlüssel und Ihre Team-ID zusammen anzeigt, samt MCP-Einrichtung.
Melden Sie sich einmal an, und die Anmeldedaten werden in ~/.loadfocus/config.json gespeichert:
loadfocus-monitoring login --apikey <your-api-key> --teamid <your-team-id>loadfocus-monitoring whoami # confirm who you are and which team you're targetingFür CI sind Umgebungsvariablen vorzuziehen (sie überschreiben die gespeicherte Konfiguration und werden nie auf die Festplatte geschrieben):
export LOADFOCUS_API_KEY="apikey_xxxxxxxx"export LOADFOCUS_TEAM_ID="team_xxxxxxxx"# optional: export LOADFOCUS_API_URL="https://apimonitor.loadfocus.com"Um später einen gespeicherten Wert zu ändern, verwenden Sie config set mit --apikey, --teamid oder --api-url. config show zeigt die Anmeldedaten, die die CLI tatsächlich verwendet, Umgebungsvariablen eingeschlossen; vom API-Schlüssel sind nur die letzten vier Zeichen sichtbar. logout entfernt den gespeicherten API-Schlüssel und die Team-ID aus ~/.loadfocus/config.json.
loadfocus-monitoring config set --teamid <your-team-id> # change one saved valueloadfocus-monitoring config show # credentials in use, API key maskedloadfocus-monitoring logout # remove the saved API key and team idEin Projekt erstellen
Abschnitt betitelt „Ein Projekt erstellen“Erzeugen Sie ein Gerüst aus Konfigurationsdatei und Beispielmonitor in Ihrem Repository:
loadfocus-monitoring initDies schreibt loadfocus.config.yaml:
project: my-project # a namespace for this set of resourcescheckMatch: - "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]projectgrenzt alles ein, was die CLI verwaltet. Ressourcen in einem Projekt werden gemeinsam abgeglichen; alles im Projekt, was nicht mehr in Ihren Dateien steht, wird beideploygelöscht. Nutzen Sie separate Projekte, um unabhängige Monitor-Sets zu verwalten.checkMatchist das Glob (bzw. die Globs) für Ihre Verfassungs-Dateien.defaultsfülltschedule,locationsundalertChannelsfür Checks aus, die sie weglassen.
init überspringt Dateien, die bereits existieren. Mit --force werden sie überschrieben.
Der Workflow
Abschnitt betitelt „Der Workflow“loadfocus-monitoring validate # compile locally + server-side dry-run; great as a PR gateloadfocus-monitoring deploy --dry-run # show the plan (created / updated / adopted / deleted)loadfocus-monitoring deploy # apply itloadfocus-monitoring list # inventory of what's deployed in the projectloadfocus-monitoring list --status # …with each check's latest up/down/degraded statusloadfocus-monitoring get <logicalId> # show one deployed resourceloadfocus-monitoring trigger --id <logicalId> # run a check now (no --id runs every deployed check)loadfocus-monitoring destroy # delete everything managed in the projectdeploy ist standardmäßig sicher: Es zeigt den Plan und fragt bei interaktiver Ausführung nach, bevor es etwas löscht. In CI (nicht-interaktiv) verweigert es das Löschen ohne --yes und beendet sich mit einem klaren Code, statt an einer Eingabeaufforderung zu hängen. Fügen Sie Lese-/Ergebnisbefehlen --json hinzu, um maschinenlesbare Ausgaben zu erhalten.
validate --no-server kompiliert Ihre Dateien nur lokal: Es braucht keine Anmeldedaten und überspringt den Server-Probelauf, eignet sich also für einen Pre-Commit-Hook. deploy verweigert außerdem die Anwendung, wenn checkMatch überhaupt keine Dateien lädt, denn dieser Plan würde jede vom Projekt verwaltete Ressource löschen; meist steckt ein falscher Ordner oder ein Tippfehler in checkMatch dahinter. deploy --dry-run zeigt diesen Plan trotzdem an. Um bewusst alles zu löschen, führen Sie destroy aus oder übergeben --allow-empty an deploy.
Checks testen, ohne zu deployen
Abschnitt betitelt „Checks testen, ohne zu deployen“loadfocus-monitoring testloadfocus-monitoring test --json # machine-readable resultstest führt jeden Check aus Ihren Dateien einmal aus, direkt aus den Dateien, und meldet für jeden, ob er bestanden hat oder fehlgeschlagen ist. Dabei wird nichts gespeichert: Kein Check wird in Ihrem Konto angelegt oder geändert. Schlägt ein Check fehl oder endet er mit einem Fehler, beendet sich der Befehl mit Exit-Code 1, sodass ein CI-Job einen Pull Request blockieren kann, bis die Checks gegen die echten Endpunkte bestehen; ein beeinträchtigtes (degraded) Ergebnis lässt den Lauf nicht scheitern. Projekte mit vielen Checks werden in Paketen zu je 20 gesendet.
Bestehende Monitore übernehmen
Abschnitt betitelt „Bestehende Monitore übernehmen“Sie haben bereits Monitore im Dashboard? Holen Sie sie in Dateien, statt sie neu zu erstellen:
loadfocus-monitoring import --project my-project --out monitorsDies schreibt eine Datei pro Ressource und eine loadfocus.config.yaml. Prüfen, committen und dann deploy --dry-run ausführen: übereinstimmende Ressourcen werden an Ort und Stelle übernommen (unter Verwaltung gestellt), statt dupliziert zu werden.
import überspringt Dateien, die im Ausgabeordner bereits existieren. Mit --force werden sie durch die Version vom Server ersetzt.
Ressourcen
Abschnitt betitelt „Ressourcen“Jede Ressource ist eine Datei mit einem kind, einer logicalId (Ihr stabiler Bezeichner) und den Feldern für dieses kind. Verweise zwischen Ressourcen nutzen logicalIds (oder Namen für Benachrichtigungskanäle), der Server löst sie auf, und die Deploy-Reihenfolge wird für Sie geregelt.
Ein check-kind deckt jeden Check-Typ über type ab: api, browser, multistep, tcp, heartbeat (in JavaScript leistet das Konstrukt Monitor dasselbe).
kind: checktype: apilogicalId: homename: Home APIschedule: "300" # seconds between runslocations: [us-east-1, eu-west-1]tags: [production, payments] # optional labelsrequest: url: "https://example.com/health" method: GETassertions: - { type: statusCode, comparison: equals, value: 200 } - { type: responseTime, comparison: less-than, value: 1000 }- api: HTTP-Anfrage mit Assertions zu Statuscode, Antwortzeit und Body. Die Vergleiche sind
equals,not-equals,greater-than,less-than,equals-or-greater-than,equals-or-less-than,containsundnot-contains. - browser: ein Playwright-User-Flow-Skript mit Screenshots und Zeiten pro Schritt (kostenpflichtig).
- multistep: eine geordnete Folge von API-Anfragen, die Daten zwischen den Schritten weitergeben (kostenpflichtig).
- tcp: eine Port-/Erreichbarkeitsprüfung aus mehreren Regionen (kostenpflichtig).
- heartbeat: ein Totmannschalter: Ein externer Job pingt eine URL nach Zeitplan, und LoadFocus benachrichtigt, wenn ein Ping ausbleibt.
Ein Check kann außerdem tags tragen, dieselben Labels, die Sie in der App neben dem Check-Namen setzen (siehe Tags von Checks). Deployen Sie eine Check-Datei ohne tags, werden die Tags dieses Checks entfernt. In JavaScript behält das Monitor-Konstrukt tags ab CLI-Version 1.0.2; ältere Versionen haben sie verworfen.
Gruppen
Abschnitt betitelt „Gruppen“Teilen Sie Standorte, Benachrichtigungskanäle, Frequenz und Aktivierung über viele Checks hinweg. Ein Check tritt einer Gruppe mit group: <logicalId> bei.
kind: grouplogicalId: webname: Web serviceslocations: [us-east-1, eu-west-1]Benachrichtigungsregeln
Abschnitt betitelt „Benachrichtigungsregeln“Benachrichtigen, wenn die Metrik eines Checks einen Schwellenwert überschreitet.
kind: alertRulelogicalId: home-latencyname: Home API latencycheck: home # reference a check by logicalIdmetric: responseTime # responseTime | statusCode | durationcondition: aboveconditionValue: 1500 # millisecondsBenachrichtigungskanäle
Abschnitt betitelt „Benachrichtigungskanäle“Verwalten Sie Benachrichtigungskanäle als Code und referenzieren Sie sie per Name aus einem Check, einer Gruppe oder einer Benachrichtigungsregel. Unterstützte types: email, slack, microsoftteams, webhook, discord, pagerduty, opsgenie. E-Mail-, Slack-, Teams- und Webhook-Kanäle gibt es in jedem Tarif; Discord, PagerDuty und Opsgenie sind kostenpflichtig. Geheime Felder (webhookUrl, routingKey, apiKey) nehmen eine {{secrets.NAME}}-Referenz entgegen, der Wert wird mit env set-secret gespeichert und beim Senden einer Benachrichtigung aufgelöst, niemals in Ihre Dateien committet.
kind: alertChannellogicalId: oncall # the name checks / groups / alert rules referencetype: pagerdutyroutingKey: "{{secrets.PAGERDUTY_KEY}}"Wartungsfenster
Abschnitt betitelt „Wartungsfenster“Unterdrücken Sie Benachrichtigungen während geplanter Arbeiten. Zeiten sind in UTC. startsAt / endsAt akzeptieren einen ISO-8601-String (z. B. "2026-07-01T00:00:00Z") oder Unix-Millisekunden.
kind: maintenanceWindowlogicalId: weekly-deployname: Weekly deploy windowenabled: truestartsAt: "2026-07-01T00:00:00Z" # ISO-8601 or unix msendsAt: "2026-07-01T02:00:00Z"repeat: weekly # none | daily | weekly | monthlyweekdays: [2] # 0=Sun … 6=Sattargets: allChecks: false checkIds: [home] # by logicalIdDashboards
Abschnitt betitelt „Dashboards“Eine gemeinsame Ansicht ausgewählter Checks, optional öffentlich über einen Slug.
kind: dashboardlogicalId: status-overviewname: Status overviewvisibility: private # private | publicchecks: [home] # by logicalIdwindow: 24h # 24h | 7d | 30dStatusseiten
Abschnitt betitelt „Statusseiten“Eine öffentliche Statusseite unter <slug>.loadfoc.us, optional auf Ihrer eigenen, benutzerdefinierten Domain.
kind: statusPagelogicalId: public-statustitle: Acme Statusslug: acme # -> acme.loadfoc.us (globally unique)enabled: truecustomDomain: status.acme.com # optional, paid; point a CNAME at cname.loadfoc.usgroups: - { id: core, name: Core Services, order: 0 }components: - id: api name: API groupId: core monitors: [home] # checks shown on this component, by logicalIdbranding: brandColor: "#5353a4" colorTheme: darkEine benutzerdefinierte Domain geht live, sobald Sie den CNAME erstellen und das Zertifikat ausgestellt ist, deploy deklariert sie; die Verifizierung erfolgt außerhalb des Ablaufs.
Variablen
Abschnitt betitelt „Variablen“Nicht geheime Werte (Basis-URLs, IDs), die API-Checks zur Laufzeit in URL, Headern, Query-Parametern und Body als ${{NAME}} referenzieren, mit demselben Platzhalter wie Secrets. Die logicalId ist der Variablenschlüssel. (Für Secrets verwenden Sie env set-secret, legen Sie sie niemals in Dateien ab.)
kind: variablelogicalId: BASE_URLvalue: "https://api.example.com"Verfassen in JavaScript oder TypeScript
Abschnitt betitelt „Verfassen in JavaScript oder TypeScript“Wenn Sie Code statt YAML bevorzugen, erstellen Sie dieselben Definitionen programmatisch und exportieren Sie sie, die Konstrukte erzeugen identische Ressourcen:
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'] }),];Exportieren Sie die Konstrukte aus der Datei (ein Array, wie oben) und benennen Sie sie so, dass checkMatch sie findet, zum Beispiel monitors/home.check.js. Die CLI lädt sie wie jede andere Ressource.
Secrets und Variablen
Abschnitt betitelt „Secrets und Variablen“Referenzieren Sie Werte aus Ihren Checks, ohne sie zu committen. Secrets (Tokens, Passwörter) werden ausschließlich imperativ verwaltet und in Check-Feldern (URL, Header, Body) als ${{NAME}} und in geheimen Feldern von Benachrichtigungskanälen als {{secrets.NAME}} referenziert. Variablen (nicht geheim) können als Dateien deklariert (kind: variable, siehe oben) oder imperativ gesetzt werden und werden in den Feldern eines API-Checks genauso als ${{NAME}} referenziert; dort wird ein Platzhalter ohne Dollarzeichen, etwa {{NAME}}, als normaler Text gesendet. Ein Multistep-Check gibt Werte stattdessen zwischen den Schritten weiter: Sein Setup-Skript liest die Variable als ${{NAME}} und legt sie in ctx.vars ab, und die Schritte verwenden sie als {{name}} (siehe Setup- und Teardown-Skripte).
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 secretloadfocus-monitoring env rm-var BASE_URL # delete a variableIn CI ausführen
Abschnitt betitelt „In CI ausführen“Eine typische Pipeline validiert bei jedem Pull Request und deployt beim Merge in den Main-Branch.
name: monitoringon: 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 --yesWissenswertes
Abschnitt betitelt „Wissenswertes“logicalIdist die Identität. Halten Sie sie stabil. Sie könnennameodertitleeines Checks beliebig ändern; das Ändern derlogicalIdwird so behandelt, als würde eine Ressource gelöscht und eine andere erstellt.- Löschungen sind auf das Projekt beschränkt.
deployentfernt nur Ressourcen im aktuellenproject, die nicht mehr in Ihren Dateien stehen, niemals etwas in einem anderen Projekt oder außerhalb von Monitoring as Code Erstelltes (bis Sie es übernehmen). - Statusseiten-Slugs sind global.
slugwird zu einer Subdomain, muss also über alle LoadFocus-Kunden hinweg eindeutig sein. - Kostenpflichtige Funktionen brauchen einen kostenpflichtigen Tarif. Ein kostenloses Team, das eine benutzerdefinierte Statusseiten-Domain deklariert, erhält bei
deployeinen klaren Fehler. Das Entfernen des "Powered by"-Badges wird in einem kostenlosen Tarif nicht angewendet: Das Feld bleibt aus. - Plan-Limits gelten. Das Erstellen von Ressourcen über die CLI unterliegt denselben Plan-Kontingenten wie das Dashboard. Eine Ressource, die ein Kontingent überschreiten würde, wird als abgelehnt gemeldet, und der Rest des Deployments läuft weiter.