Zum Inhalt

Watchdog Monitoring

Datei: watchdog/run.ts (175 Zeilen) Schedule: Alle 5 Minuten via Cron Alerting: Telegram-Bot

Übersicht

Der Watchdog prüft die Systemgesundheit in drei Kategorien:

Watchdog (alle 5 Min)
├── On-Chain Checks
│   ├── C1: Settlement-Status
│   ├── C4: Relayer-ETH-Balance
│   ├── C5: VRF-Seed-Status
│   └── S2: RPC-Erreichbarkeit
├── Database Checks
│   ├── D1: Stuck Buy-Intents
│   ├── D4: Settlement-Pipeline
│   ├── D5: DB-Connection
│   └── D6: chain_stats Frische
└── Service Checks
    └── S1: App-Erreichbarkeit

Check-Details

On-Chain Checks

Datei: watchdog/checks/onchain.ts (188 Zeilen)

C1: Settlement-Status

// Prüft ob die gestrige Ziehung settled wurde
const lastSettled = await settlement.lastSettledDay();
const expectedDay = currentDayId - 1;

if (lastSettled < expectedDay) {
  return { level: "CRITICAL", message: `Settlement fehlt: erwartet ${expectedDay}, letzter ${lastSettled}` };
}

Grace Period: Bis 00:20 UTC werden keine Settlement-Alarme ausgelöst (Settlement läuft noch).

C4: Relayer-ETH-Balance

const balance = await provider.getBalance(RELAYER_ADDRESS);
const ethBalance = parseFloat(formatEther(balance));

if (ethBalance < 0.01) return { level: "CRITICAL", message: `Relayer ETH: ${ethBalance}` };
if (ethBalance < 0.05) return { level: "HIGH", message: `Relayer ETH niedrig: ${ethBalance}` };
Schwelle Level Aktion
< 0.01 ETH CRITICAL Sofort ETH nachfüllen
< 0.05 ETH HIGH ETH bald nachfüllen

C5: VRF-Seed

const vrfSeed = await gameManager.vrfSeed();
if (vrfSeed === 0n) {
  return { level: "CRITICAL", message: "VRF Seed ist 0 - keine Tickets möglich!" };
}

S2: RPC-Erreichbarkeit

try {
  await provider.getBlockNumber();
  return { level: "OK" };
} catch (e) {
  return { level: "CRITICAL", message: `RPC nicht erreichbar: ${e.message}` };
}

Database Checks

Datei: watchdog/checks/database.ts (177 Zeilen)

D1: Stuck Buy-Intents

SELECT COUNT(*) FROM buy_intents
WHERE status IN ('SIGNED', 'EXECUTING')
  AND created_at < now() - interval '30 minutes'
Anzahl Level
0 OK
1-5 MEDIUM
> 5 HIGH

D4: Settlement-Pipeline

SELECT status FROM settlement_pipeline_runs
WHERE day_id = $1
Status Level
DONE OK
RUNNING INFO (Grace Period)
FAILED CRITICAL
Nicht vorhanden HIGH

D5: DB-Connection

Impliziter Health-Check: Wenn die Query ausführbar ist, ist die DB erreichbar.

D6: chain_stats Frische

SELECT MAX(updated_at) AS last_update
FROM chain_stats
WHERE stat_key LIKE 'jackpot_pool_%'
Alter Level
< 60 Min OK
60-120 Min MEDIUM
> 120 Min HIGH

Service Checks

Datei: watchdog/checks/service.ts (45 Zeilen)

S1: App-Erreichbarkeit

const response = await fetch(`${APP_URL}/api/global-stats`);
if (!response.ok) {
  return { level: "HIGH", message: `App nicht erreichbar: HTTP ${response.status}` };
}

Alerting

Telegram-Alerts

Datei: watchdog/alerting/telegram.ts (41 Zeilen)

🔴 CRITICAL: Relayer ETH Balance 0.008
📍 Check: C4 (onchain)
🕐 2026-02-28 14:35:00 UTC

Cooldown-System

Verhindert Alert-Spam bei anhaltenden Problemen:

Level Cooldown
CRITICAL 5 Minuten
HIGH 30 Minuten
MEDIUM 120 Minuten

Auto-Resolve

Wenn ein Check nach einem Alert wieder OK ist, wird der Alert automatisch aufgelöst:

// watchdog/run.ts:100-115
if (previousAlert && currentResult.level === "OK") {
  await pg.query(
    `UPDATE watchdog_alerts SET resolved_at = NOW() WHERE id = $1`,
    [previousAlert.id]
  );
}

Datenbank-Tracking

watchdog_runs

watchdog_runs (
  id            SERIAL PRIMARY KEY,
  started_at    TIMESTAMP,
  finished_at   TIMESTAMP,
  checks_total  INT,
  checks_ok     INT,
  checks_warn   INT,
  checks_fail   INT,
  duration_ms   INT
)

watchdog_alerts

watchdog_alerts (
  id          SERIAL PRIMARY KEY,
  run_id      INT REFERENCES watchdog_runs(id),
  check_id    VARCHAR,     -- z.B. 'C1', 'D4', 'S1'
  level       VARCHAR,     -- CRITICAL/HIGH/MEDIUM/LOW/INFO/OK
  message     TEXT,
  details     JSONB,
  notified    BOOLEAN,     -- Telegram gesendet?
  alerted_at  TIMESTAMP,
  resolved_at TIMESTAMP    -- NULL = aktiv, NOT NULL = aufgelöst
)

Check-Übersicht

Check Kategorie Beschreibung Level-Range
C1 On-Chain Settlement-Status OK / CRITICAL
C4 On-Chain Relayer-ETH-Balance OK / HIGH / CRITICAL
C5 On-Chain VRF-Seed OK / CRITICAL
S2 On-Chain RPC-Erreichbarkeit OK / CRITICAL
D1 Database Stuck Buy-Intents OK / MEDIUM / HIGH
D4 Database Settlement-Pipeline OK / INFO / HIGH / CRITICAL
D5 Database DB-Connection OK / CRITICAL
D6 Database chain_stats Frische OK / MEDIUM / HIGH
S1 Service App-Erreichbarkeit OK / HIGH

Fehlerbehandlung

  • Jeder Check ist in try/catch gewrappt
  • Einzelne Check-Fehler crashen nicht den gesamten Run
  • Check-Fehler werden als CRITICAL-Alert gemeldet
  • Watchdog-Run wird immer als Ganzes abgeschlossen