docs(ops): add runbooks for rate-limit, cache, Qdrant, Orb, and AI provider recovery#2638
Conversation
…ovider recovery A prior investigation found the dashboards, alert rules (13 groups, ~21 rules), and metrics for #1943's requested categories were already substantially complete -- the genuine gap was runbook coverage for five specific failure modes an operator can hit but had no documented recovery path for. Adds five new troubleshooting sections, each grounded in the exact metric names, label vocabularies, and alert names the code actually emits (cross- checked against src/selfhost/metrics.ts call sites and prometheus/rules/ alerts.yml, not inferred from the issue text): - GitHub rate-limit responses and admission deferrals, with PromQL to break a spike down by kind/key_scope/job_type and distinguish an expected brief admission hold from a sustained problem. - Low GitHub response-cache hit rate, with a PromQL hit-rate query by endpoint class. - Qdrant/vector-store errors, including the dimension-mismatch-on- embedding-model-change scenario and how to recreate a collection. - Orb export/relay reconciliation, pointing at the export loop's Sentry cron monitor as the fastest first check. - The AI provider circuit breaker (#2540): what it does, that it self-heals in 60s with no manual reset, and how to tell a transient trip from a persistent credential/reachability problem.
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-02 23:26:23 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 5 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
gittensory-ui | cc404f7 | Commit Preview URL Branch Preview URL |
Jul 02 2026, 11:13 PM |
Gate review round on PR #2638 flagged three real content gaps, all fixed: - Route meta description didn't mention the 5 new runbook topics. - Only the REST cache hit-rate PromQL was shown despite documenting both REST and GraphQL cache metrics -- added the GraphQL equivalent. - The Qdrant collection-drop guidance didn't name the fixed collection ("gittensory", hard-coded, not env-configurable) or warn that dropping it temporarily removes ALL indexed RAG context until reindexing completes. Also adds a drift-guard test (mirrors #2556's check-openapi-settings- parity.mjs pattern): every gittensory_*_total metric name and Gittensory* alert name referenced in the troubleshooting doc is cross-checked against the actual source files and prometheus/rules/alerts.yml, so a future rename/removal fails this test instead of the docs silently going stale. Mutation-tested (a deliberately wrong metric name correctly fails it). Separately: the self-hosting docs section was flat (13 pages under one sidebar heading) and sat as its own top-level nav category alongside "Maintainers" -- misleadingly implying self-hosting is an alternative to, rather than a maintainer concern under, "Maintainers". Nests it as 4 sub-categories (setup / integrations / operations / release & security) inside the Maintainers group instead, alongside the existing maintainer pages as a "Hosted app" sub-category. No routes changed, only the nav data model (extended to support one level of subgroups) and its render logic. Verified in a live preview: nested titles render, active-link highlighting and prev/next navigation both correctly span subgroup and group boundaries.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2638 +/- ##
=======================================
Coverage 96.06% 96.06%
=======================================
Files 234 234
Lines 26305 26305
Branches 9538 9538
=======================================
Hits 25270 25270
Misses 425 425
Partials 610 610 🚀 New features to boost your workflow:
|
…-rule syntax (#2659) * chore(selfhost): validate Grafana dashboard JSON and Prometheus alert-rule syntax (#1943) Completes the last unverified deliverable from #1943 -- the rest (dashboard panels, alert rules, troubleshooting runbooks) was audited and found already comprehensive or shipped in #2638. Grafana and Prometheus both fail OPEN on a malformed dashboard/rule file (skip it, log a warning), so nothing else catches this until an operator notices a panel or alert is simply missing. scripts/validate-observability-configs.mjs checks every grafana/dashboards/*.json file parses and has a title + panels array, and prometheus/rules/alerts.yml parses and every rule has alert/expr/labels.severity/annotations.summary. Wired into test:ci. 12 unit tests cover both validators' happy paths and failure modes. * fix(selfhost): guard against non-object dashboard/group/rule values crashing the validator Gate review caught a real bug: valid JSON/YAML that parses to a non-object (a dashboard file containing literally "null", or a YAML sequence entry like "- null") crashed the validator with a TypeError instead of producing the structured validation error it exists to provide -- the one failure mode it's explicitly meant to catch cleanly. Added an isObject() guard before every dereference (dashboard, group, rule) and 4 new regression tests covering null/array/string/primitive-at-each-level. * fix(selfhost): add a lightweight PromQL sanity check, drop unused test import Gate review correctly noted the validator claimed to check "alert rule syntax" but only verified expr was a non-empty string -- malformed PromQL like "up ==" passed silently. Added a lightweight (not a real parser -- no promtool/PromQL-grammar dependency, out of scope for this "if available" deliverable) sanity check: balanced brackets and no dangling trailing binary operator. Verified zero false positives against all 21 real rules in prometheus/rules/alerts.yml. Also dropped an unused mkdirSync import the gate flagged as a nit. * fix(selfhost): use a bracket stack, not a depth counter, in the PromQL sanity check Gate review caught a real bug: a plain depth counter only checks net nesting count, so "sum(foo[5m))" -- opened with "(" and "[", closed with ")" and ")" -- nets to depth 0 and wrongly passes as balanced, even though the second ")" doesn't match the "[" it's supposed to close. Switched to a stack that checks each closer against the delimiter it actually needs to match. Verified against the real alerts.yml (still zero false positives) and added a regression test for the exact mismatched-type case the gate identified.
Advances #1943
Investigation
Before implementing, I audited the current state of every deliverable category in the issue (Grafana dashboards, alert rules, emitted metrics, existing ops/troubleshooting docs) against the actual code, rather than assuming the issue's framing was still accurate:
incr()/gauge()/observe()call sites.docs.self-hosting-operations.tsxanddocs.self-hosting-troubleshooting.tsxcover the basics (health endpoints, log events, alerting setup, routine checks) but had no runbook for five specific failure modes an operator can actually hit.Given the infrastructure was already substantially complete, this PR is scoped to the genuine gap: five new troubleshooting runbooks.
Changes
Adds to
docs.self-hosting-troubleshooting.tsx, each grounded in metric names/labels/alert names verified directly against the source (not inferred):kind/key_scope/job_typelabel vocabulary, PromQL to break a spike down by token pool, and how to distinguish an expected brief admission hold from a sustained problem.result/classlabels and a hit-rate PromQL query.oplabel, the embedding-model-change dimension-mismatch scenario, and how to recreate a collection.Test plan
npm run ui:lint— 0 errors (pre-existing warnings in other files unrelated to this change)npm run ui:typecheckcleannpm run ui:test— 33/33 passingnpm run ui:buildsucceedsnpm run typecheckcleannpm audit --audit-level=moderate— 0 vulnerabilities/docs/self-hosting-troubleshooting, confirmed all 5 new sections render with correct heading text, code blocks, and TOC entries