These docs walk through how to migrate our JavaScript SDKs through different major versions.
- Upgrading from SDK 4.x to 5.x/6.x
- Upgrading from SDK 6.x to 7.x
- Upgrading from 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. Below we will outline the steps you need to take to tackle to deprecated methods.
Before updating to 8.x
of the SDK, we recommend upgrading to the latest version of 7.x
. You can then follow
these steps remove deprecated methods in 7.x
before upgrading to 8.x
.
The v8 version of the JavaScript SDK requires a self-hosted version of Sentry 24.4.2 (for user feedback screenshots) or higher. Lower versions may continue to work, but may not support all features (e.g. the new user feedback APIs).
Node.js: We now officially support Node 14.18+ for our CJS package, and Node 18.19.1+ for our ESM package. This
applies to @sentry/node
and all of our node-based server-side sdks (@sentry/nextjs
, @sentry/serverless
, etc.). We
no longer test against Node 8, 10, or 12 and cannot guarantee that the SDK will work as expected on these versions.
Browser: Our browser SDKs (@sentry/browser
, @sentry/react
, @sentry/vue
, etc.) now require ES2018+
compatibility plus support for
globalThis
. This means
that we no longer support IE11 (end of an era). This also means that the Browser SDK requires the fetch API to be
available in the environment.
New minimum supported browsers:
- Chrome 71
- Edge 79
- Safari 12.1, iOS Safari 12.2
- Firefox 65
- Opera 58
- Samsung Internet 10
For IE11 support please transpile your code to ES5 using babel or similar and add required polyfills.
React: The Next.js SDK now supports React 16+
Next.js: The Next.js SDK now supports Next.js 13.2.0+
Express: Complex router setups are only properly parametrized in Node 16+.
We've removed the following packages:
@sentry/hub
has been removed and will no longer be published. All of the @sentry/hub
exports have moved to
@sentry/core
.
@sentry/tracing
has been removed and will no longer be published. See
below for more details.
For Browser SDKs you can import browserTracingIntegration
from the SDK directly:
// v7
import * as Sentry from '@sentry/browser';
import { BrowserTracing } from '@sentry/tracing';
Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
integrations: [new BrowserTracing()],
});
// v8
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
integrations: [Sentry.browserTracingIntegration()],
});
If you don't want to use browserTracingIntegration
but still manually start spans, you can now use
Sentry.registerSpanErrorInstrumentation()
to setup handlers for span instrumentation.
registerSpanErrorInstrumentation
replaces the addExtensionMethods
method from @sentry/tracing
.
// v7
import * as Sentry from '@sentry/browser';
import '@sentry/tracing';
Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});
// v8
import * as Sentry from '@sentry/browser';
Sentry.registerSpanErrorInstrumentation();
Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});
For Node SDKs you no longer need the side effect import, you can remove all references to @sentry/tracing
.
// v7
const Sentry = require('@sentry/node');
require('@sentry/tracing');
Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});
// v8
const Sentry = require('@sentry/node');
Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});
@sentry/integrations
has been removed and will no longer be published. We moved pluggable integrations from their own
package (@sentry/integrations
) to @sentry/browser
and @sentry/node
. in addition they are now functions instead of
classes.
// v7
import { RewriteFrames } from '@sentry/integrations';
// v8
import { rewriteFramesIntegration } from '@sentry/browser';
Integrations that are now exported from @sentry/browser
(or framework-specific packages like @sentry/react
):
httpClientIntegration
(HTTPClient
)contextLinesIntegration
(ContextLines
)reportingObserverIntegration
(ReportingObserver
)
Integrations that are now exported from @sentry/node
and @sentry/browser
(or framework-specific packages like
@sentry/react
):
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.
@sentry/serverless
has been removed and will no longer be published. The serverless package has been split into two
different packages, @sentry/aws-serverless
and @sentry/google-cloud-serverless
.
The @sentry/google-cloud-serverless
package has also been changed to only emit CJS builds because it can only
instrument CJS. ESM support will be re-added at a later date.
In @sentry/serverless
you had to use a namespace import to initialize the SDK. This has been removed so that you can
directly import from the SDK instead.
// v7
const Sentry = require('@sentry/serverless');
Sentry.AWSLambda.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});
// v8
const Sentry = require('@sentry/aws-serverless');
Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});
// v7
const Sentry = require('@sentry/serverless');
Sentry.GCPFunction.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});
// v8
const Sentry = require('@sentry/google-cloud-serverless');
Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});
@sentry/replay
has been removed and will no longer be published. You can import replay functionality and the replay
integration directly from the Browser SDK or browser framework-specific packages like @sentry/react
.
// v7
import { Replay } from '@sentry/replay';
import { replayIntegration } from '@sentry/browser';
If you are using @sentry/node
or @sentry/bun
, or a package that depends on it (@sentry/nextjs
, @sentry/remix
,
@sentry/sveltekit
, @sentry/
), you will need to initialize the SDK differently. The primary change is to ensure that
the SDK is initialized as early as possible. See Initializing the SDK in v8 on what steps
to follow.
For example with the Remix SDK, you should initialize the SDK at the top of your entry.server.tsx
server entrypoint
before you do anything else.
// first import Sentry and initialize Sentry
import * as Sentry from '@sentry/remix';
Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
tracesSampleRate: 1,
tracePropagationTargets: ['example.org'],
// Disabling to test series of envelopes deterministically.
autoSessionTracking: false,
});
// then handle everything else
import type { EntryContext } from '@remix-run/node';
import { RemixServer } from '@remix-run/react';
import { renderToString } from 'react-dom/server';
export const handleError = Sentry.wrapRemixHandleError;
The APIs for Performance Monitoring in the SDK have been revamped to align with OpenTelemetry, an open standard for tracing and metrics. This allows us to provide a more consistent and powerful API for performance monitoring, and adds support for a variety of new integrations out of the box for our Node SDK.
Instead of using startTransaction
and span.startChild
, you rely on new helper methods to create spans top level
helpers to create spans.
// Measure how long a callback takes, `startSpan` returns the value of the callback.
// The span will become the "active span" for the duration of the callback.
const value = Sentry.startSpan({ name: 'mySpan' }, span => {
span.setAttribute('key', 'value');
return expensiveFunction();
});
// `startSpan` works with async callbacks as well - just make sure to return a promise!
const value = await Sentry.startSpan({ name: 'mySpan' }, async span => {
span.setAttribute('key', 'value');
return await expensiveFunction();
});
// You can nest spans via more `startSpan` calls.
const value = Sentry.startSpan({ name: 'mySpan' }, span => {
span.setAttribute('key1', 'value1');
// `nestedSpan` becomes the child of `mySpan`.
return Sentry.startSpan({ name: 'nestedSpan' }, nestedSpan => {
nestedSpan.setAttribute('key2', 'value2');
return expensiveFunction();
});
});
// You can also create an inactive span that does not take a callback.
// Useful when you need to pass a span reference into another closure (like measuring duration between hooks).
const span = Sentry.startInactiveSpan({ name: 'mySpan' });
// Use `startSpanManual` if you want to manually control when to end the span
// Useful when you need to hook into event emitters or similar.
function middleware(res, req, next) {
return Sentry.startSpanManual({ name: 'mySpan' }, span => {
res.on('finish', () => {
span.end();
});
return next();
});
}
You can read more about the new performance APIs here.
To accommodate these changes, we're removed the following APIs:
startTransaction
andspan.startChild
- Certain arguments in
startSpan
andstartTransaction
scope.getSpan
andscope.setSpan
- Variations of
continueTrace
We've also removed a variety of top level fields on the
span
class.
As we added support for OpenTelemetry, we have expanded the automatic instrumentation for our Node.js SDK. We are adding support for frameworks like Fastify, Nest.js, and Hapi, and expanding support for databases like Prisma and MongoDB via Mongoose.
We now support the following integrations out of the box without extra configuration:
httpIntegration
: Automatically instruments Nodehttp
andhttps
standard librariesnativeNodeFetchIntegration
: Automatically instruments top level fetch and undiciexpressIntegration
: Automatically instruments Express.jsfastifyIntegration
: Automatically instruments FastifyhapiIntegration
: Automatically instruments HapigraphqlIntegration
: Automatically instruments GraphQLmongoIntegration
: Automatically instruments MongoDBmongooseIntegration
: Automatically instruments MongoosemysqlIntegration
: Automatically instruments MySQLmysql2Integration
: Automatically instruments MySQL2redisIntegration
: Automatically instruments Redis (supported clients: ioredis)nestIntegration
: Automatically instruments Nest.jspostgresIntegration
: Automatically instruments PostgreSQLprismaIntegration
: Automatically instruments Prisma
To make sure these integrations work properly you'll have to change how you initialize the SDK
- General
- Browser SDK
- Server-side SDKs (Node, Deno, Bun)
- Next.js SDK
- SvelteKit SDK
- Astro SDK
- AWS Serverless SDK
- Ember SDK
- Svelte SDK
- React SDK
Removed top-level exports: tracingOrigins
, MetricsAggregator
, metricsAggregatorIntegration
, Severity
,
Sentry.configureScope
, Span
, spanStatusfromHttpCode
, makeMain
, pushScope
, popScope
,
addGlobalEventProcessor
, timestampWithMs
, addExtensionMethods
, addGlobalEventProcessor
, getActiveTransaction
Removed @sentry/utils
exports: timestampWithMs
, addOrUpdateIntegration
, tracingContextFromHeaders
, walk
- Deprecation of
Hub
andgetCurrentHub()
- Removal of class-based integrations
tracingOrigins
option replaced withtracePropagationTargets
- Removal of
MetricsAggregator
andmetricsAggregatorIntegration
- Removal of
Severity
Enum - Removal of
Sentry.configureScope
method - Removal of
Span
class export from SDK packages - Removal of
spanStatusfromHttpCode
in favour ofgetSpanStatusFromHttpCode
- Removal of
addGlobalEventProcessor
in favour ofaddEventProcessor
- Remove
void
from transport return types - Remove
addGlobalEventProcessor
in favor ofaddEventProcessor
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.
The hub.bindClient
and makeMain
methods have been removed entirely, see
initializing the SDK in v8 for details how to work around this.
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 docs on the new integration interface, see below.
For a list of integrations and their replacements, see below.
The getIntegration()
and getIntegrationById()
have been removed entirely, see
below.
// v7
const replay = Sentry.getIntegration(Replay);
// v8
const replay = getClient().getIntegrationByName('Replay');
Error 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.
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 Client
s option if you create them. We've also updated
the behavior of the tracePropagationTargets
option for Browser SDKs, see
below for more
details.
For example for the Browser SDKs:
// v7
Sentry.init({
dsn: '__DSN__',
integrations: [new Sentry.BrowserTracing({ tracingOrigins: ['localhost', 'example.com'] })],
});
// v8
Sentry.init({
dsn: '__DSN__',
integrations: [Sentry.browserTracingIntegration()],
tracePropagationTargets: ['localhost', 'example.com'],
});
The SDKs now support metrics features without any additional configuration.
// v7 - Server (Node/Deno/Bun)
Sentry.init({
dsn: '__DSN__',
_experiments: {
metricsAggregator: true,
},
});
// v7 - Browser
Sentry.init({
dsn: '__DSN__',
integrations: [Sentry.metricsAggregatorIntegration()],
});
// v8
Sentry.init({
dsn: '__DSN__',
});
In v7 we deprecated the Severity
enum in favor of using the SeverityLevel
type as this helps save bundle size, and
this has been removed in v8. You should now use the SeverityLevel
type directly.
// v7
import { Severity, SeverityLevel } from '@sentry/types';
const levelA = Severity.error;
const levelB: SeverityLevel = "error"
// v8
import { SeverityLevel } from '@sentry/types';
const levelA = "error" as SeverityLevel;
const levelB: SeverityLevel = "error"
The top level Sentry.configureScope
function has been removed. Instead, you should use the Sentry.getCurrentScope()
to access and mutate the current scope.
// v7
Sentry.configureScope(scope => {
scope.setTag('key', 'value');
});
// v8
Sentry.getCurrentScope().setTag('key', 'value');
In v8, we are no longer exporting the Span
class from SDK packages (e.g. @sentry/browser
or @sentry/node
).
Internally, this class is now called SentrySpan
, and it is no longer meant to be used by users directly.
In v8, we are removing the spanStatusfromHttpCode
function in favor of getSpanStatusFromHttpCode
.
// v7
const spanStatus = spanStatusfromHttpCode(200);
// v8
const spanStatus = getSpanStatusFromHttpCode(200);
In v8, we are removing the addGlobalEventProcessor
function in favor of addEventProcessor
.
// v7
addGlobalEventProcessor(event => {
delete event.extra;
return event;
});
// v8
Sentry.getGlobalScope().addEventProcessor(event => {
delete event.extra;
return event;
});
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.
// v7
interface Transport {
send(event: Event): Promise<void | TransportMakeRequestResponse>;
}
// v8
interface Transport {
send(event: Event): Promise<TransportMakeRequestResponse>;
}
In v8, we are removing the addGlobalEventProcessor
function in favor of addEventProcessor
.
// v7
addGlobalEventProcessor(event => {
delete event.extra;
return event;
});
// v8
addEventProcessor(event => {
delete event.extra;
return event;
});
The Sentry tRPC middleware got moved from Sentry.Handlers.trpcMiddleware()
to Sentry.trpcMiddleware()
. Functionally
they are the same:
Removal of Sentry.Handlers.requestHandler()
, Sentry.Handlers.tracingHandler()
and Sentry.Handlers.errorHandler()
For Express and Connect you previously had to use Sentry.Handlers.requestHandler()
,
Sentry.Handlers.tracingHandler()
, and Sentry.Handlers.errorHandler()
to add Sentry instrumentation to your app. In
8.x, you only need to use the framework specific error handler (e.g Sentry.setupExpressErrorHandler(app)
), you can
remove all other handlers.
// v7
import * as Sentry from '@sentry/node';
Sentry.Handlers.trpcMiddleware();
// v8
import * as Sentry from '@sentry/node';
Sentry.trpcMiddleware();
Removed top-level exports: Offline
, makeXHRTransport
, BrowserTracing
, wrap
- Removal of the
BrowserTracing
integration - Removal of Offline integration
- Removal of
makeXHRTransport
transport - Removal of
wrap
method - Removal of
@sentry/angular-ivy
package - Removal of
@sentry/replay
package
The BrowserTracing
integration, together with the custom routing instrumentations passed to it, are deprecated in v8.
Instead, you should use Sentry.browserTracingIntegration()
. See examples
below
The interactionsSampleRate
option that could be passed to browserTracingIntegration
or new BrowserTracing()
was
removed in v8, due to the option being redundant and in favour of bundle size minimization.
It's important to note that this sample rate only ever was applied when collecting INP (Interaction To Next Paint)
values. You most likely don't need to replace this option. Furthermore, INP values are already sampled by the
tracesSampleRate
SDK option, like
any regular span. At the time of writing, INP value collection does not deplete your span or transaction quota.
If you used interactionsSampleRate
before, and still want to reduce INP value collection, we recommend using the
tracesSampler
SDK option instead:
// v7
Sentry.init({
integrations: [new BrowserTracing({ interactionsSampleRate: 0.1 })],
});
// v8 - please read the text above, you most likely don't need this :)
Sentry.init({
tracesSampler: (ctx) => {
if (ctx.attributes?['sentry.op']?.startsWith('ui.interaction')) {
return 0.1;
}
return 0.5;
}
})
The Offline
integration has been removed in favor of the
offline transport wrapper.
The 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 wrap
method has been removed. There is no replacement API.
The @sentry/angular-ivy
package has been removed. The @sentry/angular
package now supports Ivy by default and
requires at least Angular 14. If you are using Angular 13 or lower, we suggest upgrading your Angular version before
migrating to v8. If you can't upgrade your Angular version to at least Angular 14, you can also continue using the
@sentry/angular-ivy@7
SDK. However, v7 of the SDKs will no longer be fully supported going forward.
You can import from @sentry/browser
(or from a respective SDK package like @sentry/react
or @sentry/vue
).
Removed top-level exports: enableAnrDetection
, Anr
, deepReadDirSync
, runWithAsyncContext
- Removal of
enableAnrDetection
andAnr
class - Removal of
deepReadDirSync
method - Removal of
runWithAsyncContext
method - Removal of
Apollo
integration
The enableAnrDetection
and Anr
class have been removed. See the
docs for more details. PR:
The deepReadDirSync
method has been removed. There is no replacement API.
The runWithAsyncContext
method has been removed in favour of Sentry.withIsolationScope
.
// before (v7)
Sentry.runWithAsyncContext(() => {
// Your code here...
});
// after (v8)
Sentry.withIsolationScope(() => {
// Your code here...
});
The Apollo integration has been removed in 8.x
as 8.x
automatically adds GraphQL support via graphqlIntegration
which is automatically enabled.
// before (v7)
Sentry.init({
integrations: [Sentry.integrations.Apollo()],
});
// after (v8)
Sentry.init({});
Removed top-level exports: withSentryApi
, withSentryAPI
, withSentryGetServerSideProps
, withSentryGetStaticProps
,
withSentryServerSideGetInitialProps
, withSentryServerSideAppGetInitialProps
,
withSentryServerSideDocumentGetInitialProps
, withSentryServerSideErrorGetInitialProps
, nextRouterInstrumentation
,
IS_BUILD
, isBuild
- Removal of deprecated API in
@sentry/nextjs
- Updated minimum compatible Next.js version to
13.2.0
- Merging of the Sentry Webpack Plugin options and SDK Build options
- Removal of the
sentry
property in your Next.js options (next.config.js) - Updated the
@sentry/webpack-plugin
dependency to version 2
The following previously deprecated API has been removed from the @sentry/nextjs
package:
withSentryApi
(Replacement:wrapApiHandlerWithSentry
)withSentryAPI
(Replacement:wrapApiHandlerWithSentry
)withSentryGetServerSideProps
(Replacement:wrapGetServerSidePropsWithSentry
)withSentryGetStaticProps
(Replacement:wrapGetStaticPropsWithSentry
)withSentryServerSideGetInitialProps
(Replacement:wrapGetInitialPropsWithSentry
)withSentryServerSideAppGetInitialProps
(Replacement:wrapAppGetInitialPropsWithSentry
)withSentryServerSideDocumentGetInitialProps
(Replacement:wrapDocumentGetInitialPropsWithSentry
)withSentryServerSideErrorGetInitialProps
was renamed towrapErrorGetInitialPropsWithSentry
nextRouterInstrumentation
(Replaced by usingbrowserTracingIntegration
)IS_BUILD
isBuild
The minimum version of Next.js compatible with the Sentry Next.js SDK has been raised to 13.2.0
. Older versions may
exhibit bugs or unexpected behaviour.
With version 8 of the Sentry Next.js SDK, withSentryConfig
will no longer accept 3 arguments. The second argument
(holding options for the Sentry Webpack plugin) and the third argument (holding options for SDK build-time
configuration) should now be passed as one:
// OLD
const nextConfig = {
// Your Next.js options...
};
module.exports = withSentryConfig(
nextConfig,
{
// Your Sentry Webpack Plugin Options...
},
{
// Your Sentry SDK options...
},
);
// NEW
const nextConfig = {
// Your Next.js options...
};
module.exports = withSentryConfig(nextConfig, {
// Your Sentry Webpack Plugin Options...
// AND your Sentry SDK options...
});
With version 8 of the Sentry Next.js SDK, the SDK will no longer support passing Next.js options with a sentry
property to withSentryConfig
. Please use the second argument of withSentryConfig
to configure the SDK instead:
// v7
const nextConfig = {
// Your Next.js options...
sentry: {
// Your Sentry SDK options...
},
};
module.exports = withSentryConfig(nextConfig, {
// Your Sentry Webpack Plugin Options...
});
// v8
const nextConfig = {
// Your Next.js options...
};
module.exports = withSentryConfig(nextConfig, {
// Your Sentry Webpack Plugin Options...
// AND your Sentry SDK options...
});
The reason for this change is to have one consistent way of defining the SDK options. We hope that this change will reduce confusion when setting up the SDK, with the upside that the explicit option is properly typed and will therefore have code completion.
We bumped the internal usage of @sentry/webpack-plugin
to a new major version. This comes with multiple upsides like a
simpler configuration interface and the use of new state of the art Debug ID technology. Debug IDs will simplify the
setup for source maps in Sentry and will not require you to match stack frame paths to uploaded artifacts anymore.
To see the new options, check out the docs at https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/,
or look at the TypeScript type definitions of withSentryConfig
.
With version 8 of the SDK we will no longer support the use of sentry.server.config.ts
and sentry.edge.config.ts
files. Instead, please initialize the Sentry Next.js SDK for the serverside in a
Next.js instrumentation hook.
sentry.client.config.ts|js
is still supported and encouraged for initializing the clientside SDK.
The following is an example of how to initialize the serverside SDK in a Next.js instrumentation hook:
-
First, enable the Next.js instrumentation hook by setting the
experimental.instrumentationHook
totrue
in yournext.config.js
. -
Next, create a
instrumentation.ts|js
file in the root directory of your project (or in thesrc
folder if you have have one). -
Now, export a
register
function from theinstrumentation.ts|js
file and callSentry.init()
inside of it:import * as Sentry from '@sentry/nextjs'; export function register() { if (process.env.NEXT_RUNTIME === 'nodejs') { Sentry.init({ dsn: 'YOUR_DSN', // Your Node.js Sentry configuration... }); } if (process.env.NEXT_RUNTIME === 'edge') { Sentry.init({ dsn: 'YOUR_DSN', // Your Edge Runtime Sentry configuration... }); } }
If you need to import a Node.js specific integration (like for example
@sentry/profiling-node
), you will have to import the package using a dynamic import to prevent Next.js from bundling Node.js APIs into bundles for other runtime environments (like the Browser or the Edge runtime). You can do so as follows:import * as Sentry from '@sentry/nextjs'; export async function register() { if (process.env.NEXT_RUNTIME === 'nodejs') { const { nodeProfilingIntegration } = await import('@sentry/profiling-node'); Sentry.init({ dsn: 'YOUR_DSN', integrations: [nodeProfilingIntegration()], }); } }
Note that you can initialize the SDK differently depending on which server runtime is being used.
If you are using a
Next.js custom server, the
instrumentation.ts
hook is not called by Next.js so you need to manually call it yourself from within your server
code. It is recommended to do so as early as possible in your application lifecycle.
Why are we making this change? The very simple reason is that Next.js requires us to set up OpenTelemetry
instrumentation inside the register
function of the instrumentation hook. Looking a little bit further into the
future, we also would like the Sentry SDK to be compatible with Turbopack, which is gonna be
the bundler that Next.js will be using instead of Webpack. The SDK in its previous version depended heavily on Webpack
in order to inject the sentry.(server|edge).config.ts
files into the server-side code. Because this will not be
possible in the future, we are doing ourselves a favor and doing things the way Next.js intends us to do them -
hopefully reducing bugs and jank.
Since we are dropping support for Internet Explorer 11 and other other older browser versions, we are also removing the
transpileClientSDK
option from the Next.js SDK. If you need to support these browser versions, please configure
Webpack and Next.js to down-compile the SDK.
Instead of opting-in via the middleware config, you can configure if headers should be captured via
requestDataIntegration
options, which defaults to true
but can be disabled like this:
Sentry.init({
integrations: [
Sentry.requestDataIntegration({
include: {
headers: false,
},
}),
],
});
We upgraded the @sentry/vite-plugin
from version 0.x to 2.x. This package is internally used by the
@sentry/sveltekit
SDK. With this change, resolving uploaded source maps should work out of the box much more often
than before
(more information).
To allow future upgrades of the Vite plugin without breaking stable and public APIs in sentrySvelteKit
, we modified
the sourceMapsUploadOptions
to remove the hard dependency on the API of the plugin. While you previously could specify
all version 0.x Vite plugin options, we now reduced them to
a subset of 2.x options. All of these options are
optional just like before but here's an example of using the new options.
// v7
sentrySvelteKit({
sourceMapsUploadOptions: {
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
release: '1.0.1',
injectRelease: true,
include: ['./build/*/**/*'],
ignore: ['**/build/client/**/*']
},
}),
// v8
sentrySvelteKit({
sourceMapsUploadOptions: {
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
authToken: process.env.SENTRY_AUTH_TOKEN,
release: {
name: '1.0.1',
inject: true
},
sourcemaps: {
assets: ['./build/*/**/*'],
ignore: ['**/build/client/**/*'],
filesToDeleteAfterUpload: ['./build/**/*.map']
},
},
}),
In the future, we might add additional options
from the Vite plugin but if you would like to specify some of them directly, you can do this by passing in an
unstable_sentryVitePluginOptions
object:
sentrySvelteKit({
sourceMapsUploadOptions: {
// ...
release: {
name: '1.0.1',
},
unstable_sentryVitePluginOptions: {
release: {
setCommits: {
auto: true
}
}
}
},
}),
Important: we DO NOT guarantee stability of unstable_sentryVitePluginOptions
. They can be removed or updated at any
time, including breaking changes within the same major version of the SDK.
In v6.17.2
the rethrowAfterCapture
option to wrapHandler
was deprecated. In v8
it has been removed. There is no
replacement API.
Removed top-level exports: InitSentryForEmber
, StartTransactionFunction
The InitSentryForEmber
export has been removed. Instead, you should use the Sentry.init
method to initialize the
SDK.
The following dependencies that the SDK uses have been bumped to a more recent version:
ember-auto-import
is bumped to^2.4.3
ember-cli-babel
is bumped to^8.2.0
ember-cli-typescript
is bumped to^5.3.0
Removed top-level exports: componentTrackingPreprocessor
The componentTrackingPreprocessor
export has been removed. You should instead use withSentryConfig
to configure
component tracking.
// v7 - svelte.config.js
import { componentTrackingPreprocessor } from '@sentry/svelte';
const config = {
preprocess: [
componentTrackingPreprocessor(),
// ...
],
// ...
};
export default config;
// v8 - svelte.config.js
import { withSentryConfig } from "@sentry/svelte";
const config = {
// Your svelte config
compilerOptions: {...},
};
export default withSentryConfig(config);
In v8, we are changing the ErrorBoundary
error types returned from onError
, onReset
, onUnmount
, and
beforeCapture
. to be unknown
instead of Error
. This more accurately matches behaviour of componentDidCatch
, the
lifecycle method the Sentry ErrorBoundary
component uses.
As per the React docs on error boundaries:
error: The
error
that was thrown. In practice, it will usually be an instance ofError
but this is not guaranteed because JavaScript allows to throw any value, including strings or evennull
.
This means you will have to use instanceof Error
or similar to explicitly make sure that the error thrown was an
instance of Error
.
The Sentry SDK maintainers also went ahead and made a PR to update the
TypeScript definitions of componentDidCatch
for the
React package - this will be released with React 20.
In v8, we are removing the ability to initialize the Gatsby SDK via plugin options. Instead, you should create a
sentry.config.js
file in the root of your project and initialize the SDK there.
// v7 - gatsby-config.js
module.exports = {
// ...
plugins: [
{
resolve: '@sentry/gatsby',
options: {
dsn: process.env.SENTRY_DSN,
},
},
// ...
],
};
// v8 - gatsby-config.js
module.exports = {
// ...
plugins: [
{
resolve: '@sentry/gatsby',
},
// ...
],
};
// v8 - sentry.config.js
import * as Sentry from '@sentry/gatsby';
Sentry.init({
dsn: '__PUBLIC_DSN__',
});
We've also added enableClientWebpackPlugin
which allows you to enable or disable the @sentry/webpack-plugin
in the
client-side build. By default, it is enabled.
// v8 - gatsby-config.js
module.exports = {
// ...
plugins: [
{
resolve: '@sentry/gatsby',
options: {
enableClientWebpackPlugin: false,
},
},
// ...
],
};
The Gatsby SDK no longer adds the browserTracingIntegration
automatically. If you want to enable tracing in the
browser, you need to add it manually. Make sure to also configured a tracePropagationTargets
value.
// v7 - gatsby-config.js
module.exports = {
// ...
plugins: [
{
resolve: '@sentry/gatsby',
options: {
tracesSampleRate: 1.0,
},
},
// ...
],
};
// v8 - gatsby-config.js
module.exports = {
// ...
plugins: [
{
resolve: '@sentry/gatsby',
},
// ...
],
};
// v8 - sentry.config.js
import * as Sentry from '@sentry/gatsby';
Sentry.init({
dsn: '__PUBLIC_DSN__',
integrations: [Sentry.browserTracingIntegration()],
// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for performance monitoring.
// We recommend adjusting this value in production
tracesSampleRate: 1.0,
// Set `tracePropagationTargets` to control for which URLs distributed tracing should be enabled
tracePropagationTargets: ['localhost', /^https:\/\/yourserver\.io\/api/],
});
- Updated behaviour of
tracePropagationTargets
in the browser - Updated behaviour of
extraErrorDataIntegration
- Updated behaviour of
transactionContext
passed totracesSampler
- Updated behaviour of
getClient()
- Updated behaviour of the SDK in combination with
onUncaughtException
handlers in Node.js - Updated expected return value for
captureException()
,captureMessage()
andcaptureEvent
methods on Clients - Removal of Client-Side health check transaction filters
- Change of Replay default options (
unblock
andunmask
) - Angular Tracing Decorator renaming
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"
. Going forward they will be matched against the entire URL, for example, if you were on the page
https://example.com/
and you made the same request, it would be matched against "https://example.com/api/posts"
.
But that is not all. Because it would be annoying having to create matchers for the entire URL, if the request is a
same-origin request, we also match the tracePropagationTargets
against the resolved pathname
of the request.
Meaning, a matcher like /^\/api/
would match a request call like fetch('/api/posts')
, or
fetch('https://same-origin.com/api/posts')
but not fetch('https://different-origin.com/api/posts')
.
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.
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.
Updated expected return value for captureException()
, captureMessage()
and captureEvent
methods on Clients
The Client
interface now expects implementations to always return a string representing the generated event ID for the
captureException()
, captureMessage()
, captureEvent()
methods. Previously undefined
was a valid return value.
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 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:
Sentry.init({
integrations: [
Sentry.replayIntegration({
unblock: ['.sentry-unblock, [data-sentry-unblock]'],
unmask: ['.sentry-unmask, [data-sentry-unmask]'],
}),
],
});
The usage of TraceClassDecorator
and the TraceMethodDecorator
already implies that those are decorators. The word
Decorator
is now removed from the names to avoid multiple mentioning.
Additionally, the TraceClass
and TraceMethod
decorators accept an optional name
parameter to set the transaction
name. This was added because Angular minifies class and method names, and you might want to set a more descriptive name.
If nothing provided, the name defaults to 'unnamed'
.
// v7
@Sentry.TraceClassDecorator()
export class HeaderComponent {
@Sentry.TraceMethodDecorator()
ngOnChanges(changes: SimpleChanges) {}
}
// v8
@Sentry.TraceClass({ name: 'HeaderComponent' })
export class HeaderComponent {
@Sentry.TraceMethod({ name: 'ngOnChanges' })
ngOnChanges(changes: SimpleChanges) {}
}
We now provide a proper ESM output of the SDK. There have also been some other build changes under the hood. One side
effect of this is that importing Sentry as a default import does not work anymore. Note that this was never supported
(even on v7) and this was never intended to work (and also not documented anywhere). However, it seems that for some
configuration combinations, it was still possible to do import Sentry from '@sentry/browser'
. This is not possible
anymore in v8. Please use import * as Sentry from '@sentry/browser'
instead.
For details on upgrading Feedback from the beta 7.x to the release 8.x version, please view the dedicated Feedback MIGRATION docs.
You can use the Experimental @sentry/migr8 to automatically update your SDK usage and fix most deprecations. This requires Node 18+.
npx @sentry/migr8@latest
This will let you select which updates to run, and automatically update your code. Make sure to still review all code changes!
The BrowserTracing
integration, together with the custom routing instrumentations passed to it, are deprecated in v8.
Instead, you should use Sentry.browserTracingIntegration()
.
Package-specific browser tracing integrations are available directly. In most cases, there is a single integration provided for each package, which will make sure to set up performance tracing correctly for the given SDK. For react, we provide multiple integrations to cover different router integrations:
import * as Sentry from '@sentry/browser';
Sentry.init({
integrations: [Sentry.browserTracingIntegration()],
});
import * as Sentry from '@sentry/react';
Sentry.init({
integrations: [
// No react router
Sentry.browserTracingIntegration(),
// OR, if you are using react router, instead use one of the following:
Sentry.reactRouterV6BrowserTracingIntegration({
useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
stripBasename,
}),
Sentry.reactRouterV5BrowserTracingIntegration({
history,
}),
Sentry.reactRouterV4BrowserTracingIntegration({
history,
}),
Sentry.reactRouterV3BrowserTracingIntegration({
history,
routes,
match,
}),
],
});
import * as Sentry from '@sentry/vue';
Sentry.init({
integrations: [
Sentry.browserTracingIntegration({
// pass router in, if applicable
router,
}),
],
});
import * as Sentry from '@sentry/angular';
Sentry.init({
integrations: [Sentry.browserTracingIntegration()],
});
// You still need to add the TraceService like before!
import * as Sentry from '@sentry/remix';
Sentry.init({
integrations: [
Sentry.browserTracingIntegration({
useEffect,
useLocation,
useMatches,
}),
],
});
Browser tracing is automatically set up for you in these packages. If you need to customize the options, you can do it like this:
import * as Sentry from '@sentry/nextjs';
Sentry.init({
integrations: [
Sentry.browserTracingIntegration({
// add custom options here
}),
],
});
Browser tracing is automatically set up for you. You can configure it as before through configuration.
Instead of an transactionContext
being passed to the tracesSampler
callback, the callback will directly receive
name
and attributes
going forward. You can use these to make your sampling decisions, while transactionContext
will be removed in v8. 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).
This release deprecates wrapRemixHandleError
in favor of using sentryHandleError
from @sentry/remix
. It can be
used as below:
// entry.server.ts
export const handleError = Sentry.wrapHandleErrorWithSentry(() => {
// Custom handleError implementation
});
In v8, getClient()
will stop returning undefined
if Sentry.init()
was not 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 v8, you will no longer have a Hub, only Scopes as a concept. This also means that getCurrentHub()
will eventually
be removed.
Instead of getCurrentHub()
, use the respective replacement API directly - see Deprecate Hub for
details.
In v7, integrations are classes and can be added as e.g. integrations: [new Sentry.Integrations.ContextLines()]
. 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()
becomeslinkedErrorsIntegration()
.
The following list shows how integrations should be migrated:
Old | New | Packages |
---|---|---|
new BrowserTracing() |
browserTracingIntegration() |
@sentry/browser |
new InboundFilters() |
inboundFiltersIntegration() |
@sentry/core , @sentry/browser , @sentry/node , @sentry/deno , @sentry/bun , @sentry/vercel-edge |
new FunctionToString() |
functionToStringIntegration() |
@sentry/core , @sentry/browser , @sentry/node , @sentry/deno , @sentry/bun , @sentry/vercel-edge |
new LinkedErrors() |
linkedErrorsIntegration() |
@sentry/core , @sentry/browser , @sentry/node , @sentry/deno , @sentry/bun , @sentry/vercel-edge |
new ModuleMetadata() |
moduleMetadataIntegration() |
@sentry/core , @sentry/browser |
new RequestData() |
requestDataIntegration() |
@sentry/core , @sentry/node , @sentry/deno , @sentry/bun , @sentry/vercel-edge |
new Wasm() |
wasmIntegration() |
@sentry/wasm |
new Replay() |
replayIntegration() |
@sentry/browser |
new ReplayCanvas() |
replayCanvasIntegration() |
@sentry/browser |
new Feedback() |
feedbackIntegration() |
@sentry/browser |
new CaptureConsole() |
captureConsoleIntegration() |
@sentry/integrations |
new Debug() |
debugIntegration() |
@sentry/integrations |
new Dedupe() |
dedupeIntegration() |
@sentry/browser , @sentry/integrations , @sentry/deno |
new ExtraErrorData() |
extraErrorDataIntegration() |
@sentry/integrations |
new ReportingObserver() |
reportingObserverIntegration() |
@sentry/integrations |
new RewriteFrames() |
rewriteFramesIntegration() |
@sentry/integrations |
new SessionTiming() |
sessionTimingIntegration() |
@sentry/integrations |
new HttpClient() |
httpClientIntegration() |
@sentry/integrations |
new ContextLines() |
contextLinesIntegration() |
@sentry/integrations , @sentry/node , @sentry/deno , @sentry/bun |
new Breadcrumbs() |
breadcrumbsIntegration() |
@sentry/browser , @sentry/deno |
new GlobalHandlers() |
globalHandlersIntegration() |
@sentry/browser , @sentry/deno |
new HttpContext() |
httpContextIntegration() |
@sentry/browser |
new TryCatch() |
browserApiErrorsIntegration() |
@sentry/browser , @sentry/deno |
new VueIntegration() |
vueIntegration() |
@sentry/vue |
new DenoContext() |
denoContextIntegration() |
@sentry/deno |
new DenoCron() |
denoCronIntegration() |
@sentry/deno |
new NormalizePaths() |
normalizePathsIntegration() |
@sentry/deno |
new Console() |
consoleIntegration() |
@sentry/node |
new Context() |
nodeContextIntegration() |
@sentry/node |
new Modules() |
modulesIntegration() |
@sentry/node |
new OnUncaughtException() |
onUncaughtExceptionIntegration() |
@sentry/node |
new OnUnhandledRejection() |
onUnhandledRejectionIntegration() |
@sentry/node |
new LocalVariables() |
localVariablesIntegration() |
@sentry/node |
new Spotlight() |
spotlightIntegration() |
@sentry/node |
new Anr() |
anrIntegration() |
@sentry/node |
new Hapi() |
hapiIntegration() |
@sentry/node |
new Undici() |
nativeNodeFetchIntegration() |
@sentry/node |
new Http() |
httpIntegration() |
@sentry/node |
new ProfilingIntegration() |
nodeProfilingIntegration() |
@sentry/profiling-node |
new BrowserProfilingIntegration() |
browserProfilingIntegration() |
@sentry/browser |
Instead, either directly use initAndBind()
, or the new APIs setCurrentClient()
and client.init()
. See
Initializing the SDK in v8 for more details.
This pluggable integration from @sentry/integrations
will be removed in v8. It was already undocumented and is not
necessary for the SDK to work as expected.
In v8, integrations passed to a client will have an optional setupOnce()
hook. Currently, this hook is always present,
but in v8 you will not be able to rely on this always existing anymore - any integration may have a setup
and/or a
setupOnce
hook. Additionally, setupOnce()
will not receive any arguments anymore.
This should not affect most people, but in the case that you are manually calling integration.setupOnce()
right now,
make sure to guard it's existence properly.
This deprecates getIntegration()
on both the hub & the client, as well as getIntegrationById()
on the baseclient.
Instead, use getIntegrationByName()
. You can optionally pass an integration generic to make it easier to work with
typescript:
const replay = getClient().getIntegrationByName<Replay>('Replay');
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".
Scope
s have existed before in the SDK but we are now expanding on them because we have found them powerful enough to
fully cover the Hub
API.
If you are using the Hub
right now, see the following table on how to migrate to the new API:
Old Hub API |
New Scope API |
---|---|
new Hub() |
withScope() , withIsolationScope() or new Scope() |
hub.isOlderThan() | REMOVED - Was used to compare Hub instances, which are gonna be removed |
hub.bindClient() | A combination of scope.setClient() and client.init() |
hub.pushScope() | Sentry.withScope() |
hub.popScope() | Sentry.withScope() |
hub.withScope() | Sentry.withScope() |
getClient() | Sentry.getClient() |
getScope() | Sentry.getCurrentScope() to get the currently active scope |
getIsolationScope() | Sentry.getIsolationScope() |
getStack() | REMOVED - The stack used to hold scopes. Scopes are used directly now |
getStackTop() | REMOVED - The stack used to hold scopes. Scopes are used directly now |
captureException() | Sentry.captureException() |
captureMessage() | Sentry.captureMessage() |
captureEvent() | Sentry.captureEvent() |
lastEventId() | Sentry.lastEventId() |
addBreadcrumb() | Sentry.addBreadcrumb() |
setUser() | Sentry.setUser() |
setTags() | Sentry.setTags() |
setExtras() | Sentry.setExtras() |
setTag() | Sentry.setTag() |
setExtra() | Sentry.setExtra() |
setContext() | Sentry.setContext() |
configureScope() | REMOVED - Scopes are now the unit of concurrency |
run() | Sentry.withScope() or Sentry.withIsolationScope() |
getIntegration() | client.getIntegration() |
startTransaction() | Sentry.startSpan() , Sentry.startInactiveSpan() or Sentry.startSpanManual() |
traceHeaders() | REMOVED - The closest equivalent is now spanToTraceHeader(getActiveSpan()) |
captureSession() | Sentry.captureSession() |
startSession() | Sentry.startSession() |
endSession() | Sentry.endSession() |
shouldSendDefaultPii() | REMOVED - The closest equivalent is Sentry.getClient().getOptions().sendDefaultPii |
The Hub
constructor is also deprecated and will be removed in the next major version. If you are creating Hubs for
multi-client use like so:
// OLD
const hub = new Hub();
hub.bindClient(client);
makeMain(hub);
instead initialize the client as follows:
// NEW
Sentry.withIsolationScope(() => {
Sentry.setCurrentClient(client);
client.init();
});
If you are using the Hub to capture events like so:
// OLD
const client = new Client();
const hub = new Hub(client);
hub.captureException();
instead capture isolated events as follows:
// NEW
const client = new Client();
const scope = new Scope();
scope.setClient(client);
scope.captureException();
Instead, use the new client.init()
method. You should probably not use this directly and instead use Sentry.init()
,
which calls this under the hood. But if you have a special use case that requires that, you can call client.init()
instead now.
Instead, you can get the currently active span via Sentry.getActiveSpan()
. Setting a span on the scope happens
automatically when you use the new performance APIs startSpan()
and startSpanManual()
.
Instead, you should not rely on the active transaction, but just use startSpan()
APIs, which handle this for you.
In v8, the API to start a new span will be reduced from the currently available options. Going forward, only these
argument will be passable to startSpan()
, startSpanManual()
and startInactiveSpan()
:
name
attributes
origin
op
startTime
scope
In v8, the old performance API startTransaction()
(and hub.startTransaction()
), as well as span.startChild()
, will
be removed. Instead, use the new performance APIs:
startSpan()
startSpanManual()
startInactiveSpan()
You can read more about the new performance APIs here.
The version of Sentry.continueTrace()
which does not take a callback argument will be removed in favor of the version
that does. Additionally, the callback argument will not receive an argument with the next major version.
Use Sentry.continueTrace()
as follows:
app.get('/your-route', req => {
Sentry.withIsolationScope(isolationScope => {
Sentry.continueTrace(
{
sentryTrace: req.headers.get('sentry-trace'),
baggage: req.headers.get('baggage'),
},
() => {
// All events recorded in this callback will be associated with the incoming trace. For example:
Sentry.startSpan({ name: '/my-route' }, async () => {
await doExpensiveWork();
});
},
);
});
});
In v8, the Span class is heavily reworked. The following properties & methods are thus deprecated:
span.toContext()
: Access the fields directly instead.