Overview
Add a "Monitoring" tab to the sink detail page with UI for creating, managing, and viewing monitors and their alert history.
Depends on: #1 (Schema), #2 (Context Module)
LiveView Changes: SequinWeb.SinkConsumersLive.Show
New Route
# router.ex
live "/sinks/:type/:id/monitoring", SinkConsumersLive.Show, :monitoring
New Action
defp apply_action(socket, :monitoring) do
%{consumer: consumer} = socket.assigns
assign(socket, :page_title, "#{consumer.name} | Monitoring | Sequin")
end
New Assigns
:monitors — list of monitors for this consumer (preloaded with channels + active alerts)
:selected_monitor — currently selected monitor for detail view (nil = list view)
:monitor_alerts — paginated alert history for selected monitor
LiveView Events to Handle
create-monitor — params from MonitorForm, creates monitor + channels
update-monitor — updates existing monitor
delete-monitor — deletes monitor (with confirmation)
toggle-monitor — enable/disable
test-notification — sends a test alert through all configured channels
select-monitor — shows alert history for a specific monitor
Tab URL Update
# In build_tab_urls/4 — add:
monitoring: RouteHelpers.consumer_path(consumer, "monitoring", base_params)
Render Block
<% {:monitoring, %SinkConsumer{}} -> %>
<.svelte
name="consumers/ShowMonitoring"
props={%{
consumer: encode_consumer(@consumer),
monitors: encode_monitors(@monitors),
selected_monitor: encode_monitor_detail(@selected_monitor),
alerts: encode_alerts(@monitor_alerts),
parent: "consumer-show"
}}
/>
Data Encoding
encode_monitors/1 — list of monitors with: id, name, enabled, metric, monitor_type, threshold_value, anomaly_sensitivity, cooldown_seconds, notify_on_recovery, status (from active alert), channels (list of {id, channel_type}), last_triggered_at
encode_monitor_detail/1 — full monitor with channels config (for edit form)
encode_alerts/1 — list of alerts with: id, status, metric_value, message, triggered_at, resolved_at
Svelte Components
ShowMonitoring.svelte — Main View
Empty State:
- Illustration + "No monitors configured"
- "Create your first monitor" CTA button
Monitor List:
- Card per monitor showing:
- Status indicator (green dot = OK, red dot = ALERTING, gray = disabled)
- Name + type badge ("Threshold" / "Anomaly")
- Metric label ("Pending Messages" / "Failed Messages")
- Threshold/sensitivity value
- Channel icons (webhook, Slack, Discord, PagerDuty, Incident.io)
- Last triggered time (relative)
- Actions: toggle switch, edit button, delete button
- "+ Create Monitor" button at top
Monitor Detail (when selected):
- Monitor summary card
- Alert history table (see MonitorAlertHistory)
- Back button to list
MonitorForm.svelte — Create/Edit Modal
Slide-over or modal form with sections:
-
Basics
- Name (text input, required)
- Metric (select: Pending Messages / Failed Messages)
- Monitor Type (radio group: Threshold / Anomaly Detection)
-
Threshold Config (shown when type = Threshold)
- Threshold value (number input, required)
- Window duration (select: 30s, 1m, 5m, 10m)
-
Anomaly Config (shown when type = Anomaly)
- Sensitivity (select: Low / Medium / High)
- Description text explaining each level
-
Notification Channels (repeatable)
- Channel type select (Webhook / Slack / Discord / PagerDuty / Incident.io)
- Dynamic config fields per type:
- Webhook: URL (text), headers (key-value pairs), method (select)
- Slack: Webhook URL (text)
- Discord: Webhook URL (text)
- PagerDuty: Routing Key (password field)
- Incident.io: API Key (password field), Severity (select)
- "+ Add Channel" button
- Remove channel (X button)
-
Advanced (collapsible)
- Cooldown period (select: 1m, 5m, 15m, 30m, 1h)
- Notify on recovery (toggle, default on)
-
Actions
- Save / Create button
- Cancel button
- Test Notification button (sends test alert to all channels)
MonitorAlertHistory.svelte — Alert History Table
- Sortable table with columns:
- Status (badge: Triggered/Resolved)
- Metric Value
- Message (truncated, expandable)
- Triggered At (relative + absolute on hover)
- Resolved At
- Duration (auto-calculated)
- Pagination (25 per page)
- Empty state: "No alerts have been triggered"
Files to Create
assets/svelte/consumers/ShowMonitoring.svelte
assets/svelte/consumers/MonitorForm.svelte
assets/svelte/consumers/MonitorAlertHistory.svelte
Files to Modify
lib/sequin_web/router.ex — add :monitoring route
lib/sequin_web/live/sink_consumers/show.ex — add monitoring tab, events, encoding
assets/svelte/consumers/ShowSinkHeader.svelte — add "Monitoring" tab with bell icon
assets/svelte/consumers/types.ts — add monitor TypeScript types
UI/UX Notes
- Follow existing Sequin design patterns (see ShowSink.svelte, ShowMessages.svelte)
- Use existing shadcn-svelte components (Button, Dialog, Select, Input, Badge, Table, Switch)
- Tab should show alert count badge when there are active alerts (red dot or number)
- Monitor cards should pulse/animate when in alerting state
- Channel icons: 🔗 webhook, 💬 Slack, 🎮 Discord, 📟 PagerDuty, 🚨 Incident.io
Acceptance Criteria
Overview
Add a "Monitoring" tab to the sink detail page with UI for creating, managing, and viewing monitors and their alert history.
Depends on: #1 (Schema), #2 (Context Module)
LiveView Changes:
SequinWeb.SinkConsumersLive.ShowNew Route
New Action
New Assigns
:monitors— list of monitors for this consumer (preloaded with channels + active alerts):selected_monitor— currently selected monitor for detail view (nil = list view):monitor_alerts— paginated alert history for selected monitorLiveView Events to Handle
create-monitor— params from MonitorForm, creates monitor + channelsupdate-monitor— updates existing monitordelete-monitor— deletes monitor (with confirmation)toggle-monitor— enable/disabletest-notification— sends a test alert through all configured channelsselect-monitor— shows alert history for a specific monitorTab URL Update
Render Block
Data Encoding
encode_monitors/1— list of monitors with: id, name, enabled, metric, monitor_type, threshold_value, anomaly_sensitivity, cooldown_seconds, notify_on_recovery, status (from active alert), channels (list of {id, channel_type}), last_triggered_atencode_monitor_detail/1— full monitor with channels config (for edit form)encode_alerts/1— list of alerts with: id, status, metric_value, message, triggered_at, resolved_atSvelte Components
ShowMonitoring.svelte— Main ViewEmpty State:
Monitor List:
Monitor Detail (when selected):
MonitorForm.svelte— Create/Edit ModalSlide-over or modal form with sections:
Basics
Threshold Config (shown when type = Threshold)
Anomaly Config (shown when type = Anomaly)
Notification Channels (repeatable)
Advanced (collapsible)
Actions
MonitorAlertHistory.svelte— Alert History TableFiles to Create
assets/svelte/consumers/ShowMonitoring.svelteassets/svelte/consumers/MonitorForm.svelteassets/svelte/consumers/MonitorAlertHistory.svelteFiles to Modify
lib/sequin_web/router.ex— add:monitoringroutelib/sequin_web/live/sink_consumers/show.ex— add monitoring tab, events, encodingassets/svelte/consumers/ShowSinkHeader.svelte— add "Monitoring" tab with bell iconassets/svelte/consumers/types.ts— add monitor TypeScript typesUI/UX Notes
Acceptance Criteria