Migrate from 7.x to 8.x

Learn about migrating from Sentry JavaScript SDK 7.x to 8.x

The main goal of version 8 is to improve our performance monitoring APIs, integrations API, and ESM support. This version is breaking because we removed deprecated APIs, restructured npm package contents, and introduced new dependencies on OpenTelemetry.

Before updating to 8.x of the SDK, we recommend upgrading to the latest version of 7.x. To fix most of the deprecations on 7.x, you can use the @sentry/migr8 codemod to automatically update your SDK usage. @sentry/migr8 requires Node 18+.

Copied
npx @sentry/migr8@latest

Our migration tool will let you select which updates to run, and automatically update your code. In some cases, we cannot automatically change code for you. These will be marked with a TODO(sentry) comment instead. Make sure to review all code changes after running @sentry/migr8! For more details on the deprecations, see our docs on Deprecations in 7.x. Despite having @sentry/migr8, we still recommend reading the migration guide, since @sentry/migr8 does not cover all of the changes needed to migrate.

8.x simplifies Sentry Remix SDK initialization and leverages OpenTelemetry instrumentation for performance monitoring.

We recommend you read through all the Important Changes as they affect all SDK users. The Other Changes linked below only affect users who have more customized instrumentation. There is also a Troubleshooting section for common issues.

We also have a detailed migration guide on GitHub, which has a comprehensive list of all changes alongside the source code of the SDK.

Sentry Remix SDK 8.x supports Node 14.18.0 or higher

If you need to support older versions of Node.js, please use Sentry Remix SDK 7.x.

The SDK now only works with ES2018 compatible browsers. The minimum supported browser versions are:

  • Chrome 63
  • Edge 79
  • Safari/iOS Safari 12
  • Firefox 58
  • Opera 50
  • Samsung Internet 8.2

For IE11 support please transpile your code to ES5 using babel or similar and add required polyfills.

To migrate your Remix app to Sentry Node SDK 8.x, you need to make the following changes:

  1. Move your server-side Sentry.init call so that it is called before any other require/import statements in entry.server.tsx.

Due to the way that auto instrumentation works in 8.x of the Sentry Remix SDK, it is required that you initialize Sentry before you require or import any other package. Any package that is required/imported before Sentry is initialized may not be correctly auto-instrumented.

entry.server.tsx
Copied
import * as Sentry from '@sentry/remix';

Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  tracesSampleRate: 1.0,
});

export const handleError = Sentry.wrapRemixHandleError;

// rest of your code and imports
  1. Remove any performance related integrations from your server-side init in entry.server.tsx.

All performance auto-instrumentation will be automatically enabled if the package is found. You do not need to add any integration yourself, and autoDiscoverNodePerformanceMonitoringIntegrations() has also been removed.

entry.server.tsx
Copied
import * as Sentry from '@sentry/remix';

Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  tracesSampleRate: 1.0,
});

With 8.x, @sentry/remix on the server has been completely overhauled. It is now powered by OpenTelemetry under the hood. You do not need to know or understand what OpenTelemetry is in order to use Sentry. We set up OpenTelemetry under the hood. If you use OpenTelemetry-native APIs to start spans, Sentry will pick up everything automatically.

We now support the following integrations out of the box with 0 configuration:

  • httpIntegration: Automatically instruments Node http and https standard libraries
  • nativeNodeFetchIntegration: Automatically instruments top level fetch and undici
  • graphqlIntegration: Automatically instruments GraphQL
  • mongoIntegration: Automatically instruments MongoDB
  • mongooseIntegration: Automatically instruments Mongoose
  • mysqlIntegration: Automatically instruments MySQL
  • mysql2Integration: Automatically instruments MySQL2
  • postgresIntegration: Automatically instruments PostgreSQL
  • prismaIntegration: Automatically instruments Prisma
  1. Move your client-side Sentry.init call so that it is called before any other require/import statements in entry.client.tsx.
Copied
 import * as Sentry from "@sentry/angular";

 Sentry.init({
   dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
-  integrations: [
-    new Sentry.BrowserTracing({
-      routingInstrumentation: Sentry.routingInstrumentation(router),
-    })
-  ],
+  integrations: [Sentry.browserTracingIntegration({ router })],
 });

For any non-HTTP scenarios (e.g. websockets or a scheduled job), you'll have to manually ensure request isolation by wrapping the function with Sentry.withIsolationScope(). Previously we recommended you use Sentry.runWithAsyncContext for this but that has been removed in 8.x.

Copied
const Sentry = require('@sentry/node');

function myScheduledJob() {
  return Sentry.withIsolationScope(async () => {
    await doSomething();
    await doSomethingElse();
    return { status: 'DONE' };
  });
}

This way, anything happening inside of this function will be isolated, even if they run concurrently.

The Custom Instrumentation API for Performance Monitoring has been revamped in 8.x. New methods have been introduced, and startTransaction and span.startChild has been removed. See the new Performance Monitoring APIs docs for more information.

The enableAnrDetection and Anr class exports have been removed the SDK. Instead you can now use the Sentry.anrIntegration to enable Application Not Responding detection

Copied
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [
    Sentry.anrIntegration({ captureStackTrace: true })
  ],
});

Previously the SDK exited the process by default, even though additional onUncaughtException may have been registered, that would have prevented the process from exiting. You could opt out of this behaviour by setting the exitEvenIfOtherHandlersAreRegistered: false in the onUncaughtExceptionIntegration options. Up until now the value for this option defaulted to true.

Going forward, the default value for exitEvenIfOtherHandlersAreRegistered will be false, meaning that the SDK will not exit your process when you have registered other onUncaughtException handlers.

The deepReadDirSync method has been removed as an export from the SDK. There is no replacement API.

The Sentry tRPC middleware got moved from Sentry.Handlers.trpcMiddleware() to Sentry.trpcMiddleware().

The SDK no longer filters out health check transactions by default. Instead, they are sent to Sentry but still dropped by the Sentry backend by default. You can disable dropping them in your Sentry project settings. If you still want to drop specific transactions within the SDK you can either use the ignoreTransactions SDK option.

The @sentry/replay package is no longer required. Instead you can import the relevant methods directly from your SDK. In addition to this, the integration is now functional instead of class-based.

Copied
-import { Replay } from '@sentry/replay';
-
 Sentry.init({
   dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
   integrations: [
-    new Replay(),
+    new Sentry.replayIntegration(),
   ],
 });

The Replay options unblock and unmask now have [] as default value. This means that if you want to use these options, you have to explicitly set them like this:

Copied
Sentry.init({
  integrations: [
    Sentry.replayIntegration({
      unblock: [".sentry-unblock, [data-sentry-unblock]"],
      unmask: [".sentry-unmask, [data-sentry-unmask]"],
    }),
  ],
});

The xhr transport via makeXHRTransport transport has been removed. Only makeFetchTransport is available now. This means that the Sentry SDK requires the fetch API to be available in the environment.

The Offline integration has been removed in favor of the offline transport wrapper

The Sentry.wrap export has been removed. There is no replacement API.

We updated the behaviour of the SDKs when no tracePropagationTargets option was defined. As a reminder, you can provide a list of strings or RegExes that will be matched against URLs to tell the SDK, to which outgoing requests tracing HTTP headers should be attached to. These tracing headers are used for distributed tracing.

Previously, on the browser, when tracePropagationTargets were not defined, they defaulted to the following: ['localhost', /^\/(?!\/)/]. This meant that all request targets to that had "localhost" in the URL, or started with a / were equipped with tracing headers. This default was chosen to prevent CORS errors in your browser applications. However, this default had a few flaws.

Going forward, when the tracePropagationTargets option is not set, tracing headers will be attached to all outgoing requests on the same origin. For example, if you're on https://example.com/ and you send a request to https://example.com/api, the request will be traced (ie. will have trace headers attached). Requests to https://api.example.com/ will not, because it is on a different origin. The same goes for all applications running on localhost.

When you provide a tracePropagationTargets option, all of the entries you defined will now be matched be matched against the full URL of the outgoing request. Previously, it was only matched against what you called request APIs with. For example, if you made a request like fetch("/api/posts"), the provided tracePropagationTargets were only compared against "/api/posts".

The Hub has been a very important part of the Sentry SDK API up until now. Hubs were the SDK's "unit of concurrency" to keep track of data across threads and to scope data to certain parts of your code. Because it is overly complicated and confusing to power users, it is going to be replaced by a set of new APIs: the "new Scope API". For now Hub and getCurrentHub are still available, but it will be removed in the next major version.

See Deprecate Hub for details on how to replace existing usage of the Hub APIs.

In v7, integrations are classes and can be added as e.g. integrations: [new Sentry.Replay()]. In v8, integrations will not be classes anymore, but instead functions. Both the use as a class, as well as accessing integrations from the Integrations.XXX hash, is deprecated in favor of using the new functional integrations. For example, new Integrations.LinkedErrors() becomes linkedErrorsIntegration().

For a list of integrations and their replacements, see the 7.x deprecation documentation.

The top level Sentry.configureScope function has been removed. Instead, you should use the Sentry.getCurrentScope() to access and mutate the current scope.

