Monitor the platform
A monitoring probe built for cron, CI gates, and alerting scripts. It layers the health endpoints (no credentials, no lockout risk) with one authenticated GET /topology call as the key-validity probe, and reports through exit codes:
| Exit code | Meaning | Suggested action |
|---|---|---|
0 | Platform healthy, key valid | Nothing. |
1 | Reachable, but a subsystem is degraded | Page on sustained failures. |
2 | Platform unreachable | Page; check network egress first. |
3 | API key rejected (401) | Alert the integration owner; do not auto-retry (lockout risk). |
The whole run is 5 requests, well inside the per-IP budget of 30/minute at a one-minute cadence. If several monitors share an egress IP, stagger them. Set CONSTELLATION_API_BASE and CONSTELLATION_API_TOKEN first (common setup).
- TypeScript
- Python
- Go
- cURL
const BASE = process.env.CONSTELLATION_API_BASE ?? 'https://api.constellation.space'
const TOKEN = process.env.CONSTELLATION_API_TOKEN
if (!TOKEN) {
console.error('CONSTELLATION_API_TOKEN is not set')
process.exit(3)
}
type Health = { status?: string; checks?: Record<string, { ok?: boolean; detail?: string }> }
function isHealthy(body: Health): boolean {
if (body.status !== 'ok') return false
return !Object.values(body.checks ?? {}).some((c) => c.ok === false)
}
async function probe(path: string, headers?: Record<string, string>) {
try {
const res = await fetch(`${BASE}${path}`, { headers, signal: AbortSignal.timeout(8000) })
return { status: res.status, json: (await res.json().catch(() => null)) as Health | null }
} catch {
return { status: 0, json: null }
}
}
// 1. Reachability: /health must answer 200 with a healthy body.
const health = await probe('/health')
if (health.status !== 200 || !health.json || !isHealthy(health.json)) {
console.error(`platform unreachable or unhealthy at ${BASE} (status ${health.status})`)
process.exit(2)
}
// 2. Subsystems: 503 means degraded.
let degraded = false
for (const sub of ['telemetry', 'topology', 'predictions']) {
const res = await probe(`/health/${sub}`)
const ok = res.status === 200 && res.json != null && isHealthy(res.json)
console.log(`${sub}: ${ok ? 'healthy' : `DEGRADED (status ${res.status})`}`)
if (!ok) degraded = true
}
// 3. Key validity: authed topology read with a small window.
const auth = await probe('/topology?freshness_seconds=900', { 'x-api-key': TOKEN })
if (auth.status === 401) {
console.error('API key rejected (401)')
process.exit(3)
}
if (auth.status !== 200) {
console.error(`authenticated probe failed (status ${auth.status})`)
degraded = true
} else {
const tenant = (auth.json as { tenant_key?: string } | null)?.tenant_key ?? 'unknown'
console.log(`auth: ok (tenant ${tenant})`)
}
process.exit(degraded ? 1 : 0)
import os
import sys
import requests
BASE = os.environ.get("CONSTELLATION_API_BASE", "https://api.constellation.space")
TOKEN = os.environ.get("CONSTELLATION_API_TOKEN")
if not TOKEN:
sys.exit(3)
def probe(path, headers=None):
try:
resp = requests.get(f"{BASE}{path}", headers=headers, timeout=8)
try:
return resp.status_code, resp.json()
except ValueError:
return resp.status_code, None
except requests.RequestException:
return 0, None
def is_healthy(body):
if not isinstance(body, dict) or body.get("status") != "ok":
return False
checks = body.get("checks") or {}
return not any(c.get("ok") is False for c in checks.values() if isinstance(c, dict))
# 1. Reachability.
status, body = probe("/health")
if status != 200 or not is_healthy(body):
print(f"platform unreachable or unhealthy at {BASE} (status {status})", file=sys.stderr)
sys.exit(2)
# 2. Subsystems.
degraded = False
for sub in ("telemetry", "topology", "predictions"):
status, body = probe(f"/health/{sub}")
ok = status == 200 and is_healthy(body)
print(f"{sub}: {'healthy' if ok else f'DEGRADED (status {status})'}")
degraded = degraded or not ok
# 3. Key validity.
status, body = probe("/topology?freshness_seconds=900", headers={"x-api-key": TOKEN})
if status == 401:
print("API key rejected (401)", file=sys.stderr)
sys.exit(3)
if status != 200:
print(f"authenticated probe failed (status {status})", file=sys.stderr)
degraded = True
else:
tenant = body.get("tenant_key", "unknown") if isinstance(body, dict) else "unknown"
print(f"auth: ok (tenant {tenant})")
sys.exit(1 if degraded else 0)
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"time"
)
type check struct {
OK *bool `json:"ok"`
}
type health struct {
Status string `json:"status"`
Checks map[string]check `json:"checks"`
}
var client = &http.Client{Timeout: 8 * time.Second}
func probe(base, path string, headers map[string]string) (int, []byte) {
req, err := http.NewRequest(http.MethodGet, base+path, nil)
if err != nil {
return 0, nil
}
for k, v := range headers {
req.Header.Set(k, v)
}
resp, err := client.Do(req)
if err != nil {
return 0, nil
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
return resp.StatusCode, body
}
func isHealthy(body []byte) bool {
var h health
if json.Unmarshal(body, &h) != nil || h.Status != "ok" {
return false
}
for _, c := range h.Checks {
if c.OK != nil && !*c.OK {
return false
}
}
return true
}
func main() {
base := os.Getenv("CONSTELLATION_API_BASE")
if base == "" {
base = "https://api.constellation.space"
}
token := os.Getenv("CONSTELLATION_API_TOKEN")
if token == "" {
fmt.Fprintln(os.Stderr, "CONSTELLATION_API_TOKEN is not set")
os.Exit(3)
}
// 1. Reachability.
status, body := probe(base, "/health", nil)
if status != 200 || !isHealthy(body) {
fmt.Fprintf(os.Stderr, "platform unreachable or unhealthy at %s (status %d)\n", base, status)
os.Exit(2)
}
// 2. Subsystems.
degraded := false
for _, sub := range []string{"telemetry", "topology", "predictions"} {
status, body := probe(base, "/health/"+sub, nil)
ok := status == 200 && isHealthy(body)
if ok {
fmt.Printf("%s: healthy\n", sub)
} else {
fmt.Printf("%s: DEGRADED (status %d)\n", sub, status)
degraded = true
}
}
// 3. Key validity.
status, body = probe(base, "/topology?freshness_seconds=900", map[string]string{"x-api-key": token})
switch {
case status == 401:
fmt.Fprintln(os.Stderr, "API key rejected (401)")
os.Exit(3)
case status != 200:
fmt.Fprintf(os.Stderr, "authenticated probe failed (status %d)\n", status)
degraded = true
default:
var topo struct {
TenantKey string `json:"tenant_key"`
}
_ = json.Unmarshal(body, &topo)
fmt.Printf("auth: ok (tenant %s)\n", topo.TenantKey)
}
if degraded {
os.Exit(1)
}
}
#!/usr/bin/env bash
set -uo pipefail
BASE="${CONSTELLATION_API_BASE:-https://api.constellation.space}"
: "${CONSTELLATION_API_TOKEN:?set CONSTELLATION_API_TOKEN}"
healthy() { # $1 = JSON body; healthy iff status==ok and no check has ok==false
jq -e '.status == "ok" and ([.checks // {} | .[] | select(.ok == false)] | length == 0)' \
>/dev/null 2>&1 <<<"$1"
}
# 1. Reachability.
body=$(curl -sS --max-time 8 "$BASE/health") || { echo "platform unreachable at $BASE" >&2; exit 2; }
healthy "$body" || { echo "platform unhealthy at $BASE: $body" >&2; exit 2; }
# 2. Subsystems.
degraded=0
for sub in telemetry topology predictions; do
body=$(curl -sS --max-time 8 "$BASE/health/$sub") || body=""
if healthy "$body"; then
echo "$sub: healthy"
else
echo "$sub: DEGRADED"
degraded=1
fi
done
# 3. Key validity.
status=$(curl -sS -o /tmp/topo.json -w '%{http_code}' --max-time 8 \
-H "x-api-key: $CONSTELLATION_API_TOKEN" \
"$BASE/topology?freshness_seconds=900") || status=0
if [[ "$status" == "401" ]]; then
echo "API key rejected (401)" >&2
exit 3
elif [[ "$status" != "200" ]]; then
echo "authenticated probe failed (status $status)" >&2
degraded=1
else
echo "auth: ok (tenant $(jq -r '.tenant_key' /tmp/topo.json))"
fi
exit "$degraded"
Expected output on a healthy platform:
telemetry: healthy
topology: healthy
predictions: healthy
auth: ok (tenant acme-sat)
Run the unauthenticated stages as often as every minute; run the authenticated stage at a lower cadence, since it spends tenant rate budget and a misconfigured key feeding stage 3 in a tight loop would trip the auth lockout. For a richer, human-oriented diagnostic of the same flow, see the connection smoke test.
Related
- Health API reference: what each endpoint proves.
- Errors and limits: rate budgets for probes.