Monitoring as Code

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

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).
  • Planendeploy --dry-run zeigt genau, was erstellt, aktualisiert, übernommen oder gelöscht wird.
  • Anwendendeploy gleicht 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

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/monitoring
loadfocus-monitoring --help

Authentifizierung

Die CLI authentifiziert sich mit einem LoadFocus-API-Schlüssel und einer Team-ID. Ihren API-Schlüssel finden Sie im Dashboard unter Ihren Konto-/API-Einstellungen und Ihre Team-ID auf der Teams-Seite.

Melden Sie sich einmal an, und die Anmeldedaten werden in ~/.loadfocus/config.json gespeichert:

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

Für CI sind Umgebungsvariablen vorzuziehen (sie überschreiben die gespeicherte Konfiguration und werden nie auf die Festplatte geschrieben):

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

Ein Projekt erstellen

Erzeugen Sie ein Gerüst aus Konfigurationsdatei und Beispielmonitor in Ihrem Repository:

loadfocus-monitoring init

Dies schreibt 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 grenzt alles ein, was die CLI verwaltet. Ressourcen in einem Projekt werden gemeinsam abgeglichen; alles im Projekt, was nicht mehr in Ihren Dateien steht, wird bei deploy gelöscht. Nutzen Sie separate Projekte, um unabhängige Monitor-Sets zu verwalten.
  • checkMatch ist das Glob (bzw. die Globs) für Ihre Verfassungs-Dateien.
  • defaults füllt schedule, locations und alertChannels für Checks aus, die sie weglassen.

Der 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 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.

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 monitors

Dies 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.

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.

Checks

Ein Monitor-kind deckt jeden Check-Typ über type ab: 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 — HTTP-Anfrage mit Assertions zu Status, Body, Headern, Antwortzeit, SSL-Ablauf.
  • 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.
  • tcp — eine Port-/Erreichbarkeitsprüfung aus mehreren Regionen.
  • heartbeat — ein Totmannschalter: Ein externer Job pingt eine URL nach Zeitplan, und LoadFocus benachrichtigt, wenn ein Ping ausbleibt.

Gruppen

Teilen Sie Standorte, Benachrichtigungskanäle, Frequenz und Aktivierung über viele Checks hinweg. Ein Check tritt einer Gruppe mit group: <logicalId> bei.

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

Benachrichtigungsregeln

Benachrichtigen, wenn die Metrik eines Checks einen Schwellenwert überschreitet.

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

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. 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: alertChannel
logicalId: oncall # the name checks / groups / alert rules reference
type: pagerduty
routingKey: "{{secrets.PAGERDUTY_KEY}}"

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: 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

Dashboards

Eine gemeinsame Ansicht ausgewählter Checks, optional öffentlich über einen Slug.

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

Statusseiten

Eine öffentliche Statusseite unter <slug>.loadfoc.us, optional auf Ihrer eigenen, benutzerdefinierten Domain.

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

Eine 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

Nicht geheime Werte (Basis-URLs, IDs), die Checks zur Laufzeit als {{vars.NAME}} referenzieren. Die logicalId ist der Variablenschlüssel. (Für Secrets verwenden Sie env set-secret — legen Sie sie niemals in Dateien ab.)

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

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');
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'] });

Lassen Sie checkMatch auf Ihre .js-Dateien zeigen, und die CLI lädt sie wie jede andere Ressource.

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 sowie 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 als {{vars.NAME}} referenziert.

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)

In CI ausführen

Eine typische Pipeline validiert bei jedem Pull Request und deployt beim Merge in den Main-Branch.

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

Wissenswertes

  • logicalId ist die Identität. Halten Sie sie stabil. Sie können name oder title eines Checks beliebig ändern; das Ändern der logicalId wird so behandelt, als würde eine Ressource gelöscht und eine andere erstellt.
  • Löschungen sind auf das Projekt beschränkt. deploy entfernt nur Ressourcen im aktuellen project, 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. slug wird zu einer Subdomain, muss also über alle LoadFocus-Kunden hinweg eindeutig sein.
  • Kostenpflichtige Funktionen scheitern laut. Ein kostenloses Team, das ein nur kostenpflichtiges Feld deklariert (eine benutzerdefinierte Statusseiten-Domain, das Entfernen des "Powered by"-Badges), erhält bei deploy einen klaren Fehler statt eines stillschweigend unvollständigen Ergebnisses.
  • Plan-Limits gelten. Das Erstellen von Ressourcen über die CLI unterliegt denselben Plan-Kontingenten wie das Dashboard.

Verwandt