diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93e4b3254ccf..35fb1d8d1436 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -983,7 +983,7 @@ jobs: PUBLIC_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} REACT_APP_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} E2E_TEST_SENTRY_ORG_SLUG: 'sentry-javascript-sdks' - E2E_TEST_SENTRY_TEST_PROJECT: 'sentry-javascript-e2e-tests' + E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false matrix: @@ -993,6 +993,7 @@ jobs: [ 'angular-17', 'angular-18', + 'aws-lambda-layer', 'cloudflare-astro', 'node-express', 'create-react-app', @@ -1012,7 +1013,8 @@ jobs: 'react-create-hash-router', 'react-router-6-use-routes', 'react-router-5', - 'standard-frontend-react', + 'react-router-6', + 'solidjs', 'svelte-5', 'sveltekit', 'sveltekit-2', @@ -1039,9 +1041,9 @@ jobs: - test-application: 'create-react-app' build-command: 'test:build-ts3.8' label: 'create-react-app (TS 3.8)' - - test-application: 'standard-frontend-react' + - test-application: 'react-router-6' build-command: 'test:build-ts3.8' - label: 'standard-frontend-react (TS 3.8)' + label: 'react-router-6 (TS 3.8)' - test-application: 'create-next-app' build-command: 'test:build-13' label: 'create-next-app (next@13)' @@ -1057,7 +1059,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.HEAD_COMMIT }} - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8.3.1 - name: Set up Node @@ -1132,7 +1134,7 @@ jobs: PUBLIC_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} REACT_APP_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} E2E_TEST_SENTRY_ORG_SLUG: 'sentry-javascript-sdks' - E2E_TEST_SENTRY_TEST_PROJECT: 'sentry-javascript-e2e-tests' + E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false matrix: @@ -1154,7 +1156,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.HEAD_COMMIT }} - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8.3.1 - name: Set up Node @@ -1219,7 +1221,7 @@ jobs: E2E_TEST_AUTH_TOKEN: ${{ secrets.E2E_TEST_AUTH_TOKEN }} E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} E2E_TEST_SENTRY_ORG_SLUG: 'sentry-javascript-sdks' - E2E_TEST_SENTRY_TEST_PROJECT: 'sentry-javascript-e2e-tests' + E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false matrix: @@ -1233,7 +1235,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.HEAD_COMMIT }} - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8.3.1 - name: Set up Node diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 5f58292646df..b8cffb3698ea 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -14,7 +14,7 @@ env: CACHED_BUILD_PATHS: | ${{ github.workspace }}/packages/*/*.tgz - ${{ github.workspace }}/dev-packages/event-proxy-server/build + ${{ github.workspace }}/dev-packages/test-utils/build ${{ github.workspace }}/node_modules ${{ github.workspace }}/packages/*/node_modules ${{ github.workspace }}/dev-packages/*/node_modules @@ -54,7 +54,7 @@ jobs: name: E2E ${{ matrix.label }} Test needs: [job_e2e_prepare] runs-on: ubuntu-20.04 - timeout-minutes: 15 + timeout-minutes: 20 env: E2E_TEST_AUTH_TOKEN: ${{ secrets.E2E_TEST_AUTH_TOKEN }} E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} @@ -63,7 +63,7 @@ jobs: PUBLIC_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} REACT_APP_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} E2E_TEST_SENTRY_ORG_SLUG: 'sentry-javascript-sdks' - E2E_TEST_SENTRY_TEST_PROJECT: 'sentry-javascript-e2e-tests' + E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false matrix: @@ -92,16 +92,16 @@ jobs: - test-application: 'react-create-hash-router' build-command: 'test:build-canary' label: 'react-create-hash-router (canary)' - - test-application: 'standard-frontend-react' + - test-application: 'react-router-6' build-command: 'test:build-canary' - label: 'standard-frontend-react (canary)' + label: 'react-router-6 (canary)' steps: - name: Check out current commit uses: actions/checkout@v4 with: ref: ${{ env.HEAD_COMMIT }} - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8.3.1 @@ -138,7 +138,7 @@ jobs: - name: Run E2E test working-directory: dev-packages/e2e-tests/test-applications/${{ matrix.test-application }} - timeout-minutes: 5 + timeout-minutes: 15 run: yarn test:assert - name: Create Issue diff --git a/.size-limit.js b/.size-limit.js index 8a55b86e9b5e..f9b62e7198e9 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -22,7 +22,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/index.js', import: createImport('init', 'browserTracingIntegration', 'replayIntegration'), gzip: true, - limit: '70 KB', + limit: '71 KB', }, { name: '@sentry/browser (incl. Tracing, Replay) - with treeshaking flags', @@ -211,7 +211,24 @@ module.exports = [ import: createImport('init'), ignore: [...builtinModules, ...nodePrefixedBuiltinModules], gzip: true, - limit: '180 KB', + limit: '135 KB', + }, + { + name: '@sentry/node - without tracing', + path: 'packages/node/build/esm/index.js', + import: createImport('initWithoutDefaultIntegrations', 'getDefaultIntegrationsWithoutPerformance'), + gzip: true, + limit: '110 KB', + ignore: [...builtinModules, ...nodePrefixedBuiltinModules], + modifyWebpackConfig: function (config) { + const webpack = require('webpack'); + config.plugins.push( + new webpack.DefinePlugin({ + __SENTRY_TRACING__: false, + }), + ); + return config; + }, }, // AWS SDK (ESM) { @@ -220,7 +237,7 @@ module.exports = [ import: createImport('init'), ignore: [...builtinModules, ...nodePrefixedBuiltinModules], gzip: true, - limit: '140 KB', + limit: '125 KB', }, ]; diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a0a90df7089..0f7f203ec826 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,50 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +## 8.8.0 + +- **feat: Upgrade OTEL dependencies (#12388)** + +This upgrades the OpenTelemetry dependencies to the latest versions and makes OTEL use `import-in-the-middle` `v1.8.0`. +This should fix numerous issues with using OTEL instrumentation with ESM. + +High level issues fixed with OTEL + ESM: + +- incompatibilities with using multiple loaders, commonly encountered while using `tsx` or similar libraries. +- incompatibilities with libraries that use duplicate namespace exports like `date-fns`. +- incompatibilities with libraries that use self-referencing namespace imports like `openai`. +- incompatibilities with dynamic export patterns like exports with function calls. +- `ENOENT: no such file or directory` bugs that libraries like [`discord.js`](https://github.com/discordjs/discord.js) + surface. + +If you are still encountering issues with OpenTelemetry instrumentation and ESM, please let us know. + +- deps: Bump Sentry bundler plugins to version `2.18.0` (#12381) +- feat: Add `thirdPartyErrorFilterIntegration` (#12267) +- feat(core): Filter out error events with exception values and no stacktraces, values, or types (#12387) +- feat(core): Ignore additional common but inactionable errors (#12384) +- feat(deps): Bump @opentelemetry/propagator-aws-xray from 1.3.1 to 1.24.1 (#12333) +- feat(deps): Bump @sentry/cli from 2.31.2 to 2.32.1 (#12332) +- feat(redis): Support `mget` command in caching functionality (#12380) +- feat(vercel-edge): Export core integrations from Vercel edge SDK (#12308) +- fix(browser): Fix idle span ending (#12306) +- fix(browser): Fix parenthesis parsing logic for chromium (#12373) +- fix(browser): Fix types export path for CJS (#12305) +- fix(feedback): Override TriggerLabel Option (#12316) +- fix(feedback): Wait for document to be ready before doing autoinject (#12294) +- fix(nextjs): Fix memory leak (#12335) +- fix(nextjs): Fix version detection and option insertion logic for `clientTraceMetadata` option (#12323) +- fix(nextjs): Update argument name in log message about `sentry` property on Next.js config object (#12366) +- fix(node): Do not manually finish / update root Hapi spans. (#12287) +- fix(node): Fix virtual parent span ID handling & update create-next-app E2E test (#12368) +- fix(node): Skip capturing Hapi Boom responses v8. (#12288) +- fix(performance): Fix LCP not getting picked up on initial pageload transaction by setting reportAllChanges to true + (#12360) +- fix(replay): Avoid infinite loop of logs (#12309) +- fix(replay): Ignore old events when manually starting replay (#12349) +- ref(browser): Ensure idle span ending is consistent (#12310) +- ref(profiling): unref timer (#12340) + ## 8.7.0 ### Important Changes @@ -1372,3744 +1416,9 @@ We have also removed or updated a variety of deprecated APIs. - ref: Remove usage of span tags (#10808) - ref: Remove user segment (#10575) -## 7.112.2 - -- fix(nextjs|sveltekit): Ensure we can pass `browserTracingIntegration` (#11765) - -## 7.112.1 - -- fix(ember/v7): Do not create rendering spans without transaction (#11750) - -## 7.112.0 - -### Important Changes - -- **feat: Export pluggable integrations from SDK packages (#11723)** - -Instead of installing `@sentry/integrations`, you can now import the pluggable integrations directly from your SDK -package: - -```js -// Before -import * as Sentry fromv '@sentry/browser'; -import { dedupeIntegration } from '@sentry/integrations'; - -Sentry.init({ - integrations: [dedupeIntegration()], -}); - -// After -import * as Sentry from '@sentry/browser'; - -Sentry.init({ - integrations: [Sentry.dedupeIntegration()], -}); -``` - -Note that only the functional integrations (e.g. `xxxIntegration()`) are re-exported. - -### Other Changes - -- feat(replay): Add "maxCanvasSize" option for replay canvases (#11732) -- fix(serverless): [v7] Check if cloud event callback is a function (#11734) - -## 7.111.0 - -- feat(core): Add `server.address` to browser `http.client` spans (#11663) -- fix: Ensure next & sveltekit correctly handle `browserTracingIntegration` (#11647) -- fix(browser): Don't assume window.document is available (#11598) - -## 7.110.1 - -- fix(nextjs): Fix `tunnelRoute` matching logic for hybrid cloud (#11577) - -## 7.110.0 - -### Important Changes - -- **feat(tracing): Add interactions sample rate to browser tracing integrations (#11382)** - -You can now use a `interactionsSampleRate` to control the sample rate of INP spans. `interactionsSampleRate` is applied -on top of the global `tracesSampleRate`. Therefore if `interactionsSampleRate` is `0.5` and `tracesSampleRate` is `0.1`, -then the actual sample rate for interactions is `0.05`. - -```js -Sentry.init({ - tracesSampleRate: 0.1, - integrations: [ - Sentry.browserTracingIntegration({ - interactionsSampleRate: 0.5, - }), - ], -}); -``` - -- **Deprecations** - -This release deprecates the `Hub` class, as well as the `addRequestDataToTransaction` method. The `trpcMiddleware` -method is no longer on the `Handlers` export, but instead is a standalone export. - -Please see the detailed [Migration docs](./MIGRATION.md#deprecations-in-7x) on how to migrate to the new APIs. - -- feat: Deprecate and relocate `trpcMiddleware` (#11389) -- feat(core): Deprecate `Hub` class (#11528) -- feat(types): Deprecate `Hub` interface (#11530) -- ref: Deprecate `addRequestDataToTransaction` (#11368) - -### Other Changes - -- feat(core): Update metric normalization (#11519) -- feat(feedback): Customize feedback placeholder text color (#11521) -- feat(remix): Skip span creation for `OPTIONS` and `HEAD` request. (#11485) -- feat(utils): Add metric buckets rate limit (#11506) -- fix(core): unref timer to not block node exit (#11483) -- fix(metrics): Map `statsd` to `metric_bucket` (#11505) -- fix(spans): Allow zero exclusive time for INP spans (#11408) -- ref(feedback): Configure feedback fonts (#11520) - -## 7.109.0 - -This release deprecates some exports from the `@sentry/replay` package. These exports have been moved to the browser SDK -(or related framework SDKs like `@sentry/react`). - -- feat(feedback): Make "required" text for input elements configurable (#11287) -- feat(node): Add scope to ANR events (#11267) -- feat(replay): Bump `rrweb` to 2.12.0 (#11317) -- fix(node): Local variables skipped after Promise (#11248) -- fix(node): Skip capturing Hapi Boom error responses (#11324) -- fix(web-vitals): Check for undefined navigation entry (#11312) -- ref(replay): Deprecate `@sentry/replay` exports (#11242) - -Work in this release contributed by @soerface. Thank you for your contribution! - -## 7.108.0 - -This release fixes issues with Time to First Byte (TTFB) calculation in the SDK that was introduced with `7.95.0`. It -also fixes some bugs with Interaction to First Paint (INP) instrumentation. This may impact your Sentry Performance -Score calculation. - -- feat(serverless): Add Node.js 20 to compatible runtimes (#11104) -- feat(core): Backport `ResizeObserver` and `googletag` default filters (#11210) -- feat(webvitals): Adds event entry names for INP handler. Also guard against empty metric value -- fix(metrics): use correct statsd data category (#11187) -- fix(node): Record local variables with falsy values (v7) (#11190) -- fix(node): Use unique variable for ANR context transfer (v7) (#11162) -- fix(node): Time zone handling for `cron` (#11225) -- fix(tracing): use web-vitals ttfb calculation (#11231) -- fix(types): Fix incorrect `sampled` type on `Transaction` (#11146) -- fix(webvitals): Fix mapping not being maintained properly and sometimes not sending INP spans (#11183) - -Work in this release contributed by @quisido and @joshkel. Thank you for your contributions! - -## 7.107.0 - -This release fixes issues with INP instrumentation with the Next.js SDK and adds support for the `enableInp` option in -the deprecated `BrowserTracing` integration for backwards compatibility. - -- feat(performance): Port INP span instrumentation to old browser tracing (#11085) -- fix(ember): Ensure browser tracing is correctly lazy loaded (#11027) -- fix(node): Do not assert in vendored proxy code (v7 backport) (#11009) -- fix(react): Set `handled` value in ErrorBoundary depending on fallback [v7] (#11037) - -## 7.106.1 - -- fix(nextjs/v7): Use passthrough `createReduxEnhancer` on server (#11010) - -## 7.106.0 - -- feat(nextjs): Support Hybrid Cloud DSNs with `tunnelRoute` option (#10958) -- feat(remix): Add Vite dev-mode support to Express instrumentation (#10811) -- fix(core): Undeprecate `setTransactionName` -- fix(browser): Don't use chrome variable name (#10874) -- fix(nextjs): Client code should not use Node `global` (#10925) -- fix(node): support undici headers as strings or arrays (#10938) -- fix(types): Add `AttachmentType` and use for envelope `attachment_type` property (#10946) -- ref(ember): Avoid namespace import to hopefully resolve minification issue (#10885) -- chore(sveltekit): Fix punctuation in a console.log (#10895) - -Work in this release contributed by @jessezhang91 and @bfontaine. Thank you for your contributions! - -## 7.105.0 - -### Important Changes - -- **feat: Ensure `withActiveSpan` is exported everywhere (#10877)** - -You can use the `withActiveSpan` method to ensure a certain span is the active span in a given callback. This can be -used to create a span as a child of a specific span with the `startSpan` API methods: - -```js -const parentSpan = Sentry.startInactiveSpan({ name: 'parent' }); -if (parentSpan) { - withActiveSpan(parentSpan, () => { - // This will be a direct child of parentSpan - const childSpan = Sentry.startInactiveSpan({ name: 'child' }); - }); -} -``` - -## 7.104.0 - -### Important Changes - -- **feat(performance): create Interaction standalone spans on inp events (#10709)** - -This release adds support for the INP web vital. This is currently only supported for Saas Sentry, and product support -is released with the upcoming `24.3.0` release of self-hosted. - -To opt-in to this feature, you can use the `enableInp` option in the `browserTracingIntegration`: - -```js -Sentry.init({ - integrations: [ - Sentry.browserTracingIntegration({ - enableInp: true, - }); - ] -}) -``` - -### Other Changes - -- feat(feedback): Flush replays when feedback form opens (#10567) -- feat(profiling-node): Expose `nodeProfilingIntegration` (#10864) -- fix(profiling-node): Fix dependencies to point to current versions (#10861) -- fix(replay): Add `errorHandler` for replayCanvas integration (#10796) - -## 7.103.0 - -### Important Changes - -- **feat(core): Allow to pass `forceTransaction` to `startSpan()` APIs (#10819)** - -You can now pass `forceTransaction: true` to `startSpan()`, `startSpanManual()` and `startInactiveSpan()`. This allows -you to start a span that you want to be a transaction, if possible. Under the hood, the SDK will connect this span to -the running active span (if there is one), but still send the new span as a transaction to the Sentry backend, if -possible, ensuring it shows up as a transaction throughout the system. - -Please note that setting this to `true` does not _guarantee_ that this will be sent as a transaction, but that the SDK -will try to do so. You can enable this flag if this span is important to you and you want to ensure that you can see it -in the Sentry UI. - -### Other Changes - -- fix: Make breadcrumbs option optional in WinterCGFetch integration (#10792) - -## 7.102.1 - -- fix(performance): Fixes latest route name and source for interactions not updating properly on navigation (#10702) -- fix(tracing): Guard against missing `window.location` (#10659) -- ref: Make span types more robust (#10660) -- ref(remix): Make `@remix-run/router` a dependency (v7) (#10779) - -## 7.102.0 - -- fix: Export session API (#10712) -- fix(core): Fix scope capturing via `captureContext` function (#10737) - -## 7.101.1 - -In version 7.101.0 the `@sentry/hub` package was missing due to a publishing issue. This release contains the package -again. - -- fix(nextjs): Remove `webpack://` prefix more broadly from source map `sources` field (#10641) - -## 7.101.0 - -- feat: Export semantic attribute keys from SDK packages (#10637) -- feat(core): Add metric summaries to spans (#10554) -- feat(core): Deprecate the `Hub` constructor (#10584) -- feat(core): Make custom tracing methods return spans & set default op (#10633) -- feat(replay): Add `getReplay` utility function (#10510) -- fix(angular-ivy): Add `exports` field to `package.json` (#10569) -- fix(sveltekit): Avoid capturing Http 4xx errors on the client (#10571) -- fix(sveltekit): Properly await sourcemaps flattening (#10602) - -## 7.100.1 - -This release contains build fixes for profiling-node. - -- build(profiling-node): make sure debug build plugin is used #10534 -- build: Only run profiling e2e test if bindings have changed #10542 -- fix(feedback): Replay breadcrumb for feedback events was incorrect #10536 - -## 7.100.0 - -### Important Changes - -#### Deprecations - -This release includes some deprecations. For more details please look at our -[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md). - -The deprecation most likely to affect you is the one of `BrowserTracing`. Instead of `new BrowserTracing()`, you should -now use `browserTracingIntegration()`, which will also handle framework-specific instrumentation out of the box for -you - no need to pass a custom `routingInstrumentation` anymore. For `@sentry/react`, we expose dedicated integrations -for the different react-router versions: - -- `reactRouterV6BrowserTracingIntegration()` -- `reactRouterV5BrowserTracingIntegration()` -- `reactRouterV4BrowserTracingIntegration()` -- `reactRouterV3BrowserTracingIntegration()` - -See the -[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md#depreacted-browsertracing-integration) -for details. - -- feat(angular): Export custom `browserTracingIntegration()` (#10353) -- feat(browser): Deprecate `BrowserTracing` integration (#10493) -- feat(browser): Export `browserProfilingIntegration` (#10438) -- feat(bun): Export `bunServerIntegration()` (#10439) -- feat(nextjs): Add `browserTracingIntegration` (#10397) -- feat(react): Add `reactRouterV3BrowserTracingIntegration` for react router v3 (#10489) -- feat(react): Add `reactRouterV4/V5BrowserTracingIntegration` for react router v4 & v5 (#10488) -- feat(react): Add `reactRouterV6BrowserTracingIntegration` for react router v6 & v6.4 (#10491) -- feat(remix): Add custom `browserTracingIntegration` (#10442) -- feat(node): Expose functional integrations to replace classes (#10356) -- feat(vercel-edge): Replace `WinterCGFetch` with `winterCGFetchIntegration` (#10436) -- feat: Deprecate non-callback based `continueTrace` (#10301) -- feat(vue): Deprecate `new VueIntegration()` (#10440) -- feat(vue): Implement vue `browserTracingIntegration()` (#10477) -- feat(sveltekit): Add custom `browserTracingIntegration()` (#10450) - -#### Profiling Node - -`@sentry/profiling-node` has been ported into the monorepo. Future development for it will happen here! - -- pkg(profiling-node): port profiling-node repo to monorepo (#10151) - -### Other Changes - -- feat: Export `setHttpStatus` from all packages (#10475) -- feat(bundles): Add pluggable integrations on CDN to `Sentry` namespace (#10452) -- feat(core): Pass `name` & `attributes` to `tracesSampler` (#10426) -- feat(feedback): Add `system-ui` to start of font family (#10464) -- feat(node-experimental): Add koa integration (#10451) -- feat(node-experimental): Update opentelemetry packages (#10456) -- feat(node-experimental): Update tracing integrations to functional style (#10443) -- feat(replay): Bump `rrweb` to 2.10.0 (#10445) -- feat(replay): Enforce masking of credit card fields (#10472) -- feat(utils): Add `propagationContextFromHeaders` (#10313) -- fix: Make `startSpan`, `startSpanManual` and `startInactiveSpan` pick up the scopes at time of creation instead of - termination (#10492) -- fix(feedback): Fix logo color when colorScheme is "system" (#10465) -- fix(nextjs): Do not report redirects and notFound calls as errors in server actions (#10474) -- fix(nextjs): Fix navigation tracing on app router (#10502) -- fix(nextjs): Apply server action data to correct isolation scope (#10514) -- fix(node): Use normal `require` call to import Undici (#10388) -- ref(nextjs): Remove internally used deprecated APIs (#10453) -- ref(vue): use startInactiveSpan in tracing mixin (#10406) - -## 7.99.0 - -### Important Changes - -#### Deprecations - -This release includes some deprecations for span related methods and integrations in our Deno SDK, `@sentry/deno`. For -more details please look at our -[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md). - -- feat(core): Deprecate `Span.setHttpStatus` in favor of `setHttpStatus` (#10268) -- feat(core): Deprecate `spanStatusfromHttpCode` in favour of `getSpanStatusFromHttpCode` (#10361) -- feat(core): Deprecate `StartSpanOptions.origin` in favour of passing attribute (#10274) -- feat(deno): Expose functional integrations to replace classes (#10355) - -### Other Changes - -- feat(bun): Add missing `@sentry/node` re-exports (#10396) -- feat(core): Add `afterAllSetup` hook for integrations (#10345) -- feat(core): Ensure `startSpan()` can handle spans that require parent (#10386) -- feat(core): Read propagation context off scopes in `startSpan` APIs (#10300) -- feat(remix): Export missing `@sentry/node` functions (#10385, #10391) -- feat(serverless): Add missing `@sentry/node` re-exports (#10390) -- feat(sveltekit): Add more missing `@sentry/node` re-exports (#10392) -- feat(tracing): Export proper type for browser tracing (#10411) -- feat(tracing): Expose new `browserTracingIntegration` (#10351) -- fix: Ensure `afterAllSetup` is called when using `addIntegration()` (#10372) -- fix(core): Export `spanToTraceContext` function from span utils (#10364) -- fix(core): Make `FunctionToString` integration use SETUP_CLIENTS weakmap (#10358) -- fix(deno): Call function if client is not setup (#10354) -- fix(react): Fix attachReduxState option (#10381) -- fix(spotlight): Use unpatched http.request (#10369) -- fix(tracing): Only create request span if there is active span (#10375) -- ref: Read propagation context off of scope and isolation scope when propagating and applying trace context (#10297) - -Work in this release contributed by @AleshaOleg. Thank you for your contribution! - -## 7.98.0 - -This release primarily fixes some type declaration errors: - -- feat(core): Export `IntegrationIndex` type (#10337) -- fix(nextjs): Fix Http integration type declaration (#10338) -- fix(node): Fix type definitions (#10339) - -## 7.97.0 - -Note: The 7.96.0 release was incomplete. This release is partially encompassing changes from `7.96.0`. - -- feat(react): Add `stripBasename` option for React Router 6 (#10314) - -## 7.96.0 - -Note: This release was incomplete. Not all Sentry SDK packages were released for this version. Please upgrade to 7.98.0 -directly. - -### Important Changes - -#### Deprecations - -This release includes some deprecations for integrations in `@sentry/browser` and frontend framework SDKs -(`@sentry/react`, `@sentry/vue`, etc.). Please take a look at our -[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md) for more details. - -- feat(browser): Export functional integrations & deprecate classes (#10267) - -#### Web Vitals Fix for LCP and CLS - -This release fixes an issue with the Web Vitals integration where LCP and CLS were not being captured correctly, -increasing capture rate by 10-30% for some apps. LCP and CLS capturing issues were introduced with version `7.75.0`. - -- fix(tracing): Ensure web vitals are correctly stopped/captured (#10323) - -### Other Changes - -- fix(node): Fix `node-cron` types and add test (#10315) -- fix(node): Fix downleveled types entry point (#10321) -- fix(node): LocalVariables integration should use setupOnce (#10307) -- fix(replay): Fix type for options of replayIntegration (#10325) - -Work in this release contributed by @Shubhdeep12. Thank you for your contribution! - -## 7.95.0 - -### Important Changes - -#### Deprecations - -This release includes some deprecations in preparation for v8. - -Most notably, it deprecates the `Replay` & `Feedback` classes in favor of a functional replacement: - -```js -import * as Sentry from '@sentry/browser'; - -Sentry.init({ - integrations: [ - // Instead of - new Sentry.Replay(), - new Sentry.Feedback(), - // Use the functional replacement: - Sentry.replayIntegration(), - Sentry.feedbackIntegration(), - ], -}); -``` - -- feat(core): Deprecate `Span.origin` in favor of `sentry.origin` attribute (#10260) -- feat(core): Deprecate `Span.parentSpanId` (#10244) -- feat(core): Expose `isInitialized()` to replace checking via `getClient` (#10296) -- feat(replay): Deprecate `Replay`, `ReplayCanvas`, `Feedback` classes (#10270) -- feat(wasm): Deprecate `Wasm` integration class (#10230) - -### Other Changes - -- feat: Make `parameterize` function available through browser and node API (#10085) -- feat(feedback): Configure feedback border radius (#10289) -- feat(sveltekit): Update default integration handling & deprecate `addOrUpdateIntegration` (#10263) -- fix(replay-canvas): Add missing dependency on @sentry/utils (#10279) -- fix(tracing): Don't send negative ttfb (#10286) - -Work in this release contributed by @AleshaOleg. Thank you for your contribution! - -## 7.94.1 - -This release fixes a publishing issue. - -## 7.94.0 - -### Important Changes - -#### Deprecations - -As we're moving closer to the next major version of the SDK, more public APIs were deprecated. - -To get a head start on migrating to the replacement APIs, please take a look at our -[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md). - -- feat: Deprecate user segment field (#10210) -- feat(core): Deprecate `finish` on `Span` interface in favour of `end` (#10161) -- feat(core): Deprecate `getCurrentHub()` (#10200) -- feat(core): Deprecate `hub.bindClient()` & `makeMain()` (#10188) -- feat(core): Deprecate `Span.instrumenter` (#10139) -- feat(core): Deprecate `Span.isSuccess()` in favor of reading span status (#10213) -- feat(core): Deprecate `Span.op` in favor of op attribute (#10189) -- feat(core): Deprecate `Span.spanRecorder` (#10199) -- feat(core): Deprecate `Span.status` (#10208) -- feat(core): Deprecate `Span.transaction` in favor of `getRootSpan` (#10134) -- feat(core): Deprecate `Transaction.instrumenter` (#10162) -- feat(core): Deprecate `Transaction.setMeasurement` in favor of `setMeasurement` (#10182) -- feat(core): Deprecate integration classes & `Integrations.X` (#10198) -- feat(core): Deprecate methods on `Hub` (#10124) -- feat(core): Deprecate remaining `setName` declarations on `Transaction` and `Span` (#10164) -- feat(core): Deprecate span `startTimestamp` & `endTimestamp` (#10192) -- feat(core): Deprecate `hub.bindClient()` and `makeMain()` (#10118) -- feat(types): Deprecate `op` on `Span` interface (#10217) -- feat(integrations): Deprecate `Transaction` integration (#10178) -- feat(integrations): Deprecate pluggable integration classes (#10211) - -#### Replay & Canvas - -We have added a new `ReplayCanvas` integration (#10112), which you can add to capture the contents of canvas elements -with Replay. - -Just add it _in addition_ to the regular replay integration: - -```js -Sentry.init({ - integrations: [new Sentry.Replay(), new Sentry.ReplayCanvas()], -}); -``` - -### Other Changes - -- feat(core): Add `client.getIntegrationByName()` (#10130) -- feat(core): Add `client.init()` to replace `client.setupIntegrations()` (#10118) -- feat(core): Add `withActiveSpan` (#10195) -- feat(core): Add `withIsolationScope` (#10141) -- feat(core): Streamline integration function results to be compatible (#10135) -- feat(core): Write data from `setUser`, `setTags`, `setExtras`, `setTag`, `setExtra`, and `setContext` to isolation - scope (#10163) -- feat(core): Add domain information to resource span data #10205 -- feat(feedback): Export sendFeedback from @sentry/browser (#10231) -- feat(node): Update and vendor https-proxy-agent (#10088) -- feat(node-experimental): Add `withActiveSpan` (#10194) -- feat(replays): Add snapshot function to replay canvas integration (#10066) -- feat(types): Add `SerializedEvent` interface (pre v8) (#10240) -- feat(types): Add support for new monitor config thresholds (#10225) -- fix: Ensure all integration classes have correct types (#10183) -- fix(astro): Fix import path when using external init files with default path (#10214) -- fix(cdn): Emit console warning instead of error for integration shims (#10193) -- fix(core): Take user from current scope when starting a session (#10153) -- fix(node-experimental): Ensure `http.status_code` is always a string (#10177) -- fix(node): Guard against `process.argv[1]` being undefined (#10155) -- fix(node): Module name resolution (#10144) -- fix(node): Remove leading slash in Windows filenames (#10147) -- fix(remix): Capture thrown fetch responses. (#10166) -- fix(tracing): Gate mongo operation span data behind sendDefaultPii (#10227) -- fix(tracing-internal): Delay pageload transaction finish until document is interactive (#10215) -- fix(tracing-internal): Only collect request/response spans when browser performance timing is available (#10207) -- fix(tracing-internal): Prefer `fetch` init headers over `fetch` input headers (#10176) -- fix(utils): Ensure dropUndefinedKeys() does not break class instances (#10245) - -## 7.93.0 - -### Important Changes - -#### Deprecations - -As we're moving closer to the next major version of the SDK, more public APIs were deprecated. - -To get a head start on migrating to the replacement APIs, please take a look at our -[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md). - -- feat(core): Deprecate `getActiveTransaction()` & `scope.getTransaction()` (#10098) -- feat(core): Deprecate `Hub.shouldSendDefaultPii` (#10062) -- feat(core): Deprecate `new Transaction()` (#10125) -- feat(core): Deprecate `scope.getSpan()` & `scope.setSpan()` (#10114) -- feat(core): Deprecate `scope.setTransactionName()` (#10113) -- feat(core): Deprecate `span.startChild()` (#10091) -- feat(core): Deprecate `startTransaction()` (#10073) -- feat(core): Deprecate `Transaction.getDynamicSamplingContext` in favor of `getDynamicSamplingContextFromSpan` (#10094) -- feat(core): Deprecate arguments for `startSpan()` (#10101) -- feat(core): Deprecate hub capture APIs and add them to `Scope` (#10039) -- feat(core): Deprecate session APIs on hub and add global replacements (#10054) -- feat(core): Deprecate span `name` and `description` (#10056) -- feat(core): Deprecate span `tags`, `data`, `context` & setters (#10053) -- feat(core): Deprecate transaction metadata in favor of attributes (#10097) -- feat(core): Deprecate `span.sampled` in favor of `span.isRecording()` (#10034) -- ref(node-experimental): Deprecate `lastEventId` on scope (#10093) - -#### Cron Monitoring Support for `node-schedule` library - -This release adds auto instrumented check-ins for the `node-schedule` library. - -```ts -import * as Sentry from '@sentry/node'; -import * as schedule from 'node-schedule'; - -const scheduleWithCheckIn = Sentry.cron.instrumentNodeSchedule(schedule); - -const job = scheduleWithCheckIn.scheduleJob('my-cron-job', '* * * * *', () => { - console.log('You will see this message every minute'); -}); -``` - -- feat(node): Instrumentation for `node-schedule` library (#10086) - -### Other Changes - -- feat(core): Add `span.spanContext()` (#10037) -- feat(core): Add `spanToJSON()` method to get span properties (#10074) -- feat(core): Allow to pass `scope` to `startSpan` APIs (#10076) -- feat(core): Allow to pass start/end timestamp for spans flexibly (#10060) -- feat(node): Make `getModuleFromFilename` compatible with ESM (#10061) -- feat(replay): Update rrweb to 2.7.3 (#10072) -- feat(utils): Add `parameterize` function (#9145) -- fix(astro): Use correct package name for CF (#10099) -- fix(core): Do not run `setup` for integration on client multiple times (#10116) -- fix(core): Ensure we copy passed in span data/tags/attributes (#10105) -- fix(cron): Make name required for instrumentNodeCron option (#10070) -- fix(nextjs): Don't capture not-found and redirect errors in generation functions (#10057) -- fix(node): `LocalVariables` integration should have correct name (#10084) -- fix(node): Anr events should have an `event_id` (#10068) -- fix(node): Revert to only use sync debugger for `LocalVariables` (#10077) -- fix(node): Update ANR min node version to v16.17.0 (#10107) - -## 7.92.0 - -### Important Changes - -#### Deprecations - -- feat(core): Add `span.updateName()` and deprecate `span.setName()` (#10018) -- feat(core): Deprecate `span.getTraceContext()` (#10032) -- feat(core): Deprecate `span.toTraceparent()` in favor of `spanToTraceHeader()` util (#10031) -- feat(core): Deprecate `trace` in favor of `startSpan` (#10012) -- feat(core): Deprecate span `toContext()` and `updateWithContext()` (#10030) -- ref: Deprecate `deepReadDirSync` (#10016) -- ref: Deprecate `lastEventId()` (#10043) - -Please take a look at the [Migration docs](./MIGRATION.md) for more details. These methods will be removed in the -upcoming [v8 major release](https://github.com/getsentry/sentry-javascript/discussions/9802). - -#### Cron Monitoring Support for `cron` and `node-cron` libraries - -- feat(node): Instrumentation for `cron` library (#9999) -- feat(node): Instrumentation for `node-cron` library (#9904) - -This release adds instrumentation for the `cron` and `node-cron` libraries. This allows you to monitor your cron jobs -with [Sentry cron monitors](https://docs.sentry.io/product/crons/). - -For [`cron`](https://www.npmjs.com/package/cron): - -```js -import * as Sentry from '@sentry/node'; -import { CronJob } from 'cron'; - -const CronJobWithCheckIn = Sentry.cron.instrumentCron(CronJob, 'my-cron-job'); - -// use the constructor -const job = new CronJobWithCheckIn('* * * * *', () => { - console.log('You will see this message every minute'); -}); - -// or from -const job = CronJobWithCheckIn.from({ - cronTime: '* * * * *', - onTick: () => { - console.log('You will see this message every minute'); - }, -}); -``` - -For [`node-cron`](https://www.npmjs.com/package/node-cron): - -```js -import * as Sentry from '@sentry/node'; -import cron from 'node-cron'; - -const cronWithCheckIn = Sentry.cron.instrumentNodeCron(cron); - -cronWithCheckIn.schedule( - '* * * * *', - () => { - console.log('running a task every minute'); - }, - { name: 'my-cron-job' }, -); -``` - -### Other Changes - -- feat(astro): Add `enabled` option to Astro integration options (#10007) -- feat(core): Add `attributes` to `Span` (#10008) -- feat(core): Add `setClient()` and `getClient()` to `Scope` (#10055) -- feat(integrations): Capture error cause with `captureErrorCause` in `ExtraErrorData` integration (#9914) -- feat(node-experimental): Allow to pass base span options to trace methods (#10006) -- feat(node): Local variables via async inspector in node 19+ (#9962) -- fix(astro): handle commonjs related issues (#10042) -- fix(astro): Handle non-utf8 encoded streams in middleware (#9989) -- fix(astro): prevent sentry from externalized (#9994) -- fix(core): Ensure `withScope` sets current scope correctly with async callbacks (#9974) -- fix(node): ANR fixes and additions (#9998) -- fix(node): Anr should not block exit (#10035) -- fix(node): Correctly resolve module name (#10001) -- fix(node): Handle inspector already open (#10025) -- fix(node): Make `NODE_VERSION` properties required (#9964) -- fix(node): Anr doesn't block exit (#10064) -- fix(utils): use correct typeof URL validation (#10028) -- perf(astro): reduce unnecessary path resolutions (#10021) -- ref(astro): Use astro logger instead of console (#9995) -- ref(remix): Isolate Express instrumentation from server auto-instrumentation. (#9966) - -Work in this release contributed by @joshkel. Thank you for your contribution! - -## 7.91.0 - -### Important Changes - -- **feat: Add server runtime metrics aggregator (#9894)** - -The release adds alpha support for [Sentry developer metrics](https://github.com/getsentry/sentry/discussions/58584) in -the server runtime SDKs (`@sentry/node`, `@sentry/deno`, `@sentry/nextjs` server-side, etc.). Via the newly introduced -APIs, you can now flush metrics directly to Sentry. - -To enable capturing metrics, you first need to add the `metricsAggregator` experiment to your `Sentry.init` call. - -```js -Sentry.init({ - dsn: '__DSN__', - _experiments: { - metricsAggregator: true, - }, -}); -``` - -Then you'll be able to add `counters`, `sets`, `distributions`, and `gauges` under the `Sentry.metrics` namespace. - -```js -// Add 4 to a counter named `hits` -Sentry.metrics.increment('hits', 4); - -// Add 2 to gauge named `parallel_requests`, tagged with `type: "a"` -Sentry.metrics.gauge('parallel_requests', 2, { tags: { type: 'a' } }); - -// Add 4.6 to a distribution named `response_time` with unit seconds -Sentry.metrics.distribution('response_time', 4.6, { unit: 'seconds' }); - -// Add 2 to a set named `valuable.ids` -Sentry.metrics.set('valuable.ids', 2); -``` - -- **feat(node): Rework ANR to use worker script via an integration (#9945)** - -The [ANR tracking integration for Node](https://docs.sentry.io/platforms/node/configuration/application-not-responding/) -has been reworked to use an integration. ANR tracking now requires a minimum Node version of 16 or higher. Previously -you had to call `Sentry.enableANRDetection` before running your application, now you can simply add the `Anr` -integration to your `Sentry.init` call. - -```js -import * as Sentry from '@sentry/node'; - -Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', - integrations: [new Sentry.Integrations.Anr({ captureStackTrace: true, anrThreshold: 200 })], -}); -``` - -### Other Changes - -- feat(breadcrumbs): Send component names on UI breadcrumbs (#9946) -- feat(core): Add `getGlobalScope()` method (#9920) -- feat(core): Add `getIsolationScope()` method (#9957) -- feat(core): Add `span.end()` to replace `span.finish()` (#9954) -- feat(core): Ensure `startSpan` & `startSpanManual` fork scope (#9955) -- feat(react): Send component name on spans (#9949) -- feat(replay): Send component names in replay breadcrumbs (#9947) -- feat(sveltekit): Add options to configure fetch instrumentation script for CSP (#9969) -- feat(tracing): Send component name on interaction spans (#9948) -- feat(utils): Add function to extract relevant component name (#9921) -- fix(core): Rethrow caught promise rejections in `startSpan`, `startSpanManual`, `trace` (#9958) - -## 7.90.0 - -- feat(replay): Change to use preset quality values (#9903) -- fix(replay): Adjust development hydration error messages (#9922) -- fix(sveltekit): Add `types` field to package.json `exports` (#9926) - -## 7.89.0 - -### Important Changes - -#### Deprecations - -- **feat(core): Deprecate `configureScope` (#9887)** -- **feat(core): Deprecate `pushScope` & `popScope` (#9890)** - -This release deprecates `configureScope`, `pushScope`, and `popScope`, which will be removed in the upcoming v8 major -release. - -#### Hapi Integration - -- **feat(node): Add Hapi Integration (#9539)** - -This release adds an integration for Hapi. It can be used as follows: - -```ts -const Sentry = require('@sentry/node'); -const Hapi = require('@hapi/hapi'); - -const init = async () => { - const server = Hapi.server({ - // your server configuration ... - }); - - Sentry.init({ - dsn: '__DSN__', - tracesSampleRate: 1.0, - integrations: [new Sentry.Integrations.Hapi({ server })], - }); - - server.route({ - // your route configuration ... - }); - - await server.start(); -}; -``` - -#### SvelteKit 2.0 - -- **chore(sveltekit): Add SvelteKit 2.0 to peer dependencies (#9861)** - -This release adds support for SvelteKit 2.0 in the `@sentry/sveltekit` package. If you're upgrading from SvelteKit 1.x -to 2.x and already use the Sentry SvelteKit SDK, no changes apart from upgrading to this (or a newer) version are -necessary. - -### Other Changes - -- feat(core): Add type & utility for function-based integrations (#9818) -- feat(core): Update `withScope` to return callback return value (#9866) -- feat(deno): Support `Deno.CronSchedule` for cron jobs (#9880) -- feat(nextjs): Auto instrument generation functions (#9781) -- feat(nextjs): Connect server component transactions if there is no incoming trace (#9845) -- feat(node-experimental): Update to new Scope APIs (#9799) -- feat(replay): Add `canvas.type` setting (#9877) -- fix(nextjs): Export `createReduxEnhancer` (#9854) -- fix(remix): Do not capture thrown redirect responses. (#9909) -- fix(sveltekit): Add conditional exports (#9872) -- fix(sveltekit): Avoid capturing 404 errors on client side (#9902) -- fix(utils): Do not use `Event` type in worldwide (#9864) -- fix(utils): Support crypto.getRandomValues in old Chromium versions (#9251) -- fix(utils): Update `eventFromUnknownInput` to avoid scope pollution & `getCurrentHub` (#9868) -- ref: Use `addBreadcrumb` directly & allow to pass hint (#9867) - -Work in this release contributed by @adam187, and @jghinestrosa. Thank you for your contributions! - -## 7.88.0 - -### Important Changes - -- **feat(browser): Add browser metrics sdk (#9794)** - -The release adds alpha support for [Sentry developer metrics](https://github.com/getsentry/sentry/discussions/58584) in -the Browser SDKs (`@sentry/browser` and related framework SDKs). Via the newly introduced APIs, you can now flush -metrics directly to Sentry. - -To enable capturing metrics, you first need to add the `MetricsAggregator` integration. - -```js -Sentry.init({ - dsn: '__DSN__', - integrations: [new Sentry.metrics.MetricsAggregator()], -}); -``` - -Then you'll be able to add `counters`, `sets`, `distributions`, and `gauges` under the `Sentry.metrics` namespace. - -```js -// Add 4 to a counter named `hits` -Sentry.metrics.increment('hits', 4); - -// Add 2 to gauge named `parallel_requests`, tagged with `happy: "no"` -Sentry.metrics.gauge('parallel_requests', 2, { tags: { happy: 'no' } }); - -// Add 4.6 to a distribution named `response_time` with unit seconds -Sentry.metrics.distribution('response_time', 4.6, { unit: 'seconds' }); - -// Add 2 to a set named `valuable.ids` -Sentry.metrics.set('valuable.ids', 2); -``` - -In a future release we'll add support for server runtimes (Node, Deno, Bun, Vercel Edge, etc.) - -- **feat(deno): Optionally instrument `Deno.cron` (#9808)** - -This releases add support for instrumenting [Deno cron's](https://deno.com/blog/cron) with -[Sentry cron monitors](https://docs.sentry.io/product/crons/). This requires v1.38 of Deno run with the `--unstable` -flag and the usage of the `DenoCron` Sentry integration. - -```ts -// Import from the Deno registry -import * as Sentry from 'https://deno.land/x/sentry/index.mjs'; - -Sentry.init({ - dsn: '__DSN__', - integrations: [new Sentry.DenoCron()], -}); -``` - -### Other Changes - -- feat(replay): Bump `rrweb` to 2.6.0 (#9847) -- fix(nextjs): Guard against injecting multiple times (#9807) -- ref(remix): Bump Sentry CLI to ^2.23.0 (#9773) - -## 7.87.0 - -- feat: Add top level `getCurrentScope()` method (#9800) -- feat(replay): Bump `rrweb` to 2.5.0 (#9803) -- feat(replay): Capture hydration error breadcrumb (#9759) -- feat(types): Add profile envelope types (#9798) -- fix(astro): Avoid RegExp creation during route interpolation (#9815) -- fix(browser): Avoid importing from `./exports` (#9775) -- fix(nextjs): Catch rejecting flushes (#9811) -- fix(nextjs): Fix devserver CORS blockage when `assetPrefix` is defined (#9766) -- fix(node): Capture errors in tRPC middleware (#9782) - -## 7.86.0 - -- feat(core): Use SDK_VERSION for hub API version (#9732) -- feat(nextjs): Emit warning if your app directory doesn't have a global-error.js file (#9753) -- feat(node): Add cloudflare pages commit sha (#9751) -- feat(remix): Bump @sentry/cli to 2.22.3 (#9741) -- fix(nextjs): Don't accidentally trigger static generation bailout (#9749) -- fix(node): Guard `process.env.NODE_ENV` access in Spotlight integration (#9748) -- fix(utils): Fix XHR instrumentation early return (#9770) -- ref(remix): Rework Error Handling (#9725) - -## 7.85.0 - -- feat(core): Add `addEventProcessor` method (#9554) -- feat(crons): Add interface for heartbeat checkin (#9706) -- feat(feedback): Include Feedback package in browser SDK (#9586) -- fix(astro): Isolate request instrumentation in middleware (#9709) -- fix(replay): Capture JSON XHR response bodies (#9623) -- ref(feedback): Change form `box-shadow` to use CSS var (#9630) - -## 7.84.0 - -### Important Changes - -- **ref(nextjs): Set `automaticVercelMonitors` to be `false` by default (#9697)** - -From this version onwards the default for the `automaticVercelMonitors` option in the Next.js SDK is set to false. -Previously, if you made use of Vercel Crons the SDK automatically instrumented the relevant routes to create Sentry -monitors. Because this feature will soon be generally available, we are now flipping the default to avoid situations -where quota is used unexpectedly. - -If you want to continue using this feature, make sure to set the `automaticVercelMonitors` flag to `true` in your -`next.config.js` Sentry settings. - -### Other Changes - -- chore(astro): Add 4.0.0 preview versions to `astro` peer dependency range (#9696) -- feat(metrics): Add interfaces for metrics (#9698) -- feat(web-vitals): Vendor in INP from web-vitals library (#9690) -- fix(astro): Avoid adding the Sentry Vite plugin in dev mode (#9688) -- fix(nextjs): Don't match files called `middleware` in node_modules (#9686) -- fix(remix): Don't capture error responses that are not 5xx on Remix v2. (#9655) -- fix(tracing): Don't attach resource size if null (#9669) -- fix(utils): Regex match port to stop accidental replace (#9676) -- fix(utils): Try catch new URL when extracting query params (#9675) - -## 7.83.0 - -- chore(astro): Allow Astro 4.0 in peer dependencies (#9683) -- feat(astro): Add `assets` option to source maps upload options (#9668) -- feat(react): Support `exactOptionalPropertyTypes` on `ErrorBoundary` (#9098) -- fix: Don't depend on browser types in `types` (#9682) -- fix(astro): Configure sourcemap assets directory for Vercel adapter (#9665) -- fix(remix): Check the error data before spreading. (#9664) - -## 7.82.0 - -- feat(astro): Automatically add Sentry middleware in Astro integration (#9532) -- feat(core): Add optional `setup` hook to integrations (#9556) -- feat(core): Add top level `getClient()` method (#9638) -- feat(core): Allow to pass `mechanism` as event hint (#9590) -- feat(core): Allow to use `continueTrace` without callback (#9615) -- feat(feedback): Add onClose callback to showReportDialog (#9433) (#9550) -- feat(nextjs): Add request data to all edge-capable functionalities (#9636) -- feat(node): Add Spotlight option to Node SDK (#9629) -- feat(utils): Refactor `addInstrumentationHandler` to dedicated methods (#9542) -- fix: Make full url customizable for Spotlight (#9652) -- fix(astro): Remove Auth Token existence check (#9651) -- fix(nextjs): Fix middleware detection logic (#9637) -- fix(remix): Skip capturing aborted requests (#9659) -- fix(replay): Add `BODY_PARSE_ERROR` warning & time out fetch response load (#9622) -- fix(tracing): Filter out invalid resource sizes (#9641) -- ref: Hoist `RequestData` integration to `@sentry/core` (#9597) -- ref(feedback): Rename onDialog* to onForm*, remove onActorClick (#9625) - -Work in this release contributed by @arya-s. Thank you for your contribution! - -## 7.81.1 - -- fix(astro): Remove method from span op (#9603) -- fix(deno): Make sure files get published (#9611) -- fix(nextjs): Use `globalThis` instead of `global` in edge runtime (#9612) -- fix(node): Improve error handling and shutdown handling for ANR (#9548) -- fix(tracing-internal): Fix case when originalURL contain query params (#9531) - -Work in this release contributed by @powerfulyang, @LubomirIgonda1, @joshkel, and @alexgleason. Thank you for your -contributions! - -## 7.81.0 - -### Important Changes - -**- feat(nextjs): Add instrumentation utility for server actions (#9553)** - -This release adds a utility function `withServerActionInstrumentation` to the `@sentry/nextjs` SDK for instrumenting -your Next.js server actions with error and performance monitoring. - -You can optionally pass form data and headers to record them, and configure the wrapper to record the Server Action -responses: - -```tsx -import * as Sentry from '@sentry/nextjs'; -import { headers } from 'next/headers'; - -export default function ServerComponent() { - async function myServerAction(formData: FormData) { - 'use server'; - return await Sentry.withServerActionInstrumentation( - 'myServerAction', // The name you want to associate this Server Action with in Sentry - { - formData, // Optionally pass in the form data - headers: headers(), // Optionally pass in headers - recordResponse: true, // Optionally record the server action response - }, - async () => { - // ... Your Server Action code - - return { name: 'John Doe' }; - }, - ); - } - - return ( -
- - -
- ); -} -``` - -### Other Changes - -- docs(feedback): Example docs on `sendFeedback` (#9560) -- feat(feedback): Add `level` and remove breadcrumbs from feedback event (#9533) -- feat(vercel-edge): Add fetch instrumentation (#9504) -- feat(vue): Support Vue 3 lifecycle hooks in mixin options (#9578) -- fix(nextjs): Download CLI binary if it can't be found (#9584) -- ref: Deprecate `extractTraceParentData` from `@sentry/core` & downstream packages (#9158) -- ref(replay): Add further logging to network body parsing (#9566) - -Work in this release contributed by @snoozbuster. Thank you for your contribution! - -## 7.80.1 - -- fix(astro): Adjust Vite plugin config to upload server source maps (#9541) -- fix(nextjs): Add tracing extensions in all serverside wrappers (#9537) -- fix(nextjs): Fix serverside transaction names on Windows (#9526) -- fix(node): Fix tRPC middleware typing (#9540) -- fix(replay): Add additional safeguards for capturing network bodies (#9506) -- fix(tracing): Update prisma span to be `db.prisma` (#9512) - -## 7.80.0 - -- feat(astro): Add distributed tracing via `` tags (#9483) -- feat(node): Capture internal server errors in trpc middleware (#9482) -- feat(remix): Export a type to use for `MetaFunction` parameters (#9493) -- fix(astro): Mark SDK package as Astro-external (#9509) -- ref(nextjs): Don't initialize Server SDK during build (#9503) - -## 7.79.0 - -- feat(tracing): Add span `origin` to trace context (#9472) -- fix(deno): Emit .mjs files (#9485) -- fix(nextjs): Flush servercomponent events for edge (#9487) - -## 7.78.0 - -### Important Changes - -- **Replay Bundle Size improvements** - -We've dramatically decreased the bundle size of our Replay package, reducing the minified & gzipped bundle size by ~20 -KB! This was possible by extensive use of tree shaking and a host of small changes to reduce our footprint: - -- feat(replay): Update rrweb to 2.2.0 (#9414) -- ref(replay): Use fflate instead of pako for compression (#9436) - -By using [tree shaking](https://docs.sentry.io/platforms/javascript/configuration/tree-shaking/) it is possible to shave -up to 10 additional KB off the bundle. - -### Other Changes - -- feat(astro): Add Sentry middleware (#9445) -- feat(feedback): Add "outline focus" and "foreground hover" vars (#9462) -- feat(feedback): Add `openDialog` and `closeDialog` onto integration interface (#9464) -- feat(feedback): Implement new user feedback embeddable widget (#9217) -- feat(nextjs): Add automatic sourcemapping for edge part of the SDK (#9454) -- feat(nextjs): Add client routing instrumentation for app router (#9446) -- feat(node-experimental): Add hapi tracing support (#9449) -- feat(replay): Allow to configure `beforeErrorSampling` (#9470) -- feat(replay): Stop fixing truncated JSONs in SDK (#9437) -- fix(nextjs): Fix sourcemaps resolving for local dev when basePath is set (#9457) -- fix(nextjs): Only inject basepath in dev mode (#9465) -- fix(replay): Ensure we stop for rate limit headers (#9420) -- ref(feedback): Add treeshaking for logger statements (#9475) -- ref(replay): Use rrweb for slow click detection (#9408) -- build(polyfills): Remove output format specific logic (#9467) - -## 7.77.0 - -### Security Fixes - -- fix(nextjs): Match only numbers as orgid in tunnelRoute (#9416) (CVE-2023-46729) -- fix(nextjs): Strictly validate tunnel target parameters (#9415) (CVE-2023-46729) - -### Other Changes - -- feat: Move LinkedErrors integration to @sentry/core (#9404) -- feat(remix): Update sentry-cli version to ^2.21.2 (#9401) -- feat(replay): Allow to treeshake & configure compression worker URL (#9409) -- fix(angular-ivy): Adjust package entry points to support Angular 17 with SSR config (#9412) -- fix(feedback): Fixing feedback import (#9403) -- fix(utils): Avoid keeping a reference of last used event (#9387) - -## 7.76.0 - -### Important Changes - -- **feat(core): Add cron monitor wrapper helper (#9395)** - -This release adds `Sentry.withMonitor()`, a wrapping function that wraps a callback with a cron monitor that will -automatically report completions and failures: - -```ts -import * as Sentry from '@sentry/node'; - -// withMonitor() will send checkin when callback is started/finished -// works with async and sync callbacks. -const result = Sentry.withMonitor( - 'dailyEmail', - () => { - // withCheckIn return value is same return value here - return sendEmail(); - }, - // Optional upsert options - { - schedule: { - type: 'crontab', - value: '0 * * * *', - }, - // 🇨🇦🫡 - timezone: 'Canada/Eastern', - }, -); -``` - -### Other Changes - -- chore(angular-ivy): Allow Angular 17 in peer dependencies (#9386) -- feat(nextjs): Instrument SSR page components (#9346) -- feat(nextjs): Trace errors in page component SSR (#9388) -- fix(nextjs): Instrument route handlers with `jsx` and `tsx` file extensions (#9362) -- fix(nextjs): Trace with performance disabled (#9389) -- fix(replay): Ensure `replay_id` is not added to DSC if session expired (#9359) -- fix(replay): Remove unused parts of pako from build (#9369) -- fix(serverless): Don't mark all errors as unhandled (#9368) -- fix(tracing-internal): Fix case when middleware contain array of routes with special chars as @ (#9375) -- meta(nextjs): Bump peer deps for Next.js 14 (#9390) - -Work in this release contributed by @LubomirIgonda1. Thank you for your contribution! - -## 7.75.1 - -- feat(browser): Allow collecting of pageload profiles (#9317) -- fix(browser): Correct timestamp on pageload profiles (#9350) -- fix(nextjs): Use webpack plugin release value to inject release (#9348) - -## 7.75.0 - -### Important Changes - -- **feat(opentelemetry): Add new `@sentry/opentelemetry` package (#9238)** - -This release publishes a new package, `@sentry/opentelemetry`. This is a runtime agnostic replacement for -`@sentry/opentelemetry-node` and exports a couple of useful utilities which can be used to use Sentry together with -OpenTelemetry. - -You can read more about -[@sentry/opentelemetry in the Readme](https://github.com/getsentry/sentry-javascript/tree/develop/packages/opentelemetry). - -- **feat(replay): Allow to treeshake rrweb features (#9274)** - -Starting with this release, you can configure the following build-time flags in order to reduce the SDK bundle size: - -- `__RRWEB_EXCLUDE_CANVAS__` -- `__RRWEB_EXCLUDE_IFRAME__` -- `__RRWEB_EXCLUDE_SHADOW_DOM__` - -You can read more about -[tree shaking in our docs](https://docs.sentry.io/platforms/javascript/configuration/tree-shaking/). - -### Other Changes - -- build(deno): Prepare Deno SDK for release on npm (#9281) -- feat: Remove tslib (#9299) -- feat(node): Add abnormal session support for ANR (#9268) -- feat(node): Remove `lru_map` dependency (#9300) -- feat(node): Vendor `cookie` module (#9308) -- feat(replay): Share performance instrumentation with tracing (#9296) -- feat(types): Add missing Profiling types (macho debug image, profile measurements, stack frame properties) (#9277) -- feat(types): Add statsd envelope types (#9304) -- fix(astro): Add integration default export to types entry point (#9337) -- fix(astro): Convert SDK init file import paths to POSIX paths (#9336) -- fix(astro): Make `Replay` and `BrowserTracing` integrations tree-shakeable (#9287) -- fix(integrations): Fix transaction integration (#9334) -- fix(nextjs): Restore `autoInstrumentMiddleware` functionality (#9323) -- fix(nextjs): Guard for case where `getInitialProps` may return undefined (#9342) -- fix(node-experimental): Make node-fetch support optional (#9321) -- fix(node): Check buffer length when attempting to parse ANR frame (#9314) -- fix(replay): Fix xhr start timestamps (#9341) -- fix(tracing-internal): Remove query params from urls with a trailing slash (#9328) -- fix(types): Remove typo with CheckInEnvelope (#9303) - -## 7.74.1 - -- chore(astro): Add `astro-integration` keyword (#9265) -- fix(core): Narrow filters for health check transactions (#9257) -- fix(nextjs): Fix HMR by inserting new entrypoints at the end (#9267) -- fix(nextjs): Fix resolution of request async storage module (#9259) -- fix(node-experimental): Guard against missing `fetch` (#9275) -- fix(remix): Update `defer` injection logic. (#9242) -- fix(tracing-internal): Parameterize express middleware parameters (#8668) -- fix(utils): Move Node specific ANR impl. out of utils (#9258) - -Work in this release contributed by @LubomirIgonda1. Thank you for your contribution! - -## 7.74.0 - -### Important Changes - -- **feat(astro): Add `sentryAstro` integration (#9218)** - -This Release introduces the first alpha version of our new SDK for Astro. At this time, the SDK is considered -experimental and things might break and change in future versions. - -The core of the SDK is an Astro integration which you easily add to your Astro config: - -```js -// astro.config.js -import { defineConfig } from 'astro/config'; -import sentry from '@sentry/astro'; - -export default defineConfig({ - integrations: [ - sentry({ - dsn: '__DSN__', - sourceMapsUploadOptions: { - project: 'astro', - authToken: process.env.SENTRY_AUTH_TOKEN, - }, - }), - ], -}); -``` - -Check out the [README](./packages/astro/README.md) for usage instructions and what to expect from this alpha release. - -### Other Changes - -- feat(core): Add `addIntegration` utility (#9186) -- feat(core): Add `continueTrace` method (#9164) -- feat(node-experimental): Add NodeFetch integration (#9226) -- feat(node-experimental): Use native OTEL Spans (#9161, #9214) -- feat(node-experimental): Sample in OTEL Sampler (#9203) -- feat(serverlesss): Allow disabling transaction traces (#9154) -- feat(tracing): Allow direct pg module to enable esbuild support (#9227) -- feat(utils): Move common node ANR code to utils (#9191) -- feat(vue): Expose `VueIntegration` to initialize vue app later (#9180) -- fix: Don't set `referrerPolicy` on serverside fetch transports (#9200) -- fix: Ensure we never mutate options passed to `init` (#9162) -- fix(ember): Avoid pulling in utils at build time (#9221) -- fix(ember): Drop undefined config values (#9175) -- fix(node): Ensure mysql integration works without callback (#9222) -- fix(node): Only require `inspector` when needed (#9149) -- fix(node): Remove ANR `debug` option and instead add logger.isEnabled() (#9230) -- fix(node): Strip `.mjs` and `.cjs` extensions from module name (#9231) -- fix(replay): bump rrweb to 2.0.1 (#9240) -- fix(replay): Fix potential broken CSS in styled-components (#9234) -- fix(sveltekit): Flush in server wrappers before exiting (#9153) -- fix(types): Update signature of `processEvent` integration hook (#9151) -- fix(utils): Dereference DOM events after they have servered their purpose (#9224) -- ref(integrations): Refactor pluggable integrations to use `processEvent` (#9021) -- ref(serverless): Properly deprecate `rethrowAfterCapture` option (#9159) -- ref(utils): Deprecate `walk` method (#9157) - -Work in this release contributed by @aldenquimby. Thank you for your contributions! - -## 7.73.0 - -### Important Changes - -- **feat(replay): Upgrade to rrweb2** - -This is fully backwards compatible with prior versions of the Replay SDK. The only breaking change that we will making -is to not be masking `aria-label` by default. The reason for this change is to align with our core SDK which also does -not mask `aria-label`. This change also enables better support of searching by clicks. - -Another change that needs to be highlighted is the 13% bundle size increase. This bundle size increase is necessary to -bring improved recording performance and improved replay fidelity, especially in regards to web components and iframes. -We will be investigating the reduction of the bundle size in -[this PR](https://github.com/getsentry/sentry-javascript/issues/8815). - -Here are benchmarks comparing the version 1 of rrweb to version 2 - -| metric | v1 | v2 | -| --------- | ---------- | ---------- | -| lcp | 1486.06 ms | 1529.11 ms | -| cls | 0.40 ms | 0.40 ms | -| fid | 1.53 ms | 1.50 ms | -| tbt | 3207.22 ms | 3036.80 ms | -| memoryAvg | 131.83 MB | 124.84 MB | -| memoryMax | 324.8 MB | 339.03 MB | -| netTx | 282.67 KB | 272.51 KB | -| netRx | 8.02 MB | 8.07 MB | - -### Other Changes - -- feat: Always assemble Envelopes (#9101) -- feat(node): Rate limit local variables for caught exceptions and enable `captureAllExceptions` by default (#9102) -- fix(core): Ensure `tunnel` is considered for `isSentryUrl` checks (#9130) -- fix(nextjs): Fix `RequestAsyncStorage` fallback path (#9126) -- fix(node-otel): Suppress tracing for generated sentry spans (#9142) -- fix(node): fill in span data from http request options object (#9112) -- fix(node): Fixes and improvements to ANR detection (#9128) -- fix(sveltekit): Avoid data invalidation in wrapped client-side `load` functions (#9071) -- ref(core): Refactor `InboundFilters` integration to use `processEvent` (#9020) -- ref(wasm): Refactor Wasm integration to use `processEvent` (#9019) - -Work in this release contributed by @vlad-zhukov. Thank you for your contribution! - -## 7.72.0 - -### Important Changes - -- **feat(node): App Not Responding with stack traces (#9079)** - -This release introduces support for Application Not Responding (ANR) errors for Node.js applications. These errors are -triggered when the Node.js main thread event loop of an application is blocked for more than five seconds. The Node SDK -reports ANR errors as Sentry events and can optionally attach a stacktrace of the blocking code to the ANR event. - -To enable ANR detection, import and use the `enableANRDetection` function from the `@sentry/node` package before you run -the rest of your application code. Any event loop blocking before calling `enableANRDetection` will not be detected by -the SDK. - -Example (ESM): - -```ts -import * as Sentry from '@sentry/node'; - -Sentry.init({ - dsn: '___PUBLIC_DSN___', - tracesSampleRate: 1.0, -}); - -await Sentry.enableANRDetection({ captureStackTrace: true }); -// Function that runs your app -runApp(); -``` - -Example (CJS): - -```ts -const Sentry = require('@sentry/node'); - -Sentry.init({ - dsn: '___PUBLIC_DSN___', - tracesSampleRate: 1.0, -}); - -Sentry.enableANRDetection({ captureStackTrace: true }).then(() => { - // Function that runs your app - runApp(); -}); -``` - -### Other Changes - -- fix(nextjs): Filter `RequestAsyncStorage` locations by locations that webpack will resolve (#9114) -- fix(replay): Ensure `replay_id` is not captured when session is expired (#9109) - -## 7.71.0 - -- feat(bun): Instrument Bun.serve (#9080) -- fix(core): Ensure global event processors are always applied to event (#9064) -- fix(core): Run client eventProcessors before global ones (#9032) -- fix(nextjs): Use webpack module paths to attempt to resolve internal request async storage module (#9100) -- fix(react): Add actual error name to boundary error name (#9065) -- fix(react): Compare location against `basename`-prefixed route. (#9076) -- ref(browser): Refactor browser integrations to use `processEvent` (#9022) - -Work in this release contributed by @jorrit. Thank you for your contribution! - -## 7.70.0 - -### Important Changes - -- **feat: Add Bun SDK (#9029)** - -This release contains the beta version of `@sentry/bun`, our SDK for the [Bun JavaScript runtime](https://bun.sh/)! For -details on how to use it, please see the [README](./packages/bun/README.md). Any feedback/bug reports are greatly -appreciated, please [reach out on GitHub](https://github.com/getsentry/sentry-javascript/discussions/7979). - -Note that as of now the Bun runtime does not support global error handlers. This is being actively worked on, see -[the tracking issue in Bun's GitHub repo](https://github.com/oven-sh/bun/issues/5091). - -- **feat(remix): Add Remix 2.x release support. (#8940)** - -The Sentry Remix SDK now officially supports Remix v2! See -[our Remix docs for more details](https://docs.sentry.io/platforms/javascript/guides/remix/). - -### Other Changes - -- chore(node): Upgrade cookie to ^0.5.0 (#9013) -- feat(core): Introduce `processEvent` hook on `Integration` (#9017) -- feat(node): Improve non-error messages (#9026) -- feat(vercel-edge): Add Vercel Edge Runtime package (#9041) -- fix(remix): Use `React.ComponentType` instead of `React.FC` as `withSentry`'s generic type. (#9043) -- fix(replay): Ensure replay events go through `preprocessEvent` hook (#9034) -- fix(replay): Fix typo in Replay types (#9028) -- fix(sveltekit): Adjust `handleErrorWithSentry` type (#9054) -- fix(utils): Try-catch monkeypatching to handle frozen objects/functions (#9031) - -Work in this release contributed by @Dima-Dim, @krist7599555 and @lifeiscontent. Thank you for your contributions! - -Special thanks for @isaacharrisholt for helping us implement a Vercel Edge Runtime SDK which we use under the hood for -our Next.js SDK. - -## 7.69.0 - -### Important Changes - -- **New Performance APIs** - - feat: Update span performance API names (#8971) - - feat(core): Introduce startSpanManual (#8913) - -This release introduces a new set of top level APIs for the Performance Monitoring SDKs. These aim to simplify creating -spans and reduce the boilerplate needed for performance instrumentation. The three new methods introduced are -`Sentry.startSpan`, `Sentry.startInactiveSpan`, and `Sentry.startSpanManual`. These methods are available in the browser -and node SDKs. - -`Sentry.startSpan` wraps a callback in a span. The span is automatically finished when the callback returns. This is the -recommended way to create spans. - -```js -// Start a span that tracks the duration of expensiveFunction -const result = Sentry.startSpan({ name: 'important function' }, () => { - return expensiveFunction(); -}); - -// You can also mutate the span wrapping the callback to set data or status -Sentry.startSpan({ name: 'important function' }, span => { - // span is undefined if performance monitoring is turned off or if - // the span was not sampled. This is done to reduce overhead. - span?.setData('version', '1.0.0'); - return expensiveFunction(); -}); -``` - -If you don't want the span to finish when the callback returns, use `Sentry.startSpanManual` to control when the span is -finished. This is useful for event emitters or similar. - -```js -// Start a span that tracks the duration of middleware -function middleware(_req, res, next) { - return Sentry.startSpanManual({ name: 'middleware' }, (span, finish) => { - res.once('finish', () => { - setHttpStatus(span, res.status); - finish(); - }); - return next(); - }); -} -``` - -`Sentry.startSpan` and `Sentry.startSpanManual` create a span and make it active for the duration of the callback. Any -spans created while this active span is running will be added as a child span to it. If you want to create a span -without making it active, use `Sentry.startInactiveSpan`. This is useful for creating parallel spans that are not -related to each other. - -```js -const span1 = Sentry.startInactiveSpan({ name: 'span1' }); - -someWork(); - -const span2 = Sentry.startInactiveSpan({ name: 'span2' }); - -moreWork(); - -const span3 = Sentry.startInactiveSpan({ name: 'span3' }); - -evenMoreWork(); - -span1?.finish(); -span2?.finish(); -span3?.finish(); -``` - -### Other Changes - -- feat(core): Export `BeforeFinishCallback` type (#8999) -- build(eslint): Enforce that ts-expect-error is used (#8987) -- feat(integration): Ensure `LinkedErrors` integration runs before all event processors (#8956) -- feat(node-experimental): Keep breadcrumbs on transaction (#8967) -- feat(redux): Add 'attachReduxState' option (#8953) -- feat(remix): Accept `org`, `project` and `url` as args to upload script (#8985) -- fix(utils): Prevent iterating over VueViewModel (#8981) -- fix(utils): uuidv4 fix for cloudflare (#8968) -- fix(core): Always use event message and exception values for `ignoreErrors` (#8986) -- fix(nextjs): Add new potential location for Next.js request AsyncLocalStorage (#9006) -- fix(node-experimental): Ensure we only create HTTP spans when outgoing (#8966) -- fix(node-experimental): Ignore OPTIONS & HEAD requests (#9001) -- fix(node-experimental): Ignore outgoing Sentry requests (#8994) -- fix(node-experimental): Require parent span for `pg` spans (#8993) -- fix(node-experimental): Use Sentry logger as Otel logger (#8960) -- fix(node-otel): Refactor OTEL span reference cleanup (#9000) -- fix(react): Switch to props in `useRoutes` (#8998) -- fix(remix): Add `glob` to Remix SDK dependencies. (#8963) -- fix(replay): Ensure `handleRecordingEmit` aborts when event is not added (#8938) -- fix(replay): Fully stop & restart session when it expires (#8834) - -Work in this release contributed by @Duncanxyz and @malay44. Thank you for your contributions! - -## 7.68.0 - -- feat(browser): Add `BroadcastChannel` and `SharedWorker` to TryCatch EventTargets (#8943) -- feat(core): Add `name` to `Span` (#8949) -- feat(core): Add `ServerRuntimeClient` (#8930) -- fix(node-experimental): Ensure `span.finish()` works as expected (#8947) -- fix(remix): Add new sourcemap-upload script files to prepack assets. (#8948) -- fix(publish): Publish downleveled TS3.8 types and fix types path (#8954) - -## 7.67.0 - -### Important Changes - -- **feat: Mark errors caught by the SDK as unhandled** - - feat(browser): Mark errors caught from `TryCatch` integration as unhandled (#8890) - - feat(integrations): Mark errors caught from `HttpClient` and `CaptureConsole` integrations as unhandled (#8891) - - feat(nextjs): Mark errors caught from NextJS wrappers as unhandled (#8893) - - feat(react): Mark errors captured from ErrorBoundary as unhandled (#8914) - - feat(remix): Add debugid injection and map deletion to sourcemaps script (#8814) - - feat(remix): Mark errors caught from Remix instrumentation as unhandled (#8894) - - feat(serverless): Mark errors caught in Serverless handlers as unhandled (#8907) - - feat(vue): Mark errors caught by Vue wrappers as unhandled (#8905) - -This release fixes inconsistent behaviour of when our SDKs classify captured errors as unhandled. Previously, some of -our instrumentations correctly set unhandled, while others set handled. Going forward, all errors caught automatically -from our SDKs will be marked as unhandled. If you manually capture errors (e.g. by calling `Sentry.captureException`), -your errors will continue to be reported as handled. - -This change might lead to a decrease in reported crash-free sessions and consequently in your release health score. If -you have concerns about this, feel free to open an issue. - -### Other Changes - -- feat(node-experimental): Implement new performance APIs (#8911) -- feat(node-experimental): Sync OTEL context with Sentry AsyncContext (#8797) -- feat(replay): Allow to configure `maxReplayDuration` (#8769) -- fix(browser): Add replay and profiling options to `BrowserClientOptions` (#8921) -- fix(browser): Check for existence of instrumentation targets (#8939) -- fix(nextjs): Don't re-export default in route handlers (#8924) -- fix(node): Improve mysql integration (#8923) -- fix(remix): Guard against missing default export for server instrument (#8909) -- ref(browser): Deprecate top-level `wrap` function (#8927) -- ref(node-otel): Avoid exporting internals & refactor attribute adding (#8920) - -Work in this release contributed by @SorsOps. Thank you for your contribution! - -## 7.66.0 - -- fix: Defer tracing decision to downstream SDKs when using SDK without performance (#8839) -- fix(nextjs): Fix `package.json` exports (#8895) -- fix(sveltekit): Ensure target file exists before applying auto instrumentation (#8881) -- ref: Use consistent console instrumentation (#8879) -- ref(browser): Refactor sentry breadcrumb to use hook (#8892) -- ref(tracing): Add `origin` to spans (#8765) - -## 7.65.0 - -- build: Remove build-specific polyfills (#8809) -- build(deps): bump protobufjs from 6.11.3 to 6.11.4 (#8822) -- deps(sveltekit): Bump `@sentry/vite-plugin` (#8877) -- feat(core): Introduce `Sentry.startActiveSpan` and `Sentry.startSpan` (#8803) -- fix: Memoize `AsyncLocalStorage` instance (#8831) -- fix(nextjs): Check for validity of API route handler signature (#8811) -- fix(nextjs): Fix `requestAsyncStorageShim` path resolution on windows (#8875) -- fix(node): Log entire error object in `OnUncaughtException` (#8876) -- fix(node): More relevant warning message when tracing extensions are missing (#8820) -- fix(replay): Streamline session creation/refresh (#8813) -- fix(sveltekit): Avoid invalidating data on route changes in `wrapServerLoadWithSentry` (#8801) -- fix(tracing): Better guarding for performance observer (#8872) -- ref(sveltekit): Remove custom client fetch instrumentation and use default instrumentation (#8802) -- ref(tracing-internal): Deprecate `tracePropagationTargets` in `BrowserTracing` (#8874) - -## 7.64.0 - -- feat(core): Add setMeasurement export (#8791) -- fix(nextjs): Check for existence of default export when wrapping pages (#8794) -- fix(nextjs): Ensure imports are valid relative paths (#8799) -- fix(nextjs): Only re-export default export if it exists (#8800) - -## 7.63.0 - -- build(deps): bump @opentelemetry/instrumentation from 0.41.0 to 0.41.2 -- feat(eventbuilder): Export `exceptionFromError` for use in hybrid SDKs (#8766) -- feat(node-experimental): Re-export from node (#8786) -- feat(tracing): Add db connection attributes for mysql spans (#8775) -- feat(tracing): Add db connection attributes for postgres spans (#8778) -- feat(tracing): Improve data collection for mongodb spans (#8774) -- fix(nextjs): Execute sentry config independently of `autoInstrumentServerFunctions` and `autoInstrumentAppDirectory` - (#8781) -- fix(replay): Ensure we do not flush if flush took too long (#8784) -- fix(replay): Ensure we do not try to flush when we force stop replay (#8783) -- fix(replay): Fix `hasCheckout` handling (#8782) -- fix(replay): Handle multiple clicks in a short time (#8773) -- ref(replay): Skip events being added too long after initial segment (#8768) - -## 7.62.0 - -### Important Changes - -- **feat(integrations): Add `ContextLines` integration for html-embedded JS stack frames (#8699)** - -This release adds the `ContextLines` integration as an optional integration for the Browser SDKs to -`@sentry/integrations`. - -This integration adds source code from inline JavaScript of the current page's HTML (e.g. JS in ` + + diff --git a/dev-packages/e2e-tests/test-applications/solidjs/package.json b/dev-packages/e2e-tests/test-applications/solidjs/package.json new file mode 100644 index 000000000000..1922a6e26d17 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/package.json @@ -0,0 +1,33 @@ +{ + "name": "solidjs", + "version": "0.0.0", + "description": "", + "scripts": { + "build": "vite build", + "clean": "npx rimraf node_modules pnpm-lock.yaml dist", + "dev": "vite", + "preview": "vite preview", + "start": "vite", + "test:prod": "TEST_ENV=production playwright test", + "test:build": "pnpm install && npx playwright install && pnpm build", + "test:assert": "pnpm test:prod" + }, + "license": "MIT", + "devDependencies": { + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", + "@sentry/types": "latest || *", + "@sentry/utils": "latest || *", + "autoprefixer": "^10.4.17", + "postcss": "^8.4.33", + "solid-devtools": "^0.29.2", + "tailwindcss": "^3.4.1", + "vite": "^5.0.11", + "vite-plugin-solid": "^2.8.2" + }, + "dependencies": { + "@solidjs/router": "^0.13.5", + "solid-js": "^1.8.11", + "@sentry/solidjs": "latest || *" + } +} diff --git a/dev-packages/e2e-tests/test-applications/solidjs/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/solidjs/playwright.config.mjs new file mode 100644 index 000000000000..0c468af7d879 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm preview --port 3030', + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/solidjs/postcss.config.js b/dev-packages/e2e-tests/test-applications/solidjs/postcss.config.js new file mode 100644 index 000000000000..12a703d900da --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/errors/404.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/errors/404.tsx new file mode 100644 index 000000000000..56e5ad5e3be0 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/src/errors/404.tsx @@ -0,0 +1,8 @@ +export default function NotFound() { + return ( +
+

404: Not Found

+

It's gone 😞

+
+ ); +} diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/index.css b/dev-packages/e2e-tests/test-applications/solidjs/src/index.css new file mode 100644 index 000000000000..b5c61c956711 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/src/index.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/index.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/index.tsx new file mode 100644 index 000000000000..47e7c0e52904 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/src/index.tsx @@ -0,0 +1,21 @@ +/* @refresh reload */ +import * as Sentry from '@sentry/solidjs'; +import { Router, useBeforeLeave, useLocation } from '@solidjs/router'; +import { render } from 'solid-js/web'; +import './index.css'; +import PageRoot from './pageroot'; +import { routes } from './routes'; + +Sentry.init({ + dsn: import.meta.env.PUBLIC_E2E_TEST_DSN, + debug: true, + environment: 'qa', // dynamic sampling bias to keep transactions + integrations: [Sentry.solidRouterBrowserTracingIntegration({ useBeforeLeave, useLocation })], + release: 'e2e-test', + tunnel: 'http://localhost:3031/', // proxy server + tracesSampleRate: 1.0, +}); + +const SentryRouter = Sentry.withSentryRouterRouting(Router); + +render(() => {routes}, document.getElementById('root')); diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/pageroot.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/pageroot.tsx new file mode 100644 index 000000000000..d9770c8a3868 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/src/pageroot.tsx @@ -0,0 +1,23 @@ +import { A } from '@solidjs/router'; + +export default function PageRoot(props) { + return ( + <> + +
{props.children}
+ + ); +} diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/pages/home.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/pages/home.tsx new file mode 100644 index 000000000000..7500846f0555 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/src/pages/home.tsx @@ -0,0 +1,39 @@ +import { A } from '@solidjs/router'; +import { createSignal } from 'solid-js'; + +export default function Home() { + const [count, setCount] = createSignal(0); + + return ( +
+

Home

+

This is the home page.

+ +
+ + + Count: {count()} + + +
+
+ + + User 5 + +
+
+ ); +} diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/pages/user.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/pages/user.tsx new file mode 100644 index 000000000000..639ab0be8118 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/src/pages/user.tsx @@ -0,0 +1,6 @@ +import { useParams } from '@solidjs/router'; + +export default function User() { + const params = useParams(); + return
User ID: {params.id}
; +} diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/routes.ts b/dev-packages/e2e-tests/test-applications/solidjs/src/routes.ts new file mode 100644 index 000000000000..7b115f68c00c --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/src/routes.ts @@ -0,0 +1,18 @@ +import { lazy } from 'solid-js'; + +import Home from './pages/home'; + +export const routes = [ + { + path: '/', + component: Home, + }, + { + path: '/user/:id', + component: lazy(() => import('./pages/user')), + }, + { + path: '**', + component: lazy(() => import('./errors/404')), + }, +]; diff --git a/dev-packages/e2e-tests/test-applications/solidjs/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/solidjs/start-event-proxy.mjs new file mode 100644 index 000000000000..207afe3f56e1 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'solidjs', +}); diff --git a/dev-packages/e2e-tests/test-applications/solidjs/tailwind.config.ts b/dev-packages/e2e-tests/test-applications/solidjs/tailwind.config.ts new file mode 100644 index 000000000000..f69a95185570 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/tailwind.config.ts @@ -0,0 +1,11 @@ +import type { Config } from 'tailwindcss'; + +const config: Config = { + content: ['./src/**/*.{js,jsx,ts,tsx}'], + theme: { + extend: {}, + }, + plugins: [], +}; + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/solidjs/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/solidjs/tests/errors.test.ts new file mode 100644 index 000000000000..92618f628407 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/tests/errors.test.ts @@ -0,0 +1,28 @@ +import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test('sends an error', async ({ page }) => { + const errorPromise = waitForError('solidjs', async errorEvent => { + return !errorEvent.type; + }); + + await Promise.all([page.goto(`/`), page.locator('#errorBtn').click()]); + + const error = await errorPromise; + + expect(error).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Error thrown from SolidJS E2E test app', + mechanism: { + type: 'onerror', + handled: false, + }, + }, + ], + }, + transaction: '/', + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/solidjs/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/solidjs/tests/performance.test.ts new file mode 100644 index 000000000000..166dfe01d32b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/tests/performance.test.ts @@ -0,0 +1,91 @@ +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('sends a pageload transaction', async ({ page }) => { + const transactionPromise = waitForTransaction('solidjs', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + const [, pageloadTransaction] = await Promise.all([page.goto('/'), transactionPromise]); + + expect(pageloadTransaction).toMatchObject({ + contexts: { + trace: { + op: 'pageload', + origin: 'auto.pageload.browser', + }, + }, + transaction: '/', + transaction_info: { + source: 'url', + }, + }); +}); + +test('sends a navigation transaction', async ({ page }) => { + const transactionPromise = waitForTransaction('solidjs', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; + }); + + await page.goto(`/`); + + const [, navigationTransaction] = await Promise.all([page.locator('#navLink').click(), transactionPromise]); + + expect(navigationTransaction).toMatchObject({ + contexts: { + trace: { + op: 'navigation', + origin: 'auto.navigation.solidjs.solidrouter', + }, + }, + transaction: '/user/5', + transaction_info: { + source: 'url', + }, + }); +}); + +test('updates the transaction when using the back button', async ({ page }) => { + // Solid Router sends a `-1` navigation when using the back button. + // The sentry solidRouterBrowserTracingIntegration tries to update such + // transactions with the proper name once the `useLocation` hook triggers. + const navigationTxnPromise = waitForTransaction('solidjs', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; + }); + + await page.goto(`/`); + + const [, navigationTxn] = await Promise.all([page.locator('#navLink').click(), navigationTxnPromise]); + + expect(navigationTxn).toMatchObject({ + contexts: { + trace: { + op: 'navigation', + origin: 'auto.navigation.solidjs.solidrouter', + }, + }, + transaction: '/user/5', + transaction_info: { + source: 'url', + }, + }); + + const backNavigationTxnPromise = waitForTransaction('solidjs', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; + }); + + const [, backNavigationTxn] = await Promise.all([page.goBack(), backNavigationTxnPromise]); + + expect(backNavigationTxn).toMatchObject({ + contexts: { + trace: { + op: 'navigation', + origin: 'auto.navigation.solidjs.solidrouter', + }, + }, + transaction: '/', + transaction_info: { + source: 'url', + }, + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/solidjs/tsconfig.json b/dev-packages/e2e-tests/test-applications/solidjs/tsconfig.json new file mode 100644 index 000000000000..ba12e96f069a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "types": ["vite/client"], + "noEmit": true, + "isolatedModules": true, + }, +} diff --git a/dev-packages/e2e-tests/test-applications/solidjs/vite.config.ts b/dev-packages/e2e-tests/test-applications/solidjs/vite.config.ts new file mode 100644 index 000000000000..d1835ee1b8ff --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/solidjs/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite'; +import solidPlugin from 'vite-plugin-solid'; + +export default defineConfig({ + plugins: [solidPlugin()], + build: { + target: 'esnext', + }, + envPrefix: 'PUBLIC_', +}); diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/playwright.config.ts b/dev-packages/e2e-tests/test-applications/standard-frontend-react/playwright.config.ts deleted file mode 100644 index 5f93f826ebf0..000000000000 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/playwright.config.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: { - command: 'pnpm start', - port: 3030, - env: { - PORT: '3030', - }, - }, -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts deleted file mode 100644 index 35446d1c069c..000000000000 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { expect, test } from '@playwright/test'; -import { ReplayRecordingData } from './fixtures/ReplayRecordingData'; - -const EVENT_POLLING_TIMEOUT = 90_000; - -const authToken = process.env.E2E_TEST_AUTH_TOKEN; -const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; - -test('Sends an exception to Sentry', async ({ page }) => { - await page.goto('/'); - - const exceptionButton = page.locator('id=exception-button'); - await exceptionButton.click(); - - const exceptionIdHandle = await page.waitForFunction(() => window.capturedExceptionId); - const exceptionEventId = await exceptionIdHandle.jsonValue(); - - console.log(`Polling for error eventId: ${exceptionEventId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); -}); - -test('Sends a pageload transaction to Sentry', async ({ page }) => { - await page.goto('/'); - - const recordedTransactionsHandle = await page.waitForFunction(() => { - if (window.recordedTransactions && window.recordedTransactions?.length >= 1) { - return window.recordedTransactions; - } else { - return undefined; - } - }); - const recordedTransactionEventIds = await recordedTransactionsHandle.jsonValue(); - - if (recordedTransactionEventIds === undefined) { - throw new Error("Application didn't record any transaction event IDs."); - } - - let hadPageLoadTransaction = false; - - console.log(`Polling for transaction eventIds: ${JSON.stringify(recordedTransactionEventIds)}`); - - await Promise.all( - recordedTransactionEventIds.map(async transactionEventId => { - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - - if (response.ok) { - const data = await response.json(); - if (data.contexts.trace.op === 'pageload') { - hadPageLoadTransaction = true; - } - } - - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); - }), - ); - - expect(hadPageLoadTransaction).toBe(true); -}); - -test('Sends a navigation transaction to Sentry', async ({ page }) => { - await page.goto('/'); - - // Give pageload transaction time to finish - page.waitForTimeout(4000); - - const linkElement = page.locator('id=navigation'); - await linkElement.click(); - - const recordedTransactionsHandle = await page.waitForFunction(() => { - if (window.recordedTransactions && window.recordedTransactions?.length >= 2) { - return window.recordedTransactions; - } else { - return undefined; - } - }); - const recordedTransactionEventIds = await recordedTransactionsHandle.jsonValue(); - - if (recordedTransactionEventIds === undefined) { - throw new Error("Application didn't record any transaction event IDs."); - } - - let hadPageNavigationTransaction = false; - - console.log(`Polling for transaction eventIds: ${JSON.stringify(recordedTransactionEventIds)}`); - - await Promise.all( - recordedTransactionEventIds.map(async transactionEventId => { - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - - if (response.ok) { - const data = await response.json(); - if (data.contexts.trace.op === 'navigation') { - hadPageNavigationTransaction = true; - } - } - - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); - }), - ); - - expect(hadPageNavigationTransaction).toBe(true); -}); - -test('Sends a Replay recording to Sentry', async ({ browser }) => { - const context = await browser.newContext(); - const page = await context.newPage(); - - await page.goto('/'); - - const replayId = await page.waitForFunction(() => { - return window.sentryReplayId; - }); - - // Keypress event ensures LCP is finished - await page.type('body', 'Y'); - - // Wait for replay to be sent - - if (replayId === undefined) { - throw new Error("Application didn't set a replayId"); - } - - console.log(`Polling for replay with ID: ${replayId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/replays/${replayId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); - - // now fetch the first recording segment - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/replays/${replayId}/recording-segments/?cursor=100%3A0%3A1`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - - if (response.ok) { - const data = await response.json(); - return data[0]; - } - - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toEqual(ReplayRecordingData); -}); diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts deleted file mode 100644 index 0b454ba12214..000000000000 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { expect } from '@playwright/test'; - -export const ReplayRecordingData = [ - { - type: 4, - data: { href: expect.stringMatching(/http:\/\/localhost:\d+\//), width: 1280, height: 720 }, - timestamp: expect.any(Number), - }, - { - data: { - payload: { - blockAllMedia: true, - errorSampleRate: 0, - maskAllInputs: true, - maskAllText: true, - networkCaptureBodies: true, - networkDetailHasUrls: false, - networkRequestHasHeaders: true, - networkResponseHasHeaders: true, - sessionSampleRate: 1, - shouldRecordCanvas: false, - useCompression: false, - useCompressionOption: true, - }, - tag: 'options', - }, - timestamp: expect.any(Number), - type: 5, - }, - { - type: 2, - data: { - node: { - type: 0, - childNodes: [ - { type: 1, name: 'html', publicId: '', systemId: '', id: 2 }, - { - type: 2, - tagName: 'html', - attributes: { lang: 'en' }, - childNodes: [ - { - type: 2, - tagName: 'head', - attributes: {}, - childNodes: [ - { type: 2, tagName: 'meta', attributes: { charset: 'utf-8' }, childNodes: [], id: 5 }, - { - type: 2, - tagName: 'meta', - attributes: { name: 'viewport', content: 'width=device-width,initial-scale=1' }, - childNodes: [], - id: 6, - }, - { - type: 2, - tagName: 'meta', - attributes: { name: 'theme-color', content: '#000000' }, - childNodes: [], - id: 7, - }, - { - type: 2, - tagName: 'title', - attributes: {}, - childNodes: [{ type: 3, textContent: '***** ***', id: 9 }], - id: 8, - }, - ], - id: 4, - }, - { - type: 2, - tagName: 'body', - attributes: {}, - childNodes: [ - { - type: 2, - tagName: 'noscript', - attributes: {}, - childNodes: [{ type: 3, textContent: '*** **** ** ****** ********** ** *** **** ****', id: 12 }], - id: 11, - }, - { type: 2, tagName: 'div', attributes: { id: 'root' }, childNodes: [], id: 13 }, - ], - id: 10, - }, - ], - id: 3, - }, - ], - id: 1, - }, - initialOffset: { left: 0, top: 0 }, - }, - timestamp: expect.any(Number), - }, - { - type: 3, - data: { - source: 0, - texts: [], - attributes: [], - removes: [], - adds: [ - { - parentId: 13, - nextId: null, - node: { - type: 2, - tagName: 'a', - attributes: { id: 'navigation', href: expect.stringMatching(/http:\/\/localhost:\d+\/user\/5/) }, - childNodes: [], - id: 14, - }, - }, - { parentId: 14, nextId: null, node: { type: 3, textContent: '********', id: 15 } }, - { - parentId: 13, - nextId: 14, - node: { - type: 2, - tagName: 'input', - attributes: { type: 'button', id: 'exception-button', value: '******* *********' }, - childNodes: [], - id: 16, - }, - }, - ], - }, - timestamp: expect.any(Number), - }, - { - type: 3, - data: { source: 5, text: 'Capture Exception', isChecked: false, id: 16 }, - timestamp: expect.any(Number), - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'navigation.navigate', - description: expect.stringMatching(/http:\/\/localhost:\d+\//), - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - data: { - decodedBodySize: expect.any(Number), - encodedBodySize: expect.any(Number), - duration: expect.any(Number), - domInteractive: expect.any(Number), - domContentLoadedEventEnd: expect.any(Number), - domContentLoadedEventStart: expect.any(Number), - loadEventStart: expect.any(Number), - loadEventEnd: expect.any(Number), - domComplete: expect.any(Number), - redirectCount: expect.any(Number), - size: expect.any(Number), - }, - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'resource.script', - description: expect.stringMatching(/http:\/\/localhost:\d+\/static\/js\/main.(\w+).js/), - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - data: { - decodedBodySize: expect.any(Number), - encodedBodySize: expect.any(Number), - size: expect.any(Number), - }, - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'paint', - description: 'first-paint', - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'paint', - description: 'first-contentful-paint', - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'largest-contentful-paint', - description: 'largest-contentful-paint', - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - data: { - value: expect.any(Number), - size: expect.any(Number), - nodeId: 16, - }, - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'memory', - description: 'memory', - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - data: { - memory: { - jsHeapSizeLimit: expect.any(Number), - totalJSHeapSize: expect.any(Number), - usedJSHeapSize: expect.any(Number), - }, - }, - }, - }, - }, -]; diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/package.json b/dev-packages/e2e-tests/test-applications/svelte-5/package.json index d95aa579e9a6..82c256519a36 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/package.json +++ b/dev-packages/e2e-tests/test-applications/svelte-5/package.json @@ -13,8 +13,8 @@ "test:assert": "pnpm test:prod" }, "devDependencies": { - "@playwright/test": "^1.43.1", - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@sveltejs/vite-plugin-svelte": "^3.0.2", @@ -23,8 +23,7 @@ "svelte-check": "^3.6.7", "tslib": "^2.6.2", "typescript": "^5.2.2", - "vite": "^5.2.0", - "wait-port": "1.0.4" + "vite": "^5.2.0" }, "dependencies": { "@sentry/svelte": "latest || *" diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.mjs new file mode 100644 index 000000000000..0c468af7d879 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm preview --port 3030', + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.ts b/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.ts deleted file mode 100644 index 37a5c8726a36..000000000000 --- a/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const sveltePort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './test', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${sveltePort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node ./start-event-proxy.mjs', - port: eventProxyPort, - reuseExistingServer: false, - }, - { - command: `pnpm wait-port ${eventProxyPort} && pnpm preview --port ${sveltePort}`, - port: sveltePort, - reuseExistingServer: false, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/src/main.ts b/dev-packages/e2e-tests/test-applications/svelte-5/src/main.ts index e42063fb9183..9f5fb70cea94 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/src/main.ts +++ b/dev-packages/e2e-tests/test-applications/svelte-5/src/main.ts @@ -10,7 +10,7 @@ Sentry.init({ tracesSampleRate: 1.0, integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], tunnel: 'http://localhost:3031/', // proxy server - debug: true, + debug: !!process.env.DEBUG, }); const target = document.getElementById('app'); diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/svelte-5/start-event-proxy.mjs index 51f34487945c..cd37498da887 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/svelte-5/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/test/errors.test.ts b/dev-packages/e2e-tests/test-applications/svelte-5/tests/errors.test.ts similarity index 90% rename from dev-packages/e2e-tests/test-applications/svelte-5/test/errors.test.ts rename to dev-packages/e2e-tests/test-applications/svelte-5/tests/errors.test.ts index 803e49e24fd0..6e3267eab2ed 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/test/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/svelte-5/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('sends an error', async ({ page }) => { const errorPromise = waitForError('svelte-5', async errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/test/performance.test.ts b/dev-packages/e2e-tests/test-applications/svelte-5/tests/performance.test.ts similarity index 94% rename from dev-packages/e2e-tests/test-applications/svelte-5/test/performance.test.ts rename to dev-packages/e2e-tests/test-applications/svelte-5/tests/performance.test.ts index 5e4e52d597b4..05391ed88042 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/test/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/svelte-5/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('sends a pageload transaction with component tracking init spans', async ({ page }) => { const transactionPromise = waitForTransaction('svelte-5', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json index 1e3b02d5d4b1..ef59fc456b5f 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json @@ -19,8 +19,8 @@ "@spotlightjs/spotlight": "2.0.0-alpha.1" }, "devDependencies": { - "@playwright/test": "^1.36.2", - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@sveltejs/adapter-auto": "^3.0.0", @@ -30,8 +30,7 @@ "svelte-check": "^3.6.0", "tslib": "^2.4.1", "typescript": "^5.0.0", - "vite": "^5.0.3", - "wait-port": "1.0.4" + "vite": "^5.0.3" }, "type": "module" } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.mjs new file mode 100644 index 000000000000..0c468af7d879 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm preview --port 3030', + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.ts deleted file mode 100644 index 87f7ec8bbe32..000000000000 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const svelteKitPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './test', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${svelteKitPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - reuseExistingServer: false, - }, - { - command: `pnpm wait-port ${eventProxyPort} && pnpm preview --port ${svelteKitPort}`, - port: svelteKitPort, - reuseExistingServer: false, - }, - ], -}; - -export default config; - -`node --require @sentry/node/require my-app.js`; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.client.ts index 606379b59760..91592e7ab932 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.client.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.client.ts @@ -5,7 +5,7 @@ import * as Spotlight from '@spotlightjs/spotlight'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: env.PUBLIC_E2E_TEST_DSN, - debug: true, + debug: !!env.PUBLIC_DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts index 3fedded42858..99bf4a17aa96 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts @@ -5,7 +5,7 @@ import { setupSidecar } from '@spotlightjs/spotlight/sidecar'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: E2E_TEST_DSN, - debug: true, + debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, spotlight: import.meta.env.DEV, diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/start-event-proxy.mjs index 537e4f60abe2..087080644ebb 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.client.test.ts similarity index 96% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.client.test.ts index c70b9a93dbbb..1984a0db9603 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('client-side errors', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.server.test.ts similarity index 97% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.server.test.ts index bbd87a5366a6..0764d26e05a5 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test.describe('server-side errors', () => { test('captures universal load error', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.client.test.ts similarity index 98% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.client.test.ts index 324b83977ba1..c31e51bf9e99 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('client-specific performance events', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.server.test.ts similarity index 94% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.server.test.ts index 10d0690e70b8..8c23996c9a37 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('server pageload request span has nested request span for sub request', async ({ page }) => { const serverTxnEventPromise = waitForTransaction('sveltekit-2-svelte-5', txnEvent => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts similarity index 98% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts index 83932a4ac362..622562b9ab6a 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('performance events', () => { @@ -193,7 +193,7 @@ test.describe('performance events', () => { return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.tags?.runtime === 'browser'; }); - await page.goto('/'); + await waitForInitialPageload(page, { route: '/' }); const navigationClickPromise = page.locator('#routeWithParamsLink').click(); @@ -252,8 +252,6 @@ test.describe('performance events', () => { }); test('captures one navigation transaction per redirect', async ({ page }) => { - await page.goto('/'); - const clientNavigationRedirect1TxnPromise = waitForTransaction('sveltekit-2-svelte-5', txnEvent => { return ( txnEvent?.contexts?.trace?.op === 'navigation' && @@ -278,6 +276,8 @@ test.describe('performance events', () => { ); }); + await waitForInitialPageload(page, { route: '/' }); + const navigationClickPromise = page.locator('#redirectLink').click(); const [redirect1TxnEvent, redirect2TxnEvent, redirect3TxnEvent, _] = await Promise.all([ diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/utils.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/utils.ts similarity index 95% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/utils.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/utils.ts index 5dcc01bbe7f8..e77e2eb742e2 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/utils.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/utils.ts @@ -1,5 +1,5 @@ import { Page } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; /** * Helper function that waits for the initial pageload to complete. diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json index ae18e7e34017..738f4a51bb3d 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json @@ -18,8 +18,8 @@ "@sentry/sveltekit": "latest || *" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.36.2", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@sveltejs/adapter-auto": "^3.0.0", @@ -29,8 +29,7 @@ "svelte": "^4.2.8", "svelte-check": "^3.6.0", "typescript": "^5.0.0", - "vite": "^5.0.3", - "wait-port": "1.0.4" + "vite": "^5.0.3" }, "type": "module" } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.mjs new file mode 100644 index 000000000000..71d97e4da2fd --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.mjs @@ -0,0 +1,13 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const testEnv = process.env.TEST_ENV; + +if (!testEnv) { + throw new Error('No test env defined'); +} + +const config = getPlaywrightConfig({ + startCommand: testEnv === 'development' ? `pnpm dev --port 3030` : `node build`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.ts deleted file mode 100644 index fe5a219c8e3d..000000000000 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const svelteKitPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './test', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${svelteKitPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - reuseExistingServer: false, - }, - { - command: - testEnv === 'development' - ? `pnpm wait-port ${eventProxyPort} && pnpm dev --port ${svelteKitPort}` - : `pnpm wait-port ${eventProxyPort} && PORT=${svelteKitPort} node build`, - port: svelteKitPort, - reuseExistingServer: false, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.client.ts index bfe90b150886..b174e9671b8d 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.client.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.client.ts @@ -4,7 +4,7 @@ import * as Sentry from '@sentry/sveltekit'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: env.PUBLIC_E2E_TEST_DSN, - debug: true, + debug: !!env.PUBLIC_DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts index 2a2abbb870dd..92909c53a24c 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts @@ -4,7 +4,7 @@ import * as Sentry from '@sentry/sveltekit'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: E2E_TEST_DSN, - debug: true, + debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2/start-event-proxy.mjs index fcf2c0b9addc..7ebb1c1d4d68 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.client.test.ts similarity index 96% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.client.test.ts index eb83566a475d..eecd5e00fae0 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('client-side errors', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.server.test.ts similarity index 96% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.server.test.ts index 51488b103107..64a0b2e3c855 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test.describe('server-side errors', () => { test('captures universal load error', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.client.test.ts similarity index 98% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.client.test.ts index 403701a075be..b53a881252a0 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('client-specific performance events', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.server.test.ts similarity index 93% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.server.test.ts index e04a056ca875..6f11fd17cd5b 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('server pageload request span has nested request span for sub request', async ({ page }) => { const serverTxnEventPromise = waitForTransaction('sveltekit-2', txnEvent => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts similarity index 98% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts index e2966f23fb8b..ddaac44096f5 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('performance events', () => { @@ -193,7 +193,7 @@ test.describe('performance events', () => { return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.tags?.runtime === 'browser'; }); - await page.goto('/'); + await waitForInitialPageload(page, { route: '/' }); const navigationClickPromise = page.locator('#routeWithParamsLink').click(); @@ -252,8 +252,6 @@ test.describe('performance events', () => { }); test('captures one navigation transaction per redirect', async ({ page }) => { - await page.goto('/'); - const clientNavigationRedirect1TxnPromise = waitForTransaction('sveltekit-2', txnEvent => { return ( txnEvent?.contexts?.trace?.op === 'navigation' && @@ -278,6 +276,8 @@ test.describe('performance events', () => { ); }); + await waitForInitialPageload(page, { route: '/' }); + const navigationClickPromise = page.locator('#redirectLink').click(); const [redirect1TxnEvent, redirect2TxnEvent, redirect3TxnEvent, _] = await Promise.all([ diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/utils.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/utils.ts similarity index 95% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/utils.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/utils.ts index 2fa35d9ae874..84a7e5605a1d 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/utils.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/utils.ts @@ -1,5 +1,5 @@ import { Page } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; /** * Helper function that waits for the initial pageload to complete. diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/package.json b/dev-packages/e2e-tests/test-applications/sveltekit/package.json index 84fef7db3923..e6b109c437dc 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit/package.json @@ -17,8 +17,8 @@ "@sentry/sveltekit": "latest || *" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.41.1", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@sveltejs/adapter-auto": "^2.0.0", @@ -27,8 +27,7 @@ "svelte": "^3.54.0", "svelte-check": "^3.0.1", "typescript": "^5.0.0", - "vite": "^4.2.0", - "wait-port": "1.0.4" + "vite": "^4.2.0" }, "type": "module" } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.mjs new file mode 100644 index 000000000000..222c54f87389 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.mjs @@ -0,0 +1,14 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const testEnv = process.env.TEST_ENV; + +if (!testEnv) { + throw new Error('No test env defined'); +} + +const config = getPlaywrightConfig({ + startCommand: testEnv === 'development' ? `pnpm dev --port 3030` : `pnpm preview --port 3030`, + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.ts deleted file mode 100644 index 18d60ca75ba3..000000000000 --- a/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.ts +++ /dev/null @@ -1,73 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const port = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './test', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - workers: 1, - /* Run tests in files in parallel */ - fullyParallel: false, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${port}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: 3031, - }, - { - command: - testEnv === 'development' - ? `pnpm wait-port ${eventProxyPort} && pnpm dev --port ${port}` - : `pnpm wait-port ${eventProxyPort} && pnpm preview --port ${port}`, - port, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.client.ts index bfe90b150886..b174e9671b8d 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.client.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.client.ts @@ -4,7 +4,7 @@ import * as Sentry from '@sentry/sveltekit'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: env.PUBLIC_E2E_TEST_DSN, - debug: true, + debug: !!env.PUBLIC_DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.server.ts index 375b8d2c170a..aca7e1b75139 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.server.ts @@ -4,7 +4,7 @@ import * as Sentry from '@sentry/sveltekit'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: env.E2E_TEST_DSN, - debug: true, + debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/sveltekit/start-event-proxy.mjs index cb0fd75c1530..db60ac582eb7 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/sveltekit/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.client.test.ts similarity index 96% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/errors.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.client.test.ts index 7f0a5c50faa0..b149496514c4 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/errors.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from '../utils'; test.describe('client-side errors', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.server.test.ts similarity index 97% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/errors.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.server.test.ts index 5a3940a213b5..22b6bb9d340c 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/errors.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test.describe('server-side errors', () => { test('captures universal load error', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.client.test.ts similarity index 97% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/performance.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.client.test.ts index d7107d5e7744..33515a950d3c 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from '../utils.js'; test('records manually added component tracking spans', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.server.test.ts similarity index 94% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/performance.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.server.test.ts index e462d08ddeeb..42ad638676f7 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('server pageload request span has nested request span for sub request', async ({ page }) => { const serverTxnEventPromise = waitForTransaction('sveltekit', txnEvent => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.test.ts similarity index 97% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/performance.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.test.ts index cb2ac4446a49..42d4ef82a589 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from '../utils.js'; test('sends a pageload transaction', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/utils.ts b/dev-packages/e2e-tests/test-applications/sveltekit/utils.ts index c919c1d72e95..320d41aba389 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/utils.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/utils.ts @@ -1,5 +1,5 @@ import { Page } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; /** * Helper function that waits for the initial pageload to complete. diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/package.json b/dev-packages/e2e-tests/test-applications/tanstack-router/package.json index 2f761c7d3e71..7bee3d4ba828 100644 --- a/dev-packages/e2e-tests/test-applications/tanstack-router/package.json +++ b/dev-packages/e2e-tests/test-applications/tanstack-router/package.json @@ -25,8 +25,8 @@ "@vitejs/plugin-react-swc": "^3.5.0", "typescript": "^5.2.2", "vite": "^5.2.0", - "@playwright/test": "^1.41.1", - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.ts b/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.ts deleted file mode 100644 index 2167da6d754e..000000000000 --- a/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const appPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - baseURL: `http://localhost:${appPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: appPort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/tanstack-router/start-event-proxy.mjs index d65ca64f1e59..f2ab6289d317 100644 --- a/dev-packages/e2e-tests/test-applications/tanstack-router/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/tanstack-router/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/tests/routing-instrumentation.test.ts b/dev-packages/e2e-tests/test-applications/tanstack-router/tests/routing-instrumentation.test.ts index 3201b436faba..59d15b989dd4 100644 --- a/dev-packages/e2e-tests/test-applications/tanstack-router/tests/routing-instrumentation.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstack-router/tests/routing-instrumentation.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('sends a pageload transaction with a parameterized URL', async ({ page }) => { const transactionPromise = waitForTransaction('tanstack-router', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/vue-3/package.json b/dev-packages/e2e-tests/test-applications/vue-3/package.json index 95288dc0e52f..f356285a79d9 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/package.json +++ b/dev-packages/e2e-tests/test-applications/vue-3/package.json @@ -20,8 +20,8 @@ "vue-router": "^4.2.5" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.41.1", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@tsconfig/node20": "^20.1.2", @@ -33,8 +33,7 @@ "npm-run-all2": "^6.1.1", "typescript": "~5.3.0", "vite": "^5.0.11", - "vue-tsc": "^1.8.27", - "wait-port": "1.0.4" + "vue-tsc": "^1.8.27" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.mjs new file mode 100644 index 000000000000..94f38d88ad70 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm preview --port 4173', + port: 4173, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.ts b/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.ts deleted file mode 100644 index 63c2b137a9d7..000000000000 --- a/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env['TEST_ENV'] || 'production'; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const vuePort = 4173; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${vuePort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: `pnpm wait-port ${eventProxyPort} && pnpm preview --port ${vuePort}`, - port: vuePort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/vue-3/src/main.ts b/dev-packages/e2e-tests/test-applications/vue-3/src/main.ts index 997c74fa0740..f4a01d4285c5 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/src/main.ts +++ b/dev-packages/e2e-tests/test-applications/vue-3/src/main.ts @@ -19,7 +19,6 @@ Sentry.init({ }), ], tunnel: `http://localhost:3031/`, // proxy server - debug: true, }); app.use(router); diff --git a/dev-packages/e2e-tests/test-applications/vue-3/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/vue-3/start-event-proxy.mjs index e8c8fdf3cd46..75992f4b5206 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/vue-3/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/vue-3/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/vue-3/tests/errors.test.ts index 14ab59ad7570..262cda11b366 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/vue-3/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('sends an error', async ({ page }) => { const errorPromise = waitForError('vue-3', async errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/vue-3/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/vue-3/tests/performance.test.ts index aded68211784..bdf7b5b8e1fe 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/vue-3/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('sends a pageload transaction with a parameterized URL', async ({ page }) => { const transactionPromise = waitForTransaction('vue-3', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/vue-3/tsconfig.node.json b/dev-packages/e2e-tests/test-applications/vue-3/tsconfig.node.json index 2c669eeb8e8a..280d8ca857df 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/tsconfig.node.json +++ b/dev-packages/e2e-tests/test-applications/vue-3/tsconfig.node.json @@ -1,6 +1,6 @@ { "extends": "@tsconfig/node20/tsconfig.json", - "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "nightwatch.conf.*", "playwright.config.*"], + "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "nightwatch.conf.*"], "compilerOptions": { "composite": true, "noEmit": true, diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/entry.js b/dev-packages/e2e-tests/test-applications/webpack-4/entry.js index 4fd9cd67e7e3..69877184b91a 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-4/entry.js +++ b/dev-packages/e2e-tests/test-applications/webpack-4/entry.js @@ -1,11 +1,11 @@ -import { browserTracingIntegration, captureException, init } from '@sentry/browser'; +import { browserTracingIntegration, init } from '@sentry/browser'; init({ dsn: process.env.E2E_TEST_DSN, integrations: [browserTracingIntegration()], + tunnel: 'http://localhost:3031', }); setTimeout(() => { - const eventId = captureException(new Error('I am an error!')); - window.capturedExceptionId = eventId; + throw new Error('I am an error!'); }, 2000); diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/package.json b/dev-packages/e2e-tests/test-applications/webpack-4/package.json index ee99ff43128e..311c2dcc468c 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-4/package.json +++ b/dev-packages/e2e-tests/test-applications/webpack-4/package.json @@ -8,7 +8,8 @@ "test:assert": "playwright test" }, "devDependencies": { - "@playwright/test": "^1.42.1", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/browser": "latest || *", "webpack": "^4.47.0", "terser-webpack-plugin": "^4.2.3", diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.mjs new file mode 100644 index 000000000000..4248d8d94297 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm start', +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.ts b/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.ts deleted file mode 100644 index 5f93f826ebf0..000000000000 --- a/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: { - command: 'pnpm start', - port: 3030, - env: { - PORT: '3030', - }, - }, -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/webpack-4/start-event-proxy.mjs new file mode 100644 index 000000000000..5805ae9bca52 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-4/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'webpack-4', +}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts deleted file mode 100644 index 2ef289910a6b..000000000000 --- a/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { expect, test } from '@playwright/test'; - -const EVENT_POLLING_TIMEOUT = 90_000; - -const authToken = process.env.E2E_TEST_AUTH_TOKEN; -const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; - -test('Sends an exception to Sentry', async ({ page }) => { - await page.goto('/'); - - const exceptionIdHandle = await page.waitForFunction(() => window.capturedExceptionId); - const exceptionEventId = await exceptionIdHandle.jsonValue(); - - console.log(`Polling for error eventId: ${exceptionEventId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); -}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/webpack-4/tests/errors.test.ts new file mode 100644 index 000000000000..2c2ca2dbb952 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-4/tests/errors.test.ts @@ -0,0 +1,14 @@ +import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test('Captures an exception', async ({ page }) => { + const eventPromise = waitForError('webpack-4', event => { + return event.exception?.values?.[0].value === 'I am an error!'; + }); + await page.goto('/'); + + const errorEvent = await eventPromise; + + expect(errorEvent.exception?.values?.[0].value).toBe('I am an error!'); + expect(errorEvent.transaction).toBe('/'); +}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/entry.js b/dev-packages/e2e-tests/test-applications/webpack-5/entry.js index 4fd9cd67e7e3..69877184b91a 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-5/entry.js +++ b/dev-packages/e2e-tests/test-applications/webpack-5/entry.js @@ -1,11 +1,11 @@ -import { browserTracingIntegration, captureException, init } from '@sentry/browser'; +import { browserTracingIntegration, init } from '@sentry/browser'; init({ dsn: process.env.E2E_TEST_DSN, integrations: [browserTracingIntegration()], + tunnel: 'http://localhost:3031', }); setTimeout(() => { - const eventId = captureException(new Error('I am an error!')); - window.capturedExceptionId = eventId; + throw new Error('I am an error!'); }, 2000); diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/package.json b/dev-packages/e2e-tests/test-applications/webpack-5/package.json index 871e43589971..996b4f240b74 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-5/package.json +++ b/dev-packages/e2e-tests/test-applications/webpack-5/package.json @@ -8,7 +8,8 @@ "test:assert": "playwright test" }, "devDependencies": { - "@playwright/test": "^1.42.1", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/browser": "latest || *", "webpack": "^5.91.0", "terser-webpack-plugin": "^5.3.10", diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.mjs new file mode 100644 index 000000000000..4248d8d94297 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm start', +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.ts b/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.ts deleted file mode 100644 index 5f93f826ebf0..000000000000 --- a/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: { - command: 'pnpm start', - port: 3030, - env: { - PORT: '3030', - }, - }, -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/webpack-5/start-event-proxy.mjs new file mode 100644 index 000000000000..8ee10bade2f8 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-5/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'webpack-5', +}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts deleted file mode 100644 index 2ef289910a6b..000000000000 --- a/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { expect, test } from '@playwright/test'; - -const EVENT_POLLING_TIMEOUT = 90_000; - -const authToken = process.env.E2E_TEST_AUTH_TOKEN; -const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; - -test('Sends an exception to Sentry', async ({ page }) => { - await page.goto('/'); - - const exceptionIdHandle = await page.waitForFunction(() => window.capturedExceptionId); - const exceptionEventId = await exceptionIdHandle.jsonValue(); - - console.log(`Polling for error eventId: ${exceptionEventId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); -}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/webpack-5/tests/errors.test.ts new file mode 100644 index 000000000000..c899613aafc2 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-5/tests/errors.test.ts @@ -0,0 +1,14 @@ +import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test('Captures an exception', async ({ page }) => { + const eventPromise = waitForError('webpack-5', event => { + return event.exception?.values?.[0].value === 'I am an error!'; + }); + await page.goto('/'); + + const errorEvent = await eventPromise; + + expect(errorEvent.exception?.values?.[0].value).toBe('I am an error!'); + expect(errorEvent.transaction).toBe('/'); +}); diff --git a/dev-packages/event-proxy-server/tsconfig.json b/dev-packages/event-proxy-server/tsconfig.json deleted file mode 100644 index 825380109ceb..000000000000 --- a/dev-packages/event-proxy-server/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": {}, - "include": ["src/**/*.ts"] -} diff --git a/dev-packages/node-integration-tests/suites/public-api/LocalVariables/test.ts b/dev-packages/node-integration-tests/suites/public-api/LocalVariables/test.ts index 4c564bc7ac86..f700ddd6ac67 100644 --- a/dev-packages/node-integration-tests/suites/public-api/LocalVariables/test.ts +++ b/dev-packages/node-integration-tests/suites/public-api/LocalVariables/test.ts @@ -101,8 +101,8 @@ conditionalTest({ min: 18 })('LocalVariables integration', () => { child.on('message', msg => { reportedCount++; const rssMb = (msg as { memUsage: { rss: number } }).memUsage.rss / 1024 / 1024; - // We shouldn't use more than 120MB of memory - expect(rssMb).toBeLessThan(120); + // We shouldn't use more than 135MB of memory + expect(rssMb).toBeLessThan(135); }); // Wait for 20 seconds diff --git a/dev-packages/node-integration-tests/suites/tracing/redis-cache/scenario-ioredis.js b/dev-packages/node-integration-tests/suites/tracing/redis-cache/scenario-ioredis.js index 22385f81b064..0f86c6f852a8 100644 --- a/dev-packages/node-integration-tests/suites/tracing/redis-cache/scenario-ioredis.js +++ b/dev-packages/node-integration-tests/suites/tracing/redis-cache/scenario-ioredis.js @@ -27,9 +27,14 @@ async function run() { await redis.set('test-key', 'test-value'); await redis.set('ioredis-cache:test-key', 'test-value'); + await redis.set('ioredis-cache:test-key-set-EX', 'test-value', 'EX', 10); + await redis.setex('ioredis-cache:test-key-setex', 10, 'test-value'); + await redis.get('test-key'); await redis.get('ioredis-cache:test-key'); await redis.get('ioredis-cache:unavailable-data'); + + await redis.mget('test-key', 'ioredis-cache:test-key', 'ioredis-cache:unavailable-data'); } finally { await redis.disconnect(); } diff --git a/dev-packages/node-integration-tests/suites/tracing/redis-cache/test.ts b/dev-packages/node-integration-tests/suites/tracing/redis-cache/test.ts index 3ad860bb72f4..adbd88921a66 100644 --- a/dev-packages/node-integration-tests/suites/tracing/redis-cache/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/redis-cache/test.ts @@ -48,12 +48,41 @@ describe('redis cache auto instrumentation', () => { spans: expect.arrayContaining([ // SET expect.objectContaining({ - description: 'set ioredis-cache:test-key [1 other arguments]', + description: 'ioredis-cache:test-key', op: 'cache.put', origin: 'auto.db.otel.redis', data: expect.objectContaining({ + 'sentry.origin': 'auto.db.otel.redis', 'db.statement': 'set ioredis-cache:test-key [1 other arguments]', - 'cache.key': 'ioredis-cache:test-key', + 'cache.key': ['ioredis-cache:test-key'], + 'cache.item_size': 2, + 'network.peer.address': 'localhost', + 'network.peer.port': 6379, + }), + }), + // SET (with EX) + expect.objectContaining({ + description: 'ioredis-cache:test-key-set-EX', + op: 'cache.put', + origin: 'auto.db.otel.redis', + data: expect.objectContaining({ + 'sentry.origin': 'auto.db.otel.redis', + 'db.statement': 'set ioredis-cache:test-key-set-EX [3 other arguments]', + 'cache.key': ['ioredis-cache:test-key-set-EX'], + 'cache.item_size': 2, + 'network.peer.address': 'localhost', + 'network.peer.port': 6379, + }), + }), + // SETEX + expect.objectContaining({ + description: 'ioredis-cache:test-key-setex', + op: 'cache.put', + origin: 'auto.db.otel.redis', + data: expect.objectContaining({ + 'sentry.origin': 'auto.db.otel.redis', + 'db.statement': 'setex ioredis-cache:test-key-setex [2 other arguments]', + 'cache.key': ['ioredis-cache:test-key-setex'], 'cache.item_size': 2, 'network.peer.address': 'localhost', 'network.peer.port': 6379, @@ -61,27 +90,43 @@ describe('redis cache auto instrumentation', () => { }), // GET expect.objectContaining({ - description: 'get ioredis-cache:test-key', - op: 'cache.get_item', // todo: will be changed to cache.get + description: 'ioredis-cache:test-key', + op: 'cache.get', origin: 'auto.db.otel.redis', data: expect.objectContaining({ + 'sentry.origin': 'auto.db.otel.redis', 'db.statement': 'get ioredis-cache:test-key', 'cache.hit': true, - 'cache.key': 'ioredis-cache:test-key', + 'cache.key': ['ioredis-cache:test-key'], 'cache.item_size': 10, 'network.peer.address': 'localhost', 'network.peer.port': 6379, }), }), - // GET (unavailable) + // GET (unavailable - no cache hit) expect.objectContaining({ - description: 'get ioredis-cache:unavailable-data', - op: 'cache.get_item', // todo: will be changed to cache.get + description: 'ioredis-cache:unavailable-data', + op: 'cache.get', origin: 'auto.db.otel.redis', data: expect.objectContaining({ + 'sentry.origin': 'auto.db.otel.redis', 'db.statement': 'get ioredis-cache:unavailable-data', 'cache.hit': false, - 'cache.key': 'ioredis-cache:unavailable-data', + 'cache.key': ['ioredis-cache:unavailable-data'], + 'network.peer.address': 'localhost', + 'network.peer.port': 6379, + }), + }), + // MGET + expect.objectContaining({ + description: 'test-key, ioredis-cache:test-key, ioredis-cache:unavailable-data', + op: 'cache.get', + origin: 'auto.db.otel.redis', + data: expect.objectContaining({ + 'sentry.origin': 'auto.db.otel.redis', + 'db.statement': 'mget [3 other arguments]', + 'cache.hit': true, + 'cache.key': ['test-key', 'ioredis-cache:test-key', 'ioredis-cache:unavailable-data'], 'network.peer.address': 'localhost', 'network.peer.port': 6379, }), diff --git a/dev-packages/event-proxy-server/.eslintrc.js b/dev-packages/test-utils/.eslintrc.js similarity index 100% rename from dev-packages/event-proxy-server/.eslintrc.js rename to dev-packages/test-utils/.eslintrc.js diff --git a/dev-packages/event-proxy-server/package.json b/dev-packages/test-utils/package.json similarity index 89% rename from dev-packages/event-proxy-server/package.json rename to dev-packages/test-utils/package.json index 2823c007e717..a03c8de0e99e 100644 --- a/dev-packages/event-proxy-server/package.json +++ b/dev-packages/test-utils/package.json @@ -1,7 +1,7 @@ { "private": true, "version": "8.7.0", - "name": "@sentry-internal/event-proxy-server", + "name": "@sentry-internal/test-utils", "author": "Sentry", "license": "MIT", "main": "build/cjs/index.js", @@ -40,7 +40,11 @@ "build:types": "tsc -p tsconfig.types.json", "clean": "rimraf -g ./node_modules ./build" }, + "peerDependencies": { + "@playwright/test": "^1.44.1" + }, "devDependencies": { + "@playwright/test": "^1.44.1", "@sentry/types": "8.7.0", "@sentry/utils": "8.7.0" }, diff --git a/dev-packages/event-proxy-server/rollup.npm.config.mjs b/dev-packages/test-utils/rollup.npm.config.mjs similarity index 100% rename from dev-packages/event-proxy-server/rollup.npm.config.mjs rename to dev-packages/test-utils/rollup.npm.config.mjs diff --git a/dev-packages/event-proxy-server/src/event-proxy-server.ts b/dev-packages/test-utils/src/event-proxy-server.ts similarity index 87% rename from dev-packages/event-proxy-server/src/event-proxy-server.ts rename to dev-packages/test-utils/src/event-proxy-server.ts index bb3eda188176..1274f77062bd 100644 --- a/dev-packages/event-proxy-server/src/event-proxy-server.ts +++ b/dev-packages/test-utils/src/event-proxy-server.ts @@ -17,6 +17,11 @@ interface EventProxyServerOptions { port: number; /** The name for the proxy server used for referencing it with listener functions */ proxyServerName: string; + /** + * Whether or not to forward the event to sentry. @default `true` + * This is helpful when you can't register a tunnel in the SDK setup (e.g. lambda layer without Sentry.init call) + */ + forwardToSentry?: boolean; } interface SentryRequestCallbackData { @@ -56,7 +61,9 @@ export async function startEventProxyServer(options: EventProxyServerOptions): P const envelopeHeader: EnvelopeItem[0] = JSON.parse(proxyRequestBody.split('\n')[0]); - if (!envelopeHeader.dsn) { + const shouldForwardEventToSentry = options.forwardToSentry != null ? options.forwardToSentry : true; + + if (!envelopeHeader.dsn && shouldForwardEventToSentry) { // eslint-disable-next-line no-console console.log( '[event-proxy-server] Warn: No dsn on envelope header. Maybe a client-report was received. Proxy request body:', @@ -69,6 +76,23 @@ export async function startEventProxyServer(options: EventProxyServerOptions): P return; } + if (!shouldForwardEventToSentry) { + const data: SentryRequestCallbackData = { + envelope: parseEnvelope(proxyRequestBody), + rawProxyRequestBody: proxyRequestBody, + rawSentryResponseBody: '', + sentryResponseStatusCode: 200, + }; + eventCallbackListeners.forEach(listener => { + listener(Buffer.from(JSON.stringify(data)).toString('base64')); + }); + + proxyResponse.writeHead(200); + proxyResponse.write('{}', 'utf-8'); + proxyResponse.end(); + return; + } + const { origin, pathname, host } = new URL(envelopeHeader.dsn as string); const projectId = pathname.substring(1); @@ -269,7 +293,13 @@ async function registerCallbackServerPort(serverName: string, port: string): Pro await writeFile(tmpFilePath, port, { encoding: 'utf8' }); } -function retrieveCallbackServerPort(serverName: string): Promise { - const tmpFilePath = path.join(os.tmpdir(), `${TEMP_FILE_PREFIX}${serverName}`); - return readFile(tmpFilePath, 'utf8'); +async function retrieveCallbackServerPort(serverName: string): Promise { + try { + const tmpFilePath = path.join(os.tmpdir(), `${TEMP_FILE_PREFIX}${serverName}`); + return await readFile(tmpFilePath, 'utf8'); + } catch (e) { + // eslint-disable-next-line no-console + console.log('Could not read callback server port', e); + throw e; + } } diff --git a/dev-packages/event-proxy-server/src/index.ts b/dev-packages/test-utils/src/index.ts similarity index 70% rename from dev-packages/event-proxy-server/src/index.ts rename to dev-packages/test-utils/src/index.ts index 9ee4dfc54520..4425d2688800 100644 --- a/dev-packages/event-proxy-server/src/index.ts +++ b/dev-packages/test-utils/src/index.ts @@ -5,3 +5,5 @@ export { waitForRequest, waitForTransaction, } from './event-proxy-server'; + +export { getPlaywrightConfig } from './playwright-config'; diff --git a/dev-packages/test-utils/src/playwright-config.ts b/dev-packages/test-utils/src/playwright-config.ts new file mode 100644 index 000000000000..4f2ea54bc3b4 --- /dev/null +++ b/dev-packages/test-utils/src/playwright-config.ts @@ -0,0 +1,95 @@ +import type { PlaywrightTestConfig } from '@playwright/test'; + +/** Get a playwright config to use in an E2E test app. */ +export function getPlaywrightConfig( + options: { + startCommand: string; + port?: number; + eventProxyPort?: number; + eventProxyFile?: string; + }, + overwriteConfig?: Partial, +): PlaywrightTestConfig { + const testEnv = process.env['TEST_ENV'] || 'production'; + const appPort = options.port || 3030; + const eventProxyPort = options.eventProxyPort || 3031; + const eventProxyFile = options.eventProxyFile || 'start-event-proxy.mjs'; + const { startCommand } = options; + + /** + * See https://playwright.dev/docs/test-configuration. + */ + const config: PlaywrightTestConfig = { + testDir: './tests', + /* Maximum time one test can run for. */ + timeout: 150_000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 10000, + }, + fullyParallel: false, + workers: 1, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* In dev mode some apps are flaky, so we allow retry there... */ + retries: testEnv === 'development' ? 3 : 0, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'list', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: `http://localhost:${appPort}`, + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + // This comes from `devices["Desktop Chrome"] + // We inline this instead of importing this, + // because playwright otherwise complains that it was imported twice :( + userAgent: + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36', + viewport: { width: 1280, height: 720 }, + deviceScaleFactor: 1, + isMobile: false, + hasTouch: false, + defaultBrowserType: 'chromium', + }, + }, + ], + + /* Run your local dev server before starting the tests */ + webServer: [ + { + command: `node ${eventProxyFile}`, + port: eventProxyPort, + stdout: 'pipe', + stderr: 'pipe', + }, + { + command: startCommand, + port: appPort, + stdout: 'pipe', + stderr: 'pipe', + env: { + PORT: appPort.toString(), + }, + }, + ], + }; + + return { + ...config, + ...overwriteConfig, + }; +} diff --git a/dev-packages/test-utils/tsconfig.json b/dev-packages/test-utils/tsconfig.json new file mode 100644 index 000000000000..7b0fa87fc45b --- /dev/null +++ b/dev-packages/test-utils/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "target": "ES2022", + "module": "ES2022" + }, + "include": ["src/**/*.ts"] +} diff --git a/dev-packages/event-proxy-server/tsconfig.types.json b/dev-packages/test-utils/tsconfig.types.json similarity index 100% rename from dev-packages/event-proxy-server/tsconfig.types.json rename to dev-packages/test-utils/tsconfig.types.json diff --git a/docs/changelog/v7.md b/docs/changelog/v7.md new file mode 100644 index 000000000000..4b575a7c0ab7 --- /dev/null +++ b/docs/changelog/v7.md @@ -0,0 +1,3791 @@ +# Changelog for Sentry SDK 7.x + +Support for Sentry SDK v7 will be dropped soon. We recommend migrating to the latest version of the SDK. You can migrate +from `v7` to `v8 of the SDK by following the [migration guide](../../MIGRATION.md). + +## 7.116.0 + +- build(craft): Publish lambda layer under its own name for v7 (#12098) (#12099) + +This release publishes a new AWS Lambda layer under the name `SentryNodeServerlessSDKv7` that users still running v7 can +use instead of pinning themselves to `SentryNodeServerlessSDK:235`. + +## 7.115.0 + +- feat(v7): Add support for global onUnhandled Error/Promise for Bun (#11959) +- fix(replay/v7): Fix user activity not being updated in `start()` (#12003) +- ref(api): Remove `lastEventId` deprecation warnings (#12042) + +## 7.114.0 + +### Important Changes + +- **fix(browser/v7): Continuously record CLS (#11935)** + +This release fixes a bug that caused the cumulative layout shift (CLS) web vital not to be reported in a majority of the +cases where it should have been reported. With this change, the CLS web vital should now always be reported for +pageloads with layout shift. If a pageload did not have layout shift, no CLS web vital should be reported. + +**Please note that upgrading the SDK to this version may cause data in your dashboards to drastically change.** + +### Other Changes + +- build(aws-lambda/v7): Turn off lambda layer publishing (#11875) +- feat(v7): Add `tunnel` support to multiplexed transport (#11851) +- fix(opentelemetry-node): support `HTTP_REQUEST_METHOD` attribute (#11929) +- fix(react/v7): Fix react router v4/v5 span names (#11940) + +## 7.113.0 + +### Important Changes + +- **feat(node): Support Node 22 (#11754)** + +This release adds support for Node 22! 🎉 + +It also adds prebuilt-binaries for Node 22 to `@sentry/profiling-node`. + +### Other Changes + +- feat(feedback): [v7] New feedback button design (#11841) +- feat(replay/v7): Upgrade rrweb packages to 2.15.0 (#11752) +- fix(ember/v7): Ensure unnecessary spans are avoided (#11848) + +## 7.112.2 + +- fix(nextjs|sveltekit): Ensure we can pass `browserTracingIntegration` (#11765) + +## 7.112.1 + +- fix(ember/v7): Do not create rendering spans without transaction (#11750) + +## 7.112.0 + +### Important Changes + +- **feat: Export pluggable integrations from SDK packages (#11723)** + +Instead of installing `@sentry/integrations`, you can now import the pluggable integrations directly from your SDK +package: + +```js +// Before +import * as Sentry fromv '@sentry/browser'; +import { dedupeIntegration } from '@sentry/integrations'; + +Sentry.init({ + integrations: [dedupeIntegration()], +}); + +// After +import * as Sentry from '@sentry/browser'; + +Sentry.init({ + integrations: [Sentry.dedupeIntegration()], +}); +``` + +Note that only the functional integrations (e.g. `xxxIntegration()`) are re-exported. + +### Other Changes + +- feat(replay): Add "maxCanvasSize" option for replay canvases (#11732) +- fix(serverless): [v7] Check if cloud event callback is a function (#11734) + +## 7.111.0 + +- feat(core): Add `server.address` to browser `http.client` spans (#11663) +- fix: Ensure next & sveltekit correctly handle `browserTracingIntegration` (#11647) +- fix(browser): Don't assume window.document is available (#11598) + +## 7.110.1 + +- fix(nextjs): Fix `tunnelRoute` matching logic for hybrid cloud (#11577) + +## 7.110.0 + +### Important Changes + +- **feat(tracing): Add interactions sample rate to browser tracing integrations (#11382)** + +You can now use a `interactionsSampleRate` to control the sample rate of INP spans. `interactionsSampleRate` is applied +on top of the global `tracesSampleRate`. Therefore if `interactionsSampleRate` is `0.5` and `tracesSampleRate` is `0.1`, +then the actual sample rate for interactions is `0.05`. + +```js +Sentry.init({ + tracesSampleRate: 0.1, + integrations: [ + Sentry.browserTracingIntegration({ + interactionsSampleRate: 0.5, + }), + ], +}); +``` + +- **Deprecations** + +This release deprecates the `Hub` class, as well as the `addRequestDataToTransaction` method. The `trpcMiddleware` +method is no longer on the `Handlers` export, but instead is a standalone export. + +Please see the detailed [Migration docs](./MIGRATION.md#deprecations-in-7x) on how to migrate to the new APIs. + +- feat: Deprecate and relocate `trpcMiddleware` (#11389) +- feat(core): Deprecate `Hub` class (#11528) +- feat(types): Deprecate `Hub` interface (#11530) +- ref: Deprecate `addRequestDataToTransaction` (#11368) + +### Other Changes + +- feat(core): Update metric normalization (#11519) +- feat(feedback): Customize feedback placeholder text color (#11521) +- feat(remix): Skip span creation for `OPTIONS` and `HEAD` request. (#11485) +- feat(utils): Add metric buckets rate limit (#11506) +- fix(core): unref timer to not block node exit (#11483) +- fix(metrics): Map `statsd` to `metric_bucket` (#11505) +- fix(spans): Allow zero exclusive time for INP spans (#11408) +- ref(feedback): Configure feedback fonts (#11520) + +## 7.109.0 + +This release deprecates some exports from the `@sentry/replay` package. These exports have been moved to the browser SDK +(or related framework SDKs like `@sentry/react`). + +- feat(feedback): Make "required" text for input elements configurable (#11287) +- feat(node): Add scope to ANR events (#11267) +- feat(replay): Bump `rrweb` to 2.12.0 (#11317) +- fix(node): Local variables skipped after Promise (#11248) +- fix(node): Skip capturing Hapi Boom error responses (#11324) +- fix(web-vitals): Check for undefined navigation entry (#11312) +- ref(replay): Deprecate `@sentry/replay` exports (#11242) + +Work in this release contributed by @soerface. Thank you for your contribution! + +## 7.108.0 + +This release fixes issues with Time to First Byte (TTFB) calculation in the SDK that was introduced with `7.95.0`. It +also fixes some bugs with Interaction to First Paint (INP) instrumentation. This may impact your Sentry Performance +Score calculation. + +- feat(serverless): Add Node.js 20 to compatible runtimes (#11104) +- feat(core): Backport `ResizeObserver` and `googletag` default filters (#11210) +- feat(webvitals): Adds event entry names for INP handler. Also guard against empty metric value +- fix(metrics): use correct statsd data category (#11187) +- fix(node): Record local variables with falsy values (v7) (#11190) +- fix(node): Use unique variable for ANR context transfer (v7) (#11162) +- fix(node): Time zone handling for `cron` (#11225) +- fix(tracing): use web-vitals ttfb calculation (#11231) +- fix(types): Fix incorrect `sampled` type on `Transaction` (#11146) +- fix(webvitals): Fix mapping not being maintained properly and sometimes not sending INP spans (#11183) + +Work in this release contributed by @quisido and @joshkel. Thank you for your contributions! + +## 7.107.0 + +This release fixes issues with INP instrumentation with the Next.js SDK and adds support for the `enableInp` option in +the deprecated `BrowserTracing` integration for backwards compatibility. + +- feat(performance): Port INP span instrumentation to old browser tracing (#11085) +- fix(ember): Ensure browser tracing is correctly lazy loaded (#11027) +- fix(node): Do not assert in vendored proxy code (v7 backport) (#11009) +- fix(react): Set `handled` value in ErrorBoundary depending on fallback [v7] (#11037) + +## 7.106.1 + +- fix(nextjs/v7): Use passthrough `createReduxEnhancer` on server (#11010) + +## 7.106.0 + +- feat(nextjs): Support Hybrid Cloud DSNs with `tunnelRoute` option (#10958) +- feat(remix): Add Vite dev-mode support to Express instrumentation (#10811) +- fix(core): Undeprecate `setTransactionName` +- fix(browser): Don't use chrome variable name (#10874) +- fix(nextjs): Client code should not use Node `global` (#10925) +- fix(node): support undici headers as strings or arrays (#10938) +- fix(types): Add `AttachmentType` and use for envelope `attachment_type` property (#10946) +- ref(ember): Avoid namespace import to hopefully resolve minification issue (#10885) +- chore(sveltekit): Fix punctuation in a console.log (#10895) + +Work in this release contributed by @jessezhang91 and @bfontaine. Thank you for your contributions! + +## 7.105.0 + +### Important Changes + +- **feat: Ensure `withActiveSpan` is exported everywhere (#10877)** + +You can use the `withActiveSpan` method to ensure a certain span is the active span in a given callback. This can be +used to create a span as a child of a specific span with the `startSpan` API methods: + +```js +const parentSpan = Sentry.startInactiveSpan({ name: 'parent' }); +if (parentSpan) { + withActiveSpan(parentSpan, () => { + // This will be a direct child of parentSpan + const childSpan = Sentry.startInactiveSpan({ name: 'child' }); + }); +} +``` + +## 7.104.0 + +### Important Changes + +- **feat(performance): create Interaction standalone spans on inp events (#10709)** + +This release adds support for the INP web vital. This is currently only supported for Saas Sentry, and product support +is released with the upcoming `24.3.0` release of self-hosted. + +To opt-in to this feature, you can use the `enableInp` option in the `browserTracingIntegration`: + +```js +Sentry.init({ + integrations: [ + Sentry.browserTracingIntegration({ + enableInp: true, + }); + ] +}) +``` + +### Other Changes + +- feat(feedback): Flush replays when feedback form opens (#10567) +- feat(profiling-node): Expose `nodeProfilingIntegration` (#10864) +- fix(profiling-node): Fix dependencies to point to current versions (#10861) +- fix(replay): Add `errorHandler` for replayCanvas integration (#10796) + +## 7.103.0 + +### Important Changes + +- **feat(core): Allow to pass `forceTransaction` to `startSpan()` APIs (#10819)** + +You can now pass `forceTransaction: true` to `startSpan()`, `startSpanManual()` and `startInactiveSpan()`. This allows +you to start a span that you want to be a transaction, if possible. Under the hood, the SDK will connect this span to +the running active span (if there is one), but still send the new span as a transaction to the Sentry backend, if +possible, ensuring it shows up as a transaction throughout the system. + +Please note that setting this to `true` does not _guarantee_ that this will be sent as a transaction, but that the SDK +will try to do so. You can enable this flag if this span is important to you and you want to ensure that you can see it +in the Sentry UI. + +### Other Changes + +- fix: Make breadcrumbs option optional in WinterCGFetch integration (#10792) + +## 7.102.1 + +- fix(performance): Fixes latest route name and source for interactions not updating properly on navigation (#10702) +- fix(tracing): Guard against missing `window.location` (#10659) +- ref: Make span types more robust (#10660) +- ref(remix): Make `@remix-run/router` a dependency (v7) (#10779) + +## 7.102.0 + +- fix: Export session API (#10712) +- fix(core): Fix scope capturing via `captureContext` function (#10737) + +## 7.101.1 + +In version 7.101.0 the `@sentry/hub` package was missing due to a publishing issue. This release contains the package +again. + +- fix(nextjs): Remove `webpack://` prefix more broadly from source map `sources` field (#10641) + +## 7.101.0 + +- feat: Export semantic attribute keys from SDK packages (#10637) +- feat(core): Add metric summaries to spans (#10554) +- feat(core): Deprecate the `Hub` constructor (#10584) +- feat(core): Make custom tracing methods return spans & set default op (#10633) +- feat(replay): Add `getReplay` utility function (#10510) +- fix(angular-ivy): Add `exports` field to `package.json` (#10569) +- fix(sveltekit): Avoid capturing Http 4xx errors on the client (#10571) +- fix(sveltekit): Properly await sourcemaps flattening (#10602) + +## 7.100.1 + +This release contains build fixes for profiling-node. + +- build(profiling-node): make sure debug build plugin is used #10534 +- build: Only run profiling e2e test if bindings have changed #10542 +- fix(feedback): Replay breadcrumb for feedback events was incorrect #10536 + +## 7.100.0 + +### Important Changes + +#### Deprecations + +This release includes some deprecations. For more details please look at our +[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md). + +The deprecation most likely to affect you is the one of `BrowserTracing`. Instead of `new BrowserTracing()`, you should +now use `browserTracingIntegration()`, which will also handle framework-specific instrumentation out of the box for +you - no need to pass a custom `routingInstrumentation` anymore. For `@sentry/react`, we expose dedicated integrations +for the different react-router versions: + +- `reactRouterV6BrowserTracingIntegration()` +- `reactRouterV5BrowserTracingIntegration()` +- `reactRouterV4BrowserTracingIntegration()` +- `reactRouterV3BrowserTracingIntegration()` + +See the +[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md#depreacted-browsertracing-integration) +for details. + +- feat(angular): Export custom `browserTracingIntegration()` (#10353) +- feat(browser): Deprecate `BrowserTracing` integration (#10493) +- feat(browser): Export `browserProfilingIntegration` (#10438) +- feat(bun): Export `bunServerIntegration()` (#10439) +- feat(nextjs): Add `browserTracingIntegration` (#10397) +- feat(react): Add `reactRouterV3BrowserTracingIntegration` for react router v3 (#10489) +- feat(react): Add `reactRouterV4/V5BrowserTracingIntegration` for react router v4 & v5 (#10488) +- feat(react): Add `reactRouterV6BrowserTracingIntegration` for react router v6 & v6.4 (#10491) +- feat(remix): Add custom `browserTracingIntegration` (#10442) +- feat(node): Expose functional integrations to replace classes (#10356) +- feat(vercel-edge): Replace `WinterCGFetch` with `winterCGFetchIntegration` (#10436) +- feat: Deprecate non-callback based `continueTrace` (#10301) +- feat(vue): Deprecate `new VueIntegration()` (#10440) +- feat(vue): Implement vue `browserTracingIntegration()` (#10477) +- feat(sveltekit): Add custom `browserTracingIntegration()` (#10450) + +#### Profiling Node + +`@sentry/profiling-node` has been ported into the monorepo. Future development for it will happen here! + +- pkg(profiling-node): port profiling-node repo to monorepo (#10151) + +### Other Changes + +- feat: Export `setHttpStatus` from all packages (#10475) +- feat(bundles): Add pluggable integrations on CDN to `Sentry` namespace (#10452) +- feat(core): Pass `name` & `attributes` to `tracesSampler` (#10426) +- feat(feedback): Add `system-ui` to start of font family (#10464) +- feat(node-experimental): Add koa integration (#10451) +- feat(node-experimental): Update opentelemetry packages (#10456) +- feat(node-experimental): Update tracing integrations to functional style (#10443) +- feat(replay): Bump `rrweb` to 2.10.0 (#10445) +- feat(replay): Enforce masking of credit card fields (#10472) +- feat(utils): Add `propagationContextFromHeaders` (#10313) +- fix: Make `startSpan`, `startSpanManual` and `startInactiveSpan` pick up the scopes at time of creation instead of + termination (#10492) +- fix(feedback): Fix logo color when colorScheme is "system" (#10465) +- fix(nextjs): Do not report redirects and notFound calls as errors in server actions (#10474) +- fix(nextjs): Fix navigation tracing on app router (#10502) +- fix(nextjs): Apply server action data to correct isolation scope (#10514) +- fix(node): Use normal `require` call to import Undici (#10388) +- ref(nextjs): Remove internally used deprecated APIs (#10453) +- ref(vue): use startInactiveSpan in tracing mixin (#10406) + +## 7.99.0 + +### Important Changes + +#### Deprecations + +This release includes some deprecations for span related methods and integrations in our Deno SDK, `@sentry/deno`. For +more details please look at our +[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md). + +- feat(core): Deprecate `Span.setHttpStatus` in favor of `setHttpStatus` (#10268) +- feat(core): Deprecate `spanStatusfromHttpCode` in favour of `getSpanStatusFromHttpCode` (#10361) +- feat(core): Deprecate `StartSpanOptions.origin` in favour of passing attribute (#10274) +- feat(deno): Expose functional integrations to replace classes (#10355) + +### Other Changes + +- feat(bun): Add missing `@sentry/node` re-exports (#10396) +- feat(core): Add `afterAllSetup` hook for integrations (#10345) +- feat(core): Ensure `startSpan()` can handle spans that require parent (#10386) +- feat(core): Read propagation context off scopes in `startSpan` APIs (#10300) +- feat(remix): Export missing `@sentry/node` functions (#10385, #10391) +- feat(serverless): Add missing `@sentry/node` re-exports (#10390) +- feat(sveltekit): Add more missing `@sentry/node` re-exports (#10392) +- feat(tracing): Export proper type for browser tracing (#10411) +- feat(tracing): Expose new `browserTracingIntegration` (#10351) +- fix: Ensure `afterAllSetup` is called when using `addIntegration()` (#10372) +- fix(core): Export `spanToTraceContext` function from span utils (#10364) +- fix(core): Make `FunctionToString` integration use SETUP_CLIENTS weakmap (#10358) +- fix(deno): Call function if client is not setup (#10354) +- fix(react): Fix attachReduxState option (#10381) +- fix(spotlight): Use unpatched http.request (#10369) +- fix(tracing): Only create request span if there is active span (#10375) +- ref: Read propagation context off of scope and isolation scope when propagating and applying trace context (#10297) + +Work in this release contributed by @AleshaOleg. Thank you for your contribution! + +## 7.98.0 + +This release primarily fixes some type declaration errors: + +- feat(core): Export `IntegrationIndex` type (#10337) +- fix(nextjs): Fix Http integration type declaration (#10338) +- fix(node): Fix type definitions (#10339) + +## 7.97.0 + +Note: The 7.96.0 release was incomplete. This release is partially encompassing changes from `7.96.0`. + +- feat(react): Add `stripBasename` option for React Router 6 (#10314) + +## 7.96.0 + +Note: This release was incomplete. Not all Sentry SDK packages were released for this version. Please upgrade to 7.98.0 +directly. + +### Important Changes + +#### Deprecations + +This release includes some deprecations for integrations in `@sentry/browser` and frontend framework SDKs +(`@sentry/react`, `@sentry/vue`, etc.). Please take a look at our +[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md) for more details. + +- feat(browser): Export functional integrations & deprecate classes (#10267) + +#### Web Vitals Fix for LCP and CLS + +This release fixes an issue with the Web Vitals integration where LCP and CLS were not being captured correctly, +increasing capture rate by 10-30% for some apps. LCP and CLS capturing issues were introduced with version `7.75.0`. + +- fix(tracing): Ensure web vitals are correctly stopped/captured (#10323) + +### Other Changes + +- fix(node): Fix `node-cron` types and add test (#10315) +- fix(node): Fix downleveled types entry point (#10321) +- fix(node): LocalVariables integration should use setupOnce (#10307) +- fix(replay): Fix type for options of replayIntegration (#10325) + +Work in this release contributed by @Shubhdeep12. Thank you for your contribution! + +## 7.95.0 + +### Important Changes + +#### Deprecations + +This release includes some deprecations in preparation for v8. + +Most notably, it deprecates the `Replay` & `Feedback` classes in favor of a functional replacement: + +```js +import * as Sentry from '@sentry/browser'; + +Sentry.init({ + integrations: [ + // Instead of + new Sentry.Replay(), + new Sentry.Feedback(), + // Use the functional replacement: + Sentry.replayIntegration(), + Sentry.feedbackIntegration(), + ], +}); +``` + +- feat(core): Deprecate `Span.origin` in favor of `sentry.origin` attribute (#10260) +- feat(core): Deprecate `Span.parentSpanId` (#10244) +- feat(core): Expose `isInitialized()` to replace checking via `getClient` (#10296) +- feat(replay): Deprecate `Replay`, `ReplayCanvas`, `Feedback` classes (#10270) +- feat(wasm): Deprecate `Wasm` integration class (#10230) + +### Other Changes + +- feat: Make `parameterize` function available through browser and node API (#10085) +- feat(feedback): Configure feedback border radius (#10289) +- feat(sveltekit): Update default integration handling & deprecate `addOrUpdateIntegration` (#10263) +- fix(replay-canvas): Add missing dependency on @sentry/utils (#10279) +- fix(tracing): Don't send negative ttfb (#10286) + +Work in this release contributed by @AleshaOleg. Thank you for your contribution! + +## 7.94.1 + +This release fixes a publishing issue. + +## 7.94.0 + +### Important Changes + +#### Deprecations + +As we're moving closer to the next major version of the SDK, more public APIs were deprecated. + +To get a head start on migrating to the replacement APIs, please take a look at our +[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md). + +- feat: Deprecate user segment field (#10210) +- feat(core): Deprecate `finish` on `Span` interface in favour of `end` (#10161) +- feat(core): Deprecate `getCurrentHub()` (#10200) +- feat(core): Deprecate `hub.bindClient()` & `makeMain()` (#10188) +- feat(core): Deprecate `Span.instrumenter` (#10139) +- feat(core): Deprecate `Span.isSuccess()` in favor of reading span status (#10213) +- feat(core): Deprecate `Span.op` in favor of op attribute (#10189) +- feat(core): Deprecate `Span.spanRecorder` (#10199) +- feat(core): Deprecate `Span.status` (#10208) +- feat(core): Deprecate `Span.transaction` in favor of `getRootSpan` (#10134) +- feat(core): Deprecate `Transaction.instrumenter` (#10162) +- feat(core): Deprecate `Transaction.setMeasurement` in favor of `setMeasurement` (#10182) +- feat(core): Deprecate integration classes & `Integrations.X` (#10198) +- feat(core): Deprecate methods on `Hub` (#10124) +- feat(core): Deprecate remaining `setName` declarations on `Transaction` and `Span` (#10164) +- feat(core): Deprecate span `startTimestamp` & `endTimestamp` (#10192) +- feat(core): Deprecate `hub.bindClient()` and `makeMain()` (#10118) +- feat(types): Deprecate `op` on `Span` interface (#10217) +- feat(integrations): Deprecate `Transaction` integration (#10178) +- feat(integrations): Deprecate pluggable integration classes (#10211) + +#### Replay & Canvas + +We have added a new `ReplayCanvas` integration (#10112), which you can add to capture the contents of canvas elements +with Replay. + +Just add it _in addition_ to the regular replay integration: + +```js +Sentry.init({ + integrations: [new Sentry.Replay(), new Sentry.ReplayCanvas()], +}); +``` + +### Other Changes + +- feat(core): Add `client.getIntegrationByName()` (#10130) +- feat(core): Add `client.init()` to replace `client.setupIntegrations()` (#10118) +- feat(core): Add `withActiveSpan` (#10195) +- feat(core): Add `withIsolationScope` (#10141) +- feat(core): Streamline integration function results to be compatible (#10135) +- feat(core): Write data from `setUser`, `setTags`, `setExtras`, `setTag`, `setExtra`, and `setContext` to isolation + scope (#10163) +- feat(core): Add domain information to resource span data #10205 +- feat(feedback): Export sendFeedback from @sentry/browser (#10231) +- feat(node): Update and vendor https-proxy-agent (#10088) +- feat(node-experimental): Add `withActiveSpan` (#10194) +- feat(replays): Add snapshot function to replay canvas integration (#10066) +- feat(types): Add `SerializedEvent` interface (pre v8) (#10240) +- feat(types): Add support for new monitor config thresholds (#10225) +- fix: Ensure all integration classes have correct types (#10183) +- fix(astro): Fix import path when using external init files with default path (#10214) +- fix(cdn): Emit console warning instead of error for integration shims (#10193) +- fix(core): Take user from current scope when starting a session (#10153) +- fix(node-experimental): Ensure `http.status_code` is always a string (#10177) +- fix(node): Guard against `process.argv[1]` being undefined (#10155) +- fix(node): Module name resolution (#10144) +- fix(node): Remove leading slash in Windows filenames (#10147) +- fix(remix): Capture thrown fetch responses. (#10166) +- fix(tracing): Gate mongo operation span data behind sendDefaultPii (#10227) +- fix(tracing-internal): Delay pageload transaction finish until document is interactive (#10215) +- fix(tracing-internal): Only collect request/response spans when browser performance timing is available (#10207) +- fix(tracing-internal): Prefer `fetch` init headers over `fetch` input headers (#10176) +- fix(utils): Ensure dropUndefinedKeys() does not break class instances (#10245) + +## 7.93.0 + +### Important Changes + +#### Deprecations + +As we're moving closer to the next major version of the SDK, more public APIs were deprecated. + +To get a head start on migrating to the replacement APIs, please take a look at our +[migration guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md). + +- feat(core): Deprecate `getActiveTransaction()` & `scope.getTransaction()` (#10098) +- feat(core): Deprecate `Hub.shouldSendDefaultPii` (#10062) +- feat(core): Deprecate `new Transaction()` (#10125) +- feat(core): Deprecate `scope.getSpan()` & `scope.setSpan()` (#10114) +- feat(core): Deprecate `scope.setTransactionName()` (#10113) +- feat(core): Deprecate `span.startChild()` (#10091) +- feat(core): Deprecate `startTransaction()` (#10073) +- feat(core): Deprecate `Transaction.getDynamicSamplingContext` in favor of `getDynamicSamplingContextFromSpan` (#10094) +- feat(core): Deprecate arguments for `startSpan()` (#10101) +- feat(core): Deprecate hub capture APIs and add them to `Scope` (#10039) +- feat(core): Deprecate session APIs on hub and add global replacements (#10054) +- feat(core): Deprecate span `name` and `description` (#10056) +- feat(core): Deprecate span `tags`, `data`, `context` & setters (#10053) +- feat(core): Deprecate transaction metadata in favor of attributes (#10097) +- feat(core): Deprecate `span.sampled` in favor of `span.isRecording()` (#10034) +- ref(node-experimental): Deprecate `lastEventId` on scope (#10093) + +#### Cron Monitoring Support for `node-schedule` library + +This release adds auto instrumented check-ins for the `node-schedule` library. + +```ts +import * as Sentry from '@sentry/node'; +import * as schedule from 'node-schedule'; + +const scheduleWithCheckIn = Sentry.cron.instrumentNodeSchedule(schedule); + +const job = scheduleWithCheckIn.scheduleJob('my-cron-job', '* * * * *', () => { + console.log('You will see this message every minute'); +}); +``` + +- feat(node): Instrumentation for `node-schedule` library (#10086) + +### Other Changes + +- feat(core): Add `span.spanContext()` (#10037) +- feat(core): Add `spanToJSON()` method to get span properties (#10074) +- feat(core): Allow to pass `scope` to `startSpan` APIs (#10076) +- feat(core): Allow to pass start/end timestamp for spans flexibly (#10060) +- feat(node): Make `getModuleFromFilename` compatible with ESM (#10061) +- feat(replay): Update rrweb to 2.7.3 (#10072) +- feat(utils): Add `parameterize` function (#9145) +- fix(astro): Use correct package name for CF (#10099) +- fix(core): Do not run `setup` for integration on client multiple times (#10116) +- fix(core): Ensure we copy passed in span data/tags/attributes (#10105) +- fix(cron): Make name required for instrumentNodeCron option (#10070) +- fix(nextjs): Don't capture not-found and redirect errors in generation functions (#10057) +- fix(node): `LocalVariables` integration should have correct name (#10084) +- fix(node): Anr events should have an `event_id` (#10068) +- fix(node): Revert to only use sync debugger for `LocalVariables` (#10077) +- fix(node): Update ANR min node version to v16.17.0 (#10107) + +## 7.92.0 + +### Important Changes + +#### Deprecations + +- feat(core): Add `span.updateName()` and deprecate `span.setName()` (#10018) +- feat(core): Deprecate `span.getTraceContext()` (#10032) +- feat(core): Deprecate `span.toTraceparent()` in favor of `spanToTraceHeader()` util (#10031) +- feat(core): Deprecate `trace` in favor of `startSpan` (#10012) +- feat(core): Deprecate span `toContext()` and `updateWithContext()` (#10030) +- ref: Deprecate `deepReadDirSync` (#10016) +- ref: Deprecate `lastEventId()` (#10043) + +Please take a look at the [Migration docs](./MIGRATION.md) for more details. These methods will be removed in the +upcoming [v8 major release](https://github.com/getsentry/sentry-javascript/discussions/9802). + +#### Cron Monitoring Support for `cron` and `node-cron` libraries + +- feat(node): Instrumentation for `cron` library (#9999) +- feat(node): Instrumentation for `node-cron` library (#9904) + +This release adds instrumentation for the `cron` and `node-cron` libraries. This allows you to monitor your cron jobs +with [Sentry cron monitors](https://docs.sentry.io/product/crons/). + +For [`cron`](https://www.npmjs.com/package/cron): + +```js +import * as Sentry from '@sentry/node'; +import { CronJob } from 'cron'; + +const CronJobWithCheckIn = Sentry.cron.instrumentCron(CronJob, 'my-cron-job'); + +// use the constructor +const job = new CronJobWithCheckIn('* * * * *', () => { + console.log('You will see this message every minute'); +}); + +// or from +const job = CronJobWithCheckIn.from({ + cronTime: '* * * * *', + onTick: () => { + console.log('You will see this message every minute'); + }, +}); +``` + +For [`node-cron`](https://www.npmjs.com/package/node-cron): + +```js +import * as Sentry from '@sentry/node'; +import cron from 'node-cron'; + +const cronWithCheckIn = Sentry.cron.instrumentNodeCron(cron); + +cronWithCheckIn.schedule( + '* * * * *', + () => { + console.log('running a task every minute'); + }, + { name: 'my-cron-job' }, +); +``` + +### Other Changes + +- feat(astro): Add `enabled` option to Astro integration options (#10007) +- feat(core): Add `attributes` to `Span` (#10008) +- feat(core): Add `setClient()` and `getClient()` to `Scope` (#10055) +- feat(integrations): Capture error cause with `captureErrorCause` in `ExtraErrorData` integration (#9914) +- feat(node-experimental): Allow to pass base span options to trace methods (#10006) +- feat(node): Local variables via async inspector in node 19+ (#9962) +- fix(astro): handle commonjs related issues (#10042) +- fix(astro): Handle non-utf8 encoded streams in middleware (#9989) +- fix(astro): prevent sentry from externalized (#9994) +- fix(core): Ensure `withScope` sets current scope correctly with async callbacks (#9974) +- fix(node): ANR fixes and additions (#9998) +- fix(node): Anr should not block exit (#10035) +- fix(node): Correctly resolve module name (#10001) +- fix(node): Handle inspector already open (#10025) +- fix(node): Make `NODE_VERSION` properties required (#9964) +- fix(node): Anr doesn't block exit (#10064) +- fix(utils): use correct typeof URL validation (#10028) +- perf(astro): reduce unnecessary path resolutions (#10021) +- ref(astro): Use astro logger instead of console (#9995) +- ref(remix): Isolate Express instrumentation from server auto-instrumentation. (#9966) + +Work in this release contributed by @joshkel. Thank you for your contribution! + +## 7.91.0 + +### Important Changes + +- **feat: Add server runtime metrics aggregator (#9894)** + +The release adds alpha support for [Sentry developer metrics](https://github.com/getsentry/sentry/discussions/58584) in +the server runtime SDKs (`@sentry/node`, `@sentry/deno`, `@sentry/nextjs` server-side, etc.). Via the newly introduced +APIs, you can now flush metrics directly to Sentry. + +To enable capturing metrics, you first need to add the `metricsAggregator` experiment to your `Sentry.init` call. + +```js +Sentry.init({ + dsn: '__DSN__', + _experiments: { + metricsAggregator: true, + }, +}); +``` + +Then you'll be able to add `counters`, `sets`, `distributions`, and `gauges` under the `Sentry.metrics` namespace. + +```js +// Add 4 to a counter named `hits` +Sentry.metrics.increment('hits', 4); + +// Add 2 to gauge named `parallel_requests`, tagged with `type: "a"` +Sentry.metrics.gauge('parallel_requests', 2, { tags: { type: 'a' } }); + +// Add 4.6 to a distribution named `response_time` with unit seconds +Sentry.metrics.distribution('response_time', 4.6, { unit: 'seconds' }); + +// Add 2 to a set named `valuable.ids` +Sentry.metrics.set('valuable.ids', 2); +``` + +- **feat(node): Rework ANR to use worker script via an integration (#9945)** + +The [ANR tracking integration for Node](https://docs.sentry.io/platforms/node/configuration/application-not-responding/) +has been reworked to use an integration. ANR tracking now requires a minimum Node version of 16 or higher. Previously +you had to call `Sentry.enableANRDetection` before running your application, now you can simply add the `Anr` +integration to your `Sentry.init` call. + +```js +import * as Sentry from '@sentry/node'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + integrations: [new Sentry.Integrations.Anr({ captureStackTrace: true, anrThreshold: 200 })], +}); +``` + +### Other Changes + +- feat(breadcrumbs): Send component names on UI breadcrumbs (#9946) +- feat(core): Add `getGlobalScope()` method (#9920) +- feat(core): Add `getIsolationScope()` method (#9957) +- feat(core): Add `span.end()` to replace `span.finish()` (#9954) +- feat(core): Ensure `startSpan` & `startSpanManual` fork scope (#9955) +- feat(react): Send component name on spans (#9949) +- feat(replay): Send component names in replay breadcrumbs (#9947) +- feat(sveltekit): Add options to configure fetch instrumentation script for CSP (#9969) +- feat(tracing): Send component name on interaction spans (#9948) +- feat(utils): Add function to extract relevant component name (#9921) +- fix(core): Rethrow caught promise rejections in `startSpan`, `startSpanManual`, `trace` (#9958) + +## 7.90.0 + +- feat(replay): Change to use preset quality values (#9903) +- fix(replay): Adjust development hydration error messages (#9922) +- fix(sveltekit): Add `types` field to package.json `exports` (#9926) + +## 7.89.0 + +### Important Changes + +#### Deprecations + +- **feat(core): Deprecate `configureScope` (#9887)** +- **feat(core): Deprecate `pushScope` & `popScope` (#9890)** + +This release deprecates `configureScope`, `pushScope`, and `popScope`, which will be removed in the upcoming v8 major +release. + +#### Hapi Integration + +- **feat(node): Add Hapi Integration (#9539)** + +This release adds an integration for Hapi. It can be used as follows: + +```ts +const Sentry = require('@sentry/node'); +const Hapi = require('@hapi/hapi'); + +const init = async () => { + const server = Hapi.server({ + // your server configuration ... + }); + + Sentry.init({ + dsn: '__DSN__', + tracesSampleRate: 1.0, + integrations: [new Sentry.Integrations.Hapi({ server })], + }); + + server.route({ + // your route configuration ... + }); + + await server.start(); +}; +``` + +#### SvelteKit 2.0 + +- **chore(sveltekit): Add SvelteKit 2.0 to peer dependencies (#9861)** + +This release adds support for SvelteKit 2.0 in the `@sentry/sveltekit` package. If you're upgrading from SvelteKit 1.x +to 2.x and already use the Sentry SvelteKit SDK, no changes apart from upgrading to this (or a newer) version are +necessary. + +### Other Changes + +- feat(core): Add type & utility for function-based integrations (#9818) +- feat(core): Update `withScope` to return callback return value (#9866) +- feat(deno): Support `Deno.CronSchedule` for cron jobs (#9880) +- feat(nextjs): Auto instrument generation functions (#9781) +- feat(nextjs): Connect server component transactions if there is no incoming trace (#9845) +- feat(node-experimental): Update to new Scope APIs (#9799) +- feat(replay): Add `canvas.type` setting (#9877) +- fix(nextjs): Export `createReduxEnhancer` (#9854) +- fix(remix): Do not capture thrown redirect responses. (#9909) +- fix(sveltekit): Add conditional exports (#9872) +- fix(sveltekit): Avoid capturing 404 errors on client side (#9902) +- fix(utils): Do not use `Event` type in worldwide (#9864) +- fix(utils): Support crypto.getRandomValues in old Chromium versions (#9251) +- fix(utils): Update `eventFromUnknownInput` to avoid scope pollution & `getCurrentHub` (#9868) +- ref: Use `addBreadcrumb` directly & allow to pass hint (#9867) + +Work in this release contributed by @adam187, and @jghinestrosa. Thank you for your contributions! + +## 7.88.0 + +### Important Changes + +- **feat(browser): Add browser metrics sdk (#9794)** + +The release adds alpha support for [Sentry developer metrics](https://github.com/getsentry/sentry/discussions/58584) in +the Browser SDKs (`@sentry/browser` and related framework SDKs). Via the newly introduced APIs, you can now flush +metrics directly to Sentry. + +To enable capturing metrics, you first need to add the `MetricsAggregator` integration. + +```js +Sentry.init({ + dsn: '__DSN__', + integrations: [new Sentry.metrics.MetricsAggregator()], +}); +``` + +Then you'll be able to add `counters`, `sets`, `distributions`, and `gauges` under the `Sentry.metrics` namespace. + +```js +// Add 4 to a counter named `hits` +Sentry.metrics.increment('hits', 4); + +// Add 2 to gauge named `parallel_requests`, tagged with `happy: "no"` +Sentry.metrics.gauge('parallel_requests', 2, { tags: { happy: 'no' } }); + +// Add 4.6 to a distribution named `response_time` with unit seconds +Sentry.metrics.distribution('response_time', 4.6, { unit: 'seconds' }); + +// Add 2 to a set named `valuable.ids` +Sentry.metrics.set('valuable.ids', 2); +``` + +In a future release we'll add support for server runtimes (Node, Deno, Bun, Vercel Edge, etc.) + +- **feat(deno): Optionally instrument `Deno.cron` (#9808)** + +This releases add support for instrumenting [Deno cron's](https://deno.com/blog/cron) with +[Sentry cron monitors](https://docs.sentry.io/product/crons/). This requires v1.38 of Deno run with the `--unstable` +flag and the usage of the `DenoCron` Sentry integration. + +```ts +// Import from the Deno registry +import * as Sentry from 'https://deno.land/x/sentry/index.mjs'; + +Sentry.init({ + dsn: '__DSN__', + integrations: [new Sentry.DenoCron()], +}); +``` + +### Other Changes + +- feat(replay): Bump `rrweb` to 2.6.0 (#9847) +- fix(nextjs): Guard against injecting multiple times (#9807) +- ref(remix): Bump Sentry CLI to ^2.23.0 (#9773) + +## 7.87.0 + +- feat: Add top level `getCurrentScope()` method (#9800) +- feat(replay): Bump `rrweb` to 2.5.0 (#9803) +- feat(replay): Capture hydration error breadcrumb (#9759) +- feat(types): Add profile envelope types (#9798) +- fix(astro): Avoid RegExp creation during route interpolation (#9815) +- fix(browser): Avoid importing from `./exports` (#9775) +- fix(nextjs): Catch rejecting flushes (#9811) +- fix(nextjs): Fix devserver CORS blockage when `assetPrefix` is defined (#9766) +- fix(node): Capture errors in tRPC middleware (#9782) + +## 7.86.0 + +- feat(core): Use SDK_VERSION for hub API version (#9732) +- feat(nextjs): Emit warning if your app directory doesn't have a global-error.js file (#9753) +- feat(node): Add cloudflare pages commit sha (#9751) +- feat(remix): Bump @sentry/cli to 2.22.3 (#9741) +- fix(nextjs): Don't accidentally trigger static generation bailout (#9749) +- fix(node): Guard `process.env.NODE_ENV` access in Spotlight integration (#9748) +- fix(utils): Fix XHR instrumentation early return (#9770) +- ref(remix): Rework Error Handling (#9725) + +## 7.85.0 + +- feat(core): Add `addEventProcessor` method (#9554) +- feat(crons): Add interface for heartbeat checkin (#9706) +- feat(feedback): Include Feedback package in browser SDK (#9586) +- fix(astro): Isolate request instrumentation in middleware (#9709) +- fix(replay): Capture JSON XHR response bodies (#9623) +- ref(feedback): Change form `box-shadow` to use CSS var (#9630) + +## 7.84.0 + +### Important Changes + +- **ref(nextjs): Set `automaticVercelMonitors` to be `false` by default (#9697)** + +From this version onwards the default for the `automaticVercelMonitors` option in the Next.js SDK is set to false. +Previously, if you made use of Vercel Crons the SDK automatically instrumented the relevant routes to create Sentry +monitors. Because this feature will soon be generally available, we are now flipping the default to avoid situations +where quota is used unexpectedly. + +If you want to continue using this feature, make sure to set the `automaticVercelMonitors` flag to `true` in your +`next.config.js` Sentry settings. + +### Other Changes + +- chore(astro): Add 4.0.0 preview versions to `astro` peer dependency range (#9696) +- feat(metrics): Add interfaces for metrics (#9698) +- feat(web-vitals): Vendor in INP from web-vitals library (#9690) +- fix(astro): Avoid adding the Sentry Vite plugin in dev mode (#9688) +- fix(nextjs): Don't match files called `middleware` in node_modules (#9686) +- fix(remix): Don't capture error responses that are not 5xx on Remix v2. (#9655) +- fix(tracing): Don't attach resource size if null (#9669) +- fix(utils): Regex match port to stop accidental replace (#9676) +- fix(utils): Try catch new URL when extracting query params (#9675) + +## 7.83.0 + +- chore(astro): Allow Astro 4.0 in peer dependencies (#9683) +- feat(astro): Add `assets` option to source maps upload options (#9668) +- feat(react): Support `exactOptionalPropertyTypes` on `ErrorBoundary` (#9098) +- fix: Don't depend on browser types in `types` (#9682) +- fix(astro): Configure sourcemap assets directory for Vercel adapter (#9665) +- fix(remix): Check the error data before spreading. (#9664) + +## 7.82.0 + +- feat(astro): Automatically add Sentry middleware in Astro integration (#9532) +- feat(core): Add optional `setup` hook to integrations (#9556) +- feat(core): Add top level `getClient()` method (#9638) +- feat(core): Allow to pass `mechanism` as event hint (#9590) +- feat(core): Allow to use `continueTrace` without callback (#9615) +- feat(feedback): Add onClose callback to showReportDialog (#9433) (#9550) +- feat(nextjs): Add request data to all edge-capable functionalities (#9636) +- feat(node): Add Spotlight option to Node SDK (#9629) +- feat(utils): Refactor `addInstrumentationHandler` to dedicated methods (#9542) +- fix: Make full url customizable for Spotlight (#9652) +- fix(astro): Remove Auth Token existence check (#9651) +- fix(nextjs): Fix middleware detection logic (#9637) +- fix(remix): Skip capturing aborted requests (#9659) +- fix(replay): Add `BODY_PARSE_ERROR` warning & time out fetch response load (#9622) +- fix(tracing): Filter out invalid resource sizes (#9641) +- ref: Hoist `RequestData` integration to `@sentry/core` (#9597) +- ref(feedback): Rename onDialog* to onForm*, remove onActorClick (#9625) + +Work in this release contributed by @arya-s. Thank you for your contribution! + +## 7.81.1 + +- fix(astro): Remove method from span op (#9603) +- fix(deno): Make sure files get published (#9611) +- fix(nextjs): Use `globalThis` instead of `global` in edge runtime (#9612) +- fix(node): Improve error handling and shutdown handling for ANR (#9548) +- fix(tracing-internal): Fix case when originalURL contain query params (#9531) + +Work in this release contributed by @powerfulyang, @LubomirIgonda1, @joshkel, and @alexgleason. Thank you for your +contributions! + +## 7.81.0 + +### Important Changes + +**- feat(nextjs): Add instrumentation utility for server actions (#9553)** + +This release adds a utility function `withServerActionInstrumentation` to the `@sentry/nextjs` SDK for instrumenting +your Next.js server actions with error and performance monitoring. + +You can optionally pass form data and headers to record them, and configure the wrapper to record the Server Action +responses: + +```tsx +import * as Sentry from '@sentry/nextjs'; +import { headers } from 'next/headers'; + +export default function ServerComponent() { + async function myServerAction(formData: FormData) { + 'use server'; + return await Sentry.withServerActionInstrumentation( + 'myServerAction', // The name you want to associate this Server Action with in Sentry + { + formData, // Optionally pass in the form data + headers: headers(), // Optionally pass in headers + recordResponse: true, // Optionally record the server action response + }, + async () => { + // ... Your Server Action code + + return { name: 'John Doe' }; + }, + ); + } + + return ( +
+ + +
+ ); +} +``` + +### Other Changes + +- docs(feedback): Example docs on `sendFeedback` (#9560) +- feat(feedback): Add `level` and remove breadcrumbs from feedback event (#9533) +- feat(vercel-edge): Add fetch instrumentation (#9504) +- feat(vue): Support Vue 3 lifecycle hooks in mixin options (#9578) +- fix(nextjs): Download CLI binary if it can't be found (#9584) +- ref: Deprecate `extractTraceParentData` from `@sentry/core` & downstream packages (#9158) +- ref(replay): Add further logging to network body parsing (#9566) + +Work in this release contributed by @snoozbuster. Thank you for your contribution! + +## 7.80.1 + +- fix(astro): Adjust Vite plugin config to upload server source maps (#9541) +- fix(nextjs): Add tracing extensions in all serverside wrappers (#9537) +- fix(nextjs): Fix serverside transaction names on Windows (#9526) +- fix(node): Fix tRPC middleware typing (#9540) +- fix(replay): Add additional safeguards for capturing network bodies (#9506) +- fix(tracing): Update prisma span to be `db.prisma` (#9512) + +## 7.80.0 + +- feat(astro): Add distributed tracing via `` tags (#9483) +- feat(node): Capture internal server errors in trpc middleware (#9482) +- feat(remix): Export a type to use for `MetaFunction` parameters (#9493) +- fix(astro): Mark SDK package as Astro-external (#9509) +- ref(nextjs): Don't initialize Server SDK during build (#9503) + +## 7.79.0 + +- feat(tracing): Add span `origin` to trace context (#9472) +- fix(deno): Emit .mjs files (#9485) +- fix(nextjs): Flush servercomponent events for edge (#9487) + +## 7.78.0 + +### Important Changes + +- **Replay Bundle Size improvements** + +We've dramatically decreased the bundle size of our Replay package, reducing the minified & gzipped bundle size by ~20 +KB! This was possible by extensive use of tree shaking and a host of small changes to reduce our footprint: + +- feat(replay): Update rrweb to 2.2.0 (#9414) +- ref(replay): Use fflate instead of pako for compression (#9436) + +By using [tree shaking](https://docs.sentry.io/platforms/javascript/configuration/tree-shaking/) it is possible to shave +up to 10 additional KB off the bundle. + +### Other Changes + +- feat(astro): Add Sentry middleware (#9445) +- feat(feedback): Add "outline focus" and "foreground hover" vars (#9462) +- feat(feedback): Add `openDialog` and `closeDialog` onto integration interface (#9464) +- feat(feedback): Implement new user feedback embeddable widget (#9217) +- feat(nextjs): Add automatic sourcemapping for edge part of the SDK (#9454) +- feat(nextjs): Add client routing instrumentation for app router (#9446) +- feat(node-experimental): Add hapi tracing support (#9449) +- feat(replay): Allow to configure `beforeErrorSampling` (#9470) +- feat(replay): Stop fixing truncated JSONs in SDK (#9437) +- fix(nextjs): Fix sourcemaps resolving for local dev when basePath is set (#9457) +- fix(nextjs): Only inject basepath in dev mode (#9465) +- fix(replay): Ensure we stop for rate limit headers (#9420) +- ref(feedback): Add treeshaking for logger statements (#9475) +- ref(replay): Use rrweb for slow click detection (#9408) +- build(polyfills): Remove output format specific logic (#9467) + +## 7.77.0 + +### Security Fixes + +- fix(nextjs): Match only numbers as orgid in tunnelRoute (#9416) (CVE-2023-46729) +- fix(nextjs): Strictly validate tunnel target parameters (#9415) (CVE-2023-46729) + +### Other Changes + +- feat: Move LinkedErrors integration to @sentry/core (#9404) +- feat(remix): Update sentry-cli version to ^2.21.2 (#9401) +- feat(replay): Allow to treeshake & configure compression worker URL (#9409) +- fix(angular-ivy): Adjust package entry points to support Angular 17 with SSR config (#9412) +- fix(feedback): Fixing feedback import (#9403) +- fix(utils): Avoid keeping a reference of last used event (#9387) + +## 7.76.0 + +### Important Changes + +- **feat(core): Add cron monitor wrapper helper (#9395)** + +This release adds `Sentry.withMonitor()`, a wrapping function that wraps a callback with a cron monitor that will +automatically report completions and failures: + +```ts +import * as Sentry from '@sentry/node'; + +// withMonitor() will send checkin when callback is started/finished +// works with async and sync callbacks. +const result = Sentry.withMonitor( + 'dailyEmail', + () => { + // withCheckIn return value is same return value here + return sendEmail(); + }, + // Optional upsert options + { + schedule: { + type: 'crontab', + value: '0 * * * *', + }, + // 🇨🇦🫡 + timezone: 'Canada/Eastern', + }, +); +``` + +### Other Changes + +- chore(angular-ivy): Allow Angular 17 in peer dependencies (#9386) +- feat(nextjs): Instrument SSR page components (#9346) +- feat(nextjs): Trace errors in page component SSR (#9388) +- fix(nextjs): Instrument route handlers with `jsx` and `tsx` file extensions (#9362) +- fix(nextjs): Trace with performance disabled (#9389) +- fix(replay): Ensure `replay_id` is not added to DSC if session expired (#9359) +- fix(replay): Remove unused parts of pako from build (#9369) +- fix(serverless): Don't mark all errors as unhandled (#9368) +- fix(tracing-internal): Fix case when middleware contain array of routes with special chars as @ (#9375) +- meta(nextjs): Bump peer deps for Next.js 14 (#9390) + +Work in this release contributed by @LubomirIgonda1. Thank you for your contribution! + +## 7.75.1 + +- feat(browser): Allow collecting of pageload profiles (#9317) +- fix(browser): Correct timestamp on pageload profiles (#9350) +- fix(nextjs): Use webpack plugin release value to inject release (#9348) + +## 7.75.0 + +### Important Changes + +- **feat(opentelemetry): Add new `@sentry/opentelemetry` package (#9238)** + +This release publishes a new package, `@sentry/opentelemetry`. This is a runtime agnostic replacement for +`@sentry/opentelemetry-node` and exports a couple of useful utilities which can be used to use Sentry together with +OpenTelemetry. + +You can read more about +[@sentry/opentelemetry in the Readme](https://github.com/getsentry/sentry-javascript/tree/develop/packages/opentelemetry). + +- **feat(replay): Allow to treeshake rrweb features (#9274)** + +Starting with this release, you can configure the following build-time flags in order to reduce the SDK bundle size: + +- `__RRWEB_EXCLUDE_CANVAS__` +- `__RRWEB_EXCLUDE_IFRAME__` +- `__RRWEB_EXCLUDE_SHADOW_DOM__` + +You can read more about +[tree shaking in our docs](https://docs.sentry.io/platforms/javascript/configuration/tree-shaking/). + +### Other Changes + +- build(deno): Prepare Deno SDK for release on npm (#9281) +- feat: Remove tslib (#9299) +- feat(node): Add abnormal session support for ANR (#9268) +- feat(node): Remove `lru_map` dependency (#9300) +- feat(node): Vendor `cookie` module (#9308) +- feat(replay): Share performance instrumentation with tracing (#9296) +- feat(types): Add missing Profiling types (macho debug image, profile measurements, stack frame properties) (#9277) +- feat(types): Add statsd envelope types (#9304) +- fix(astro): Add integration default export to types entry point (#9337) +- fix(astro): Convert SDK init file import paths to POSIX paths (#9336) +- fix(astro): Make `Replay` and `BrowserTracing` integrations tree-shakeable (#9287) +- fix(integrations): Fix transaction integration (#9334) +- fix(nextjs): Restore `autoInstrumentMiddleware` functionality (#9323) +- fix(nextjs): Guard for case where `getInitialProps` may return undefined (#9342) +- fix(node-experimental): Make node-fetch support optional (#9321) +- fix(node): Check buffer length when attempting to parse ANR frame (#9314) +- fix(replay): Fix xhr start timestamps (#9341) +- fix(tracing-internal): Remove query params from urls with a trailing slash (#9328) +- fix(types): Remove typo with CheckInEnvelope (#9303) + +## 7.74.1 + +- chore(astro): Add `astro-integration` keyword (#9265) +- fix(core): Narrow filters for health check transactions (#9257) +- fix(nextjs): Fix HMR by inserting new entrypoints at the end (#9267) +- fix(nextjs): Fix resolution of request async storage module (#9259) +- fix(node-experimental): Guard against missing `fetch` (#9275) +- fix(remix): Update `defer` injection logic. (#9242) +- fix(tracing-internal): Parameterize express middleware parameters (#8668) +- fix(utils): Move Node specific ANR impl. out of utils (#9258) + +Work in this release contributed by @LubomirIgonda1. Thank you for your contribution! + +## 7.74.0 + +### Important Changes + +- **feat(astro): Add `sentryAstro` integration (#9218)** + +This Release introduces the first alpha version of our new SDK for Astro. At this time, the SDK is considered +experimental and things might break and change in future versions. + +The core of the SDK is an Astro integration which you easily add to your Astro config: + +```js +// astro.config.js +import { defineConfig } from 'astro/config'; +import sentry from '@sentry/astro'; + +export default defineConfig({ + integrations: [ + sentry({ + dsn: '__DSN__', + sourceMapsUploadOptions: { + project: 'astro', + authToken: process.env.SENTRY_AUTH_TOKEN, + }, + }), + ], +}); +``` + +Check out the [README](./packages/astro/README.md) for usage instructions and what to expect from this alpha release. + +### Other Changes + +- feat(core): Add `addIntegration` utility (#9186) +- feat(core): Add `continueTrace` method (#9164) +- feat(node-experimental): Add NodeFetch integration (#9226) +- feat(node-experimental): Use native OTEL Spans (#9161, #9214) +- feat(node-experimental): Sample in OTEL Sampler (#9203) +- feat(serverlesss): Allow disabling transaction traces (#9154) +- feat(tracing): Allow direct pg module to enable esbuild support (#9227) +- feat(utils): Move common node ANR code to utils (#9191) +- feat(vue): Expose `VueIntegration` to initialize vue app later (#9180) +- fix: Don't set `referrerPolicy` on serverside fetch transports (#9200) +- fix: Ensure we never mutate options passed to `init` (#9162) +- fix(ember): Avoid pulling in utils at build time (#9221) +- fix(ember): Drop undefined config values (#9175) +- fix(node): Ensure mysql integration works without callback (#9222) +- fix(node): Only require `inspector` when needed (#9149) +- fix(node): Remove ANR `debug` option and instead add logger.isEnabled() (#9230) +- fix(node): Strip `.mjs` and `.cjs` extensions from module name (#9231) +- fix(replay): bump rrweb to 2.0.1 (#9240) +- fix(replay): Fix potential broken CSS in styled-components (#9234) +- fix(sveltekit): Flush in server wrappers before exiting (#9153) +- fix(types): Update signature of `processEvent` integration hook (#9151) +- fix(utils): Dereference DOM events after they have servered their purpose (#9224) +- ref(integrations): Refactor pluggable integrations to use `processEvent` (#9021) +- ref(serverless): Properly deprecate `rethrowAfterCapture` option (#9159) +- ref(utils): Deprecate `walk` method (#9157) + +Work in this release contributed by @aldenquimby. Thank you for your contributions! + +## 7.73.0 + +### Important Changes + +- **feat(replay): Upgrade to rrweb2** + +This is fully backwards compatible with prior versions of the Replay SDK. The only breaking change that we will making +is to not be masking `aria-label` by default. The reason for this change is to align with our core SDK which also does +not mask `aria-label`. This change also enables better support of searching by clicks. + +Another change that needs to be highlighted is the 13% bundle size increase. This bundle size increase is necessary to +bring improved recording performance and improved replay fidelity, especially in regards to web components and iframes. +We will be investigating the reduction of the bundle size in +[this PR](https://github.com/getsentry/sentry-javascript/issues/8815). + +Here are benchmarks comparing the version 1 of rrweb to version 2 + +| metric | v1 | v2 | +| --------- | ---------- | ---------- | +| lcp | 1486.06 ms | 1529.11 ms | +| cls | 0.40 ms | 0.40 ms | +| fid | 1.53 ms | 1.50 ms | +| tbt | 3207.22 ms | 3036.80 ms | +| memoryAvg | 131.83 MB | 124.84 MB | +| memoryMax | 324.8 MB | 339.03 MB | +| netTx | 282.67 KB | 272.51 KB | +| netRx | 8.02 MB | 8.07 MB | + +### Other Changes + +- feat: Always assemble Envelopes (#9101) +- feat(node): Rate limit local variables for caught exceptions and enable `captureAllExceptions` by default (#9102) +- fix(core): Ensure `tunnel` is considered for `isSentryUrl` checks (#9130) +- fix(nextjs): Fix `RequestAsyncStorage` fallback path (#9126) +- fix(node-otel): Suppress tracing for generated sentry spans (#9142) +- fix(node): fill in span data from http request options object (#9112) +- fix(node): Fixes and improvements to ANR detection (#9128) +- fix(sveltekit): Avoid data invalidation in wrapped client-side `load` functions (#9071) +- ref(core): Refactor `InboundFilters` integration to use `processEvent` (#9020) +- ref(wasm): Refactor Wasm integration to use `processEvent` (#9019) + +Work in this release contributed by @vlad-zhukov. Thank you for your contribution! + +## 7.72.0 + +### Important Changes + +- **feat(node): App Not Responding with stack traces (#9079)** + +This release introduces support for Application Not Responding (ANR) errors for Node.js applications. These errors are +triggered when the Node.js main thread event loop of an application is blocked for more than five seconds. The Node SDK +reports ANR errors as Sentry events and can optionally attach a stacktrace of the blocking code to the ANR event. + +To enable ANR detection, import and use the `enableANRDetection` function from the `@sentry/node` package before you run +the rest of your application code. Any event loop blocking before calling `enableANRDetection` will not be detected by +the SDK. + +Example (ESM): + +```ts +import * as Sentry from '@sentry/node'; + +Sentry.init({ + dsn: '___PUBLIC_DSN___', + tracesSampleRate: 1.0, +}); + +await Sentry.enableANRDetection({ captureStackTrace: true }); +// Function that runs your app +runApp(); +``` + +Example (CJS): + +```ts +const Sentry = require('@sentry/node'); + +Sentry.init({ + dsn: '___PUBLIC_DSN___', + tracesSampleRate: 1.0, +}); + +Sentry.enableANRDetection({ captureStackTrace: true }).then(() => { + // Function that runs your app + runApp(); +}); +``` + +### Other Changes + +- fix(nextjs): Filter `RequestAsyncStorage` locations by locations that webpack will resolve (#9114) +- fix(replay): Ensure `replay_id` is not captured when session is expired (#9109) + +## 7.71.0 + +- feat(bun): Instrument Bun.serve (#9080) +- fix(core): Ensure global event processors are always applied to event (#9064) +- fix(core): Run client eventProcessors before global ones (#9032) +- fix(nextjs): Use webpack module paths to attempt to resolve internal request async storage module (#9100) +- fix(react): Add actual error name to boundary error name (#9065) +- fix(react): Compare location against `basename`-prefixed route. (#9076) +- ref(browser): Refactor browser integrations to use `processEvent` (#9022) + +Work in this release contributed by @jorrit. Thank you for your contribution! + +## 7.70.0 + +### Important Changes + +- **feat: Add Bun SDK (#9029)** + +This release contains the beta version of `@sentry/bun`, our SDK for the [Bun JavaScript runtime](https://bun.sh/)! For +details on how to use it, please see the [README](./packages/bun/README.md). Any feedback/bug reports are greatly +appreciated, please [reach out on GitHub](https://github.com/getsentry/sentry-javascript/discussions/7979). + +Note that as of now the Bun runtime does not support global error handlers. This is being actively worked on, see +[the tracking issue in Bun's GitHub repo](https://github.com/oven-sh/bun/issues/5091). + +- **feat(remix): Add Remix 2.x release support. (#8940)** + +The Sentry Remix SDK now officially supports Remix v2! See +[our Remix docs for more details](https://docs.sentry.io/platforms/javascript/guides/remix/). + +### Other Changes + +- chore(node): Upgrade cookie to ^0.5.0 (#9013) +- feat(core): Introduce `processEvent` hook on `Integration` (#9017) +- feat(node): Improve non-error messages (#9026) +- feat(vercel-edge): Add Vercel Edge Runtime package (#9041) +- fix(remix): Use `React.ComponentType` instead of `React.FC` as `withSentry`'s generic type. (#9043) +- fix(replay): Ensure replay events go through `preprocessEvent` hook (#9034) +- fix(replay): Fix typo in Replay types (#9028) +- fix(sveltekit): Adjust `handleErrorWithSentry` type (#9054) +- fix(utils): Try-catch monkeypatching to handle frozen objects/functions (#9031) + +Work in this release contributed by @Dima-Dim, @krist7599555 and @lifeiscontent. Thank you for your contributions! + +Special thanks for @isaacharrisholt for helping us implement a Vercel Edge Runtime SDK which we use under the hood for +our Next.js SDK. + +## 7.69.0 + +### Important Changes + +- **New Performance APIs** + - feat: Update span performance API names (#8971) + - feat(core): Introduce startSpanManual (#8913) + +This release introduces a new set of top level APIs for the Performance Monitoring SDKs. These aim to simplify creating +spans and reduce the boilerplate needed for performance instrumentation. The three new methods introduced are +`Sentry.startSpan`, `Sentry.startInactiveSpan`, and `Sentry.startSpanManual`. These methods are available in the browser +and node SDKs. + +`Sentry.startSpan` wraps a callback in a span. The span is automatically finished when the callback returns. This is the +recommended way to create spans. + +```js +// Start a span that tracks the duration of expensiveFunction +const result = Sentry.startSpan({ name: 'important function' }, () => { + return expensiveFunction(); +}); + +// You can also mutate the span wrapping the callback to set data or status +Sentry.startSpan({ name: 'important function' }, span => { + // span is undefined if performance monitoring is turned off or if + // the span was not sampled. This is done to reduce overhead. + span?.setData('version', '1.0.0'); + return expensiveFunction(); +}); +``` + +If you don't want the span to finish when the callback returns, use `Sentry.startSpanManual` to control when the span is +finished. This is useful for event emitters or similar. + +```js +// Start a span that tracks the duration of middleware +function middleware(_req, res, next) { + return Sentry.startSpanManual({ name: 'middleware' }, (span, finish) => { + res.once('finish', () => { + setHttpStatus(span, res.status); + finish(); + }); + return next(); + }); +} +``` + +`Sentry.startSpan` and `Sentry.startSpanManual` create a span and make it active for the duration of the callback. Any +spans created while this active span is running will be added as a child span to it. If you want to create a span +without making it active, use `Sentry.startInactiveSpan`. This is useful for creating parallel spans that are not +related to each other. + +```js +const span1 = Sentry.startInactiveSpan({ name: 'span1' }); + +someWork(); + +const span2 = Sentry.startInactiveSpan({ name: 'span2' }); + +moreWork(); + +const span3 = Sentry.startInactiveSpan({ name: 'span3' }); + +evenMoreWork(); + +span1?.finish(); +span2?.finish(); +span3?.finish(); +``` + +### Other Changes + +- feat(core): Export `BeforeFinishCallback` type (#8999) +- build(eslint): Enforce that ts-expect-error is used (#8987) +- feat(integration): Ensure `LinkedErrors` integration runs before all event processors (#8956) +- feat(node-experimental): Keep breadcrumbs on transaction (#8967) +- feat(redux): Add 'attachReduxState' option (#8953) +- feat(remix): Accept `org`, `project` and `url` as args to upload script (#8985) +- fix(utils): Prevent iterating over VueViewModel (#8981) +- fix(utils): uuidv4 fix for cloudflare (#8968) +- fix(core): Always use event message and exception values for `ignoreErrors` (#8986) +- fix(nextjs): Add new potential location for Next.js request AsyncLocalStorage (#9006) +- fix(node-experimental): Ensure we only create HTTP spans when outgoing (#8966) +- fix(node-experimental): Ignore OPTIONS & HEAD requests (#9001) +- fix(node-experimental): Ignore outgoing Sentry requests (#8994) +- fix(node-experimental): Require parent span for `pg` spans (#8993) +- fix(node-experimental): Use Sentry logger as Otel logger (#8960) +- fix(node-otel): Refactor OTEL span reference cleanup (#9000) +- fix(react): Switch to props in `useRoutes` (#8998) +- fix(remix): Add `glob` to Remix SDK dependencies. (#8963) +- fix(replay): Ensure `handleRecordingEmit` aborts when event is not added (#8938) +- fix(replay): Fully stop & restart session when it expires (#8834) + +Work in this release contributed by @Duncanxyz and @malay44. Thank you for your contributions! + +## 7.68.0 + +- feat(browser): Add `BroadcastChannel` and `SharedWorker` to TryCatch EventTargets (#8943) +- feat(core): Add `name` to `Span` (#8949) +- feat(core): Add `ServerRuntimeClient` (#8930) +- fix(node-experimental): Ensure `span.finish()` works as expected (#8947) +- fix(remix): Add new sourcemap-upload script files to prepack assets. (#8948) +- fix(publish): Publish downleveled TS3.8 types and fix types path (#8954) + +## 7.67.0 + +### Important Changes + +- **feat: Mark errors caught by the SDK as unhandled** + - feat(browser): Mark errors caught from `TryCatch` integration as unhandled (#8890) + - feat(integrations): Mark errors caught from `HttpClient` and `CaptureConsole` integrations as unhandled (#8891) + - feat(nextjs): Mark errors caught from NextJS wrappers as unhandled (#8893) + - feat(react): Mark errors captured from ErrorBoundary as unhandled (#8914) + - feat(remix): Add debugid injection and map deletion to sourcemaps script (#8814) + - feat(remix): Mark errors caught from Remix instrumentation as unhandled (#8894) + - feat(serverless): Mark errors caught in Serverless handlers as unhandled (#8907) + - feat(vue): Mark errors caught by Vue wrappers as unhandled (#8905) + +This release fixes inconsistent behaviour of when our SDKs classify captured errors as unhandled. Previously, some of +our instrumentations correctly set unhandled, while others set handled. Going forward, all errors caught automatically +from our SDKs will be marked as unhandled. If you manually capture errors (e.g. by calling `Sentry.captureException`), +your errors will continue to be reported as handled. + +This change might lead to a decrease in reported crash-free sessions and consequently in your release health score. If +you have concerns about this, feel free to open an issue. + +### Other Changes + +- feat(node-experimental): Implement new performance APIs (#8911) +- feat(node-experimental): Sync OTEL context with Sentry AsyncContext (#8797) +- feat(replay): Allow to configure `maxReplayDuration` (#8769) +- fix(browser): Add replay and profiling options to `BrowserClientOptions` (#8921) +- fix(browser): Check for existence of instrumentation targets (#8939) +- fix(nextjs): Don't re-export default in route handlers (#8924) +- fix(node): Improve mysql integration (#8923) +- fix(remix): Guard against missing default export for server instrument (#8909) +- ref(browser): Deprecate top-level `wrap` function (#8927) +- ref(node-otel): Avoid exporting internals & refactor attribute adding (#8920) + +Work in this release contributed by @SorsOps. Thank you for your contribution! + +## 7.66.0 + +- fix: Defer tracing decision to downstream SDKs when using SDK without performance (#8839) +- fix(nextjs): Fix `package.json` exports (#8895) +- fix(sveltekit): Ensure target file exists before applying auto instrumentation (#8881) +- ref: Use consistent console instrumentation (#8879) +- ref(browser): Refactor sentry breadcrumb to use hook (#8892) +- ref(tracing): Add `origin` to spans (#8765) + +## 7.65.0 + +- build: Remove build-specific polyfills (#8809) +- build(deps): bump protobufjs from 6.11.3 to 6.11.4 (#8822) +- deps(sveltekit): Bump `@sentry/vite-plugin` (#8877) +- feat(core): Introduce `Sentry.startActiveSpan` and `Sentry.startSpan` (#8803) +- fix: Memoize `AsyncLocalStorage` instance (#8831) +- fix(nextjs): Check for validity of API route handler signature (#8811) +- fix(nextjs): Fix `requestAsyncStorageShim` path resolution on windows (#8875) +- fix(node): Log entire error object in `OnUncaughtException` (#8876) +- fix(node): More relevant warning message when tracing extensions are missing (#8820) +- fix(replay): Streamline session creation/refresh (#8813) +- fix(sveltekit): Avoid invalidating data on route changes in `wrapServerLoadWithSentry` (#8801) +- fix(tracing): Better guarding for performance observer (#8872) +- ref(sveltekit): Remove custom client fetch instrumentation and use default instrumentation (#8802) +- ref(tracing-internal): Deprecate `tracePropagationTargets` in `BrowserTracing` (#8874) + +## 7.64.0 + +- feat(core): Add setMeasurement export (#8791) +- fix(nextjs): Check for existence of default export when wrapping pages (#8794) +- fix(nextjs): Ensure imports are valid relative paths (#8799) +- fix(nextjs): Only re-export default export if it exists (#8800) + +## 7.63.0 + +- build(deps): bump @opentelemetry/instrumentation from 0.41.0 to 0.41.2 +- feat(eventbuilder): Export `exceptionFromError` for use in hybrid SDKs (#8766) +- feat(node-experimental): Re-export from node (#8786) +- feat(tracing): Add db connection attributes for mysql spans (#8775) +- feat(tracing): Add db connection attributes for postgres spans (#8778) +- feat(tracing): Improve data collection for mongodb spans (#8774) +- fix(nextjs): Execute sentry config independently of `autoInstrumentServerFunctions` and `autoInstrumentAppDirectory` + (#8781) +- fix(replay): Ensure we do not flush if flush took too long (#8784) +- fix(replay): Ensure we do not try to flush when we force stop replay (#8783) +- fix(replay): Fix `hasCheckout` handling (#8782) +- fix(replay): Handle multiple clicks in a short time (#8773) +- ref(replay): Skip events being added too long after initial segment (#8768) + +## 7.62.0 + +### Important Changes + +- **feat(integrations): Add `ContextLines` integration for html-embedded JS stack frames (#8699)** + +This release adds the `ContextLines` integration as an optional integration for the Browser SDKs to +`@sentry/integrations`. + +This integration adds source code from inline JavaScript of the current page's HTML (e.g. JS in `