import React, { useEffect, useMemo, useState } from "react"; import { apiFetch } from "../api"; import { useAuth } from "../state"; const initialForm = { name: "", description: "", target_id: "", sql_text: "SELECT count(*)::float FROM pg_stat_activity WHERE state = 'active'", comparison: "gte", warning_threshold: "", alert_threshold: "", enabled: true, }; function formatAlertValue(value) { if (value === null || value === undefined) return "-"; if (Number.isInteger(value)) return String(value); return Number(value).toFixed(2); } export function AlertsPage() { const { tokens, refresh, me } = useAuth(); const [targets, setTargets] = useState([]); const [status, setStatus] = useState({ warnings: [], alerts: [], warning_count: 0, alert_count: 0 }); const [definitions, setDefinitions] = useState([]); const [form, setForm] = useState(initialForm); const [error, setError] = useState(""); const [loading, setLoading] = useState(true); const [testing, setTesting] = useState(false); const [testResult, setTestResult] = useState(""); const [saving, setSaving] = useState(false); const canManageAlerts = me?.role === "admin" || me?.role === "operator"; const loadAll = async () => { try { setError(""); const [targetRows, statusPayload] = await Promise.all([ apiFetch("/targets", {}, tokens, refresh), apiFetch("/alerts/status", {}, tokens, refresh), ]); setTargets(targetRows); setStatus(statusPayload); if (canManageAlerts) { const defs = await apiFetch("/alerts/definitions", {}, tokens, refresh); setDefinitions(defs); } } catch (e) { setError(String(e.message || e)); } finally { setLoading(false); } }; useEffect(() => { loadAll(); }, [canManageAlerts]); useEffect(() => { const timer = setInterval(() => { apiFetch("/alerts/status", {}, tokens, refresh) .then(setStatus) .catch(() => {}); }, 20000); return () => clearInterval(timer); }, [tokens, refresh]); const targetOptions = useMemo( () => [{ id: "", name: "All targets" }, ...targets.map((t) => ({ id: String(t.id), name: `${t.name} (${t.host}:${t.port})` }))], [targets] ); const createDefinition = async (e) => { e.preventDefault(); setSaving(true); setTestResult(""); try { await apiFetch( "/alerts/definitions", { method: "POST", body: JSON.stringify({ name: form.name, description: form.description || null, target_id: form.target_id ? Number(form.target_id) : null, sql_text: form.sql_text, comparison: form.comparison, warning_threshold: form.warning_threshold === "" ? null : Number(form.warning_threshold), alert_threshold: Number(form.alert_threshold), enabled: !!form.enabled, }), }, tokens, refresh ); setForm(initialForm); await loadAll(); } catch (e) { setError(String(e.message || e)); } finally { setSaving(false); } }; const testDefinition = async () => { if (!form.target_id) { setTestResult("Select a specific target to test this SQL query."); return; } setTesting(true); setTestResult(""); try { const res = await apiFetch( "/alerts/definitions/test", { method: "POST", body: JSON.stringify({ target_id: Number(form.target_id), sql_text: form.sql_text, }), }, tokens, refresh ); if (res.ok) { setTestResult(`Query test succeeded. Returned value: ${formatAlertValue(res.value)}`); } else { setTestResult(`Query test failed: ${res.error}`); } } catch (e) { setTestResult(String(e.message || e)); } finally { setTesting(false); } }; const removeDefinition = async (definitionId) => { if (!confirm("Delete this custom alert definition?")) return; try { await apiFetch(`/alerts/definitions/${definitionId}`, { method: "DELETE" }, tokens, refresh); await loadAll(); } catch (e) { setError(String(e.message || e)); } }; const toggleDefinition = async (definition) => { try { await apiFetch( `/alerts/definitions/${definition.id}`, { method: "PUT", body: JSON.stringify({ enabled: !definition.enabled }) }, tokens, refresh ); await loadAll(); } catch (e) { setError(String(e.message || e)); } }; if (loading) return
Loading alerts...
; return (

Alerts

Warnings are early signals. Alerts are critical thresholds reached or exceeded.

{error &&
{error}
}
{status.warning_count || 0} Warnings
{status.alert_count || 0} Alerts

Warnings

{status.warnings?.length ? (
{status.warnings.map((item) => (
Warning {item.name} {item.target_name}

{item.description}

{item.message}

))}
) : (

No warning-level alerts right now.

)}

Alerts

{status.alerts?.length ? (
{status.alerts.map((item) => (
Alert {item.name} {item.target_name}

{item.description}

{item.message}

))}
) : (

No critical alerts right now.

)}
{canManageAlerts && ( <>

Create Custom Alert

Admins and operators can add SQL-based checks with warning and alert thresholds.

setForm({ ...form, name: e.target.value })} placeholder="e.g. High Active Sessions" required />
setForm({ ...form, description: e.target.value })} placeholder="What does this check validate?" />
setForm({ ...form, warning_threshold: e.target.value })} placeholder="e.g. 20" />
setForm({ ...form, alert_threshold: e.target.value })} placeholder="e.g. 50" required />