Skip to content

Cut Sentry event volume: sample traces, stop bot URLs causing 500s - #20

Merged
needs merged 1 commit into
masterfrom
sentry-quota-overage-cause
Aug 12, 2026
Merged

Cut Sentry event volume: sample traces, stop bot URLs causing 500s#20
needs merged 1 commit into
masterfrom
sentry-quota-overage-cause

Conversation

@needs

@needs needs commented Aug 12, 2026

Copy link
Copy Markdown
Owner

The frontend ran tracesSampleRate: 1 across the server, client and edge configs, so every request became a transaction with a span per Prisma query and nothing absorbed it (/ and /status are force-dynamic, every other page reads searchParams); it now samples 1% via SENTRY_TRACES_SAMPLE_RATE, drops crawlers with isbot, and drops the tunnel route and static paths with Sentry's ignoreTransactions.

Two unguarded parses also turned ordinary bot traffic into unhandled 500s that were each billed as an error event — decodeString threw URIError on any malformed percent-escape (/player/%, used by the player, clan, gametype and map routes) and the [port] param coerced without a fallback, so both now fall back to a value that matches no record and 404 instead of throwing.

Added app/error.tsx, which reports only client-side errors (server ones already arrive reported, keyed off error.digest) so nothing is billed twice, and made the root layout's query degrade to empty tabs since error.tsx cannot catch root-layout errors.

Removed the per-game-server captureMessage in gameServerScheduler, which fired once per server per 5-minute poll — roughly 10k events an hour at ~900 servers — for a single global condition already logged once a minute.

Replay session sampling also drops from 0.1 to 0 against a free-plan allowance of ~50 per month, and isbot is the only added dependency.

🤖 Generated with Claude Code

The frontend ran tracesSampleRate: 1 on the server, client and edge, so
every request became a transaction with a span per Prisma query. Nothing
absorbed that traffic: / and /status are force-dynamic and every other
page reads searchParams. Sample 1% instead (SENTRY_TRACES_SAMPLE_RATE),
drop crawlers via isbot, and drop the tunnel route and static paths via
ignoreTransactions.

Separately, two unguarded parses turned ordinary bot traffic into
unhandled 500s, each one a billed error event:

- decodeString called decodeURIComponent on user-controlled path
  segments, which throws URIError on any malformed percent-escape
  (/player/%). Used by the player, clan, gametype and map routes.
- The [port] param coerced without a fallback, so /server/1.2.3.4/x
  threw. generateMetadata hit this even though the page already guarded
  with safeParse.

Both now fall back to a value that matches no record, so these 404 rather
than throwing. Added app/error.tsx, which reports only client-side errors
(server ones already arrive reported, keyed off error.digest), and made
the root layout's query degrade to empty tabs, since error.tsx cannot
catch root layout errors.

Also removed the per-game-server captureMessage in gameServerScheduler:
it fired once per server per 5-minute poll, which at ~900 servers is
~10k events an hour for a single global condition already logged once a
minute. It was inert only because apps/scheduler/src/sentry.ts is never
imported.

Replay session sampling goes 0.1 -> 0 (free plan allows ~50/month).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@needs
needs merged commit de41a10 into master Aug 12, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant