Skip to content

feat(export): add slack, pagerduty, and discord webhook sinks#83

Open
abhinavuser wants to merge 6 commits into
optiqor:mainfrom
abhinavuser:feat/sinks-integrations
Open

feat(export): add slack, pagerduty, and discord webhook sinks#83
abhinavuser wants to merge 6 commits into
optiqor:mainfrom
abhinavuser:feat/sinks-integrations

Conversation

@abhinavuser
Copy link
Copy Markdown

fixes #29

added built-in webhook sinks for kerno doctor findings. wired up the --sink, --severity-floor, and --sink-dedupe flags.
what's included:

  • Sink interface with exponential backoff retries on 5xx errors
  • in-memory deduplicator to prevent flapping rules from spamming on-call
  • slack integration using block kit format for clean readability
  • pagerduty integration via events api v2. handles trigger events and automatically sends a resolve event when a finding clears in continuous mode
  • discord integration utilizing discord's native slack-compat url suffix
  • kerno_sinks_deduped_total and kerno_sinks_failed_total metrics
  • full test suite using httptest.Server
    all env vars like KERNO_SLACK_WEBHOOK_URL are expanded automatically if passed as flag values to keep shell history clean.

Signed-off-by: abhinavuser abhinavkumarv2101@gmail.com

@abhinavuser abhinavuser requested a review from btwshivam as a code owner May 16, 2026 15:53
@github-actions
Copy link
Copy Markdown

🚀 First PR — welcome aboard!

A few things to expect:

  1. CI: every PR runs build + race tests + lint + (eventually) the kernel matrix. If something fails, the log will tell you exactly which gate.
  2. DCO: every commit needs Signed-off-by:git commit -s adds it automatically.
  3. Conventional Commits: PR titles like feat(doctor): add new rule or fix(bpf): handle X. We squash-merge by default.
  4. Review: a maintainer will review within 72 hours. Suggestions are conversations, not orders — push back if something doesn't fit your context.

If you get stuck, reply here or jump to Discussions. We want this PR to land.

@github-actions github-actions Bot added testing Tests and test coverage area/integrations External integrations (sinks, exports, CI) labels May 16, 2026
@btwshivam
Copy link
Copy Markdown
Member

dont spam. first get your past pRs merged

@btwshivam
Copy link
Copy Markdown
Member

fix conflict and rebase with main.. then ill review tag me

fixes optiqor#29

Signed-off-by: abhinavuser <abhinavkumarv2101@gmail.com>
… package)

Signed-off-by: abhinavuser <abhinavkumarv2101@gmail.com>
@abhinavuser abhinavuser force-pushed the feat/sinks-integrations branch from 814d347 to fa6c43c Compare May 31, 2026 12:28
@github-actions github-actions Bot added the level:advanced 200+ lines or 6+ files (auto-applied) label May 31, 2026
Signed-off-by: abhinavuser <abhinavkumarv2101@gmail.com>
…lloc)

Signed-off-by: abhinavuser <abhinavkumarv2101@gmail.com>
Signed-off-by: abhinavuser <abhinavkumarv2101@gmail.com>
@abhinavuser
Copy link
Copy Markdown
Author

hey @btwshivam i was waitin for my first pr to get merged thats why the delay but now the rebase is done and the merge conflict in internal/cli/doctor.go is resolved
i also noticed and fixed a small unused import/missing io package issue in sink.go that is causing the CI linter to fail early
ready for your review when you have a chance

Signed-off-by: abhinavuser <abhinavkumarv2101@gmail.com>
Copy link
Copy Markdown
Member

@btwshivam btwshivam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solid sink package: raw net/http with per-client timeouts, sinks run after render and failures are logged not fatal, dedupe and pagerduty state are both mutex-guarded, and no webhook urls get logged. two notes, neither blocking.

Comment thread internal/cli/doctor.go
}

deduped := deduper.Filter(filtered)
for _, sink := range activeSinks {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sinks send synchronously and sequentially here. each Send can take ~30s on a dead endpoint (10s client timeout times up to 3 retries plus backoff), so three unreachable sinks hang the command ~90s after the report already printed, and in continuous mode it stalls the next cycle. rendering first and treating failures as non-fatal is right, but dispatch each sink in its own goroutine (a sync.WaitGroup, the per-request timeouts already bound each one) so one slow webhook doesn't block the others or the cli.

Comment thread internal/cli/doctor.go
flags.StringSliceVar(&sinkURLs, "sink", nil, "webhook sinks (e.g. slack://..., pagerduty://...)")
flags.StringVar(&sevFloor, "severity-floor", "warning", "minimum severity to send to sinks (info, warning, critical)")
flags.DurationVar(&sinkDedupe, "sink-dedupe", 5*time.Minute, "deduplication window to prevent alert flapping")
flags.BoolVar(&dryRunSink, "dry-run-sinks", false, "print payloads instead of sending (useful for debugging sinks)")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--dry-run-sinks help says print payloads instead of sending, but the dry-run branches only log the finding count (dry-run sink ... findings=N), not the actual slack/pagerduty/discord json. debugging a block-kit or events-api-v2 payload is exactly when you'd want to see the body. either render the payload each sink would send, or change the help text to match what it does.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/integrations External integrations (sinks, exports, CI) level:advanced 200+ lines or 6+ files (auto-applied) testing Tests and test coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sinks: Slack / PagerDuty / Discord webhook integrations

2 participants