Enable privacy-safe Sentry DB query tracing - #1540
Conversation
Turn on a 10% traces sample rate with Supabase span instrumentation so Sentry Queries can show slowest tables/operations, while keeping PostgREST filters, mutation bodies, and other clinical payloads redacted. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in:56 seconds Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThe PR enables configurable Sentry performance tracing for Supabase operations. It adds privacy-safe transaction and span scrubbing, server and edge wiring, admin client instrumentation, tests, and configuration documentation. ChangesSentry tracing and privacy controls
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant SupabaseClient
participant SentryIntegration
participant SentrySDK
participant TransactionScrubber
SupabaseClient->>SentryIntegration: emit PostgREST operation span
SentryIntegration->>SentrySDK: submit sampled transaction
SentrySDK->>TransactionScrubber: process transaction event
TransactionScrubber-->>SentrySDK: return sanitized transaction
Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Comment |
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
BigSimmo
commented
Jul 31, 2026
@cursoragent Unblock the current open PR. Confirm the PR number and GitHub head first from context. If more than one open PR could apply, stop and say which one you would use and why. Fetch and start from the remote tip that matches that GitHub head. If the named branch ref is missing or stale, use the PR head ref. Preserve unrelated local WIP; do not discard dirty work; do not treat a local-ahead commit as the reviewed tip. Do not merge the PR, force-push, rebase, or arm auto-merge. No provider-backed gates without approval. If you cannot push or resolve threads, diagnose and comment only; if inline replies fail, resolve when possible and put blocker dispositions in the summary comment. If auto-merge is already armed, push only for a real blocker and avoid cancelling in-flight required CI unless the push clears that blocker. If the PR is already merged or closed: confirm outcome, post one summary, and stop. Primary job: clear mergeability and required-CI blockers on this tip. Do a full product review only if needed to explain or fix a blocker. Stay light otherwise—no broad verification suites or Playwright unless needed to prove one concrete unblock fix. Snapshot the GitHub head: tip, behind/ahead, mergeable state, merge-tree versus origin/main (real conflict versus behind-but-clean), required checks on that tip including Production UI when selected, and unresolved threads that block merge or required CI. Missing checks while dirty are not green. Tip moved → re-snapshot. Ledger-lookup against that GitHub head under an unblock/fix scope for this PR. If already handled at this head for unblock work, merge-tree clean, required checks green, and no blocking threads: summarize, comment, stop. Unblock once: real conflict → merge origin/main with the smallest correct resolution (prefer main’s shared queues; keep this PR’s notes); behind-but-clean → one sync, late if required CI is in flight; clean → leave. skip-branch-sync and similar labels do not block a manual sync needed to clear a real blocker. No sync thrash. After any sync or push, re-snapshot tip, merge-tree, and required checks before declaring done. Dedupe the ledger if a merge touched it. Fix only what blocks required checks or mergeability on this tip. Ignore advisory red unless it reveals a real required failure. Prefer the smallest safe fix; if a bot/autofix commit caused the break, prefer revert. Prove with the smallest targeted check only. Format and commit before push. Push only blocker-fix commits. Append ledger for the final GitHub head under the unblock scope. Never push a ledger-only tip. One PR comment: tip, sync/merge-tree, what blocked and what you fixed or dispositioned, required CI status, residual risks; merge left to me. Stop when merge-tree is clean on the current GitHub tip, no blocking threads remain for merge/required CI, and required checks are green or clearly in progress. |
PR #1540 — tip Blocker: Fix pushed: local structural types instead of State: merge-tree clean, behind 0 / ahead 2, no blocking threads, auto-merge off. Required CI re-queued on the new tip ( |
PR Summary by QodoEnable privacy-safe Sentry Supabase DB query tracing
AI Description
Diagram
High-Level Assessment
Files changed (8) |
Static PR checks failed check:knip on an unlisted @sentry/core import. Use local structural transaction/span types instead so the privacy scrubber stays dependency-clean. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
Unblock summary — PR #1540Tip: What blocked
What I fixed
Required CI status
Residual risks
Merge left to you. |
Code Review by Qodo
1. Edits committed to .env.example |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Append the pr-1540-unblock review row for 0dfb7a3 after the static-pr knip fix landed. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
BigSimmo
commented
Jul 31, 2026
@cursoragent Work the current open PR. Confirm the PR number and GitHub head first from context. If more than one open PR could apply, stop and say which one you would use and why. Fetch and start from the remote tip that matches that GitHub head. If the named branch ref is missing or stale, use the PR head ref. Preserve unrelated local WIP; do not discard dirty work; do not treat a local-ahead commit as the reviewed tip. Do not merge the PR, force-push, rebase, or arm auto-merge unless I explicitly ask. No provider-backed gates without approval. If you cannot push or resolve threads, diagnose and comment only; if inline replies fail, resolve when possible and put dispositions in the summary comment. If auto-merge is already armed, push only for a real blocker and avoid cancelling in-flight required CI unless the push clears that blocker. If the PR is already merged or closed: confirm outcome, post one summary, and stop. Goal: review and Bugbot the tip, fix actionable issues with the smallest correct changes, clear merge / required-CI / thread blockers, prove fixes with focused local checks, push, append ledger, and post one PR summary. Use broader offline gates only when the delta or a failed required check warrants them. Regenerate large assets only when a fix requires it. Snapshot the GitHub head: tip, behind/ahead, mergeable state, merge-tree versus origin/main, required checks on that tip including Production UI when selected, unresolved actionable threads. Missing checks while dirty are not green. Tip moved → re-snapshot. Ledger-lookup against that GitHub head under the review-and-fix scope for this PR. Already reviewed at this head with clean merge-tree, green required checks, and no new actionable threads → summarize, comment, stop unless I asked for a fresh superseding pass. Unblock once: real conflict → merge origin/main (prefer main’s shared queues; keep this PR’s notes); behind-but-clean → one sync, late if required CI is in flight; clean → leave. After any sync or push, re-snapshot before declaring done. No sync thrash. Review high-confidence issues only. Separate PR-introduced defects from pre-existing re-emitted data. For generated assets, review contracts, aliases, and cache—not every generated line. Flag RAG or governance before editing; fix PR-body policy text only when wrong or missing. Ignore bot noise. Fix P0/P1 always; clear scoped P2 when locally provable; else disposition and resolve. Required-check failures on this tip only; ignore advisory. Prove each fix with the smallest targeted check; escalate to cheap or PR-local verification only when the change set, risk surface, or CI failure needs that breadth. Format and commit before push. Push only this PR’s fix commits. Append ledger for the final GitHub head. Never push a ledger-only tip. One PR comment: tip, sync/merge-tree, fixed versus dispositioned, required CI, decisive local proof, residual risks; merge left to me. Stop when merge-tree is clean on the current GitHub tip, no actionable threads remain, required checks are green or clearly in progress, summary posted, merge left to me. |
PR #1540 tip Fixed
Dispositioned
State: merge-tree clean, 3/3 threads resolved, required CI in progress on the new tip. Merge left to you. |
Move Supabase client instrumentation into a server-only module so error-tracking stays Edge-safe, and install DB tracing only when a DSN is set and SENTRY_TRACES_SAMPLE_RATE resolves above zero. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Review-and-fix summary — PR #1540Tip: Fixed
Dispositioned
All three Qodo threads replied + resolved. Required CIRe-queued on Local proof
Residual risks
Merge left to you. |
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/lib/observability/error-tracking.ts (1)
97-106: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider Zod for sample-rate parsing.
resolveTracesSampleRatemanually parses and range-checksSENTRY_TRACES_SAMPLE_RATEwithNumber()andNumber.isFinite. As per coding guidelines,**/*.{ts,tsx}files must "validate environment variables and requests with Zod 4." A schema such asz.coerce.number().min(0).max(1).catch(DEFAULT_TRACES_SAMPLE_RATE)would centralize this validation and match the project convention.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/observability/error-tracking.ts` around lines 97 - 106, Update resolveTracesSampleRate to validate SENTRY_TRACES_SAMPLE_RATE through a Zod 4 schema using coercion and inclusive 0–1 bounds, with DEFAULT_TRACES_SAMPLE_RATE as the fallback for missing, blank, non-numeric, or out-of-range values. Remove the manual Number and Number.isFinite validation while preserving the function’s existing return behavior.Source: Coding guidelines
tests/error-tracking.test.ts (1)
75-142: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the auth-operation and fallback span-description branches.
The current test covers the
db.table/db.operationcombination but not theauth.-prefixed operation branch or the parameterized-route fallback branch ofprivacySafeSpanDescription(src/lib/observability/error-tracking.tsLines 112-114 and 122-132). These branches decide what span description text is exported to Sentry, so untested paths could silently leak or drop data if the regex/logic regresses.🧪 Suggested additional test cases
it("keeps auth spans and drops free-form/query-bearing fallback descriptions",()=>{constauthSpan=privacySafeTransactionEvent({type: "transaction",spans: [{span_id: "span-auth",trace_id: "trace-1",op: "auth",start_timestamp: 1,data: {"db.operation": "auth.signInWithPassword"},},],}).spans?.[0];expect(authSpan?.description).toBe("auth signInWithPassword");constfallbackSpan=privacySafeTransactionEvent({type: "transaction",spans: [{span_id: "span-route",trace_id: "trace-1",description: "GET /api/answer?q=Jane",start_timestamp: 1,data: {},},],}).spans?.[0];expect(fallbackSpan?.description).toBeUndefined();});🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/error-tracking.test.ts` around lines 75 - 142, Extend the privacySafeTransactionEvent tests with separate auth and fallback span cases. Verify an auth operation such as auth.signInWithPassword produces the privacy-safe description “auth signInWithPassword”, and verify a parameterized or query-bearing fallback description such as a route with query data is omitted. Anchor both assertions to the returned span description.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/lib/observability/error-tracking.ts`:
- Around line 97-106: Update resolveTracesSampleRate to validate
SENTRY_TRACES_SAMPLE_RATE through a Zod 4 schema using coercion and inclusive
0–1 bounds, with DEFAULT_TRACES_SAMPLE_RATE as the fallback for missing, blank,
non-numeric, or out-of-range values. Remove the manual Number and
Number.isFinite validation while preserving the function’s existing return
behavior.
In `@tests/error-tracking.test.ts`:
- Around line 75-142: Extend the privacySafeTransactionEvent tests with separate
auth and fallback span cases. Verify an auth operation such as
auth.signInWithPassword produces the privacy-safe description “auth
signInWithPassword”, and verify a parameterized or query-bearing fallback
description such as a route with query data is omitted. Anchor both assertions
to the returned span description.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 08d7e5dd-fbb4-4c13-8fcf-4a80e0484ea9
📒 Files selected for processing (9)
.env.exampledocs/branch-review-ledger.mddocs/codebase-index.mddocs/error-tracking.mdsrc/lib/observability/error-tracking.tssrc/lib/supabase/admin.tssrc/sentry.edge.config.tssrc/sentry.server.config.tstests/error-tracking.test.ts
Uh oh!
There was an error while loading. Please reload this page.


Summary
SENTRY_TRACES_SAMPLE_RATE, set0to disable) so Supabase PostgREST spans can populate Sentry Queries / Traces.Sentry.supabaseIntegration(plus admin-clientinstrumentSupabaseClientForTracing) withsendOperationData: false/dataCollection.databaseQueryData: falseso filter values and mutation bodies are never attached.privacySafeTransactionEventto rewrite span descriptions toselect from(<table>)and allowlist only safe DB attributes before export; keep breadcrumbs off (maxBreadcrumbs: 0).SENTRY_TRACES_SAMPLE_RATE=0), and.env.exampleknobs; extend unit coverage for sampling + transaction scrubbing.Verification
npx vitest run tests/error-tracking.test.ts— 5/5 passednpx tsc --noEmit— cleannpm run verify:pr-local— passed (format, lint, typecheck, full unit suite, production build, RAG fixtures)Risk and rollout
sendOperationData: truewould be a privacy regression — guarded in init + scrubber tests.SENTRY_TRACES_SAMPLE_RATE=0(or removeSENTRY_DSN) and restart.SENTRY_DSNset, Sentry begins receiving sampled transactions with redacted DB spans. Confirm one sample in Explore → Traces and Dashboards → Queries after deploy.Notes
NEXT_PUBLICDSN path).Summary by CodeRabbit
New Features
SENTRY_TRACES_SAMPLE_RATE=0.Documentation