Alert Triage (#alerts β Linear) β
How we turn production alerts into tracked work. The review-issue Claude Code skill reads the #alerts Slack channel (Sentry + Grafana alerts), pulls the real error from the logs, dedups against Linear, and β on explicit approval β files or links an issue and closes the loop in Slack with a reaction + threaded link.
It runs inside Claude Code via MCP. This page is the setup; the full procedure lives in the skill itself (apps/docs/skills/review-issue/SKILL.md).
Prerequisites β connect 4 MCP servers β
The process needs grafana, slack, linear, and sentry. The simplest path: ask Claude directly β "connect the grafana, slack, linear and sentry MCP servers" β and follow the auth flow.
| Server | What to provide |
|---|---|
| grafana | URL https://tellia.grafana.net + a Viewer service-account token. Both are in 1Password ("Grafana MCP" / "Grafana service account"). |
| slack | Authorize the connector. The account must be a member of #alerts (C0AQ0UZL0RM) and #dev (C09CL4Q7Y3D). |
| linear | Authorize the connector (workspace tell-ia). |
| sentry | Authorize the connector for org tellia-dl (tellia-dl.sentry.io). |
Don't hardcode tokens in a file β let Claude wire the connections; only Grafana needs values pasted (from 1Password). Confirm all four with /mcp before triaging.
Install the skill β
The skill is not auto-loaded β .claude/ is gitignored, so a fresh checkout has no review-issue skill. Its tracked source of truth lives at apps/docs/skills/review-issue/SKILL.md. Install it into your .claude/ β project-local (.claude/skills/review-issue/) or global (~/.claude/skills/review-issue/):
- Ask Claude β "add the
review-issueskill" β it copies the tracked source into.claude/. - Or copy it yourself:
cp -R apps/docs/skills/review-issue .claude/skills/review-issue
Restart Claude Code and confirm /review-issue appears in the skill list. The full procedure lives in that SKILL.md; see the shared skills README for the complete list and install options.
How triage works β
Run it by saying "check #alerts". For every alert the skill:
- Log-first (hard gate). Reads the real error before any disposition β never infers from the alert title or source code. This is non-negotiable; skipping it has filed real bugs late.
- Backend (Grafana) alerts β Loki error-level sweep for the exact window:
{service_name="tellia-agri-backend", level="error", deployment_environment="production"}, then Tempo for provider/worker/latency spans. (A loose|~ "<id>"filter that returns info lines is not the check.) - Frontend (Sentry) alerts β Sentry is the frontend log. Read occurrences, users-impacted, status (escalating?), first/last-seen. A high-volume / multi-user / still-firing FE error is actionable even when the backend is clean β clientβsocket/transport and render bugs never touch the backend. "transient / browser / Failed-to-fetch" is a verdict you earn from the counts, never a default.
- Backend (Grafana) alerts β Loki error-level sweep for the exact window:
- Match alert β error by exact timestamp (alert fires ~1β3 min after the error; times are CEST).
- Assess ownership β our code Β· provider Β· browser/device Β· mislogged noise Β· rule misconfig.
- Dedup β search Linear and read the candidate's full content (
get_issue) before calling it a duplicate. - Present, then wait. Nothing is written until you give an explicit action word (
do it/create/dup/skip). Flagging a missed alert is not approval.
Assignee is derived from .github/CODEOWNERS (last match wins) + TEAM.md, never guessed. Estimates use the Linear estimate field in points per PLANNING.md (1 pt = ΒΌ day).
Slack reaction key β
| Reaction | Meaning |
|---|---|
β
white_check_mark | New issue created (thread links it) |
β no_entry | Duplicate of / covered by an existing linked issue |
β fast_forward | Not-actionable, no linked issue (browser/3rd-party/transient/rule noise) |
| (none) | On hold β log not found yet; come back to it |
The Slack MCP can't edit messages or remove reactions β get it right the first time.
Fixed facts β
- #alerts
C0AQ0UZL0RMΒ· #devC09CL4Q7Y3D - Loki datasource UID
grafanacloud-logsΒ· Tempografanacloud-traces - Backend log label:
service_name="tellia-agri-backend"Β· env labeldeployment_environment - #alerts carries several Grafana rules (error-log, OpenAI-error, BullMQ-failure, HTTP-5xx, HTTP-latency) β the Slack block is empty, so one failing job can trip several at once.
Weekly recap β
When asked for the weekly report, the skill renders it in chat first (wait for approval), then saves to ~/Documents/WeeklyReport/triage-report-<start>_to_<end>.md and posts to #dev. It includes a per-issue fix-status (Linear state + merged-PR check) and a Completed-this-week section (dev-team velocity).
See also β
- Dashboarding & Alerting β where the alert rules live
- Incident Response β for active production incidents