From 41124acaf358ced6aba2be7a5d5c4225a71d7771 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 20 Jan 2025 12:08:06 +0000 Subject: [PATCH 1/4] feat(remix)!: Remove `autoInstrumentRemix` option --- .../instrument.mjs | 1 - .../create-remix-app-express/instrument.mjs | 1 - .../create-remix-app-v2/instrument.server.cjs | 1 - packages/remix/src/index.server.ts | 5 +- packages/remix/src/utils/instrumentServer.ts | 198 ++---------------- packages/remix/src/utils/remixOptions.ts | 20 +- .../test/integration/app/entry.server.tsx | 1 - .../test/integration/instrument.server.mjs | 1 - 8 files changed, 15 insertions(+), 213 deletions(-) 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/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/src/index.server.ts b/packages/remix/src/index.server.ts index 04b9a3859351..129690c0381f 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -153,8 +153,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[]; } @@ -186,7 +185,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 0ea54986f55c..babfac486514 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 } 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 { captureRemixServerException } from './errors'; import { extractData, isDeferredData, isResponse, isRouteErrorResponse, json } from './vendor/response'; import type { AppData, @@ -31,12 +20,9 @@ import type { CreateRequestHandlerFunction, DataFunction, DataFunctionArgs, - EntryContext, - HandleDocumentRequestFunction, RemixRequest, RequestHandler, ServerBuild, - ServerRoute, ServerRouteManifest, } from './vendor/types'; @@ -94,93 +80,6 @@ export function wrapHandleErrorWithSentry( }; } -function makeWrappedDocumentRequestFunction(autoInstrumentRemix?: boolean) { - return function (origDocumentRequestFunction: HandleDocumentRequestFunction): HandleDocumentRequestFunction { - return async function ( - this: unknown, - request: Request, - responseStatusCode: number, - responseHeaders: Headers, - context: EntryContext, - loadContext?: Record, - ): Promise { - const documentRequestContext = { - 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 { - 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); - } - }; -} - -const makeWrappedAction = - (id: string, autoInstrumentRemix?: boolean) => - (origAction: DataFunction): DataFunction => { - return makeWrappedDataFunction(origAction, id, 'action', autoInstrumentRemix); - }; - -const makeWrappedLoader = - (id: string, autoInstrumentRemix?: boolean) => - (origLoader: DataFunction): DataFunction => { - return makeWrappedDataFunction(origLoader, id, 'loader', autoInstrumentRemix); - }; - function getTraceAndBaggage(): { sentryTrace?: string; sentryBaggage?: string; @@ -241,16 +140,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 @@ -258,16 +148,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(); @@ -279,13 +159,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)) { @@ -298,29 +171,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; }, ); @@ -328,32 +178,13 @@ 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 } }; - // Not keeping boolean flags like it's done for `requestHandler` functions, - // Because the build can change between build and runtime. - // So if there is a new `loader` or`action` or `documentRequest` after build. - // 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)); - } - for (const [id, route] of Object.entries(build.routes)) { const wrappedRoute = { ...route, module: { ...route.module } }; - const routeAction = wrappedRoute.module.action as undefined | WrappedFunction; - if (routeAction && !routeAction.__sentry_original__) { - fill(wrappedRoute.module, 'action', makeWrappedAction(id, autoInstrumentRemix)); - } - - const routeLoader = wrappedRoute.module.loader as undefined | WrappedFunction; - if (routeLoader && !routeLoader.__sentry_original__) { - fill(wrappedRoute.module, 'loader', makeWrappedLoader(id, autoInstrumentRemix)); - } - // Entry module should have a loader function to provide `sentry-trace` and `baggage` // They will be available for the root `meta` function as `data.sentryTrace` and `data.sentryBaggage` if (!wrappedRoute.parentId) { @@ -376,40 +207,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); }; }; @@ -417,7 +243,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'); @@ -428,5 +254,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..907b4569e1bf 100644 --- a/packages/remix/test/integration/app/entry.server.tsx +++ b/packages/remix/test/integration/app/entry.server.tsx @@ -5,7 +5,6 @@ if (process.env.USE_OTEL !== '1') { dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1, tracePropagationTargets: ['example.org'], - autoInstrumentRemix: false, }); } 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, }); From 561b44681fd6fca1ba6c0ad0c09fdd745fa0c3c9 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Tue, 21 Jan 2025 15:30:09 +0000 Subject: [PATCH 2/4] rm legacy e2e tests --- .../.eslintrc.cjs | 79 ---------- .../.gitignore | 6 - .../create-remix-app-express-legacy/.npmrc | 2 - .../app/entry.client.tsx | 31 ---- .../app/entry.server.tsx | 141 ------------------ .../app/root.tsx | 80 ---------- .../app/routes/_index.tsx | 28 ---- .../app/routes/action-formdata.tsx | 17 --- .../app/routes/client-error.tsx | 24 --- .../app/routes/loader-error.tsx | 16 -- .../app/routes/navigate.tsx | 20 --- .../app/routes/user.$id.tsx | 3 - .../create-remix-app-express-legacy/env.d.ts | 2 - .../globals.d.ts | 7 - .../instrument.cjs | 14 -- .../package.json | 56 ------- .../playwright.config.mjs | 7 - .../server.mjs | 52 ------- .../start-event-proxy.mjs | 6 - .../tests/client-errors.test.ts | 29 ---- .../tests/client-transactions.test.ts | 57 ------- .../tests/server-errors.test.ts | 14 -- .../tests/server-transactions.test.ts | 133 ----------------- .../tsconfig.json | 22 --- .../vite.config.ts | 18 --- .../create-remix-app-v2-legacy/.eslintrc.js | 4 - .../create-remix-app-v2-legacy/.gitignore | 6 - .../create-remix-app-v2-legacy/.npmrc | 2 - .../create-remix-app-v2-legacy/README.md | 61 -------- .../app/entry.client.tsx | 38 ----- .../app/entry.server.tsx | 137 ----------------- .../create-remix-app-v2-legacy/app/root.tsx | 80 ---------- .../app/routes/_index.tsx | 26 ---- .../app/routes/client-error.tsx | 13 -- .../app/routes/navigate.tsx | 20 --- .../app/routes/user.$id.tsx | 3 - .../create-remix-app-v2-legacy/globals.d.ts | 7 - .../create-remix-app-v2-legacy/package.json | 37 ----- .../playwright.config.mjs | 7 - .../remix.config.js | 9 -- .../create-remix-app-v2-legacy/remix.env.d.ts | 2 - .../start-event-proxy.mjs | 6 - .../tests/client-errors.test.ts | 29 ---- .../tests/client-transactions.test.ts | 57 ------- .../tests/server-transactions.test.ts | 57 ------- .../create-remix-app-v2-legacy/tsconfig.json | 22 --- 46 files changed, 1487 deletions(-) delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/.eslintrc.cjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/.gitignore delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/.npmrc delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/entry.client.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/entry.server.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/root.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/_index.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/action-formdata.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/client-error.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/loader-error.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/navigate.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/routes/user.$id.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/env.d.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/globals.d.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/instrument.cjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/package.json delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/server.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/start-event-proxy.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/client-errors.test.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/client-transactions.test.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/server-errors.test.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tests/server-transactions.test.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/tsconfig.json delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/vite.config.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.eslintrc.js delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.gitignore delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/.npmrc delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/README.md delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/entry.client.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/entry.server.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/root.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/_index.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/client-error.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/navigate.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/app/routes/user.$id.tsx delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/globals.d.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/package.json delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/remix.config.js delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/remix.env.d.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/start-event-proxy.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/client-errors.test.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/client-transactions.test.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tests/server-transactions.test.ts delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2-legacy/tsconfig.json diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/.eslintrc.cjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/.eslintrc.cjs deleted file mode 100644 index 7adbd6f482f6..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/.eslintrc.cjs +++ /dev/null @@ -1,79 +0,0 @@ -/** - * This is intended to be a basic starting point for linting in your app. - * It relies on recommended configs out of the box for simplicity, but you can - * and should modify this configuration to best suit your team's needs. - */ - -/** @type {import('eslint').Linter.Config} */ -module.exports = { - root: true, - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - ecmaFeatures: { - jsx: true, - }, - }, - env: { - browser: true, - commonjs: true, - es6: true, - }, - - // Base config - extends: ['eslint:recommended'], - - overrides: [ - // React - { - files: ['**/*.{js,jsx,ts,tsx}'], - plugins: ['react', 'jsx-a11y'], - extends: [ - 'plugin:react/recommended', - 'plugin:react/jsx-runtime', - 'plugin:react-hooks/recommended', - 'plugin:jsx-a11y/recommended', - ], - settings: { - react: { - version: 'detect', - }, - formComponents: ['Form'], - linkComponents: [ - { name: 'Link', linkAttribute: 'to' }, - { name: 'NavLink', linkAttribute: 'to' }, - ], - 'import/resolver': { - typescript: {}, - }, - }, - }, - - // Typescript - { - files: ['**/*.{ts,tsx}'], - plugins: ['@typescript-eslint', 'import'], - parser: '@typescript-eslint/parser', - settings: { - 'import/internal-regex': '^~/', - 'import/resolver': { - node: { - extensions: ['.ts', '.tsx'], - }, - typescript: { - alwaysTryTypes: true, - }, - }, - }, - extends: ['plugin:@typescript-eslint/recommended', 'plugin:import/recommended', 'plugin:import/typescript'], - }, - - // Node - { - files: ['.eslintrc.cjs', 'server.js'], - env: { - node: true, - }, - }, - ], -}; diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/.gitignore b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/.gitignore deleted file mode 100644 index 3f7bf98da3e1..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-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-express-legacy/.npmrc b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/.npmrc deleted file mode 100644 index 070f80f05092..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-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-express-legacy/app/entry.client.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/entry.client.tsx deleted file mode 100644 index 46a0d015cdc0..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/entry.client.tsx +++ /dev/null @@ -1,31 +0,0 @@ -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! - 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-express-legacy/app/entry.server.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/entry.server.tsx deleted file mode 100644 index a387f32ee7a6..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/entry.server.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import * as Sentry from '@sentry/remix'; - -import { PassThrough } from 'node:stream'; -import * as isbotModule from 'isbot'; - -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 { renderToPipeableStream } from 'react-dom/server'; - -installGlobals(); - -const ABORT_DELAY = 5_000; - -export const handleError = Sentry.sentryHandleError; - -export default function handleRequest( - request: Request, - responseStatusCode: number, - responseHeaders: Headers, - remixContext: EntryContext, - loadContext: AppLoadContext, -) { - return isBotRequest(request.headers.get('user-agent')) - ? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext) - : handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext); -} - -// We have some Remix apps in the wild already running with isbot@3 so we need -// to maintain backwards compatibility even though we want new apps to use -// isbot@4. That way, we can ship this as a minor Semver update to @remix-run/dev. -function isBotRequest(userAgent: string | null) { - if (!userAgent) { - return false; - } - - // isbot >= 3.8.0, >4 - if ('isbot' in isbotModule && typeof isbotModule.isbot === 'function') { - return isbotModule.isbot(userAgent); - } - - // isbot < 3.8.0 - if ('default' in isbotModule && typeof isbotModule.default === 'function') { - return isbotModule.default(userAgent); - } - - return false; -} - -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-express-legacy/app/root.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-express-legacy/app/root.tsx deleted file mode 100644 index 517a37a9d76b..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-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 ( - - - - -