Copied
- Sentry.configureScope((scope) => {
-  scope.setTag("key", "value");
- });
+ Sentry.getCurrentScope().setTag("key", "value");

tracingOrigins is now removed in favor of the tracePropagationTargets option. The tracePropagationTargets option should be set in the Sentry.init() options, or in your custom Clients option if you create them.

Copied
Sentry.init({
  dsn: "__DSN__",
  integrations: [Sentry.browserTracingIntegration()],
  tracePropagationTargets: ["localhost", "example.com"],
});

In 7.x, you had to enable the metrics aggregator by setting the _experiments option to { metricsAggregator: true }. In addition for browser environments you had to add the metricsAggregatorIntegration to the integrations array.

Copied
// v7 - Server (Node/Deno/Bun)
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  _experiments: {
    metricsAggregator: true,
  },
});

// v7 - Browser
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [Sentry.metricsAggregatorIntegration()],
});

Sentry.metrics.increment("my_metric");

In 8.x no additional configuration is needed to use metrics APIs.

Copied
// v8
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
});

Sentry.metrics.increment("my_metric");

In 7.x we deprecated the Severity enum in favor of using the SeverityLevel type as this helps save bundle size, and this has been removed in 8.x. You should now use the SeverityLevel type directly.

Copied
- import { Severity } from '@sentry/types';
+ import { SeverityLevel } from '@sentry/types';

- const level = Severity.error;
+ const level: SeverityLevel = "error";

In 8.x, we are removing the spanStatusfromHttpCode function in favor of getSpanStatusFromHttpCode.

Copied
- const spanStatus = spanStatusfromHttpCode(200);
+ const spanStatus = getSpanStatusFromHttpCode(200);

Errors with framesToPop property will have the specified number of frames removed from the top of the stack. This changes compared to the v7 where the property framesToPop was used to remove top n lines from the stack string.

In 8.x, we are no longer exporting the Span class from SDK packages. Internally, this class is now called SentrySpan, and it is no longer meant to be used by users directly.

The lastEventId function has been removed. See below for more details.

The send method on the Transport interface now always requires a TransportMakeRequestResponse to be returned in the promise. This means that the void return type is no longer allowed.

Copied
// v7
 interface Transport {
-  send(event: Event): Promise<void | TransportMakeRequestResponse>;
+  send(event: Event): Promise<TransportMakeRequestResponse>;
 }

The extraErrorDataIntegration integration now looks at error.cause by default.

Instead of an transactionContext being passed to the tracesSampler callback, the callback will directly receive name and attributes going forward. Note that the attributes are only the attributes at span creation time, and some attributes may only be set later during the span lifecycle (and thus not be available during sampling).

getClient() now always returns a client if Sentry.init() was called. For cases where this may be used to check if Sentry was actually initialized, using getClient() will thus not work anymore. Instead, you should use the new Sentry.isInitialized() utility to check this.

In 8.x, we are removing the addGlobalEventProcessor function in favor of addEventProcessor.

Copied
- Sentry.addGlobalEventProcessor((event) => {
+ Sentry.getGlobalScope().addEventProcessor((event) => {
   delete event.extra;
   return event;
 });

@sentry/integrations has been removed and will no longer be published. We moved pluggable integrations from their own package (@sentry/integrations) to @sentry/remix. In addition they are now functions instead of classes.

Integrations that are now exported from @sentry/remix for client-side init:

  • httpClientIntegration (HTTPClient)
  • contextLinesIntegration (ContextLines)
  • reportingObserverIntegration (ReportingObserver)

Integrations that are now exported from @sentry/remix for client-side and server-side init:

  • captureConsoleIntegration (CaptureConsole)
  • debugIntegration (Debug)
  • extraErrorDataIntegration (ExtraErrorData)
  • rewriteFramesIntegration (RewriteFrames)
  • sessionTimingIntegration (SessionTiming)
  • dedupeIntegration (Dedupe) - Note: enabled by default, not pluggable

The Transaction integration has been removed from @sentry/integrations. There is no replacement API.

If you are getting errors from within the Sentry SDK that it is trying to access certain functions that are not available, for example "... is not a function", it is possible that there are misaligned versions installed.

The Sentry JavaScript Bundler Plugins (@sentry/webpack-plugin, @sentry/vite-plugin, @sentry/esbuild-plugin, @sentry/rollup-plugin) used to depend on certain Sentry SDK packages on version 7 wich may clash with version 8 of the SDK.

The recommendation is to upgrade the JavaScript Bundler Plugin packages to at least version 2.14.2 which will no longer include dependencies on v7 of the Sentry JavaScript SDK.

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").