Cloudflare

Learn how to manually set up Sentry for Cloudflare Workers and Cloudflare Pages and capture your first errors.

Use this guide for general instructions on using the Sentry SDK with Cloudflare. If you're using any of the listed frameworks, follow their specific setup instructions:

You need:

Choose the features you want to configure, and this guide will show you how:

Want to learn more about these features?
  • Issues (always enabled): Sentry's core error monitoring product that automatically reports errors, uncaught exceptions, and unhandled rejections. If you have something that looks like an exception, Sentry can capture it.
  • Tracing: Track software performance while seeing the impact of errors across multiple systems. For example, distributed tracing allows you to follow a request from the frontend to the backend and back.
  • Logs: Centralize and analyze your application logs to correlate them with errors and performance issues. Search, filter, and visualize log data to understand what's happening in your applications.

Run the command for your preferred package manager to add the Sentry SDK to your application:

Copied
npm install @sentry/cloudflare --save

The main Sentry configuration should happen as early as possible in your app's lifecycle.

Since the SDK needs access to the AsyncLocalStorage API, you need to set either the nodejs_compat or nodejs_als compatibility flags in your wrangler.(jsonc|toml) configuration file:

wrangler.jsonc
Copied
{
  "compatibility_flags": [
    "nodejs_als",
    // "nodejs_compat"
  ],
}

Additionally, add the CF_VERSION_METADATA binding in the same file:

wrangler.jsonc
Copied
{
  // ...
  "version_metadata": {
    "binding": "CF_VERSION_METADATA",
  },
}

Wrap your worker handler with the withSentry function, for example, in your index.ts file, to initialize the Sentry SDK and hook into the environment:

index.ts
Copied
import { Hono, HTTPException } from "hono";
import * as Sentry from "@sentry/cloudflare";

export default Sentry.withSentry(
  (env: Env) => {
    const { id: versionId } = env.CF_VERSION_METADATA;

    return {
      dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",

      release: versionId,

      // Adds request headers and IP for users, for more info visit:
      // https://docs.sentry.io/platforms/javascript/guides/cloudflare/configuration/options/#sendDefaultPii
      sendDefaultPii: true,
      //  logs

      // Enable logs to be sent to Sentry
      enableLogs: true,
      //  logs
      //  performance

      // Set tracesSampleRate to 1.0 to capture 100% of spans for tracing.
      // Learn more at
      https://docs.sentry.io/platforms/javascript/guides/cloudflare/configuration/options/#tracesSampleRate
      tracesSampleRate: 1.0,
      //  performance
    };
  },
  // your existing worker export
  app
);
Don't have access to onRequest?

If you don't have access to the onRequest middleware API, you can use the wrapRequestHandler API instead. For example:

Copied
// hooks.server.js
import * as Sentry from "@sentry/cloudflare";

export const handle = ({ event, resolve }) => {
  const requestHandlerOptions = {
    options: {
      dsn: event.platform.env.SENTRY_DSN,
      tracesSampleRate: 1.0,
    },
    request: event.request,
    context: event.platform.ctx,
  };
  return Sentry.wrapRequestHandler(requestHandlerOptions, () =>
    resolve(event),
  );
};

To use the Sentry SDK, add the sentryPagesPlugin as middleware to your Cloudflare Pages application. For this, we recommend you create a functions/_middleware.js file to set up the middleware for your entire app:

functions/_middleware.js
Copied
import * as Sentry from "@sentry/cloudflare";

export const onRequest = [
  // Make sure Sentry is the first middleware
  Sentry.sentryPagesPlugin((context) => {
    const { id: versionId } = env.CF_VERSION_METADATA;

    return {
      dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",

      release: versionId,

      // Adds request headers and IP for users, for more info visit:
      // https://docs.sentry.io/platforms/javascript/guides/cloudflare/configuration/options/#sendDefaultPii
      sendDefaultPii: true,
      //  logs

      // Enable logs to be sent to Sentry
      enableLogs: true,
      //  logs
      //  performance

      // Set tracesSampleRate to 1.0 to capture 100% of spans for tracing.
      // Learn more at
      // https://docs.sentry.io/platforms/javascript/guides/cloudflare/configuration/options/#tracesSampleRate
      tracesSampleRate: 1.0,
      //  performance
    };
  }),
  // Add more middlewares here
];

The stack traces in your Sentry errors probably won't look like your actual code. To fix this, upload your source maps to Sentry.

First, set the upload_source_maps option to true in your wrangler.(jsonc|toml) config file to enable source map uploading:

wrangler.jsonc
Copied
{
  "upload_source_maps": true,
}

Next, run the Sentry Wizard to finish your setup:

Copied
npx @sentry/wizard@latest -i sourcemaps

Let's test your setup and confirm that Sentry is working correctly and sending data to your Sentry project.

First, let's make sure Sentry is correctly capturing errors and creating issues in your project.

Add the following code snippet to your main worker file to create a /debug-sentry route that triggers an error when called:

index.js
Copied
export default {
  async fetch(request) {
    const url = new URL(request.url);

    if (url.pathname === "/debug-sentry") {
      throw new Error("My first Sentry error!");
    }

    // Your existing routes and logic here...
    return new Response("...");
  },
};

Create a new route that throws an error when called by adding the following code snippet to a file in your functions directory, such as functions/debug-sentry.js:

debug-sentry.js
Copied
export async function onRequest(context) {
  throw new Error("My first Sentry error!");
}

To test your tracing configuration, update the previous code snippet by starting a trace to measure the time it takes to run your code.

index.js
Copied
export default {
  async fetch(request) {
    const url = new URL(request.url);

    if (url.pathname === "/debug-sentry") {
      await Sentry.startSpan(
        {
          op: "test",
          name: "My First Test Transaction",
        },
        async () => {
          await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for 100ms
          throw new Error("My first Sentry error!");
        },
      );
    }

    // Your existing routes and logic here...
    return new Response("...");
  },
};

debug-sentry.js
Copied
export async function onRequest(context) {
  await Sentry.startSpan(
    {
      op: "test",
      name: "My First Test Transaction",
    },
    async () => {
      await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for 100ms
      throw new Error("My first Sentry error!");
    },
  );
}

Now, head over to your project on Sentry.io to view the collected data (it takes a couple of moments for the data to appear).

Need help locating the captured errors in your Sentry project?
  1. Open the Issues page and select an error from the issues list to view the full details and context of this error. For more details, see this interactive walkthrough.
  2. Open the Traces page and select a trace to reveal more information about each span, its duration, and any errors. For an interactive UI walkthrough, click here.
  3. Open the Logs page and filter by service, environment, or search keywords to view log entries from your application. For an interactive UI walkthrough, click here.

At this point, you should have integrated Sentry and should already be sending data to your Sentry project.

Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are:

Are you having problems setting up the SDK?
Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").