Skip to content

Commit 41124ac

Browse files
author
Luca Forstner
committed
feat(remix)!: Remove autoInstrumentRemix option
1 parent 9cdf720 commit 41124ac

File tree

8 files changed

+15
-213
lines changed

8 files changed

+15
-213
lines changed

dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/instrument.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@ Sentry.init({
66
environment: 'qa', // dynamic sampling bias to keep transactions
77
dsn: process.env.E2E_TEST_DSN,
88
tunnel: 'http://localhost:3031/', // proxy server
9-
autoInstrumentRemix: true, // auto instrument Remix
109
integrations: [Sentry.nativeNodeFetchIntegration()],
1110
});

dev-packages/e2e-tests/test-applications/create-remix-app-express/instrument.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ Sentry.init({
77
dsn: process.env.E2E_TEST_DSN,
88
tunnel: 'http://localhost:3031/', // proxy server
99
sendDefaultPii: true, // Testing the FormData
10-
autoInstrumentRemix: true, // auto instrument Remix
1110
captureActionFormDataKeys: {
1211
file: true,
1312
text: true,

dev-packages/e2e-tests/test-applications/create-remix-app-v2/instrument.server.cjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@ Sentry.init({
55
environment: 'qa', // dynamic sampling bias to keep transactions
66
dsn: process.env.E2E_TEST_DSN,
77
tunnel: 'http://localhost:3031/', // proxy server
8-
autoInstrumentRemix: true, // auto instrument Remix
98
});

packages/remix/src/index.server.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,7 @@ export function getRemixDefaultIntegrations(options: RemixOptions): Integration[
153153
return [
154154
...getDefaultNodeIntegrations(options as NodeOptions).filter(integration => integration.name !== 'Http'),
155155
httpIntegration(),
156-
// eslint-disable-next-line deprecation/deprecation
157-
options.autoInstrumentRemix ? remixIntegration() : undefined,
156+
remixIntegration(),
158157
].filter(int => int) as Integration[];
159158
}
160159

@@ -186,7 +185,7 @@ export function init(options: RemixOptions): NodeClient | undefined {
186185

187186
const client = nodeInit(options as NodeOptions);
188187

189-
instrumentServer(options);
188+
instrumentServer();
190189

191190
return client;
192191
}
Lines changed: 12 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,28 @@
1-
/* eslint-disable max-lines */
2-
import type { RequestEventData, Span, TransactionSource, WrappedFunction } from '@sentry/core';
1+
import type { RequestEventData } from '@sentry/core';
32
import {
4-
SEMANTIC_ATTRIBUTE_SENTRY_OP,
5-
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
6-
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
73
continueTrace,
84
fill,
9-
getActiveSpan,
105
getClient,
11-
getRootSpan,
126
getTraceData,
137
hasTracingEnabled,
148
isNodeEnv,
159
loadModule,
1610
logger,
17-
setHttpStatus,
18-
spanToJSON,
19-
startSpan,
2011
winterCGRequestToRequestData,
2112
withIsolationScope,
2213
} from '@sentry/core';
2314
import { DEBUG_BUILD } from './debug-build';
24-
import { captureRemixServerException, errorHandleDataFunction, errorHandleDocumentRequestFunction } from './errors';
25-
import type { RemixOptions } from './remixOptions';
26-
import { createRoutes, getTransactionName } from './utils';
15+
import { captureRemixServerException } from './errors';
2716
import { extractData, isDeferredData, isResponse, isRouteErrorResponse, json } from './vendor/response';
2817
import type {
2918
AppData,
3019
AppLoadContext,
3120
CreateRequestHandlerFunction,
3221
DataFunction,
3322
DataFunctionArgs,
34-
EntryContext,
35-
HandleDocumentRequestFunction,
3623
RemixRequest,
3724
RequestHandler,
3825
ServerBuild,
39-
ServerRoute,
4026
ServerRouteManifest,
4127
} from './vendor/types';
4228

@@ -94,93 +80,6 @@ export function wrapHandleErrorWithSentry(
9480
};
9581
}
9682

97-
function makeWrappedDocumentRequestFunction(autoInstrumentRemix?: boolean) {
98-
return function (origDocumentRequestFunction: HandleDocumentRequestFunction): HandleDocumentRequestFunction {
99-
return async function (
100-
this: unknown,
101-
request: Request,
102-
responseStatusCode: number,
103-
responseHeaders: Headers,
104-
context: EntryContext,
105-
loadContext?: Record<string, unknown>,
106-
): Promise<Response> {
107-
const documentRequestContext = {
108-
request,
109-
responseStatusCode,
110-
responseHeaders,
111-
context,
112-
loadContext,
113-
};
114-
115-
if (!autoInstrumentRemix) {
116-
const activeSpan = getActiveSpan();
117-
const rootSpan = activeSpan && getRootSpan(activeSpan);
118-
119-
const name = rootSpan ? spanToJSON(rootSpan).description : undefined;
120-
121-
return startSpan(
122-
{
123-
// If we don't have a root span, `onlyIfParent` will lead to the span not being created anyhow
124-
// So we don't need to care too much about the fallback name, it's just for typing purposes....
125-
name: name || '<unknown>',
126-
onlyIfParent: true,
127-
attributes: {
128-
method: request.method,
129-
url: request.url,
130-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.remix',
131-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.remix.document_request',
132-
},
133-
},
134-
() => {
135-
return errorHandleDocumentRequestFunction.call(this, origDocumentRequestFunction, documentRequestContext);
136-
},
137-
);
138-
} else {
139-
return errorHandleDocumentRequestFunction.call(this, origDocumentRequestFunction, documentRequestContext);
140-
}
141-
};
142-
};
143-
}
144-
145-
function makeWrappedDataFunction(
146-
origFn: DataFunction,
147-
id: string,
148-
name: 'action' | 'loader',
149-
autoInstrumentRemix?: boolean,
150-
): DataFunction {
151-
return async function (this: unknown, args: DataFunctionArgs): Promise<Response | AppData> {
152-
if (!autoInstrumentRemix) {
153-
return startSpan(
154-
{
155-
op: `function.remix.${name}`,
156-
name: id,
157-
attributes: {
158-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.remix',
159-
name,
160-
},
161-
},
162-
(span: Span) => {
163-
return errorHandleDataFunction.call(this, origFn, name, args, span);
164-
},
165-
);
166-
} else {
167-
return errorHandleDataFunction.call(this, origFn, name, args);
168-
}
169-
};
170-
}
171-
172-
const makeWrappedAction =
173-
(id: string, autoInstrumentRemix?: boolean) =>
174-
(origAction: DataFunction): DataFunction => {
175-
return makeWrappedDataFunction(origAction, id, 'action', autoInstrumentRemix);
176-
};
177-
178-
const makeWrappedLoader =
179-
(id: string, autoInstrumentRemix?: boolean) =>
180-
(origLoader: DataFunction): DataFunction => {
181-
return makeWrappedDataFunction(origLoader, id, 'loader', autoInstrumentRemix);
182-
};
183-
18483
function getTraceAndBaggage(): {
18584
sentryTrace?: string;
18685
sentryBaggage?: string;
@@ -241,33 +140,14 @@ function makeWrappedRootLoader() {
241140
};
242141
}
243142

244-
function wrapRequestHandler(
245-
origRequestHandler: RequestHandler,
246-
build: ServerBuild | (() => ServerBuild | Promise<ServerBuild>),
247-
autoInstrumentRemix: boolean,
248-
): RequestHandler {
249-
let resolvedBuild: ServerBuild;
250-
let routes: ServerRoute[];
251-
let name: string;
252-
let source: TransactionSource;
253-
143+
function wrapRequestHandler(origRequestHandler: RequestHandler): RequestHandler {
254144
return async function (this: unknown, request: RemixRequest, loadContext?: AppLoadContext): Promise<Response> {
255145
const upperCaseMethod = request.method.toUpperCase();
256146
// We don't want to wrap OPTIONS and HEAD requests
257147
if (upperCaseMethod === 'OPTIONS' || upperCaseMethod === 'HEAD') {
258148
return origRequestHandler.call(this, request, loadContext);
259149
}
260150

261-
if (!autoInstrumentRemix) {
262-
if (typeof build === 'function') {
263-
resolvedBuild = await build();
264-
} else {
265-
resolvedBuild = build;
266-
}
267-
268-
routes = createRoutes(resolvedBuild.routes);
269-
}
270-
271151
return withIsolationScope(async isolationScope => {
272152
const options = getClient()?.getOptions();
273153

@@ -279,13 +159,6 @@ function wrapRequestHandler(
279159
DEBUG_BUILD && logger.warn('Failed to normalize Remix request');
280160
}
281161

282-
if (!autoInstrumentRemix) {
283-
const url = new URL(request.url);
284-
[name, source] = getTransactionName(routes, url);
285-
286-
isolationScope.setTransactionName(name);
287-
}
288-
289162
isolationScope.setSDKProcessingMetadata({ normalizedRequest });
290163

291164
if (!options || !hasTracingEnabled(options)) {
@@ -298,62 +171,20 @@ function wrapRequestHandler(
298171
baggage: request.headers.get('baggage') || '',
299172
},
300173
async () => {
301-
if (!autoInstrumentRemix) {
302-
return startSpan(
303-
{
304-
name,
305-
attributes: {
306-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.remix',
307-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
308-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',
309-
method: request.method,
310-
},
311-
},
312-
async span => {
313-
const res = (await origRequestHandler.call(this, request, loadContext)) as Response;
314-
315-
if (isResponse(res)) {
316-
setHttpStatus(span, res.status);
317-
}
318-
319-
return res;
320-
},
321-
);
322-
}
323-
324174
return (await origRequestHandler.call(this, request, loadContext)) as Response;
325175
},
326176
);
327177
});
328178
};
329179
}
330180

331-
function instrumentBuildCallback(build: ServerBuild, autoInstrumentRemix: boolean): ServerBuild {
181+
function instrumentBuildCallback(build: ServerBuild): ServerBuild {
332182
const routes: ServerRouteManifest = {};
333183
const wrappedEntry = { ...build.entry, module: { ...build.entry.module } };
334184

335-
// Not keeping boolean flags like it's done for `requestHandler` functions,
336-
// Because the build can change between build and runtime.
337-
// So if there is a new `loader` or`action` or `documentRequest` after build.
338-
// We should be able to wrap them, as they may not be wrapped before.
339-
const defaultExport = wrappedEntry.module.default as undefined | WrappedFunction;
340-
if (defaultExport && !defaultExport.__sentry_original__) {
341-
fill(wrappedEntry.module, 'default', makeWrappedDocumentRequestFunction(autoInstrumentRemix));
342-
}
343-
344185
for (const [id, route] of Object.entries(build.routes)) {
345186
const wrappedRoute = { ...route, module: { ...route.module } };
346187

347-
const routeAction = wrappedRoute.module.action as undefined | WrappedFunction;
348-
if (routeAction && !routeAction.__sentry_original__) {
349-
fill(wrappedRoute.module, 'action', makeWrappedAction(id, autoInstrumentRemix));
350-
}
351-
352-
const routeLoader = wrappedRoute.module.loader as undefined | WrappedFunction;
353-
if (routeLoader && !routeLoader.__sentry_original__) {
354-
fill(wrappedRoute.module, 'loader', makeWrappedLoader(id, autoInstrumentRemix));
355-
}
356-
357188
// Entry module should have a loader function to provide `sentry-trace` and `baggage`
358189
// They will be available for the root `meta` function as `data.sentryTrace` and `data.sentryBaggage`
359190
if (!wrappedRoute.parentId) {
@@ -376,48 +207,43 @@ function instrumentBuildCallback(build: ServerBuild, autoInstrumentRemix: boolea
376207
*/
377208
export function instrumentBuild(
378209
build: ServerBuild | (() => ServerBuild | Promise<ServerBuild>),
379-
options: RemixOptions,
380210
): ServerBuild | (() => ServerBuild | Promise<ServerBuild>) {
381-
// eslint-disable-next-line deprecation/deprecation
382-
const autoInstrumentRemix = options?.autoInstrumentRemix || false;
383-
384211
if (typeof build === 'function') {
385212
return function () {
386213
const resolvedBuild = build();
387214

388215
if (resolvedBuild instanceof Promise) {
389216
return resolvedBuild.then(build => {
390-
return instrumentBuildCallback(build, autoInstrumentRemix);
217+
return instrumentBuildCallback(build);
391218
});
392219
} else {
393-
return instrumentBuildCallback(resolvedBuild, autoInstrumentRemix);
220+
return instrumentBuildCallback(resolvedBuild);
394221
}
395222
};
396223
} else {
397-
return instrumentBuildCallback(build, autoInstrumentRemix);
224+
return instrumentBuildCallback(build);
398225
}
399226
}
400227

401-
const makeWrappedCreateRequestHandler = (options: RemixOptions) =>
228+
const makeWrappedCreateRequestHandler = () =>
402229
function (origCreateRequestHandler: CreateRequestHandlerFunction): CreateRequestHandlerFunction {
403230
return function (
404231
this: unknown,
405232
build: ServerBuild | (() => Promise<ServerBuild>),
406233
...args: unknown[]
407234
): RequestHandler {
408-
const newBuild = instrumentBuild(build, options);
235+
const newBuild = instrumentBuild(build);
409236
const requestHandler = origCreateRequestHandler.call(this, newBuild, ...args);
410237

411-
// eslint-disable-next-line deprecation/deprecation
412-
return wrapRequestHandler(requestHandler, newBuild, options.autoInstrumentRemix || false);
238+
return wrapRequestHandler(requestHandler);
413239
};
414240
};
415241

416242
/**
417243
* Monkey-patch Remix's `createRequestHandler` from `@remix-run/server-runtime`
418244
* which Remix Adapters (https://remix.run/docs/en/v1/api/remix) use underneath.
419245
*/
420-
export function instrumentServer(options: RemixOptions): void {
246+
export function instrumentServer(): void {
421247
const pkg = loadModule<{
422248
createRequestHandler: CreateRequestHandlerFunction;
423249
}>('@remix-run/server-runtime');
@@ -428,5 +254,5 @@ export function instrumentServer(options: RemixOptions): void {
428254
return;
429255
}
430256

431-
fill(pkg, 'createRequestHandler', makeWrappedCreateRequestHandler(options));
257+
fill(pkg, 'createRequestHandler', makeWrappedCreateRequestHandler());
432258
}

packages/remix/src/utils/remixOptions.ts

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,4 @@ import type { BrowserOptions } from '@sentry/react';
44

55
export type RemixOptions = (Options | BrowserOptions | NodeOptions) & {
66
captureActionFormDataKeys?: Record<string, string | boolean>;
7-
} & (
8-
| {
9-
/**
10-
* Enables OpenTelemetry Remix instrumentation.
11-
*
12-
* Note: This option will be the default behavior and will be removed in the next major version.
13-
*/
14-
autoInstrumentRemix?: true;
15-
}
16-
| {
17-
/**
18-
* Enables OpenTelemetry Remix instrumentation
19-
*
20-
* @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.
21-
* It is recommended to set this option to `true`.
22-
*/
23-
autoInstrumentRemix?: false;
24-
}
25-
);
7+
};

packages/remix/test/integration/app/entry.server.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ if (process.env.USE_OTEL !== '1') {
55
dsn: 'https://public@dsn.ingest.sentry.io/1337',
66
tracesSampleRate: 1,
77
tracePropagationTargets: ['example.org'],
8-
autoInstrumentRemix: false,
98
});
109
}
1110

packages/remix/test/integration/instrument.server.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ Sentry.init({
44
dsn: 'https://public@dsn.ingest.sentry.io/1337',
55
tracesSampleRate: 1,
66
tracePropagationTargets: ['example.org'],
7-
autoInstrumentRemix: true,
87
});

0 commit comments

Comments
 (0)