Skip to content

Commit 04702ae

Browse files
committed
fix(react-router): Fix createRequestHandler patching
1 parent 3d18c8e commit 04702ae

File tree

1 file changed

+54
-55
lines changed

1 file changed

+54
-55
lines changed

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

Lines changed: 54 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -37,75 +37,74 @@ export class ReactRouterInstrumentation extends InstrumentationBase<Instrumentat
3737
COMPONENT,
3838
supportedVersions,
3939
(moduleExports: ReactRouterModuleExports) => {
40-
return this._createPatchedModuleProxy(moduleExports);
41-
},
42-
(_moduleExports: unknown) => {
43-
// nothing to unwrap here
44-
return _moduleExports;
40+
41+
const original = moduleExports.createRequestHandler;
42+
43+
Object.defineProperty(moduleExports, 'createRequestHandler', {
44+
enumerable: true,
45+
get: () => this._createPatchedFunction(original),
46+
});
47+
48+
return moduleExports;
4549
},
4650
);
4751

4852
return reactRouterServerModule;
4953
}
5054

5155
/**
52-
* Creates a proxy around the React Router module exports that patches the createRequestHandler function.
56+
* Creates a patched createRequestHandler function.
57+
*
5358
* This allows us to wrap the request handler to add performance monitoring for data loaders and actions.
5459
*/
55-
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);
60+
private _createPatchedFunction(
61+
original: reactRouter.CreateRequestHandlerFunction,
62+
): reactRouter.CreateRequestHandlerFunction {
63+
return function (this: unknown, ...args: unknown[]) {
64+
const originalRequestHandler = original.apply(this, args);
6265

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-
}
66+
return async function sentryWrappedRequestHandler(request: Request, initialContext?: unknown) {
67+
let url: URL;
68+
try {
69+
url = new URL(request.url);
70+
} catch (error) {
71+
return originalRequestHandler(request, initialContext);
72+
}
7073

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

76-
const activeSpan = getActiveSpan();
77-
const rootSpan = activeSpan && getRootSpan(activeSpan);
79+
const activeSpan = getActiveSpan();
80+
const rootSpan = activeSpan && getRootSpan(activeSpan);
7881

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

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-
});
87+
// Set the source and overwrite attributes on the root span to ensure the transaction name
88+
// is derived from the raw URL pathname rather than any parameterized route that may be set later
89+
// TODO: try to set derived parameterized route from build here (args[0])
90+
rootSpan.setAttributes({
91+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
92+
[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE]: `${request.method} ${url.pathname}`,
93+
});
9194

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-
},
99-
},
100-
() => {
101-
return originalRequestHandler(request, initialContext);
102-
},
103-
);
104-
};
105-
};
106-
}
107-
return Reflect.get(target, prop, receiver);
108-
},
109-
});
95+
return startSpan(
96+
{
97+
name: getSpanName(url.pathname, request.method),
98+
attributes: {
99+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router',
100+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: getOpName(url.pathname, request.method),
101+
},
102+
},
103+
() => {
104+
return originalRequestHandler(request, initialContext);
105+
},
106+
);
107+
};
108+
};
110109
}
111110
}

0 commit comments

Comments
 (0)