Skip to content

refactor: monitoring reliability, SNS removal, and IAM least-privilege docs - #44

Merged
AhmadHammad21 merged 3 commits into
mainfrom
feat/monitoring-refactor
May 21, 2026
Merged

AhmadHammad21 merged 3 commits into
mainfrom
feat/monitoring-refactor

Conversation

@AhmadHammad21

@AhmadHammad21 AhmadHammad21 commented May 20, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Shared investigation runner (src/agent/investigation_runner.py) — extracted ~130 lines of duplicated streaming logic from poller and event consumer; both now delegate to a single run_investigation() function. Also synthesizes a _status: failed result when the LLM completes the loop without calling submit_investigation (fixes silent drop with weak models like Gemma).
  • Bounded poller thread pool — ThreadPoolExecutor(max_workers=4, thread_name_prefix="poller") isolates poller boto3 calls from the app's default executor, preventing thread pool exhaustion under concurrent alarms.
  • Service health DB fallback — get_services() rebuilds the in-memory service grid from the alerts table on restart instead of returning empty state. Also fixed a pre-existing bug where completed always showed as unknown (amber) instead of healthy.
  • Real-time monitoring SSE — GET /api/monitoring/stream pushes new alerts to the frontend via SSE as they arrive (heartbeat every 20s, falls back to 30s polling on disconnect). Replaces the previous 30s interval poll.
  • SQS DLQ verification — scripts/test_dlq.py (end-to-end AWS script) and tests/integration/test_dlq_logic.py (7 unit tests, all passing) confirm the existing maxReceiveCount=5 redrive policy works correctly.
  • Full SNS removal — deleted src/tools/sns.py; removed all SNS config, UI fields, permission checks, and delivery code from the event consumer, poller, init store, settings page, init page, and env example.
  • IAM two-policy split (docs/iam_setup.md) — separate Operational policy (reads use *) and Setup policy (create/delete/put scoped to opendevops-* resources only). No hardcoded account IDs.
  • Docs updated — monitoring.md, event_detection.md, slack_and_polling.md, and README.md reflect all of the above.

Test plan

  • Shared runner — trigger an event via scripts/test_pipeline.py, confirm alert appears on /monitoring with correct confidence level and session link
  • Failed-result fallback — set LLM_MODEL to a weak model (e.g. openrouter/google/gemma-4-26b-a4b-it), trigger an event; confirm a FAILED alert is persisted rather than the investigation silently disappearing
  • Service health on restart — run event consumer, then restart the server; confirm /monitoring services panel shows last-known status without needing a new event
  • SSE stream — open /monitoring in the browser, trigger a test event via Send test event; confirm the new alert card appears without a page refresh
  • DLQ — run uv run python scripts/test_dlq.py --profile <your-profile> with the server stopped; confirm ✓ PASS output
  • Unit tests — uv run pytest tests/integration/test_dlq_logic.py -v → 7 passed
  • No SNS — confirm SNS_TOPIC_ARN is absent from .env.example, Settings page, and Init page; confirm event consumer sends Slack notification only
  • IAM policy — create the two policies from docs/iam_setup.md, attach to a test user; run Settings → AWS Configuration → Run checks; confirm all required services pass

…reliability

- Extract _run_investigation into src/agent/investigation_runner.py, eliminating
  ~130 lines of copy-paste between poller.py and event_consumer.py
- Synthesise a failed result when agent completes without calling submit_investigation
  (handles models with weak tool-use support like Gemma) so the event is always
  persisted and notified rather than silently dropped
- Add SSE push at GET /api/monitoring/stream; MonitoringPage switches from 30s
  polling to real-time alert delivery via EventSource with 30s fallback on error
- Fix services grid to survive restarts by falling back to DB-derived status when
  in-memory dict is empty; fix status mapping so completed investigations show
  as healthy (green) instead of amber
- Isolate poller boto3 calls to a dedicated ThreadPoolExecutor(max_workers=4)
  so poller ticks cannot saturate the shared default pool used by API requests
SNS was fully optional (poller never used it, event consumer gated on
sns_topic_arn being set) and added IAM surface area with no benefit over
the existing Slack and Telegram channels.

- Delete src/tools/sns.py
- Remove SNS block from event_consumer._deliver(); sns_sent hardcoded False
- Remove sns_topic_arn from appsettings, init_store (_default + accessor),
  SetupBody, and /api/init/setup handler
- Remove SNS permission check from permission_checker.check_permissions()
- Remove SNS field from SettingsPage AWS Configuration tab and InitPage wizard
- Remove SNS_TOPIC_ARN from .env.example
- Clean up permission_checker line lengths while touching the file
…and investigation_runner notes

Two-policy IAM split (Operational reads *, Setup writes scoped to opendevops-*).
Removes all SNS mentions from docs, monitoring flow, and README roadmap.
Adds SSE stream endpoint to monitoring API reference.
Documents service health DB fallback, investigation_runner, and poller thread pool.
@AhmadHammad21
AhmadHammad21 merged commit 3488e71 into main May 21, 2026
2 checks passed
@AhmadHammad21
AhmadHammad21 deleted the feat/monitoring-refactor branch May 21, 2026 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant