Repository navigation
feat: alert when octolens mapping discovery looks unhealthy - #4968
Conversation
Add an hourly cron_service job that posts to the integrations alerts channel when keyword-to-project mapping discovery has not written for over 3 hours, and lists every mapping it deactivated since the last report (warning persona on a burst). Redis keeps a reported-until cursor and a per-integration stale marker so alerts do not repeat. Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>
Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>
…ns-mapping-health-check Signed-off-by: Uroš Marolt <uros@marolt.me>
PR SummaryMedium Risk Overview New DAL helpers report platform-wide discovery health ( Alerts distinguish bulk deactivations (warning) from smaller batches (info), cap long Slack lists, escape/truncate names, and include manual Reviewed by Cursor Bugbot for commit 0ed0c15. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
🟡 Changes recommended
Alerts can be lost during retries or payload pruning, and partial discovery writes can incorrectly indicate healthy discovery.
4 open findings
What changed in this PR
Adds production monitoring for Octolens mapping discovery, alerting when discovery appears stale or mappings are deactivated.
Changes:
- Adds health-state and deactivation queries.
- Adds an hourly Slack alert job with Redis retry and reminder tracking.
- Adds database and alert-logic tests.
| File | Description |
|---|---|
| services/libs/data-access-layer/src/octolens/index.ts | Adds discovery health queries. |
| services/libs/data-access-layer/src/octolens/index.test.ts | Tests query results and time boundaries. |
| services/apps/cron_service/src/jobs/octolensMappingHealthCheck.job.ts | Connects the hourly job to PostgreSQL, Redis, and Slack. |
| services/apps/cron_service/src/jobs/octolensMappingHealth.ts | Implements alert formatting and delivery tracking. |
| services/apps/cron_service/src/jobs/octolensMappingHealth.test.ts | Tests thresholds, reminders, and retries. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…st active lastSeenAt Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>
Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>
…ns-mapping-health-check Signed-off-by: Uroš Marolt <uros@marolt.me> # Conflicts: # services/libs/data-access-layer/src/octolens/index.test.ts # services/libs/data-access-layer/src/octolens/index.ts
…ntegrations Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>
…ubproject filter Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>
…ns-mapping-health-check
…ed keywords apart Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>
Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>
…ns-mapping-health-check Signed-off-by: Uroš Marolt <uros@marolt.me>
… formatting slack text Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>
…ns-mapping-health-check
…of calling it covered Refs linuxfoundation/lfx-cdp-insights-ops#806 Signed-off-by: Uroš Marolt <uros@marolt.me>


Summary
Adds an hourly cron job that posts to the integrations alerts channel when Octolens keyword mapping discovery looks unhealthy. Discovery is judged once for the whole platform, across every per-subproject Octolens integration: it alerts when discovery hasn't written any mappings in over 3 hours, and when it deactivated mappings since the last report. It's quiet when healthy, and quiet before discovery has ever written a mapping (no token yet, or never run). This is visibility only; ingestion is unchanged.
Mentions are no longer re-fetched automatically, so both alerts give the exact recovery command for the manual backfill script (
pnpm --filter @crowd/connectors-worker run script:backfill-octolens-mentions, added in #5013):--keywordsfor a keyword that gets mapped again,--from <last write>after a discovery outage, each with a hint to try--dry-runfirst. If--fromis refused (not earlier than the current start date), the poll may already have read past skipped mentions, so the alert points to a--keywordsbackfill for keywords mapped since then.The diff is about 1.1k lines, mostly tests (about 700). The backfill script PR must merge before this one, since both alerts name its command.
Changes
octolens/health.ts, plusexporton the existingOWNS_NO_ACTIVE_SYNC_UNITSfilter inoctolens/index.tsso both share it.getOctolensMappingDiscoveryHealthreturnsnullwhen there are no active mappings, otherwise the active mapping count, the number of subproject integrations they belong to, and the newestlastSeenAtamong them. Only live subproject integrations count. Soft-deleted ones, the segment-less anchor that owns the mention poll, and any integration owning an active sync unit are left out, using the same rule as discovery. Discovery stamps every mapping it keeps in one transaction, so the newestlastSeenAtis its last write.listOctolensKeywordMappingsDeactivatedBetweenreturns mappings deactivated in a window with their project name and slug, plus the project the keyword is mapped to now if it moved (only a live subproject integration counts, by the same rule as above, so a stray mapping under a legacy sync-unit owner can't hide a real deactivation). It keeps mappings whose subproject integration is now soft-deleted, because discovery soft-deletes a subproject in the same run that deactivates its last keyword, and that's the deactivation most worth seeing.octolens-mapping-health-checkjob: hourly at :30 (discovery runs on the hour), prod only, reads from the primary. It checks staleness first, then deactivations, each in its own try/catch, so a failure in one never skips the other.CROWD_OCTOLENS_API_TOKENis unset. This keeps it from alerting every hour before the first run.lastSeenAtis over 3 hours old, which with hourly discovery means about three runs in a row wrote nothing. A failed run, an incomplete Octolens snapshot, a run that finds no mappings and a missingCROWD_OCTOLENS_API_TOKENall write nothing; the alert names them, the schedule and the logs to check, and the--from <last write>command that recovers mentions of keywords added meanwhile. One alert per episode, keyed on that timestamp, plus a reminder at most once a day (Redis key with a 24h expiry).--keywordsbackfill command for when they are mapped again. If any discovery run in the window deactivated 3 or more mappings, or at least 25% of them, the alert goes out as a warning titled "in bulk" instead of info. Rows from one run share a timestamp, because discovery deactivates in one transaction. The list shows the newest deactivations first and is capped at 25 mappings and at 2,800 characters after escaping, with "… and N more" beyond that. Names are truncated when long and shown as code, so*,_or~in a keyword or project name can't format the message. That keeps it inside one Slack section block, so@crowd/slacknever prunes the message after the cursor has moved.deactivatedAtis that transaction's start time. The first run looks back 24 hours. If the cursor is lost, the next run repeats up to a day of deactivations; none are dropped.Type of change
Related issue
Closes linuxfoundation/lfx-cdp-insights-ops#806