Skip to content

Sink Health Monitoring: Slack & Discord Notification Channels #5

Description

@joejohnson123

Overview

Add Slack and Discord as notification channel types with rich formatting.

Depends on: #4 (Notification Dispatcher & Webhook Channel)

Slack Channel: Sequin.Monitors.Channels.Slack

Implementation

  • POST to Slack incoming webhook URL
  • Use Block Kit for rich formatting
  • Color coding: red (#E74C3C) for triggered, green (#2ECC71) for resolved

Message Format (Block Kit)

{
  "attachments": [{
    "color": "#E74C3C",
    "blocks": [
      {
        "type": "header",
        "text": {"type": "plain_text", "text": "🚨 Monitor Alert: High failure rate"}
      },
      {
        "type": "section",
        "fields": [
          {"type": "mrkdwn", "text": "*Sink:*\nmy-webhook-sink"},
          {"type": "mrkdwn", "text": "*Metric:*\nFailed Messages"},
          {"type": "mrkdwn", "text": "*Current Value:*\n150"},
          {"type": "mrkdwn", "text": "*Threshold:*\n100"}
        ]
      },
      {
        "type": "context",
        "elements": [{"type": "mrkdwn", "text": "Triggered at 2026-02-26 13:00 UTC"}]
      },
      {
        "type": "actions",
        "elements": [{
          "type": "button",
          "text": {"type": "plain_text", "text": "View Sink"},
          "url": "https://app.sequinstream.com/sinks/..."
        }]
      }
    ]
  }]
}

Recovery Message

  • Green color, ✅ emoji in header
  • Shows how long the alert was active
  • Same field layout

Discord Channel: Sequin.Monitors.Channels.Discord

Implementation

  • POST to Discord webhook URL
  • Use embed format for rich messages
  • Color coding: red (0xE74C3C) for triggered, green (0x2ECC71) for resolved

Message Format (Embed)

{
  "embeds": [{
    "title": "🚨 Monitor Alert: High failure rate",
    "color": 15158332,
    "fields": [
      {"name": "Sink", "value": "my-webhook-sink", "inline": true},
      {"name": "Metric", "value": "Failed Messages", "inline": true},
      {"name": "Current Value", "value": "150", "inline": true},
      {"name": "Threshold", "value": "100", "inline": true}
    ],
    "footer": {"text": "Triggered at 2026-02-26 13:00 UTC"},
    "url": "https://app.sequinstream.com/sinks/..."
  }]
}

Files to Create

  • lib/sequin/monitors/channels/slack.ex
  • lib/sequin/monitors/channels/discord.ex
  • test/sequin/monitors/channels/slack_test.exs
  • test/sequin/monitors/channels/discord_test.exs

Implementation Notes

  • Both use simple HTTP POST to webhook URLs (no OAuth needed)
  • Slack webhook URL format: https://hooks.slack.com/services/T.../B.../...
  • Discord webhook URL format: https://discord.com/api/webhooks/{id}/{token}
  • Use Req for HTTP requests with 10s timeout
  • Format metric names as human-readable (:failed_messages → "Failed Messages")
  • For anomaly monitors, show detected value vs expected range instead of threshold

Acceptance Criteria

  • Slack messages render with correct Block Kit format
  • Discord messages render with correct embed format
  • Color coding works for both triggered and resolved states
  • "View Sink" link is included and correct
  • Both handle HTTP errors gracefully
  • Tests verify payload structure

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions