Skip to content

Sink Health Monitoring: YAML Config Support #10

Description

@joejohnson123

Overview

Extend Sequin's YAML configuration system to support declaring monitors as part of sink definitions, enabling infrastructure-as-code workflows.

Depends on: #1 (Schema), #2 (Context Module)

YAML Schema

Monitors are nested under sink definitions:

sinks:
  - name: my-webhook-sink
    type: http_push
    # ... existing sink config ...

    monitors:
      - name: "High failure rate"
        metric: failed_messages       # pending_messages | failed_messages
        type: threshold               # threshold | anomaly
        threshold: 100                # required for threshold type
        window: 60s                   # threshold debounce window (default: 60s)
        cooldown: 5m                  # min time between re-alerts (default: 5m)
        notify_on_recovery: true      # send resolved notification (default: true)
        channels:
          - type: slack
            webhook_url: "https://hooks.slack.com/services/..."
          - type: discord
            webhook_url: "https://discord.com/api/webhooks/..."
          - type: webhook
            url: "https://my-app.com/alerts"
            headers:
              Authorization: "Bearer token"
          - type: pagerduty
            routing_key: "your-key"
          - type: incident_io
            api_key: "inc_..."
            severity: critical

      - name: "Pending anomaly"
        metric: pending_messages
        type: anomaly
        sensitivity: medium            # low | medium | high
        cooldown: 15m
        channels:
          - type: slack
            webhook_url: "https://hooks.slack.com/services/..."

Duration Parsing

Support human-readable durations:

  • 30s → 30 seconds
  • 1m → 60 seconds
  • 5m → 300 seconds
  • 1h → 3600 seconds
  • 60 → 60 seconds (plain integer = seconds)

Config Parser Changes

In Sequin.ConfigParser

  1. After parsing a sink consumer, check for monitors key
  2. For each monitor definition:
    • Validate required fields based on type
    • Parse duration strings to seconds
    • Create SinkMonitor changeset
    • Create nested SinkMonitorNotificationChannel changesets for each channel
  3. On apply:
    • Upsert monitors by (sink_consumer_id, name) unique key
    • Remove monitors that exist in DB but not in YAML (declarative sync)
    • Upsert channels within each monitor

Validation Rules

  • name is required
  • metric must be one of pending_messages, failed_messages
  • type must be one of threshold, anomaly
  • If type: threshold: threshold is required (positive integer)
  • If type: anomaly: sensitivity is required (low/medium/high)
  • channels must have at least one entry
  • Each channel must have type + required config fields for that type

Export Support

Also support exporting monitors back to YAML (for sequin export or API export):

  • Add monitors key to sink export
  • Convert seconds back to human-readable durations
  • Mask secrets in channel configs (show **** for webhook URLs, keys)

Files to Modify

  • lib/sequin/config_parser.ex — add monitor parsing within sink parsing
  • test/sequin_web/controllers/yaml_controller_test.exs — add monitor YAML test cases

Implementation Notes

  • Follow existing YAML parsing patterns in config_parser.ex
  • Monitors should be processed AFTER the sink is created/found (they reference sink_consumer_id)
  • Use the same Repo.transact pattern as other YAML entities
  • Channel config validation should match the schema validation in the Ecto changeset
  • Secret values in YAML should be handled consistently with existing secret handling (env var references, etc.)

Acceptance Criteria

  • Monitors can be defined in YAML under sinks
  • All monitor types and channel types parse correctly
  • Duration strings parsed to seconds
  • Validation errors are clear and reference the YAML path
  • Declarative sync: monitors in DB but not YAML are removed
  • Existing monitors are updated (not duplicated) on re-apply
  • Export includes monitors with masked secrets
  • Integration test: full YAML with monitors → apply → verify DB state

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