Skip to content

Commit d5f6a2a

Browse files
committed
fix(react-router): Avoid proxying the entire react-router module
1 parent 952373e commit d5f6a2a

2 files changed

Lines changed: 46 additions & 48 deletions

File tree

  • dev-packages/e2e-tests/test-applications/react-router-7-framework
  • packages/react-router/src/server/instrumentation

dev-packages/e2e-tests/test-applications/react-router-7-framework/instrument.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ Sentry.init({
66
environment: 'qa', // dynamic sampling bias to keep transactions
77
tracesSampleRate: 1.0,
88
tunnel: `http://localhost:3031/`, // proxy server
9+
// integrations: integs => integs.filter(i => i.name !== 'ReactRouterServer'),
910
});

packages/react-router/src/server/instrumentation/reactRouter.ts

Lines changed: 45 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -49,63 +49,60 @@ export class ReactRouterInstrumentation extends InstrumentationBase<Instrumentat
4949
}
5050

5151
/**
52-
* Creates a proxy around the React Router module exports that patches the createRequestHandler function.
53-
* This allows us to wrap the request handler to add performance monitoring for data loaders and actions.
52+
* Creates a proxy around the createRequestHandler function.
53+
* This allows us to wrap the request handler to add tracing for data loaders and actions.
5454
*/
5555
private _createPatchedModuleProxy(moduleExports: ReactRouterModuleExports): ReactRouterModuleExports {
56-
return new Proxy(moduleExports, {
57-
get(target, prop, receiver) {
58-
if (prop === 'createRequestHandler') {
59-
const original = target[prop];
60-
return function sentryWrappedCreateRequestHandler(this: unknown, ...args: unknown[]) {
61-
const originalRequestHandler = original.apply(this, args);
56+
if (typeof moduleExports.createRequestHandler === 'function') {
57+
moduleExports.createRequestHandler = new Proxy(moduleExports.createRequestHandler, {
58+
apply(target, thisArg, originalArgs) {
59+
const originalRequestHandler = target.apply(thisArg, originalArgs);
6260

63-
return async function sentryWrappedRequestHandler(request: Request, initialContext?: unknown) {
64-
let url: URL;
65-
try {
66-
url = new URL(request.url);
67-
} catch (error) {
68-
return originalRequestHandler(request, initialContext);
69-
}
61+
return async function sentryWrappedRequestHandler(request: Request, initialContext?: unknown) {
62+
let url: URL;
63+
try {
64+
url = new URL(request.url);
65+
} catch (error) {
66+
return originalRequestHandler(request, initialContext);
67+
}
7068

71-
// We currently just want to trace loaders and actions
72-
if (!isDataRequest(url.pathname)) {
73-
return originalRequestHandler(request, initialContext);
74-
}
69+
// We currently just want to trace loaders and actions
70+
if (!isDataRequest(url.pathname)) {
71+
return originalRequestHandler(request, initialContext);
72+
}
7573

76-
const activeSpan = getActiveSpan();
77-
const rootSpan = activeSpan && getRootSpan(activeSpan);
74+
const activeSpan = getActiveSpan();
75+
const rootSpan = activeSpan && getRootSpan(activeSpan);
7876

79-
if (!rootSpan) {
80-
DEBUG_BUILD && logger.debug('No active root span found, skipping tracing for data request');
81-
return originalRequestHandler(request, initialContext);
82-
}
77+
if (!rootSpan) {
78+
DEBUG_BUILD && logger.debug('No active root span found, skipping tracing for data request');
79+
return originalRequestHandler(request, initialContext);
80+
}
8381

84-
// Set the source and overwrite attributes on the root span to ensure the transaction name
85-
// is derived from the raw URL pathname rather than any parameterized route that may be set later
86-
// TODO: try to set derived parameterized route from build here (args[0])
87-
rootSpan.setAttributes({
88-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
89-
[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE]: `${request.method} ${url.pathname}`,
90-
});
82+
// Set the source and overwrite attributes on the root span to ensure the transaction name
83+
// is derived from the raw URL pathname rather than any parameterized route that may be set later
84+
// TODO: try to set derived parameterized route from build here (args[0])
85+
rootSpan.setAttributes({
86+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
87+
[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE]: `${request.method} ${url.pathname}`,
88+
});
9189

92-
return startSpan(
93-
{
94-
name: getSpanName(url.pathname, request.method),
95-
attributes: {
96-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router',
97-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: getOpName(url.pathname, request.method),
98-
},
90+
return startSpan(
91+
{
92+
name: getSpanName(url.pathname, request.method),
93+
attributes: {
94+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router',
95+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: getOpName(url.pathname, request.method),
9996
},
100-
() => {
101-
return originalRequestHandler(request, initialContext);
102-
},
103-
);
104-
};
97+
},
98+
() => {
99+
return originalRequestHandler(request, initialContext);
100+
},
101+
);
105102
};
106-
}
107-
return Reflect.get(target, prop, receiver);
108-
},
109-
});
103+
},
104+
});
105+
}
106+
return moduleExports;
110107
}
111108
}

0 commit comments

Comments
 (0)