>) => {
- return [
- {
- env: data.ENV,
- },
- {
- name: 'sentry-trace',
- content: data.sentryTrace,
- },
- {
- name: 'baggage',
- content: data.sentryBaggage,
- },
- ];
-};
-
-export function ErrorBoundary() {
- const error = useRouteError();
- const eventId = captureRemixErrorBoundaryError(error);
-
- return (
-
- ErrorBoundary Error
- {eventId}
-
- );
-}
-
-function App() {
- const { ENV } = useLoaderData();
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default withSentry(App);
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/_index.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/_index.tsx
deleted file mode 100644
index 69f39f7bc801..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/_index.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Link, useSearchParams } from '@remix-run/react';
-import * as Sentry from '@sentry/remix';
-
-export default function Index() {
- const [searchParams] = useSearchParams();
-
- if (searchParams.get('tag')) {
- Sentry.setTags({
- sentry_test: searchParams.get('tag'),
- });
- }
-
- return (
-
- {
- throw new Error('I am an error!');
- }}
- />
-
- navigate
-
-
- );
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/action-formdata.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/action-formdata.tsx
deleted file mode 100644
index 884beb2f51e9..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/action-formdata.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { json } from '@remix-run/node';
-import { Form } from '@remix-run/react';
-
-export async function action() {
- return json({ message: 'success' });
-}
-
-export default function ActionFormData() {
- return (
-
- );
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/client-error.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/client-error.tsx
deleted file mode 100644
index f4d6ec9c4f0a..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/client-error.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { useSearchParams } from '@remix-run/react';
-import * as Sentry from '@sentry/remix';
-
-import { useState } from 'react';
-
-export default function ErrorBoundaryCapture() {
- const [searchParams] = useSearchParams();
-
- if (searchParams.get('tag')) {
- Sentry.setTags({
- sentry_test: searchParams.get('tag'),
- });
- }
-
- const [count, setCount] = useState(0);
-
- if (count > 0) {
- throw new Error('Sentry React Component Error');
- } else {
- setTimeout(() => setCount(count + 1), 0);
- }
-
- return {count}
;
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/loader-error.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/loader-error.tsx
deleted file mode 100644
index 75d454571fa5..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/loader-error.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { LoaderFunction } from '@remix-run/node';
-import { useLoaderData } from '@remix-run/react';
-
-export default function LoaderError() {
- useLoaderData();
-
- return (
-
-
Loader Error
-
- );
-}
-
-export const loader: LoaderFunction = () => {
- throw new Error('Loader Error');
-};
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/navigate.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/navigate.tsx
deleted file mode 100644
index a84df11e7bb7..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/navigate.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { LoaderFunction } from '@remix-run/node';
-import { useLoaderData } from '@remix-run/react';
-
-export const loader: LoaderFunction = async ({ params: { id } }) => {
- if (id === '-1') {
- throw new Error('Unexpected Server Error');
- }
-
- return null;
-};
-
-export default function LoaderError() {
- const data = useLoaderData();
-
- return (
-
-
{data?.test ? data.test : 'Not Found'}
-
- );
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/user.$id.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/user.$id.tsx
deleted file mode 100644
index 13b2e0a34d1e..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/user.$id.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function User() {
- return I am a blank page
;
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/env.d.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/env.d.ts
deleted file mode 100644
index 78ed2345c6e4..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/env.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-///
-///
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/globals.d.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/globals.d.ts
deleted file mode 100644
index 4130ac6a8a09..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/globals.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-interface Window {
- recordedTransactions?: string[];
- capturedExceptionId?: string;
- ENV: {
- SENTRY_DSN: string;
- };
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/instrument.cjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/instrument.cjs
deleted file mode 100644
index feea6fb5388e..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/instrument.cjs
+++ /dev/null
@@ -1,14 +0,0 @@
-const Sentry = require('@sentry/remix');
-const process = require('process');
-
-Sentry.init({
- tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
- environment: 'qa', // dynamic sampling bias to keep transactions
- dsn: process.env.E2E_TEST_DSN,
- tunnel: 'http://localhost:3031/', // proxy server
- sendDefaultPii: true, // Testing the FormData
- captureActionFormDataKeys: {
- file: true,
- text: true,
- },
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/package.json
deleted file mode 100644
index 5c362ffb97a1..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/package.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "private": true,
- "sideEffects": false,
- "type": "module",
- "scripts": {
- "build": "remix vite:build",
- "dev": "node ./server.mjs",
- "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
- "start": "cross-env NODE_ENV=production node ./server.mjs",
- "typecheck": "tsc",
- "clean": "npx rimraf node_modules pnpm-lock.yaml",
- "test:build": "pnpm install && pnpm build",
- "test:assert": "pnpm playwright test"
- },
- "dependencies": {
- "@remix-run/css-bundle": "^2.7.2",
- "@remix-run/express": "^2.7.2",
- "@remix-run/node": "^2.7.2",
- "@remix-run/react": "^2.7.2",
- "@sentry/remix": "latest || *",
- "compression": "^1.7.4",
- "cross-env": "^7.0.3",
- "express": "^4.18.2",
- "isbot": "^4.1.0",
- "morgan": "^1.10.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "source-map-support": "^0.5.21"
- },
- "devDependencies": {
- "@playwright/test": "^1.44.1",
- "@sentry-internal/test-utils": "link:../../../test-utils",
- "@remix-run/dev": "^2.7.2",
- "@sentry/core": "latest || *",
- "@types/compression": "^1.7.2",
- "@types/express": "^4.17.17",
- "@types/morgan": "^1.9.4",
- "@types/react": "^18.2.20",
- "@types/react-dom": "^18.2.7",
- "@types/source-map-support": "^0.5.6",
- "@typescript-eslint/eslint-plugin": "^6.7.4",
- "chokidar": "^3.5.3",
- "eslint": "^8.38.0",
- "eslint-import-resolver-typescript": "^3.6.1",
- "eslint-plugin-import": "^2.28.1",
- "eslint-plugin-jsx-a11y": "^6.7.1",
- "eslint-plugin-react": "^7.33.2",
- "eslint-plugin-react-hooks": "^4.6.0",
- "tsx": "4.7.2",
- "typescript": "^5.1.6",
- "vite-tsconfig-paths": "^4.2.1"
- },
- "volta": {
- "extends": "../../package.json"
- }
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/playwright.config.mjs
deleted file mode 100644
index 31f2b913b58b..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/playwright.config.mjs
+++ /dev/null
@@ -1,7 +0,0 @@
-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/create-remix-app-express-legacy/server.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/server.mjs
deleted file mode 100644
index bde5876f4b29..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/server.mjs
+++ /dev/null
@@ -1,52 +0,0 @@
-import './instrument.cjs';
-
-import { createRequestHandler } from '@remix-run/express';
-import { installGlobals } from '@remix-run/node';
-import compression from 'compression';
-import express from 'express';
-import morgan from 'morgan';
-
-installGlobals();
-
-const viteDevServer =
- process.env.NODE_ENV === 'production'
- ? undefined
- : await import('vite').then(vite =>
- vite.createServer({
- server: { middlewareMode: true },
- }),
- );
-
-const app = express();
-
-app.use(compression());
-
-// http://expressjs.com/en/advanced/best-practice-security.html#at-a-minimum-disable-x-powered-by-header
-app.disable('x-powered-by');
-
-// handle asset requests
-if (viteDevServer) {
- app.use(viteDevServer.middlewares);
-} else {
- // Vite fingerprints its assets so we can cache forever.
- app.use('/assets', express.static('build/client/assets', { immutable: true, maxAge: '1y' }));
-}
-
-// Everything else (like favicon.ico) is cached for an hour. You may want to be
-// more aggressive with this caching.
-app.use(express.static('build/client', { maxAge: '1h' }));
-
-app.use(morgan('tiny'));
-
-// handle SSR requests
-app.all(
- '*',
- createRequestHandler({
- build: viteDevServer
- ? () => viteDevServer.ssrLoadModule('virtual:remix/server-build')
- : await import('./build/server/index.js'),
- }),
-);
-
-const port = process.env.PORT || 3030;
-app.listen(port, () => console.log(`Express server listening at http://localhost:${port}`));
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/start-event-proxy.mjs
deleted file mode 100644
index ccbe23f1804d..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/start-event-proxy.mjs
+++ /dev/null
@@ -1,6 +0,0 @@
-import { startEventProxyServer } from '@sentry-internal/test-utils';
-
-startEventProxyServer({
- port: 3031,
- proxyServerName: 'create-remix-app-express-legacy',
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/client-errors.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/client-errors.test.ts
deleted file mode 100644
index 2dc323ec4c47..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/client-errors.test.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForError } from '@sentry-internal/test-utils';
-
-test('Sends a client-side exception to Sentry', async ({ page }) => {
- const errorPromise = waitForError('create-remix-app-express-legacy', errorEvent => {
- return errorEvent.exception?.values?.[0].value === 'I am an error!';
- });
-
- await page.goto('/');
-
- const exceptionButton = page.locator('id=exception-button');
- await exceptionButton.click();
-
- const errorEvent = await errorPromise;
-
- expect(errorEvent).toBeDefined();
-});
-
-test('Sends a client-side ErrorBoundary exception to Sentry', async ({ page }) => {
- const errorPromise = waitForError('create-remix-app-express-legacy', errorEvent => {
- return errorEvent.exception?.values?.[0].value === 'Sentry React Component Error';
- });
-
- await page.goto('/client-error');
-
- const errorEvent = await errorPromise;
-
- expect(errorEvent).toBeDefined();
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/client-transactions.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/client-transactions.test.ts
deleted file mode 100644
index 1dfec26a0a4d..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/client-transactions.test.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
-
-test('Sends a pageload transaction to Sentry', async ({ page }) => {
- const transactionPromise = waitForTransaction('create-remix-app-express-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'pageload' && transactionEvent.transaction === 'routes/_index';
- });
-
- await page.goto('/');
-
- const transactionEvent = await transactionPromise;
-
- expect(transactionEvent).toBeDefined();
-});
-
-test('Sends a navigation transaction to Sentry', async ({ page }) => {
- const transactionPromise = waitForTransaction('create-remix-app-express-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'navigation' && transactionEvent.transaction === 'routes/user.$id';
- });
-
- await page.goto('/');
-
- const linkElement = page.locator('id=navigation');
- await linkElement.click();
-
- const transactionEvent = await transactionPromise;
-
- expect(transactionEvent).toBeDefined();
-});
-
-test('Renders `sentry-trace` and `baggage` meta tags for the root route', async ({ page }) => {
- await page.goto('/');
-
- const sentryTraceMetaTag = await page.waitForSelector('meta[name="sentry-trace"]', {
- state: 'attached',
- });
- const baggageMetaTag = await page.waitForSelector('meta[name="baggage"]', {
- state: 'attached',
- });
-
- expect(sentryTraceMetaTag).toBeTruthy();
- expect(baggageMetaTag).toBeTruthy();
-});
-
-test('Renders `sentry-trace` and `baggage` meta tags for a sub-route', async ({ page }) => {
- await page.goto('/user/123');
-
- const sentryTraceMetaTag = await page.waitForSelector('meta[name="sentry-trace"]', {
- state: 'attached',
- });
- const baggageMetaTag = await page.waitForSelector('meta[name="baggage"]', {
- state: 'attached',
- });
-
- expect(sentryTraceMetaTag).toBeTruthy();
- expect(baggageMetaTag).toBeTruthy();
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/server-errors.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/server-errors.test.ts
deleted file mode 100644
index 8d76e15db32c..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/server-errors.test.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForError } from '@sentry-internal/test-utils';
-
-test('Sends a loader error to Sentry', async ({ page }) => {
- const loaderErrorPromise = waitForError('create-remix-app-express-legacy', errorEvent => {
- return errorEvent.exception.values[0].value === 'Loader Error';
- });
-
- await page.goto('/loader-error');
-
- const loaderError = await loaderErrorPromise;
-
- expect(loaderError).toBeDefined();
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/server-transactions.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/server-transactions.test.ts
deleted file mode 100644
index 24b6024273d3..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/server-transactions.test.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { uuid4 } from '@sentry/core';
-
-import { waitForTransaction } from '@sentry-internal/test-utils';
-
-test.describe.configure({ mode: 'serial' });
-
-test('Sends parameterized transaction name to Sentry', async ({ page }) => {
- const transactionPromise = waitForTransaction('create-remix-app-express-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'http.server';
- });
-
- await page.goto('/user/123');
-
- const transaction = await transactionPromise;
-
- expect(transaction).toBeDefined();
- expect(transaction.transaction).toBe('routes/user.$id');
-});
-
-test('Sends form data with action span to Sentry', async ({ page }) => {
- const formdataActionTransaction = waitForTransaction('create-remix-app-express-legacy', transactionEvent => {
- return transactionEvent?.spans?.some(span => span.op === 'function.remix.action');
- });
-
- await page.goto('/action-formdata');
-
- await page.fill('input[name=text]', 'test');
- await page.setInputFiles('input[type=file]', {
- name: 'file.txt',
- mimeType: 'text/plain',
- buffer: Buffer.from('this is test'),
- });
-
- await page.locator('button[type=submit]').click();
-
- const actionSpan = (await formdataActionTransaction).spans.find(span => span.op === 'function.remix.action');
-
- expect(actionSpan).toBeDefined();
- expect(actionSpan.op).toBe('function.remix.action');
- expect(actionSpan.data).toMatchObject({
- 'remix.action_form_data.text': 'test',
- 'remix.action_form_data.file': 'file.txt',
- });
-});
-
-test('Sends a loader span to Sentry', async ({ page }) => {
- const loaderTransactionPromise = waitForTransaction('create-remix-app-express-legacy', transactionEvent => {
- return transactionEvent?.spans?.some(span => span.op === 'function.remix.loader');
- });
-
- await page.goto('/');
-
- const loaderSpan = (await loaderTransactionPromise).spans.find(span => span.op === 'function.remix.loader');
-
- expect(loaderSpan).toBeDefined();
- expect(loaderSpan.op).toBe('function.remix.loader');
-});
-test('Propagates trace when ErrorBoundary is triggered', async ({ page }) => {
- // We use this to identify the transactions
- const testTag = uuid4();
-
- const httpServerTransactionPromise = waitForTransaction('create-remix-app-express-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'http.server' && transactionEvent.tags?.['sentry_test'] === testTag;
- });
-
- const pageLoadTransactionPromise = waitForTransaction('create-remix-app-express-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'pageload' && transactionEvent.tags?.['sentry_test'] === testTag;
- });
-
- page.goto(`/client-error?tag=${testTag}`);
-
- const pageloadTransaction = await pageLoadTransactionPromise;
- const httpServerTransaction = await httpServerTransactionPromise;
-
- expect(pageloadTransaction).toBeDefined();
- expect(httpServerTransaction).toBeDefined();
-
- const httpServerTraceId = httpServerTransaction.contexts?.trace?.trace_id;
- const httpServerSpanId = httpServerTransaction.contexts?.trace?.span_id;
-
- const pageLoadTraceId = pageloadTransaction.contexts?.trace?.trace_id;
- const pageLoadSpanId = pageloadTransaction.contexts?.trace?.span_id;
- const pageLoadParentSpanId = pageloadTransaction.contexts?.trace?.parent_span_id;
-
- expect(httpServerTransaction.transaction).toBe('routes/client-error');
- expect(pageloadTransaction.transaction).toBe('routes/client-error');
-
- expect(httpServerTraceId).toBeDefined();
- expect(httpServerSpanId).toBeDefined();
-
- expect(pageLoadTraceId).toEqual(httpServerTraceId);
- expect(pageLoadParentSpanId).toEqual(httpServerSpanId);
- expect(pageLoadSpanId).not.toEqual(httpServerSpanId);
-});
-
-test('Sends two linked transactions (server & client) to Sentry', async ({ page }) => {
- // We use this to identify the transactions
- const testTag = uuid4();
-
- const httpServerTransactionPromise = waitForTransaction('create-remix-app-express-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'http.server' && transactionEvent.tags?.['sentry_test'] === testTag;
- });
-
- const pageLoadTransactionPromise = waitForTransaction('create-remix-app-express-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'pageload' && transactionEvent.tags?.['sentry_test'] === testTag;
- });
-
- page.goto(`/?tag=${testTag}`);
-
- const pageloadTransaction = await pageLoadTransactionPromise;
- const httpServerTransaction = await httpServerTransactionPromise;
-
- expect(pageloadTransaction).toBeDefined();
- expect(httpServerTransaction).toBeDefined();
-
- const httpServerTraceId = httpServerTransaction.contexts?.trace?.trace_id;
- const httpServerSpanId = httpServerTransaction.contexts?.trace?.span_id;
-
- const pageLoadTraceId = pageloadTransaction.contexts?.trace?.trace_id;
- const pageLoadSpanId = pageloadTransaction.contexts?.trace?.span_id;
- const pageLoadParentSpanId = pageloadTransaction.contexts?.trace?.parent_span_id;
-
- expect(httpServerTransaction.transaction).toBe('routes/_index');
- expect(pageloadTransaction.transaction).toBe('routes/_index');
-
- expect(httpServerTraceId).toBeDefined();
- expect(httpServerSpanId).toBeDefined();
-
- expect(pageLoadTraceId).toEqual(httpServerTraceId);
- expect(pageLoadParentSpanId).toEqual(httpServerSpanId);
- expect(pageLoadSpanId).not.toEqual(httpServerSpanId);
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tsconfig.json b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tsconfig.json
deleted file mode 100644
index b58e7d722f35..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tsconfig.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "include": ["env.d.ts", "**/*.ts", "**/*.tsx"],
- "compilerOptions": {
- "lib": ["DOM", "DOM.Iterable", "ES2022"],
- "isolatedModules": true,
- "esModuleInterop": true,
- "jsx": "react-jsx",
- "moduleResolution": "Bundler",
- "resolveJsonModule": true,
- "target": "ES2022",
- "strict": true,
- "allowJs": true,
- "skipLibCheck": true,
- "forceConsistentCasingInFileNames": true,
- "baseUrl": ".",
- "paths": {
- "~/*": ["./app/*"]
- },
- // Remix takes care of building everything in `remix build`.
- "noEmit": true,
- },
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/vite.config.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/vite.config.ts
deleted file mode 100644
index 13de9243b22a..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/vite.config.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { vitePlugin as remix } from '@remix-run/dev';
-import { defineConfig } from 'vite';
-import tsconfigPaths from 'vite-tsconfig-paths';
-
-import { installGlobals } from '@remix-run/node';
-
-installGlobals();
-
-export default defineConfig({
- plugins: [
- remix(),
- tsconfigPaths({
- // The dev server config errors are not relevant to this test app
- // https://github.com/aleclarson/vite-tsconfig-paths?tab=readme-ov-file#options
- ignoreConfigErrors: true,
- }),
- ],
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/instrument.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/instrument.mjs
index 5fb6bd039fdb..b52053445456 100644
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/instrument.mjs
+++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/instrument.mjs
@@ -6,6 +6,5 @@ Sentry.init({
environment: 'qa', // dynamic sampling bias to keep transactions
dsn: process.env.E2E_TEST_DSN,
tunnel: 'http://localhost:3031/', // proxy server
- autoInstrumentRemix: true, // auto instrument Remix
integrations: [Sentry.nativeNodeFetchIntegration()],
});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express/instrument.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express/instrument.mjs
index f2e7d35fab80..0cbfe8ec4e5b 100644
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-express/instrument.mjs
+++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express/instrument.mjs
@@ -7,7 +7,6 @@ Sentry.init({
dsn: process.env.E2E_TEST_DSN,
tunnel: 'http://localhost:3031/', // proxy server
sendDefaultPii: true, // Testing the FormData
- autoInstrumentRemix: true, // auto instrument Remix
captureActionFormDataKeys: {
file: true,
text: true,
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.eslintrc.js b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.eslintrc.js
deleted file mode 100644
index f2faf1470fd8..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.eslintrc.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/** @type {import('eslint').Linter.Config} */
-module.exports = {
- extends: ['@remix-run/eslint-config', '@remix-run/eslint-config/node'],
-};
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.gitignore b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.gitignore
deleted file mode 100644
index 3f7bf98da3e1..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-node_modules
-
-/.cache
-/build
-/public/build
-.env
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.npmrc b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.npmrc
deleted file mode 100644
index 070f80f05092..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.npmrc
+++ /dev/null
@@ -1,2 +0,0 @@
-@sentry:registry=http://127.0.0.1:4873
-@sentry-internal:registry=http://127.0.0.1:4873
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/README.md b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/README.md
deleted file mode 100644
index 54336d746713..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# Welcome to Remix!
-
-- [Remix Docs](https://remix.run/docs)
-
-## Development
-
-From your terminal:
-
-```sh
-npm run dev
-```
-
-This starts your app in development mode, rebuilding assets on file changes.
-
-## Deployment
-
-First, build your app for production:
-
-```sh
-npm run build
-```
-
-Then run the app in production mode:
-
-```sh
-npm start
-```
-
-Now you'll need to pick a host to deploy it to.
-
-### DIY
-
-If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
-
-Make sure to deploy the output of `remix build`
-
-- `build/`
-- `public/build/`
-
-### Using a Template
-
-When you ran `npx create-remix@latest` there were a few choices for hosting. You can run that again to create a new
-project, then copy over relevant code/assets from your current app to the new project that's pre-configured for your
-target server.
-
-Most importantly, this means everything in the `app/` directory, but if you've further customized your current
-application outside of there it may also include:
-
-- Any assets you've added/updated in `public/`
-- Any updated versions of root files such as `.eslintrc.js`, etc.
-
-```sh
-cd ..
-# create a new project, and pick a pre-configured host
-npx create-remix@latest
-cd my-new-remix-app
-# remove the new project's app (not the old one!)
-rm -rf app
-# copy your app over
-cp -R ../my-old-remix-app/app app
-```
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/entry.client.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/entry.client.tsx
deleted file mode 100644
index 2109aad0a421..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/entry.client.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * By default, Remix will handle hydrating your app on the client for you.
- * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
- * For more information, see https://remix.run/file-conventions/entry.client
- */
-
-import { RemixBrowser, useLocation, useMatches } from '@remix-run/react';
-import * as Sentry from '@sentry/remix';
-import { StrictMode, startTransition, useEffect } from 'react';
-import { hydrateRoot } from 'react-dom/client';
-
-Sentry.init({
- environment: 'qa', // dynamic sampling bias to keep transactions
- dsn: window.ENV.SENTRY_DSN,
- integrations: [
- Sentry.browserTracingIntegration({
- useEffect,
- useLocation,
- useMatches,
- }),
- Sentry.replayIntegration(),
- ],
- // Performance Monitoring
- tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
- // Session Replay
- replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
- replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
- tunnel: 'http://localhost:3031/', // proxy server
-});
-
-startTransition(() => {
- hydrateRoot(
- document,
-
-
- ,
- );
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/entry.server.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/entry.server.tsx
deleted file mode 100644
index c34e49664197..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/entry.server.tsx
+++ /dev/null
@@ -1,137 +0,0 @@
-import * as Sentry from '@sentry/remix';
-
-Sentry.init({
- tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
- environment: 'qa', // dynamic sampling bias to keep transactions
- dsn: process.env.E2E_TEST_DSN,
- tunnel: 'http://localhost:3031/', // proxy server
-});
-
-/**
- * By default, Remix will handle generating the HTTP Response for you.
- * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
- * For more information, see https://remix.run/file-conventions/entry.server
- */
-
-import { PassThrough } from 'node:stream';
-
-import type { AppLoadContext, EntryContext } from '@remix-run/node';
-import { createReadableStreamFromReadable } from '@remix-run/node';
-import { installGlobals } from '@remix-run/node';
-import { RemixServer } from '@remix-run/react';
-import isbot from 'isbot';
-import { renderToPipeableStream } from 'react-dom/server';
-
-installGlobals();
-
-const ABORT_DELAY = 5_000;
-
-const handleErrorImpl = () => {
- Sentry.setTag('remix-test-tag', 'remix-test-value');
-};
-
-export const handleError = Sentry.wrapHandleErrorWithSentry(handleErrorImpl);
-
-export default function handleRequest(
- request: Request,
- responseStatusCode: number,
- responseHeaders: Headers,
- remixContext: EntryContext,
- loadContext: AppLoadContext,
-) {
- return isbot(request.headers.get('user-agent'))
- ? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext)
- : handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext);
-}
-
-function handleBotRequest(
- request: Request,
- responseStatusCode: number,
- responseHeaders: Headers,
- remixContext: EntryContext,
-) {
- return new Promise((resolve, reject) => {
- let shellRendered = false;
- const { pipe, abort } = renderToPipeableStream(
- ,
- {
- onAllReady() {
- shellRendered = true;
- const body = new PassThrough();
- const stream = createReadableStreamFromReadable(body);
-
- responseHeaders.set('Content-Type', 'text/html');
-
- resolve(
- new Response(stream, {
- headers: responseHeaders,
- status: responseStatusCode,
- }),
- );
-
- pipe(body);
- },
- onShellError(error: unknown) {
- reject(error);
- },
- onError(error: unknown) {
- responseStatusCode = 500;
- // Log streaming rendering errors from inside the shell. Don't log
- // errors encountered during initial shell rendering since they'll
- // reject and get logged in handleDocumentRequest.
- if (shellRendered) {
- console.error(error);
- }
- },
- },
- );
-
- setTimeout(abort, ABORT_DELAY);
- });
-}
-
-function handleBrowserRequest(
- request: Request,
- responseStatusCode: number,
- responseHeaders: Headers,
- remixContext: EntryContext,
-) {
- return new Promise((resolve, reject) => {
- let shellRendered = false;
- const { pipe, abort } = renderToPipeableStream(
- ,
- {
- onShellReady() {
- shellRendered = true;
- const body = new PassThrough();
- const stream = createReadableStreamFromReadable(body);
-
- responseHeaders.set('Content-Type', 'text/html');
-
- resolve(
- new Response(stream, {
- headers: responseHeaders,
- status: responseStatusCode,
- }),
- );
-
- pipe(body);
- },
- onShellError(error: unknown) {
- reject(error);
- },
- onError(error: unknown) {
- responseStatusCode = 500;
- // Log streaming rendering errors from inside the shell. Don't log
- // errors encountered during initial shell rendering since they'll
- // reject and get logged in handleDocumentRequest.
- if (shellRendered) {
- console.error(error);
- }
- },
- },
- );
-
- setTimeout(abort, ABORT_DELAY);
- });
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/root.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/root.tsx
deleted file mode 100644
index 517a37a9d76b..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/root.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-import { cssBundleHref } from '@remix-run/css-bundle';
-import { LinksFunction, MetaFunction, json } from '@remix-run/node';
-import {
- Links,
- LiveReload,
- Meta,
- Outlet,
- Scripts,
- ScrollRestoration,
- useLoaderData,
- useRouteError,
-} from '@remix-run/react';
-import { captureRemixErrorBoundaryError, withSentry } from '@sentry/remix';
-import type { SentryMetaArgs } from '@sentry/remix';
-
-export const links: LinksFunction = () => [...(cssBundleHref ? [{ rel: 'stylesheet', href: cssBundleHref }] : [])];
-
-export const loader = () => {
- return json({
- ENV: {
- SENTRY_DSN: process.env.E2E_TEST_DSN,
- },
- });
-};
-
-export const meta = ({ data }: SentryMetaArgs>) => {
- return [
- {
- env: data.ENV,
- },
- {
- name: 'sentry-trace',
- content: data.sentryTrace,
- },
- {
- name: 'baggage',
- content: data.sentryBaggage,
- },
- ];
-};
-
-export function ErrorBoundary() {
- const error = useRouteError();
- const eventId = captureRemixErrorBoundaryError(error);
-
- return (
-
- ErrorBoundary Error
- {eventId}
-
- );
-}
-
-function App() {
- const { ENV } = useLoaderData();
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-export default withSentry(App);
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/_index.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/_index.tsx
deleted file mode 100644
index 40de0390d6ac..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/_index.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Link, useSearchParams } from '@remix-run/react';
-import * as Sentry from '@sentry/remix';
-
-export default function Index() {
- const [searchParams] = useSearchParams();
-
- if (searchParams.get('tag')) {
- Sentry.setTag('sentry_test', searchParams.get('tag'));
- }
-
- return (
-
- {
- throw new Error('I am an error!');
- }}
- />
-
- navigate
-
-
- );
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/client-error.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/client-error.tsx
deleted file mode 100644
index 4e5330621191..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/client-error.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { useState } from 'react';
-
-export default function ErrorBoundaryCapture() {
- const [count, setCount] = useState(0);
-
- if (count > 0) {
- throw new Error('Sentry React Component Error');
- } else {
- setTimeout(() => setCount(count + 1), 0);
- }
-
- return {count}
;
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/navigate.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/navigate.tsx
deleted file mode 100644
index a84df11e7bb7..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/navigate.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { LoaderFunction } from '@remix-run/node';
-import { useLoaderData } from '@remix-run/react';
-
-export const loader: LoaderFunction = async ({ params: { id } }) => {
- if (id === '-1') {
- throw new Error('Unexpected Server Error');
- }
-
- return null;
-};
-
-export default function LoaderError() {
- const data = useLoaderData();
-
- return (
-
-
{data?.test ? data.test : 'Not Found'}
-
- );
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/user.$id.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/user.$id.tsx
deleted file mode 100644
index 13b2e0a34d1e..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/user.$id.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function User() {
- return I am a blank page
;
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/globals.d.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/globals.d.ts
deleted file mode 100644
index 4130ac6a8a09..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/globals.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-interface Window {
- recordedTransactions?: string[];
- capturedExceptionId?: string;
- ENV: {
- SENTRY_DSN: string;
- };
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/package.json
deleted file mode 100644
index 77058ff26783..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/package.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "private": true,
- "sideEffects": false,
- "scripts": {
- "build": "remix build",
- "dev": "remix dev",
- "start": "remix-serve build/index.js",
- "typecheck": "tsc",
- "clean": "npx rimraf node_modules pnpm-lock.yaml",
- "test:build": "pnpm install && pnpm build",
- "test:assert": "pnpm playwright test"
- },
- "dependencies": {
- "@sentry/remix": "latest || *",
- "@remix-run/css-bundle": "2.7.2",
- "@remix-run/node": "2.7.2",
- "@remix-run/react": "2.7.2",
- "@remix-run/serve": "2.7.2",
- "isbot": "^3.6.8",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- },
- "devDependencies": {
- "@playwright/test": "^1.44.1",
- "@sentry-internal/test-utils": "link:../../../test-utils",
- "@remix-run/dev": "2.7.2",
- "@remix-run/eslint-config": "2.7.2",
- "@sentry/core": "latest || *",
- "@types/react": "^18.0.35",
- "@types/react-dom": "^18.0.11",
- "eslint": "^8.38.0",
- "typescript": "^5.0.4"
- },
- "volta": {
- "extends": "../../package.json"
- }
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/playwright.config.mjs
deleted file mode 100644
index 31f2b913b58b..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/playwright.config.mjs
+++ /dev/null
@@ -1,7 +0,0 @@
-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/create-remix-app-v2-legacy/remix.config.js b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/remix.config.js
deleted file mode 100644
index cb3c8c7a9fb7..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/remix.config.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/** @type {import('@remix-run/dev').AppConfig} */
-module.exports = {
- ignoredRouteFiles: ['**/.*'],
- // appDirectory: 'app',
- // assetsBuildDirectory: 'public/build',
- // serverBuildPath: 'build/index.js',
- // publicPath: '/build/',
- serverModuleFormat: 'cjs',
-};
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/remix.env.d.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/remix.env.d.ts
deleted file mode 100644
index dcf8c45e1d4c..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/remix.env.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-///
-///
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/start-event-proxy.mjs
deleted file mode 100644
index 1719aa397840..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/start-event-proxy.mjs
+++ /dev/null
@@ -1,6 +0,0 @@
-import { startEventProxyServer } from '@sentry-internal/test-utils';
-
-startEventProxyServer({
- port: 3031,
- proxyServerName: 'create-remix-app-v2-legacy',
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/client-errors.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/client-errors.test.ts
deleted file mode 100644
index 1e7aa050756e..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/client-errors.test.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForError } from '@sentry-internal/test-utils';
-
-test('Sends a client-side exception to Sentry', async ({ page }) => {
- const errorPromise = waitForError('create-remix-app-v2-legacy', errorEvent => {
- return errorEvent.exception?.values?.[0].value === 'I am an error!';
- });
-
- await page.goto('/');
-
- const exceptionButton = page.locator('id=exception-button');
- await exceptionButton.click();
-
- const errorEvent = await errorPromise;
-
- expect(errorEvent).toBeDefined();
-});
-
-test('Sends a client-side ErrorBoundary exception to Sentry', async ({ page }) => {
- const errorPromise = waitForError('create-remix-app-v2-legacy', errorEvent => {
- return errorEvent.exception?.values?.[0].value === 'Sentry React Component Error';
- });
-
- await page.goto('/client-error');
-
- const errorEvent = await errorPromise;
-
- expect(errorEvent).toBeDefined();
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/client-transactions.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/client-transactions.test.ts
deleted file mode 100644
index 6c6a23405b4c..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/client-transactions.test.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
-
-test('Sends a pageload transaction to Sentry', async ({ page }) => {
- const transactionPromise = waitForTransaction('create-remix-app-v2-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'pageload' && transactionEvent.transaction === 'routes/_index';
- });
-
- await page.goto('/');
-
- const transactionEvent = await transactionPromise;
-
- expect(transactionEvent).toBeDefined();
-});
-
-test('Sends a navigation transaction to Sentry', async ({ page }) => {
- const transactionPromise = waitForTransaction('create-remix-app-v2-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'navigation' && transactionEvent.transaction === 'routes/user.$id';
- });
-
- await page.goto('/');
-
- const linkElement = page.locator('id=navigation');
- await linkElement.click();
-
- const transactionEvent = await transactionPromise;
-
- expect(transactionEvent).toBeDefined();
-});
-
-test('Renders `sentry-trace` and `baggage` meta tags for the root route', async ({ page }) => {
- await page.goto('/');
-
- const sentryTraceMetaTag = await page.waitForSelector('meta[name="sentry-trace"]', {
- state: 'attached',
- });
- const baggageMetaTag = await page.waitForSelector('meta[name="baggage"]', {
- state: 'attached',
- });
-
- expect(sentryTraceMetaTag).toBeTruthy();
- expect(baggageMetaTag).toBeTruthy();
-});
-
-test('Renders `sentry-trace` and `baggage` meta tags for a sub-route', async ({ page }) => {
- await page.goto('/user/123');
-
- const sentryTraceMetaTag = await page.waitForSelector('meta[name="sentry-trace"]', {
- state: 'attached',
- });
- const baggageMetaTag = await page.waitForSelector('meta[name="baggage"]', {
- state: 'attached',
- });
-
- expect(sentryTraceMetaTag).toBeTruthy();
- expect(baggageMetaTag).toBeTruthy();
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/server-transactions.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/server-transactions.test.ts
deleted file mode 100644
index e19a7056e158..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/server-transactions.test.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { uuid4 } from '@sentry/core';
-
-import { waitForTransaction } from '@sentry-internal/test-utils';
-
-test.describe.configure({ mode: 'serial' });
-
-test('Sends parameterized transaction name to Sentry', async ({ page }) => {
- const transactionPromise = waitForTransaction('create-remix-app-v2-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'http.server';
- });
-
- await page.goto('/user/123');
-
- const transaction = await transactionPromise;
-
- expect(transaction).toBeDefined();
- expect(transaction.transaction).toBe('routes/user.$id');
-});
-
-test('Sends two linked transactions (server & client) to Sentry', async ({ page }) => {
- // We use this to identify the transactions
- const testTag = uuid4();
-
- const httpServerTransactionPromise = waitForTransaction('create-remix-app-v2-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'http.server' && transactionEvent.tags?.['sentry_test'] === testTag;
- });
-
- const pageLoadTransactionPromise = waitForTransaction('create-remix-app-v2-legacy', transactionEvent => {
- return transactionEvent.contexts?.trace?.op === 'pageload' && transactionEvent.tags?.['sentry_test'] === testTag;
- });
-
- page.goto(`/?tag=${testTag}`);
-
- const pageloadTransaction = await pageLoadTransactionPromise;
- const httpServerTransaction = await httpServerTransactionPromise;
-
- expect(pageloadTransaction).toBeDefined();
- expect(httpServerTransaction).toBeDefined();
-
- const httpServerTraceId = httpServerTransaction.contexts?.trace?.trace_id;
- const httpServerSpanId = httpServerTransaction.contexts?.trace?.span_id;
-
- const pageLoadTraceId = pageloadTransaction.contexts?.trace?.trace_id;
- const pageLoadSpanId = pageloadTransaction.contexts?.trace?.span_id;
- const pageLoadParentSpanId = pageloadTransaction.contexts?.trace?.parent_span_id;
-
- expect(httpServerTransaction.transaction).toBe('routes/_index');
- expect(pageloadTransaction.transaction).toBe('routes/_index');
-
- expect(httpServerTraceId).toBeDefined();
- expect(httpServerSpanId).toBeDefined();
-
- expect(pageLoadTraceId).toEqual(httpServerTraceId);
- expect(pageLoadParentSpanId).toEqual(httpServerSpanId);
- expect(pageLoadSpanId).not.toEqual(httpServerSpanId);
-});
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tsconfig.json b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tsconfig.json
deleted file mode 100644
index 20f8a386a6c4..000000000000
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tsconfig.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
- "compilerOptions": {
- "lib": ["DOM", "DOM.Iterable", "ES2019"],
- "isolatedModules": true,
- "esModuleInterop": true,
- "jsx": "react-jsx",
- "moduleResolution": "node",
- "resolveJsonModule": true,
- "target": "ES2019",
- "strict": true,
- "allowJs": true,
- "forceConsistentCasingInFileNames": true,
- "baseUrl": ".",
- "paths": {
- "~/*": ["./app/*"]
- },
-
- // Remix takes care of building everything in `remix build`.
- "noEmit": true
- }
-}
diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/instrument.server.cjs b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/instrument.server.cjs
index 5b80ca7b8695..6d211cac4592 100644
--- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/instrument.server.cjs
+++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/instrument.server.cjs
@@ -5,5 +5,4 @@ Sentry.init({
environment: 'qa', // dynamic sampling bias to keep transactions
dsn: process.env.E2E_TEST_DSN,
tunnel: 'http://localhost:3031/', // proxy server
- autoInstrumentRemix: true, // auto instrument Remix
});
diff --git a/packages/remix/package.json b/packages/remix/package.json
index 838a46a34e5e..afca2a11055a 100644
--- a/packages/remix/package.json
+++ b/packages/remix/package.json
@@ -91,14 +91,8 @@
"fix": "eslint . --format stylish --fix",
"lint": "eslint . --format stylish",
"test": "yarn test:unit",
- "test:integration": "run-s test:integration:otel test:integration:legacy",
- "test:integration:otel": "export USE_OTEL=1 && yarn test:integration:v2",
- "test:integration:legacy": "export USE_OTEL=0 && yarn test:integration:v2",
- "test:integration:v2": "run-s test:integration:clean test:integration:prepare test:integration:client test:integration:server",
- "test:integration:ci": "run-s test:integration:ci:otel test:integration:ci:legacy",
- "test:integration:ci:otel": "USE_OTEL=1 yarn test:integration:ci:common",
- "test:integration:ci:legacy": "USE_OTEL=0 yarn test:integration:ci:common",
- "test:integration:ci:common": "run-s test:integration:clean test:integration:prepare test:integration:client:ci test:integration:server",
+ "test:integration": "run-s test:integration:clean test:integration:prepare test:integration:client test:integration:server",
+ "test:integration:ci": "run-s test:integration:clean test:integration:prepare test:integration:client:ci test:integration:server",
"test:integration:prepare": "(cd test/integration && yarn install)",
"test:integration:clean": "(cd test/integration && rimraf .cache node_modules build)",
"test:integration:client": "yarn playwright install-deps && yarn playwright test test/integration/test/client/ --project='chromium'",
diff --git a/packages/remix/playwright.config.ts b/packages/remix/playwright.config.ts
index 6e9fde329fd3..cacbe1f561ec 100644
--- a/packages/remix/playwright.config.ts
+++ b/packages/remix/playwright.config.ts
@@ -13,7 +13,7 @@ const config: PlaywrightTestConfig = {
// Note that 3 is a random number selected to work well with our CI setup
workers: process.env.CI ? 3 : undefined,
webServer: {
- command: `(cd test/integration/ && yarn build && yarn ${process.env.USE_OTEL === '1' ? 'start:otel' : 'start'})`,
+ command: `(cd test/integration/ && yarn build && yarn start)`,
port: 3000,
},
projects: [
diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts
index bd2a270edf5c..640282b57bed 100644
--- a/packages/remix/src/index.server.ts
+++ b/packages/remix/src/index.server.ts
@@ -151,8 +151,7 @@ export function getRemixDefaultIntegrations(options: RemixOptions): Integration[
return [
...getDefaultNodeIntegrations(options as NodeOptions).filter(integration => integration.name !== 'Http'),
httpIntegration(),
- // eslint-disable-next-line deprecation/deprecation
- options.autoInstrumentRemix ? remixIntegration() : undefined,
+ remixIntegration(),
].filter(int => int) as Integration[];
}
@@ -170,7 +169,7 @@ export function init(options: RemixOptions): NodeClient | undefined {
const client = nodeInit(options as NodeOptions);
- instrumentServer(options);
+ instrumentServer();
return client;
}
diff --git a/packages/remix/src/utils/instrumentServer.ts b/packages/remix/src/utils/instrumentServer.ts
index 90ce8217f4db..a0dd11874416 100644
--- a/packages/remix/src/utils/instrumentServer.ts
+++ b/packages/remix/src/utils/instrumentServer.ts
@@ -1,29 +1,18 @@
-/* eslint-disable max-lines */
-import type { RequestEventData, Span, TransactionSource, WrappedFunction } from '@sentry/core';
+import type { RequestEventData, WrappedFunction } from '@sentry/core';
import {
- SEMANTIC_ATTRIBUTE_SENTRY_OP,
- SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
- SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
continueTrace,
fill,
- getActiveSpan,
getClient,
- getRootSpan,
getTraceData,
hasTracingEnabled,
isNodeEnv,
loadModule,
logger,
- setHttpStatus,
- spanToJSON,
- startSpan,
winterCGRequestToRequestData,
withIsolationScope,
} from '@sentry/core';
import { DEBUG_BUILD } from './debug-build';
import { captureRemixServerException, errorHandleDataFunction, errorHandleDocumentRequestFunction } from './errors';
-import type { RemixOptions } from './remixOptions';
-import { createRoutes, getTransactionName } from './utils';
import { extractData, isDeferredData, isResponse, isRouteErrorResponse, json } from './vendor/response';
import type {
AppData,
@@ -36,7 +25,6 @@ import type {
RemixRequest,
RequestHandler,
ServerBuild,
- ServerRoute,
ServerRouteManifest,
} from './vendor/types';
@@ -89,7 +77,23 @@ export function wrapHandleErrorWithSentry(
};
}
-function makeWrappedDocumentRequestFunction(autoInstrumentRemix?: boolean) {
+function getTraceAndBaggage(): {
+ sentryTrace?: string;
+ sentryBaggage?: string;
+} {
+ if (isNodeEnv()) {
+ const traceData = getTraceData();
+
+ return {
+ sentryTrace: traceData['sentry-trace'],
+ sentryBaggage: traceData.baggage,
+ };
+ }
+
+ return {};
+}
+
+function makeWrappedDocumentRequestFunction() {
return function (origDocumentRequestFunction: HandleDocumentRequestFunction): HandleDocumentRequestFunction {
return async function (
this: unknown,
@@ -99,99 +103,35 @@ function makeWrappedDocumentRequestFunction(autoInstrumentRemix?: boolean) {
context: EntryContext,
loadContext?: Record,
): Promise {
- const documentRequestContext = {
+ return errorHandleDocumentRequestFunction.call(this, origDocumentRequestFunction, {
request,
responseStatusCode,
responseHeaders,
context,
loadContext,
- };
-
- if (!autoInstrumentRemix) {
- const activeSpan = getActiveSpan();
- const rootSpan = activeSpan && getRootSpan(activeSpan);
-
- const name = rootSpan ? spanToJSON(rootSpan).description : undefined;
-
- return startSpan(
- {
- // If we don't have a root span, `onlyIfParent` will lead to the span not being created anyhow
- // So we don't need to care too much about the fallback name, it's just for typing purposes....
- name: name || '',
- onlyIfParent: true,
- attributes: {
- method: request.method,
- url: request.url,
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.remix',
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.remix.document_request',
- },
- },
- () => {
- return errorHandleDocumentRequestFunction.call(this, origDocumentRequestFunction, documentRequestContext);
- },
- );
- } else {
- return errorHandleDocumentRequestFunction.call(this, origDocumentRequestFunction, documentRequestContext);
- }
+ });
};
};
}
-function makeWrappedDataFunction(
- origFn: DataFunction,
- id: string,
- name: 'action' | 'loader',
- autoInstrumentRemix?: boolean,
-): DataFunction {
+function makeWrappedDataFunction(origFn: DataFunction, id: string, name: 'action' | 'loader'): DataFunction {
return async function (this: unknown, args: DataFunctionArgs): Promise {
- if (!autoInstrumentRemix) {
- return startSpan(
- {
- op: `function.remix.${name}`,
- name: id,
- attributes: {
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.remix',
- name,
- },
- },
- (span: Span) => {
- return errorHandleDataFunction.call(this, origFn, name, args, span);
- },
- );
- } else {
- return errorHandleDataFunction.call(this, origFn, name, args);
- }
+ return errorHandleDataFunction.call(this, origFn, name, args);
};
}
const makeWrappedAction =
- (id: string, autoInstrumentRemix?: boolean) =>
+ (id: string) =>
(origAction: DataFunction): DataFunction => {
- return makeWrappedDataFunction(origAction, id, 'action', autoInstrumentRemix);
+ return makeWrappedDataFunction(origAction, id, 'action');
};
const makeWrappedLoader =
- (id: string, autoInstrumentRemix?: boolean) =>
+ (id: string) =>
(origLoader: DataFunction): DataFunction => {
- return makeWrappedDataFunction(origLoader, id, 'loader', autoInstrumentRemix);
+ return makeWrappedDataFunction(origLoader, id, 'loader');
};
-function getTraceAndBaggage(): {
- sentryTrace?: string;
- sentryBaggage?: string;
-} {
- if (isNodeEnv()) {
- const traceData = getTraceData();
-
- return {
- sentryTrace: traceData['sentry-trace'],
- sentryBaggage: traceData.baggage,
- };
- }
-
- return {};
-}
-
function makeWrappedRootLoader() {
return function (origLoader: DataFunction): DataFunction {
return async function (this: unknown, args: DataFunctionArgs): Promise {
@@ -236,16 +176,7 @@ function makeWrappedRootLoader() {
};
}
-function wrapRequestHandler(
- origRequestHandler: RequestHandler,
- build: ServerBuild | (() => ServerBuild | Promise),
- autoInstrumentRemix: boolean,
-): RequestHandler {
- let resolvedBuild: ServerBuild;
- let routes: ServerRoute[];
- let name: string;
- let source: TransactionSource;
-
+function wrapRequestHandler(origRequestHandler: RequestHandler): RequestHandler {
return async function (this: unknown, request: RemixRequest, loadContext?: AppLoadContext): Promise {
const upperCaseMethod = request.method.toUpperCase();
// We don't want to wrap OPTIONS and HEAD requests
@@ -253,16 +184,6 @@ function wrapRequestHandler(
return origRequestHandler.call(this, request, loadContext);
}
- if (!autoInstrumentRemix) {
- if (typeof build === 'function') {
- resolvedBuild = await build();
- } else {
- resolvedBuild = build;
- }
-
- routes = createRoutes(resolvedBuild.routes);
- }
-
return withIsolationScope(async isolationScope => {
const options = getClient()?.getOptions();
@@ -274,13 +195,6 @@ function wrapRequestHandler(
DEBUG_BUILD && logger.warn('Failed to normalize Remix request');
}
- if (!autoInstrumentRemix) {
- const url = new URL(request.url);
- [name, source] = getTransactionName(routes, url);
-
- isolationScope.setTransactionName(name);
- }
-
isolationScope.setSDKProcessingMetadata({ normalizedRequest });
if (!options || !hasTracingEnabled(options)) {
@@ -293,29 +207,6 @@ function wrapRequestHandler(
baggage: request.headers.get('baggage') || '',
},
async () => {
- if (!autoInstrumentRemix) {
- return startSpan(
- {
- name,
- attributes: {
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.remix',
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',
- method: request.method,
- },
- },
- async span => {
- const res = (await origRequestHandler.call(this, request, loadContext)) as Response;
-
- if (isResponse(res)) {
- setHttpStatus(span, res.status);
- }
-
- return res;
- },
- );
- }
-
return (await origRequestHandler.call(this, request, loadContext)) as Response;
},
);
@@ -323,7 +214,7 @@ function wrapRequestHandler(
};
}
-function instrumentBuildCallback(build: ServerBuild, autoInstrumentRemix: boolean): ServerBuild {
+function instrumentBuildCallback(build: ServerBuild): ServerBuild {
const routes: ServerRouteManifest = {};
const wrappedEntry = { ...build.entry, module: { ...build.entry.module } };
@@ -333,7 +224,7 @@ function instrumentBuildCallback(build: ServerBuild, autoInstrumentRemix: boolea
// We should be able to wrap them, as they may not be wrapped before.
const defaultExport = wrappedEntry.module.default as undefined | WrappedFunction;
if (defaultExport && !defaultExport.__sentry_original__) {
- fill(wrappedEntry.module, 'default', makeWrappedDocumentRequestFunction(autoInstrumentRemix));
+ fill(wrappedEntry.module, 'default', makeWrappedDocumentRequestFunction());
}
for (const [id, route] of Object.entries(build.routes)) {
@@ -341,12 +232,12 @@ function instrumentBuildCallback(build: ServerBuild, autoInstrumentRemix: boolea
const routeAction = wrappedRoute.module.action as undefined | WrappedFunction;
if (routeAction && !routeAction.__sentry_original__) {
- fill(wrappedRoute.module, 'action', makeWrappedAction(id, autoInstrumentRemix));
+ fill(wrappedRoute.module, 'action', makeWrappedAction(id));
}
const routeLoader = wrappedRoute.module.loader as undefined | WrappedFunction;
if (routeLoader && !routeLoader.__sentry_original__) {
- fill(wrappedRoute.module, 'loader', makeWrappedLoader(id, autoInstrumentRemix));
+ fill(wrappedRoute.module, 'loader', makeWrappedLoader(id));
}
// Entry module should have a loader function to provide `sentry-trace` and `baggage`
@@ -371,40 +262,35 @@ function instrumentBuildCallback(build: ServerBuild, autoInstrumentRemix: boolea
*/
export function instrumentBuild(
build: ServerBuild | (() => ServerBuild | Promise),
- options: RemixOptions,
): ServerBuild | (() => ServerBuild | Promise) {
- // eslint-disable-next-line deprecation/deprecation
- const autoInstrumentRemix = options?.autoInstrumentRemix || false;
-
if (typeof build === 'function') {
return function () {
const resolvedBuild = build();
if (resolvedBuild instanceof Promise) {
return resolvedBuild.then(build => {
- return instrumentBuildCallback(build, autoInstrumentRemix);
+ return instrumentBuildCallback(build);
});
} else {
- return instrumentBuildCallback(resolvedBuild, autoInstrumentRemix);
+ return instrumentBuildCallback(resolvedBuild);
}
};
} else {
- return instrumentBuildCallback(build, autoInstrumentRemix);
+ return instrumentBuildCallback(build);
}
}
-const makeWrappedCreateRequestHandler = (options: RemixOptions) =>
+const makeWrappedCreateRequestHandler = () =>
function (origCreateRequestHandler: CreateRequestHandlerFunction): CreateRequestHandlerFunction {
return function (
this: unknown,
build: ServerBuild | (() => Promise),
...args: unknown[]
): RequestHandler {
- const newBuild = instrumentBuild(build, options);
+ const newBuild = instrumentBuild(build);
const requestHandler = origCreateRequestHandler.call(this, newBuild, ...args);
- // eslint-disable-next-line deprecation/deprecation
- return wrapRequestHandler(requestHandler, newBuild, options.autoInstrumentRemix || false);
+ return wrapRequestHandler(requestHandler);
};
};
@@ -412,7 +298,7 @@ const makeWrappedCreateRequestHandler = (options: RemixOptions) =>
* Monkey-patch Remix's `createRequestHandler` from `@remix-run/server-runtime`
* which Remix Adapters (https://remix.run/docs/en/v1/api/remix) use underneath.
*/
-export function instrumentServer(options: RemixOptions): void {
+export function instrumentServer(): void {
const pkg = loadModule<{
createRequestHandler: CreateRequestHandlerFunction;
}>('@remix-run/server-runtime');
@@ -423,5 +309,5 @@ export function instrumentServer(options: RemixOptions): void {
return;
}
- fill(pkg, 'createRequestHandler', makeWrappedCreateRequestHandler(options));
+ fill(pkg, 'createRequestHandler', makeWrappedCreateRequestHandler());
}
diff --git a/packages/remix/src/utils/remixOptions.ts b/packages/remix/src/utils/remixOptions.ts
index 58e8ae74b1d2..e65305c7696f 100644
--- a/packages/remix/src/utils/remixOptions.ts
+++ b/packages/remix/src/utils/remixOptions.ts
@@ -4,22 +4,4 @@ import type { BrowserOptions } from '@sentry/react';
export type RemixOptions = (Options | BrowserOptions | NodeOptions) & {
captureActionFormDataKeys?: Record;
-} & (
- | {
- /**
- * Enables OpenTelemetry Remix instrumentation.
- *
- * Note: This option will be the default behavior and will be removed in the next major version.
- */
- autoInstrumentRemix?: true;
- }
- | {
- /**
- * Enables OpenTelemetry Remix instrumentation
- *
- * @deprecated Setting this option to `false` is deprecated as the next major version will default to behaving as if this option were `true` and the option itself will be removed.
- * It is recommended to set this option to `true`.
- */
- autoInstrumentRemix?: false;
- }
- );
+};
diff --git a/packages/remix/test/integration/app/entry.server.tsx b/packages/remix/test/integration/app/entry.server.tsx
index f7ca9d82345a..86b0312eb92f 100644
--- a/packages/remix/test/integration/app/entry.server.tsx
+++ b/packages/remix/test/integration/app/entry.server.tsx
@@ -1,14 +1,5 @@
import * as Sentry from '@sentry/remix';
-if (process.env.USE_OTEL !== '1') {
- Sentry.init({
- dsn: 'https://public@dsn.ingest.sentry.io/1337',
- tracesSampleRate: 1,
- tracePropagationTargets: ['example.org'],
- autoInstrumentRemix: false,
- });
-}
-
import type { EntryContext } from '@remix-run/node';
import { RemixServer } from '@remix-run/react';
import { renderToString } from 'react-dom/server';
diff --git a/packages/remix/test/integration/instrument.server.mjs b/packages/remix/test/integration/instrument.server.mjs
index 3efde8ef19c4..5598d81af581 100644
--- a/packages/remix/test/integration/instrument.server.mjs
+++ b/packages/remix/test/integration/instrument.server.mjs
@@ -4,5 +4,4 @@ Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
tracesSampleRate: 1,
tracePropagationTargets: ['example.org'],
- autoInstrumentRemix: true,
});
diff --git a/packages/remix/test/integration/package.json b/packages/remix/test/integration/package.json
index 518cee89ec18..28bbfe12396e 100644
--- a/packages/remix/test/integration/package.json
+++ b/packages/remix/test/integration/package.json
@@ -5,8 +5,7 @@
"scripts": {
"build": "remix build",
"dev": "remix dev",
- "start": "remix-serve build/index.js",
- "start:otel": "NODE_OPTIONS='--import=./instrument.server.mjs' remix-serve build/index.js"
+ "start": "NODE_OPTIONS='--import=./instrument.server.mjs' remix-serve build/index.js"
},
"dependencies": {
"@remix-run/express": "2.15.2",
diff --git a/packages/remix/test/integration/test/server/instrumentation-legacy/action.test.ts b/packages/remix/test/integration/test/server/instrumentation-legacy/action.test.ts
deleted file mode 100644
index c502b801ed81..000000000000
--- a/packages/remix/test/integration/test/server/instrumentation-legacy/action.test.ts
+++ /dev/null
@@ -1,497 +0,0 @@
-import { describe, it } from 'vitest';
-import { RemixTestEnv, assertSentryEvent, assertSentryTransaction } from '../utils/helpers';
-
-describe('Remix API Actions', () => {
- it('correctly instruments a parameterized Remix API action', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/action-json-response/123123`;
- const envelope = await env.getEnvelopeRequest({
- url,
- method: 'post',
- envelopeType: 'transaction',
- });
- const transaction = envelope[2]!;
-
- assertSentryTransaction(transaction, {
- transaction: `routes/action-json-response.$id`,
- spans: [
- {
- description: `routes/action-json-response.$id`,
- op: 'function.remix.action',
- },
- {
- description: 'root',
- op: 'function.remix.loader',
- },
- {
- description: `routes/action-json-response.$id`,
- op: 'function.remix.loader',
- },
- {
- description: `routes/action-json-response.$id`,
- op: 'function.remix.document_request',
- },
- ],
- request: {
- method: 'POST',
- url,
- cookies: expect.any(Object),
- headers: {
- 'user-agent': expect.any(String),
- host: expect.stringContaining('localhost:'),
- },
- },
- });
- });
-
- it('reports an error thrown from the action', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/action-json-response/-1`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 2,
- method: 'post',
- envelopeType: ['transaction', 'event'],
- });
-
- const [transaction] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
-
- assertSentryTransaction(transaction![2]!, {
- contexts: {
- trace: {
- status: 'internal_error',
- data: {
- 'http.response.status_code': 500,
- },
- },
- },
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/action-json-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Unexpected Server Error',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'remix.server.handleError',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('includes request data in transaction and error events', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/action-json-response/-1`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 2,
- method: 'post',
- envelopeType: ['transaction', 'event'],
- });
-
- const [transaction] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
-
- assertSentryTransaction(transaction![2]!, {
- transaction: `routes/action-json-response.$id`,
- request: {
- method: 'POST',
- url,
- cookies: expect.any(Object),
- headers: {
- 'user-agent': expect.any(String),
- host: expect.stringContaining('localhost:'),
- },
- },
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/action-json-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Unexpected Server Error',
- },
- ],
- },
- request: {
- method: 'POST',
- url,
- cookies: expect.any(Object),
- headers: {
- 'user-agent': expect.any(String),
- host: expect.stringContaining('localhost:'),
- },
- },
- });
- });
-
- it('handles an error-throwing redirection target', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/action-json-response/-2`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 3,
- method: 'post',
- envelopeType: ['transaction', 'event'],
- });
-
- const [transaction_1, transaction_2] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
- assertSentryTransaction(transaction_1![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'ok',
- data: {
- method: 'POST',
- 'http.response.status_code': 302,
- },
- },
- },
- transaction: 'routes/action-json-response.$id',
- });
-
- assertSentryTransaction(transaction_2![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'internal_error',
- data: {
- method: 'GET',
- 'http.response.status_code': 500,
- },
- },
- },
- transaction: 'routes/action-json-response.$id',
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/action-json-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Unexpected Server Error',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'remix.server.handleError',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('handles a thrown `json()` error response with `statusText`', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/action-json-response/-3`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 2,
- method: 'post',
- envelopeType: ['transaction', 'event'],
- });
-
- const [transaction] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
-
- assertSentryTransaction(transaction![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'internal_error',
- data: {
- method: 'POST',
- 'http.response.status_code': 500,
- },
- },
- },
- transaction: 'routes/action-json-response.$id',
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/action-json-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Sentry Test Error',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'action',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('handles a thrown `json()` error response without `statusText`', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/action-json-response/-4`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 2,
- method: 'post',
- envelopeType: ['transaction', 'event'],
- });
-
- const [transaction] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
-
- assertSentryTransaction(transaction![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'internal_error',
- data: {
- method: 'POST',
- 'http.response.status_code': 500,
- },
- },
- },
- transaction: 'routes/action-json-response.$id',
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/action-json-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Object captured as exception with keys: data',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'action',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('handles a thrown `json()` error response with string body', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/action-json-response/-5`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 2,
- method: 'post',
- envelopeType: ['transaction', 'event'],
- });
-
- const [transaction] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
-
- assertSentryTransaction(transaction![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'internal_error',
- data: {
- method: 'POST',
- 'http.response.status_code': 500,
- },
- },
- },
- transaction: 'routes/action-json-response.$id',
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/action-json-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Sentry Test Error [string body]',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'action',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('handles a thrown `json()` error response with an empty object', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/action-json-response/-6`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 2,
- method: 'post',
- envelopeType: ['transaction', 'event'],
- });
-
- const [transaction] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
-
- assertSentryTransaction(transaction![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'internal_error',
- data: {
- method: 'POST',
- 'http.response.status_code': 500,
- },
- },
- },
- transaction: 'routes/action-json-response.$id',
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/action-json-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Object captured as exception with keys: [object has no keys]',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'action',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('handles thrown string (primitive) from an action', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/server-side-unexpected-errors/-1`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 2,
- method: 'post',
- envelopeType: ['event', 'transaction'],
- });
-
- const [transaction] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
-
- assertSentryTransaction(transaction![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'internal_error',
- data: {
- method: 'POST',
- 'http.response.status_code': 500,
- },
- },
- },
- transaction: 'routes/server-side-unexpected-errors.$id',
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/server-side-unexpected-errors(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Thrown String Error',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'remix.server.handleError',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('handles thrown object from an action', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/server-side-unexpected-errors/-2`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 2,
- method: 'post',
- envelopeType: ['event', 'transaction'],
- });
-
- const [transaction] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
-
- assertSentryTransaction(transaction![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'internal_error',
- data: {
- method: 'POST',
- 'http.response.status_code': 500,
- },
- },
- },
- transaction: 'routes/server-side-unexpected-errors.$id',
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/server-side-unexpected-errors(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Thrown Object Error',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'remix.server.handleError',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-});
diff --git a/packages/remix/test/integration/test/server/instrumentation-legacy/loader.test.ts b/packages/remix/test/integration/test/server/instrumentation-legacy/loader.test.ts
deleted file mode 100644
index 79fb7bb270d3..000000000000
--- a/packages/remix/test/integration/test/server/instrumentation-legacy/loader.test.ts
+++ /dev/null
@@ -1,270 +0,0 @@
-import { Event } from '@sentry/core';
-import { describe, expect, it } from 'vitest';
-import { RemixTestEnv, assertSentryEvent, assertSentryTransaction } from '../utils/helpers';
-
-describe('Remix API Loaders', () => {
- it('reports an error thrown from the loader', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/loader-json-response/-2`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({ url, count: 2, envelopeType: ['transaction', 'event'] });
-
- const event = envelopes[0]?.[2]?.type === 'transaction' ? envelopes[1]?.[2] : envelopes[0]?.[2];
- const transaction = envelopes[0]?.[2]?.type === 'transaction' ? envelopes[0]?.[2] : envelopes[1]?.[2];
-
- assertSentryTransaction(transaction!, {
- contexts: {
- trace: {
- status: 'internal_error',
- data: {
- 'http.response.status_code': 500,
- },
- },
- },
- });
-
- assertSentryEvent(event!, {
- transaction: expect.stringMatching(/routes\/loader-json-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Unexpected Server Error',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'remix.server.handleError',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('reports a thrown error response the loader', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/loader-throw-response/-1`;
-
- // We also wait for the transaction, even though we don't care about it for this test
- // but otherwise this may leak into another test
- const envelopes = await env.getMultipleEnvelopeRequest({ url, count: 2, envelopeType: ['event', 'transaction'] });
-
- const event = envelopes[0]?.[2]?.type === 'transaction' ? envelopes[1]?.[2] : envelopes[0]?.[2];
- const transaction = envelopes[0]?.[2]?.type === 'transaction' ? envelopes[0]?.[2] : envelopes[1]?.[2];
-
- assertSentryTransaction(transaction!, {
- contexts: {
- trace: {
- status: 'internal_error',
- data: {
- 'http.response.status_code': 500,
- },
- },
- },
- });
-
- assertSentryEvent(event!, {
- transaction: expect.stringMatching(/routes\/loader-throw-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Not found',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'loader',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('correctly instruments a parameterized Remix API loader', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/loader-json-response/123123`;
- const envelope = await env.getEnvelopeRequest({ url, envelopeType: 'transaction' });
- const transaction = envelope[2]!;
-
- assertSentryTransaction(transaction, {
- transaction: 'routes/loader-json-response.$id',
- transaction_info: {
- source: 'route',
- },
- spans: [
- {
- description: 'root',
- op: 'function.remix.loader',
- },
- {
- description: 'routes/loader-json-response.$id',
- op: 'function.remix.loader',
- },
- {
- description: 'routes/loader-json-response.$id',
- op: 'function.remix.document_request',
- },
- ],
- });
- });
-
- it('handles an error-throwing redirection target', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/loader-json-response/-1`;
-
- const envelopes = await env.getMultipleEnvelopeRequest({
- url,
- count: 3,
- envelopeType: ['transaction', 'event'],
- });
-
- const [transaction_1, transaction_2] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
-
- assertSentryTransaction(transaction_1![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'ok',
- data: {
- method: 'GET',
- 'http.response.status_code': 302,
- },
- },
- },
- transaction: 'routes/loader-json-response.$id',
- });
-
- assertSentryTransaction(transaction_2![2]!, {
- contexts: {
- trace: {
- op: 'http.server',
- status: 'internal_error',
- data: {
- method: 'GET',
- 'http.response.status_code': 500,
- },
- },
- },
- transaction: 'routes/loader-json-response.$id',
- });
-
- assertSentryEvent(event![2]!, {
- transaction: expect.stringMatching(/routes\/loader-json-response(\/|\.)\$id/),
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Unexpected Server Error',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'remix.server.handleError',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-
- it('makes sure scope does not bleed between requests', async () => {
- const env = await RemixTestEnv.init();
-
- const envelopes = await Promise.all([
- env.getEnvelopeRequest({ url: `${env.url}/scope-bleed/1`, endServer: false, envelopeType: 'transaction' }),
- env.getEnvelopeRequest({ url: `${env.url}/scope-bleed/2`, endServer: false, envelopeType: 'transaction' }),
- env.getEnvelopeRequest({ url: `${env.url}/scope-bleed/3`, endServer: false, envelopeType: 'transaction' }),
- env.getEnvelopeRequest({ url: `${env.url}/scope-bleed/4`, endServer: false, envelopeType: 'transaction' }),
- ]);
-
- await new Promise(resolve => env.server.close(resolve));
-
- envelopes.forEach(envelope => {
- const tags = envelope[2]?.tags as NonNullable;
- const customTagArr = Object.keys(tags).filter(t => t.startsWith('tag'));
- expect(customTagArr).toHaveLength(1);
-
- const key = customTagArr[0]!;
- const val = key[key.length - 1];
- expect(tags[key]).toEqual(val);
- });
- });
-
- it('continues transaction from sentry-trace header and baggage', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/loader-json-response/3`;
-
- // send sentry-trace and baggage headers to loader
- env.setAxiosConfig({
- headers: {
- 'sentry-trace': '12312012123120121231201212312012-1121201211212012-1',
- baggage: 'sentry-version=1.0,sentry-environment=production,sentry-trace_id=12312012123120121231201212312012',
- },
- });
- const envelope = await env.getEnvelopeRequest({ url, envelopeType: 'transaction' });
-
- expect(envelope[0]?.trace).toMatchObject({
- trace_id: '12312012123120121231201212312012',
- });
-
- assertSentryTransaction(envelope![2]!, {
- contexts: {
- trace: {
- trace_id: '12312012123120121231201212312012',
- parent_span_id: '1121201211212012',
- },
- },
- });
- });
-
- it('correctly instruments a deferred loader', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/loader-defer-response/123123`;
- const envelope = await env.getEnvelopeRequest({ url, envelopeType: 'transaction' });
- const transaction = envelope[2]!;
-
- assertSentryTransaction(transaction, {
- transaction: 'routes/loader-defer-response.$id',
- transaction_info: {
- source: 'route',
- },
- spans: [
- {
- description: 'root',
- op: 'function.remix.loader',
- },
- {
- description: 'routes/loader-defer-response.$id',
- op: 'function.remix.loader',
- },
- {
- description: 'routes/loader-defer-response.$id',
- op: 'function.remix.document_request',
- },
- ],
- });
- });
-
- it('does not capture thrown redirect responses', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/throw-redirect`;
-
- const envelopesCount = await env.countEnvelopes({
- url,
- envelopeType: 'event',
- timeout: 3000,
- });
-
- expect(envelopesCount).toBe(0);
- });
-});
diff --git a/packages/remix/test/integration/test/server/instrumentation-legacy/ssr.test.ts b/packages/remix/test/integration/test/server/instrumentation-legacy/ssr.test.ts
deleted file mode 100644
index c4ea2503e67f..000000000000
--- a/packages/remix/test/integration/test/server/instrumentation-legacy/ssr.test.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { describe, expect, it } from 'vitest';
-import { RemixTestEnv, assertSentryEvent, assertSentryTransaction } from '../utils/helpers';
-
-describe('Server Side Rendering', () => {
- it('correctly reports a server side rendering error', async () => {
- const env = await RemixTestEnv.init();
- const url = `${env.url}/ssr-error`;
- const envelopes = await env.getMultipleEnvelopeRequest({ url, count: 2, envelopeType: ['transaction', 'event'] });
- const [transaction] = envelopes.filter(envelope => envelope[1]?.type === 'transaction');
- const [event] = envelopes.filter(envelope => envelope[1]?.type === 'event');
- assertSentryTransaction(transaction![2]!, {
- contexts: {
- trace: {
- status: 'internal_error',
- data: {
- 'http.response.status_code': 500,
- },
- },
- },
- tags: {
- // Testing that the wrapped `handleError` correctly adds tags
- 'remix-test-tag': 'remix-test-value',
- },
- });
-
- assertSentryEvent(event![2]!, {
- transaction: 'routes/ssr-error',
- exception: {
- values: [
- {
- type: 'Error',
- value: 'Sentry SSR Test Error',
- stacktrace: expect.any(Object),
- mechanism: {
- data: {
- function: 'remix.server.handleError',
- },
- handled: false,
- type: 'instrument',
- },
- },
- ],
- },
- });
- });
-});
diff --git a/packages/remix/test/integration/test/server/instrumentation-otel/action.test.ts b/packages/remix/test/integration/test/server/instrumentation/action.test.ts
similarity index 100%
rename from packages/remix/test/integration/test/server/instrumentation-otel/action.test.ts
rename to packages/remix/test/integration/test/server/instrumentation/action.test.ts
diff --git a/packages/remix/test/integration/test/server/instrumentation-otel/loader.test.ts b/packages/remix/test/integration/test/server/instrumentation/loader.test.ts
similarity index 100%
rename from packages/remix/test/integration/test/server/instrumentation-otel/loader.test.ts
rename to packages/remix/test/integration/test/server/instrumentation/loader.test.ts
diff --git a/packages/remix/test/integration/test/server/instrumentation-otel/ssr.test.ts b/packages/remix/test/integration/test/server/instrumentation/ssr.test.ts
similarity index 100%
rename from packages/remix/test/integration/test/server/instrumentation-otel/ssr.test.ts
rename to packages/remix/test/integration/test/server/instrumentation/ssr.test.ts
diff --git a/packages/remix/vitest.config.ts b/packages/remix/vitest.config.ts
index 774227165ee3..d2194a288aa1 100644
--- a/packages/remix/vitest.config.ts
+++ b/packages/remix/vitest.config.ts
@@ -1,13 +1,11 @@
import { defineConfig } from 'vitest/config';
-const useOtel = process.env.USE_OTEL === '1';
-
export default defineConfig({
test: {
globals: true,
disableConsoleIntercept: true,
silent: false,
- setupFiles: useOtel ? './test/integration/instrument.server.mjs' : undefined,
- include: useOtel ? ['**/instrumentation-otel/*.test.ts'] : ['**/instrumentation-legacy/*.test.ts'],
+ setupFiles: './test/integration/instrument.server.mjs',
+ include: ['**/integration/test/server/**/*.test.ts'],
},
});