Skip to content

Sink Health Monitoring: Monitoring Tab UI (LiveView + Svelte) #8

Description

@joejohnson123

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:

  1. Basics

    • Name (text input, required)
    • Metric (select: Pending Messages / Failed Messages)
    • Monitor Type (radio group: Threshold / Anomaly Detection)
  2. Threshold Config (shown when type = Threshold)

    • Threshold value (number input, required)
    • Window duration (select: 30s, 1m, 5m, 10m)
  3. Anomaly Config (shown when type = Anomaly)

    • Sensitivity (select: Low / Medium / High)
    • Description text explaining each level
  4. 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)
  5. Advanced (collapsible)

    • Cooldown period (select: 1m, 5m, 15m, 30m, 1h)
    • Notify on recovery (toggle, default on)
  6. 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

  • Monitoring tab visible and accessible from sink detail page
  • Create monitor form works with all field combinations
  • Threshold and Anomaly configs show/hide correctly based on type selection
  • Multiple notification channels can be added/removed
  • Monitor list shows correct status indicators
  • Enable/disable toggle works
  • Delete with confirmation
  • Alert history table loads and paginates
  • Test notification button sends to all channels
  • Tab shows active alert indicator

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions