Skip to content

Commit de3fe46

Browse files
committed
Bring error handling back
1 parent 4977e22 commit de3fe46

File tree

1 file changed

+62
-2
lines changed

1 file changed

+62
-2
lines changed

packages/remix/src/utils/instrumentServer.ts

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { RequestEventData } from '@sentry/core';
1+
import type { RequestEventData, WrappedFunction } from '@sentry/core';
22
import {
33
continueTrace,
44
fill,
@@ -12,14 +12,16 @@ import {
1212
withIsolationScope,
1313
} from '@sentry/core';
1414
import { DEBUG_BUILD } from './debug-build';
15-
import { captureRemixServerException } from './errors';
15+
import { captureRemixServerException, errorHandleDataFunction, errorHandleDocumentRequestFunction } from './errors';
1616
import { extractData, isDeferredData, isResponse, isRouteErrorResponse, json } from './vendor/response';
1717
import type {
1818
AppData,
1919
AppLoadContext,
2020
CreateRequestHandlerFunction,
2121
DataFunction,
2222
DataFunctionArgs,
23+
EntryContext,
24+
HandleDocumentRequestFunction,
2325
RemixRequest,
2426
RequestHandler,
2527
ServerBuild,
@@ -91,6 +93,45 @@ function getTraceAndBaggage(): {
9193
return {};
9294
}
9395

96+
function makeWrappedDocumentRequestFunction() {
97+
return function (origDocumentRequestFunction: HandleDocumentRequestFunction): HandleDocumentRequestFunction {
98+
return async function (
99+
this: unknown,
100+
request: Request,
101+
responseStatusCode: number,
102+
responseHeaders: Headers,
103+
context: EntryContext,
104+
loadContext?: Record<string, unknown>,
105+
): Promise<Response> {
106+
return errorHandleDocumentRequestFunction.call(this, origDocumentRequestFunction, {
107+
request,
108+
responseStatusCode,
109+
responseHeaders,
110+
context,
111+
loadContext,
112+
});
113+
};
114+
};
115+
}
116+
117+
function makeWrappedDataFunction(origFn: DataFunction, id: string, name: 'action' | 'loader'): DataFunction {
118+
return async function (this: unknown, args: DataFunctionArgs): Promise<Response | AppData> {
119+
return errorHandleDataFunction.call(this, origFn, name, args);
120+
};
121+
}
122+
123+
const makeWrappedAction =
124+
(id: string) =>
125+
(origAction: DataFunction): DataFunction => {
126+
return makeWrappedDataFunction(origAction, id, 'action');
127+
};
128+
129+
const makeWrappedLoader =
130+
(id: string) =>
131+
(origLoader: DataFunction): DataFunction => {
132+
return makeWrappedDataFunction(origLoader, id, 'loader');
133+
};
134+
94135
function makeWrappedRootLoader() {
95136
return function (origLoader: DataFunction): DataFunction {
96137
return async function (this: unknown, args: DataFunctionArgs): Promise<Response | AppData> {
@@ -177,9 +218,28 @@ function instrumentBuildCallback(build: ServerBuild): ServerBuild {
177218
const routes: ServerRouteManifest = {};
178219
const wrappedEntry = { ...build.entry, module: { ...build.entry.module } };
179220

221+
// Not keeping boolean flags like it's done for `requestHandler` functions,
222+
// Because the build can change between build and runtime.
223+
// So if there is a new `loader` or`action` or `documentRequest` after build.
224+
// We should be able to wrap them, as they may not be wrapped before.
225+
const defaultExport = wrappedEntry.module.default as undefined | WrappedFunction;
226+
if (defaultExport && !defaultExport.__sentry_original__) {
227+
fill(wrappedEntry.module, 'default', makeWrappedDocumentRequestFunction());
228+
}
229+
180230
for (const [id, route] of Object.entries(build.routes)) {
181231
const wrappedRoute = { ...route, module: { ...route.module } };
182232

233+
const routeAction = wrappedRoute.module.action as undefined | WrappedFunction;
234+
if (routeAction && !routeAction.__sentry_original__) {
235+
fill(wrappedRoute.module, 'action', makeWrappedAction(id));
236+
}
237+
238+
const routeLoader = wrappedRoute.module.loader as undefined | WrappedFunction;
239+
if (routeLoader && !routeLoader.__sentry_original__) {
240+
fill(wrappedRoute.module, 'loader', makeWrappedLoader(id));
241+
}
242+
183243
// Entry module should have a loader function to provide `sentry-trace` and `baggage`
184244
// They will be available for the root `meta` function as `data.sentryTrace` and `data.sentryBaggage`
185245
if (!wrappedRoute.parentId) {

0 commit comments

Comments
 (0)