diff --git a/frontend/src/pages/AlertsPage.jsx b/frontend/src/pages/AlertsPage.jsx index 2d96407..b684606 100644 --- a/frontend/src/pages/AlertsPage.jsx +++ b/frontend/src/pages/AlertsPage.jsx @@ -24,6 +24,56 @@ function formatTs(ts) { return new Date(ts).toLocaleString(); } +function buildAlertSuggestions(item) { + const name = (item?.name || "").toLowerCase(); + const category = (item?.category || "").toLowerCase(); + const source = (item?.source || "").toLowerCase(); + const value = Number(item?.value || 0); + const suggestions = []; + + if (name.includes("reachability") || name.includes("connectivity") || category === "availability") { + suggestions.push("Verify host, port, firewall rules, and network routing between backend container and DB target."); + suggestions.push("Check PostgreSQL `listen_addresses` and `pg_hba.conf` on the monitored instance."); + } + if (name.includes("freshness") || item?.message?.toLowerCase().includes("no metrics")) { + suggestions.push("Check collector logs and polling interval. Confirm the target credentials are still valid."); + suggestions.push("Run a manual connection test in Targets Management and verify SSL mode."); + } + if (name.includes("cache hit") || category === "performance") { + suggestions.push("Inspect slow queries and add/adjust indexes for frequent WHERE/JOIN columns."); + suggestions.push("Review shared buffers and query patterns that cause high disk reads."); + } + if (name.includes("lock") || category === "contention") { + suggestions.push("Inspect blocking sessions in `pg_stat_activity` and long transactions."); + suggestions.push("Reduce transaction scope/duration and add missing indexes to avoid lock escalation."); + } + if (name.includes("deadlock")) { + suggestions.push("Enforce a consistent table access order in transactions to prevent deadlocks."); + suggestions.push("Retry deadlocked transactions in the application with backoff."); + } + if (name.includes("checkpoint") || category === "io") { + suggestions.push("Review `max_wal_size`, `checkpoint_timeout`, and write burst patterns."); + suggestions.push("Check disk throughput and WAL pressure during peak load."); + } + if (name.includes("rollback")) { + suggestions.push("Investigate application errors causing transaction rollbacks."); + suggestions.push("Validate constraints/input earlier to reduce failed writes."); + } + if (name.includes("query") || category === "query" || source === "custom") { + suggestions.push("Run `EXPLAIN (ANALYZE, BUFFERS)` for the affected query and optimize highest-cost nodes."); + suggestions.push("Prioritize fixes for high total-time queries first, then high mean-time queries."); + } + if (value > 0 && item?.comparison && item?.alert_threshold !== null && item?.alert_threshold !== undefined) { + suggestions.push(`Current value is ${value.toFixed(2)} with threshold rule ${item.comparison} ${Number(item.alert_threshold).toFixed(2)}.`); + } + if (!suggestions.length) { + suggestions.push("Start with target activity, locks, and query insights to isolate the root cause."); + suggestions.push("Compare current values to the last stable period and tune threshold sensitivity if needed."); + } + + return suggestions.slice(0, 4); +} + export function AlertsPage() { const { tokens, refresh, me } = useAuth(); const [targets, setTargets] = useState([]); @@ -196,6 +246,7 @@ export function AlertsPage() {
{item.sql_text}{item.sql_text}