- Create /chinh-sach-bao-mat (Privacy Policy) with 10 sections - Create /dieu-khoan-su-dung (Terms of Service) with 11 sections - Add legal link group to footer (vi + en i18n) - Add legalLinks prop to Footer for bottom-bar display - Wire links into public layout Co-Authored-By: Paperclip <noreply@paperclip.ing>
6.3 KiB
Sentry Alert Routing — Runbook
Audience: SRE on-call & platform engineers. Scope: How Sentry P1/P2 alerts are wired into Slack & email for the GoodGo platform, and how to verify routing end-to-end. Related ticket: GOO-178 (gap surfaced by GOO-117 audit).
1. Sentry projects & SDK wiring
The SDK is initialised in three Next.js entrypoints (server, client, edge):
| File | DSN env | Notes |
|---|---|---|
apps/web/sentry.server.config.ts |
SENTRY_DSN |
Server-side errors, traces (tracesSampleRate=0.2 in prod). |
apps/web/sentry.client.config.ts |
NEXT_PUBLIC_SENTRY_DSN |
Browser errors + session replay on error. |
apps/web/sentry.edge.config.ts |
SENTRY_DSN |
Edge runtime. |
Required env (see .env.example):
SENTRY_DSN,NEXT_PUBLIC_SENTRY_DSNSENTRY_AUTH_TOKEN(CI source-map upload)SENTRY_ORG,SENTRY_PROJECTSENTRY_RELEASE/NEXT_PUBLIC_SENTRY_RELEASE(set per deploy by CI)
environment is set from NODE_ENV on every init call, so all events are tagged production / staging / development automatically.
2. Severity model
We classify Sentry events into two routing tiers using event tags. Tag severity is set either by the SDK (Sentry.setTag('severity', 'P1')) at capture time, or via Sentry Issue tagging rules based on event.level / fingerprint.
| Tier | Trigger criteria | Routing target | SLA |
|---|---|---|---|
| P1 | level:fatal OR tags[severity]=P1 OR fingerprint in critical group (payments, auth, data loss) |
Slack #alerts-p1-sentry (immediate) + email to oncall@goodgo.vn |
Page on-call within 5 min |
| P2 | level:error AND environment:production AND not P1 |
Slack #alerts-p2-sentry (digest, every 30 min) |
Triage within 4 business hours |
| Below P2 (warn / info / staging-only) | Everything else | No paging — visible only in Sentry UI dashboards | Best effort |
3. Required Sentry integrations
Verify in Sentry → Settings → Integrations:
- Slack — workspace
goodgo, channels#alerts-p1-sentryand#alerts-p2-sentryauthorised. - Email — built-in;
oncall@goodgo.vnis a verified team mailing list and a member of the GoodGo team for the project.
If either integration is missing, install it before configuring rules below.
4. Alert rule configuration
Configure under Sentry → Alerts → Create Alert → Issues.
4.1 P1 — immediate page
- Name:
P1 — immediate page - Environment:
production - When: "An issue is first seen" OR "An event is captured"
- If (all):
event.levelequalsfatal- OR
event.tags[severity]equalsP1
- Then:
- Send a Slack notification to
#alerts-p1-sentry - Send an email notification to Team
oncall
- Send a Slack notification to
- Frequency: every 1 minute (no batching)
- Owner: SRE team
4.2 P2 — production errors digest
- Name:
P2 — production errors - Environment:
production - When: "An issue changes state from resolved to unresolved" OR "A new issue is created"
- If (all):
event.levelequalserrorevent.tags[severity]does not equalP1
- Then:
- Send a Slack notification to
#alerts-p2-sentry
- Send a Slack notification to
- Frequency: every 30 minutes (batched/digest)
4.3 Noise control
- Suppress alerts for environments other than
production(a separatestagingrule may post to#alerts-stagingonly). - Use Inbound filters to drop browser extension errors, ResizeObserver loops, and known third-party noise.
- Per-issue Mute → ignore until for known-noisy fingerprints.
5. Test fire procedure (Sentry.captureException)
Use this whenever rules change or a quarterly verification is due.
5.1 Staging fire
- Deploy the staging branch with
SENTRY_DSNpopulated. - Trigger the dedicated test endpoint (or via curl in staging shell):
// apps/web/app/api/_debug/sentry-test/route.ts (staging only — guard with env) import * as Sentry from '@sentry/nextjs'; export async function GET() { Sentry.captureException(new Error('GOO-178 routing test — P1'), { tags: { severity: 'P1', source: 'manual_routing_test' }, }); return Response.json({ ok: true }); }curl -fsS https://staging.goodgo.vn/api/_debug/sentry-test - Expected:
- Event appears in Sentry within ~30s tagged
severity:P1,source:manual_routing_test. - Slack
#alerts-p1-sentryreceives the notification. - Email lands at
oncall@goodgo.vnwithin ~2 min.
- Event appears in Sentry within ~30s tagged
- Repeat without the
severity:P1tag and withlevel:errorto validate the P2 batched route (expect Slack message in next 30-min digest).
5.2 CLI alternative (no deploy)
SENTRY_DSN=$STAGING_SENTRY_DSN npx -y @sentry/cli send-event \
--message "GOO-178 routing test (P1)" \
--level fatal \
--tag severity:P1 \
--tag source:manual_routing_test \
--release "$(git rev-parse --short HEAD)"
5.3 Cleanup
- Resolve the test issue in Sentry.
- Add
source:manual_routing_testto the inbound filter ignore list if it generates additional noise.
6. Verification checklist (run quarterly)
- Slack integration shows "Connected" in Sentry → Integrations.
- Email integration: open one P1 alert, confirm
oncall@goodgo.vnreceived it. - Both rules listed under Alerts with correct environment/scope.
- Test fire produces messages in
#alerts-p1-sentryAND#alerts-p2-sentryper tier. - On-call rotation in PagerDuty / Slack matches Sentry team membership.
- Inbound filters review — drop new noise sources surfaced since last review.
Record verification results as a comment on a tracking issue and update the last verified date in section 7.
7. Change log
| Date | Author | Change |
|---|---|---|
| 2026-04-23 | SRE Engineer (GOO-178) | Initial runbook documenting P1/P2 routing model, alert rule definitions, and test fire procedure. |
8. Outstanding
- Sentry org/project access not yet provisioned for the agent. Live verification of integrations + a real test fire is blocked until
SENTRY_AUTH_TOKEN,SENTRY_ORG,SENTRY_PROJECTare provided to staging and to the SRE agent. See GOO-178 for the open blocker.