diff --git a/client/src/SettingsWizard.js b/client/src/SettingsWizard.js index b5f7484..060a46c 100644 --- a/client/src/SettingsWizard.js +++ b/client/src/SettingsWizard.js @@ -35,6 +35,7 @@ function SettingsWizard() { items_per_page: 20, refresh_interval: 5000, incident_failure_threshold: 10, + slow_alert_consecutive: 3, }); const [testResult, setTestResult] = useState(null); @@ -529,6 +530,18 @@ function SettingsWizard() { Number of consecutive failures before triggering an alert (default: 3) +
+ + setSettings({ ...settings, slow_alert_consecutive: parseInt(e.target.value) })} + min="1" + max="20" + /> + Consecutive slow checks required before alerting — 1 = any spike, 3 = default, 5+ = only sustained slowness +
+
diff --git a/server/index.js b/server/index.js index c2b3652..6fd140a 100644 --- a/server/index.js +++ b/server/index.js @@ -147,6 +147,7 @@ function buildSettingsFromDb(dbSettings = {}) { ntfy_url: dbSettings.ntfy_url || process.env.NTFY_URL || 'https://ntfy.sh', ntfy_topic: dbSettings.ntfy_topic || process.env.NTFY_TOPIC || '', incident_failure_threshold: parseInt(dbSettings.incident_failure_threshold || process.env.INCIDENT_FAILURE_THRESHOLD) || 10, + slow_alert_consecutive: parseInt(dbSettings.slow_alert_consecutive || process.env.SLOW_ALERT_CONSECUTIVE) || 3, webhook_template: dbSettings.webhook_template || process.env.WEBHOOK_TEMPLATE || '', }; } @@ -773,6 +774,7 @@ app.post('/api/settings', (req, res) => { ntfy_url: { env: 'NTFY_URL', coerce: v => v || 'https://ntfy.sh' }, ntfy_topic: { env: 'NTFY_TOPIC', coerce: v => v || '' }, incident_failure_threshold: { env: 'INCIDENT_FAILURE_THRESHOLD', coerce: v => String(v || 10) }, + slow_alert_consecutive: { env: 'SLOW_ALERT_CONSECUTIVE', coerce: v => String(v || 3) }, }; // Collect only the fields present in this request diff --git a/server/scheduler.js b/server/scheduler.js index 861191b..a55e63c 100644 --- a/server/scheduler.js +++ b/server/scheduler.js @@ -181,8 +181,9 @@ class Scheduler { if (result.response_time > effectiveThreshold) { const consecutive = (this.slowConsecutiveCount.get(resource.id) || 0) + 1; this.slowConsecutiveCount.set(resource.id, consecutive); - // Require 3 consecutive slow checks before alerting (avoids single-spike false positives) - if (consecutive >= 3) { + const slowAlertConsecutiveSetting = db.prepare(`SELECT value FROM settings WHERE key = 'slow_alert_consecutive'`).get(); + const slowAlertConsecutive = parseInt(slowAlertConsecutiveSetting?.value) || 3; + if (consecutive >= slowAlertConsecutive) { const lastSlowAlert = this.slowAlertCooldown.get(resource.id) || 0; if (now - lastSlowAlert > 60 * 60 * 1000) { this.slowAlertCooldown.set(resource.id, now);