Sentry is an application monitoring platform that helps developers track errors, performance issues, and application health in real-time. It provides:
- Error Monitoring: Captures uncaught exceptions and manually reported errors with detailed stack traces, context, and breadcrumbs.
- Performance Monitoring: Tracks performance metrics like request latency, transaction durations, and slow API calls using distributed tracing.
- Session Replay: Records user sessions to help reproduce issues (not supported in Cloudflare Workers due to runtime limitations).
- Logging: Captures logs and custom events for debugging.
- Source Maps: Maps minified production code to your source code for readable stack traces.
- Release Tracking: Associates errors with specific code releases for easier debugging.
Sentry supports JavaScript environments, including Node.js, browsers, and serverless platforms like Cloudflare Workers, through dedicated SDKs.
Key Concepts of Sentry
- DSN (Data Source Name): A unique identifier for your Sentry project, used to send events to Sentry. It looks like
https://<key>@o<org_id>.ingest.sentry.io/<project_id>. - Breadcrumbs: A trail of events (e.g., user actions, HTTP requests) leading up to an error, providing context.
- Integrations: Plugins like
browserTracingIntegrationorconsoleLoggingIntegrationthat extend Sentry’s functionality. - Tracing: Tracks performance by creating spans for operations like HTTP requests or database queries.
- Source Maps: Maps minified code to source code, crucial for debugging in production.
- Crons Monitoring: Monitors scheduled tasks (e.g., Cloudflare Workers’ cron triggers).
- Experiments: Features like logging (
enableLogs) that are in beta.
For Cloudflare Workers, Sentry provides the @sentry/cloudflare SDK, designed to work with the Workers runtime, which differs from Node.js and browser environments due to its V8-based, serverless nature.
Challenges with Next.js + Cloudflare Workers
Cloudflare Workers use the workerd runtime, which has limitations compared to Node.js:
- No full Node.js API: Only a subset of Node.js APIs is available via compatibility flags (
nodejs_compatornodejs_als). - Event Loop Constraints: Asynchronous tasks (e.g., Sentry’s event sending) may be canceled if not handled properly, requiring
event.waitUntil()to ensure completion. - Middleware Limitations: Next.js middleware running on Workers has issues with top-level async operations (e.g.,
randomUUID), which can conflict with Sentry’s initialization. - Source Maps: Workers’ minified code requires source maps for readable stack traces, which need special handling.
The @sentry/nextjs SDK is optimized for Node.js-based Next.js deployments (e.g., Vercel), but it’s not fully compatible with Cloudflare Workers due to runtime differences. Instead, you’ll use @sentry/cloudflare and configure it to work with Next.js.
Step-by-Step Integration Guide
Here’s how to integrate Sentry with a Next.js + TypeScript project deployed on Cloudflare Workers using the @opennextjs/cloudflare adapter.
1. Set Up a Sentry Project
- Log in to Sentry.io and create a new project.
- Choose JavaScript as the platform (Cloudflare Workers isn’t listed explicitly but is supported via the
@sentry/cloudflareSDK). - Note the DSN provided by Sentry for your project.
2. Install Dependencies
In your Next.js project, install the Sentry Cloudflare SDK and TypeScript types:
npm install @sentry/cloudflare @cloudflare/workers-types
If you’re using the nodejs_compat flag in your wrangler.toml, also install Node.js types:
npm install -D @types/node
3. Configure Wrangler for TypeScript and Compatibility
Ensure your wrangler.toml is set up to support TypeScript and Sentry’s requirements:
name = "your-worker-name"
compatibility_date = "2024-09-23" # Or later
compatibility_flags = ["nodejs_als"] # Required for Sentry's AsyncLocalStorage
main = "worker.js" # Entry point for your Worker
[build]
command = "npx @opennextjs/cloudflare"
[build.upload]
format = "modules"
- Run
wrangler typesto generate TypeScript types for your Worker’s bindings and runtime, which will create aworker-configuration.d.tsfile. - Update your
tsconfig.jsonto include the generated types:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"strict": true,
"types": ["@cloudflare/workers-types", "./worker-configuration.d.ts"]
}
}
4. Initialize Sentry in Your Worker
Since Next.js on Cloudflare Workers uses the @opennextjs/cloudflare adapter, you’ll wrap your Worker’s handler with Sentry. Create or modify the Worker entry point (e.g., worker.ts) to initialize Sentry.
Example worker.ts:
import * as Sentry from '@sentry/cloudflare';
import { withSentry } from '@sentry/cloudflare';
import { createRequestHandler } from '@opennextjs/cloudflare';
// Initialize your Next.js app
const app = createRequestHandler({
// Your OpenNext configuration
});
// Sentry configuration
const sentryOptions = {
dsn: process.env.SENTRY_DSN || 'https://<your-dsn>@o0.ingest.sentry.io/<project-id>',
tracesSampleRate: 1.0, // Capture 100% of transactions for performance monitoring
sendDefaultPii: true, // Include request headers and IP (be cautious with PII)
release: process.env.CF_VERSION_METADATA?.id, // Use Cloudflare's version metadata
_experiments: {
enableLogs: true, // Enable logging to Sentry
},
};
// Wrap the Next.js handler with Sentry
export default withSentry(sentryOptions, app);
- DSN: Replace with your Sentry project’s DSN.
- tracesSampleRate: Set to
1.0for full tracing or lower (e.g.,0.2) to sample fewer transactions. - release: Use Cloudflare’s version metadata for release tracking.
- enableLogs: Enables console logs to be sent to Sentry.
5. Handle Middleware (Optional)
If your Next.js app uses middleware (e.g., middleware.ts), you may encounter issues with Sentry’s initialization due to top-level async operations. To work around this, use wrapRequestHandler instead of sentryPagesPlugin.
Example middleware.ts:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import * as Sentry from '@sentry/cloudflare';
import { getRequestContext } from '@cloudflare/next-on-pages';
export async function middleware(request: NextRequest) {
const context = getRequestContext();
const requestHandlerOptions = {
options: {
dsn: context.env.SENTRY_DSN,
tracesSampleRate: 1.0,
},
request,
context: context.platform.ctx,
};
return Sentry.wrapRequestHandler(requestHandlerOptions, () => NextResponse.next());
}
- getRequestContext: Accesses Cloudflare’s environment and context.
- wrapRequestHandler: Ensures Sentry captures errors in middleware without top-level async issues.
6. Upload Source Maps
To make stack traces readable, upload source maps to Sentry. Configure your wrangler.toml to enable source map uploading:
[build.upload]
source_maps = true
Use the Sentry CLI to upload source maps during deployment:
npm install -g @sentry/cli
SENTRY_AUTH_TOKEN=<your-auth-token> sentry-cli sourcemaps upload --org <your-org> --project <your-project> ./dist
- Get your
SENTRY_AUTH_TOKENfrom Sentry’s settings. - Ensure your build process generates source maps (e.g., set
sourceMap: truein your Webpack config if using a custom setup).
7. Capture Manual Events
You can manually capture errors, messages, or breadcrumbs in your Next.js components or API routes:
import * as Sentry from '@sentry/cloudflare';
// In an API route or server-side function
export async function GET(request: Request) {
try {
// Your logic
Sentry.addBreadcrumb({ message: 'Fetching data', level: 'info' });
throw new Error('Something went wrong');
} catch (error) {
Sentry.captureException(error);
return new Response('Error occurred', { status: 500 });
}
}
8. Instrument Cloudflare Bindings
If your app uses Cloudflare bindings (e.g., D1 database, R2 storage), instrument them with Sentry:
import * as Sentry from '@sentry/cloudflare';
// Instrument D1 database
const db = Sentry.instrumentD1WithSentry(env.DB);
await db.prepare('SELECT * FROM table WHERE id = ?').bind(1).run();
9. Monitor Cron Jobs
If your Worker uses scheduled tasks, use withMonitor for cron monitoring:
export default {
async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext) {
ctx.waitUntil(
Sentry.withMonitor('my-cron-job', async () => {
// Your cron logic
}, {
schedule: { type: 'crontab', value: '* * * * *' },
checkinMargin: 2,
maxRuntime: 10,
})
);
},
};
10. Deploy and Test
- Deploy your Worker using
wrangler deploy. - Test Sentry by throwing an intentional error (e.g., add
throw new Error('Test error')in an API route). - Check Sentry’s dashboard to verify errors, performance traces, and logs.
11. Troubleshooting
- Errors not captured: Ensure
nodejs_alsornodejs_compatis set inwrangler.toml. Useevent.waitUntil()for async Sentry operations. - Middleware issues: Avoid top-level async code in
middleware.ts. UsewrapRequestHandleras shown above. - Unreadable stack traces: Verify source maps are uploaded and match your deployed code.
- Performance: Set
tracesSampleRateto a lower value (e.g.,0.2) in production to reduce overhead.
Best Practices
- Environment Variables: Store
SENTRY_DSNinwrangler.tomlor Cloudflare’s dashboard to avoid hardcoding. - Minimal PII: Disable
sendDefaultPiiif you don’t need user IPs or headers to comply with privacy regulations. - Optimize Tracing: Adjust
tracesSampleRatebased on your traffic to balance monitoring and cost. - CI/CD Integration: Automate source map uploads in your deployment pipeline using Sentry CLI.
- Testing Locally: Use
wrangler devto test your Worker locally and verify Sentry integration.
Limitations
- Session Replay: Not supported in Cloudflare Workers due to runtime constraints.
- Middleware Compatibility:
@sentry/nextjsmiddleware integration may not work due torandomUUIDissues. Use@sentry/cloudflare’swrapRequestHandler. - Tail Workers: Cloudflare’s Sentry integration via Tail Workers is not supported for Pages projects and is limited to error reporting.
References
- Sentry Cloudflare SDK: docs.sentry.io
- Cloudflare Workers Docs: developers.cloudflare.com
- Next.js on Cloudflare: developers.cloudflare.com
- Sentry Next.js Issues: github.com
Comments