Sentry
CÉNIT usa Sentry para captura de errores y observabilidad en los
tres runtimes de Next.js: client, server y edge. Cada
runtime tiene su config separada (sentry.client.config.ts,
sentry.server.config.ts, sentry.edge.config.ts). En producción,
el server y edge runtime corren bajo Cloudflare Workers — donde
@sentry/cloudflare toma el control vía worker-entry.ts y los
init de @sentry/nextjs quedan deshabilitados para evitar doble
captura.
Configuración por runtime
Sección titulada «Configuración por runtime»Client (sentry.client.config.ts)
Sección titulada «Client (sentry.client.config.ts)»- DSN:
NEXT_PUBLIC_SENTRY_DSN. tracesSampleRate: 100% en dev, 10% en prod.replaysOnErrorSampleRate: 50% en prod (replays conmaskAllText: trueyblockAllMedia: truepara no exponer datos sensibles).replaysSessionSampleRate: 0 — no se graban sesiones sanas.
Server (sentry.server.config.ts)
Sección titulada «Server (sentry.server.config.ts)»- DSN:
SENTRY_DSN(sin prefijoNEXT_PUBLIC_). tracesSampleRate: 10% en prod.- Skip si
NEXT_RUNTIME === 'cloudflare'—@sentry/cloudflareya está activo en ese entorno; init doble dispararía eventos duplicados.
Edge (sentry.edge.config.ts)
Sección titulada «Edge (sentry.edge.config.ts)»- DSN:
SENTRY_DSN. tracesSampleRate: 50% en prod.- Mismo skip por
NEXT_RUNTIME === 'cloudflare'.
Scrubbing de PII
Sección titulada «Scrubbing de PII»beforeSend() filtra campos sensibles del payload antes de enviar el
evento a Sentry. Lista actual (client + server):
- Auth:
password,confirm,token,api_key,secret,service_role_key. - Clínica:
diagnosis,notes,mental_notes,injury_type,body_part. - Wellness:
muscle_soreness,fatigue,stress,sleep_quality,rpe,hooper_index.
Cualquier match se reemplaza por [Filtered]. Esto es defense in
depth — el origen de la PII debería estar en server actions, donde el
payload del request no debería incluir estos campos en form-data.
Release tracking
Sección titulada «Release tracking»Cada evento se taggea con el commit SHA del build:
- Client:
NEXT_PUBLIC_GITHUB_SHA(inlineada en el bundle). - Server / edge:
GITHUB_SHA.
CI (cloudflare-deploy.yml) exporta estas vars en el env: del job
de build, así Sentry vincula cada evento al deploy exacto. En local
quedan undefined y los eventos no se tagan.
En producción los tag pushes (v*) crean releases nombradas con
el tag; los deploys de staging usan el SHA del commit.
Patrones de uso
Sección titulada «Patrones de uso»Captura explícita con contexto
Sección titulada «Captura explícita con contexto»Sentry.withScope(scope => { scope.setTag('email_to', to) scope.setExtra('resend_status', res.status) scope.setLevel('error') Sentry.captureException(new Error('Resend API error'))})Ver lib/send-email.ts y app/api/stripe/webhook/route.ts para
ejemplos canónicos.
Tags transversales
Sección titulada «Tags transversales»Convención de tags útiles: route: stripe/webhook, event: checkout.session.completed, eventId: evt_xxx, email_to,
customerId. Permiten filtrar incidentes rápido en el dashboard.
Variables de entorno
Sección titulada «Variables de entorno»NEXT_PUBLIC_SENTRY_DSN=SENTRY_DSN=NEXT_PUBLIC_GITHUB_SHA= # CIGITHUB_SHA= # CISENTRY_AUTH_TOKEN= # solo para upload de sourcemaps en buildIntegraciones
Sección titulada «Integraciones»- Email (Resend) —
sendEmailcaptura errores de Resend con tags. - Plans y billing — el webhook de Stripe captura todo error de procesamiento.
- CI/CD — el SHA del build se inyecta como release.
Limitaciones / roadmap
Sección titulada «Limitaciones / roadmap»- Error digests de Next.js 16 en producción — Next reemplaza los
mensajes del server por un código digest (
XXXXXXXX@EX). Para debuggear el mensaje real hay que ir a Sentry (donde sí queda loggeado) o a los logs de Workers (wrangler tail). - Replays a 50% en prod — alto, pero útil mientras estamos descubriendo bugs de UI. Bajar a 20-30% una vez estable.
- Lista de scrubbing manual — agregar campos clínicos nuevos al array de SCRUB cuando aparezcan en formularios futuros.