InfraGuard

Alerts

Build alert-group policies bundling system, web, DB, and security conditions; on breach they notify recipients by SMS and email automatically.

Overview — what it does

Infrastructure ▸ Alerts (/infra/alert) is the alert-group (policy) console. An operator adds conditions across four areas (system / web / DB / security) to a single policy (infr_alert_policy), tunes each threshold factor on screen, and when a breach occurs the group's recipients (infr_alert_recipient) are notified by SMS/email automatically.

It replaces the old "Capacity & Alerts" page (/infra/capacity), which now redirects here.

Key characteristics:

This screen manages only policies, alerts, and delivery history. For per-server graphs see Servers; for web uptime see Service ▸ Web; for DB load see Service ▸ Database. Threshold defaults are defined in Operations Policy.

When to use

Layout

Policy card grid

Each policy renders as one card summarizing its active toggle, severity badge, enabled areas, and recipient count, with these actions:

Action Description Access
Active/paused toggle is_active — whether the scheduler evaluates it level≥2
Edit Modal for areas, conditions, channels, recipients level≥2
Check now Evaluate + dispatch this policy immediately (run) level≥2
Test Send a test mail/SMS to recipients now (test) level≥2
Delete Remove policy + recipients level≥2
Drag reorder Display/evaluation order (seq, reorder) level≥2

Edit modal (areas, conditions, channels, recipients)

Recent alerts feed

Shows infr_alert ordered by last_seen desc, up to 60 rows (30s polling). Each row shows the observed value, threshold, aggregate count, and sent ok/total (from infr_alert_delivery), with [Ack] and [Close] status transitions.

How to use

1) Create a policy

  1. [New alert group] → enter name, severity, cooldown.
  2. Enable the areas you want to watch.
  3. For each area, enable conditions and adjust threshold factors. Defaults are prefilled from Operations Policy alertDefaults().
  4. Pick channels (SMS/mail) and add recipients.
  5. Save.

2) Condition catalog

System (server_status, seq window)

Condition Toggle Factor Default Emitted metric
Load average over sys_load_on sys_load_max 20 load_avg (>20, per server)
Free disk below sys_disk_on sys_disk_free_mb 500 disk_free (<500MB)

Web (live HTTP probe · infr_web_cert)

Condition Toggle Factor Default Emitted metric
Service OFF (status ≠ expected) web_code_on web_expect_code 200 http_status
Latency over web_latency_on web_latency_ms 5000 latency
Cert expiry imminent web_cert_on web_cert_hours 48 cert_expiry

Enabling just "Cert expiry imminent" watches every site's certificate. It is not per-site — it is a global scan across all domains.

Database (infr_db_metric latest sample)

Condition Toggle Factor Default Emitted metric
Pending queue rising db_waiting_on db_waiting_max 5 db_waiting (>=5)
Hourly slow query db_slow_on db_slow_per_hour 60 db_slow (slow_qps×3600 >= 60)

Security (legacy_glory detection tables · composite)

The evaluation window is sec_window_min (default 10 min). Any one signal over its threshold fires a breach.

Condition Toggle Factor Default Source
IDS severity + count sec_ids_on sec_ids_severity, sec_ids_count 2, 20 suricata_alert_ct (severity≥S, in-window count≥N)
AI anomaly-block surge sec_kitsune_on sec_kitsune_count 5 kitsune_detail_log (is_blocked=1, count≥N)
New blocked-IP surge sec_blacklist_on sec_blacklist_count 10 blacklist_info (new created_at in window, count≥N)

Related: Threats · Detections · Blocklist.

3) Check now / Test

4) Automatic evaluation (schedule)

Active policies are evaluated and dispatched automatically every minute.

Schedule::command('infr:eval-alerts --quiet-if-ok')
    ->everyMinute()
    ->withoutOverlapping(2)
    ->onOneServer()
    ->when($is_leader);

Manual runs:

# Evaluate all active policies (single-shot, exits after — not a daemon)
php artisan infr:eval-alerts

# A single policy only
php artisan infr:eval-alerts --policy=12

# Suppress output when there is no breach (scheduler default)
php artisan infr:eval-alerts --quiet-if-ok

infr:eval-alerts is a single-shot command that exits (it loops the policies and returns). Never turn it into an infinite-loop daemon — spawning a never-exiting daemon from the scheduler exhausts shared DB connections (see the pulse:check connection-leak lesson). The scheduler safely launches a fresh instance every minute.

Data sources

Write tables (new infr_)

Table Migration Role
infr_alert_policy 000700 Alert group (policy). scopes/targets/conditions/channels JSON + severity, cooldown_min, seq
infr_alert_recipient 000701 Per-policy recipients (inline). email/phone + via_mail/via_sms/is_active/seq
infr_alert 000702 Alert instance (fire log / triage queue). Dedup key (policy_id, metric, entity_key, status='open'), notified_at cooldown
infr_alert_delivery 000703 Delivery history. channel/address/ok/provider_code/message_id/error/latency_ms

Read sources (legacy + new, read-only)

Dedup / cooldown / auto-close flow

  1. AlertEvaluator::evaluate($policy) → array of breach candidates per active area. Area exceptions are isolated (one area failing does not block the rest).
  2. AlertDispatcher::handle($policy, $breaches):
    • Each breach is looked up by (policy_id, metric, entity_key, status=open) → if found, update + count++; else insert new (first_seen, count=1, notified_at=null).
    • Notifiable = new OR notified_at null OR notified_at <= now - cooldown_min.
    • Auto-close: open alerts of this policy not present in this round's breaches → status='closed'.
    • Batch send: notifiable alerts are bundled into one message per recipient per channel (body max 8 lines, overflow "+N more"; SMS capped at 140 chars). After sending, each target's notified_at=now.
    • One infr_alert_delivery row per (recipient, channel).

Access

Operation Min level Audit
View console/list/feed (index/list/feed) 1 (read) —
Save/delete/reorder policy (save/delete/reorder) 2 (write) alert_policy.create / .update / .delete
Alert ack/close 2 alert.ack / alert.closed
Check now (run) 2 alert.fire on send
Test send (test) 2 alert.test
Scheduled auto-send (system) alert.fire

Level scale: demo=1 · staff=5 · admin=10. Reads require level≥1; writes and dispatch require level≥2. All destructive/dispatch operations are recorded in infr_audit_log (see Audit Log). Delivery-channel providers are configured by an admin (level≥10).

Troubleshooting & FAQ

Q. I enabled a condition but no alert arrives.

  1. Confirm the policy is active and the scheduler (schedule:work / prod supervisor) is running.
  2. No channel provider — check the card warning and configure a default provider in Mail Adapters/SMS Adapters.
  3. Verify the intersection of recipient via_mail/via_sms with the policy channels is non-empty, and that email/phone are filled.
  4. During cooldown, re-sends are suppressed (cooldown_min, default 30 min). Use [Check now] to verify immediately, but an already-notified alert only re-sends after cooldown passes.

Q. My DB/system conditions stay quiet.

Q. Does cert-expiry watch only a specific site?

Q. Does the same breach keep piling up?

Q. Does the web probe slow down evaluation?

Related

Alerts — policy cards and the recent alert feed
Alerts — policy cards and the recent alert feed