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
Overview
Add Slack and Discord as notification channel types with rich formatting.
Depends on: #4 (Notification Dispatcher & Webhook Channel)
Slack Channel:
Sequin.Monitors.Channels.SlackImplementation
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
Discord Channel:
Sequin.Monitors.Channels.DiscordImplementation
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.exlib/sequin/monitors/channels/discord.extest/sequin/monitors/channels/slack_test.exstest/sequin/monitors/channels/discord_test.exsImplementation Notes
https://hooks.slack.com/services/T.../B.../...https://discord.com/api/webhooks/{id}/{token}Reqfor HTTP requests with 10s timeout:failed_messages→ "Failed Messages")Acceptance Criteria