Skip to content

Commit c2cdf92

Browse files
authored
fix(remix): Wrap domains properly on instrumentServer (#5590)
#5570 merged, but the tests were being very flaky. I took another look and figured out that we only needed to wrap our instrumentation with a domain once. Wrapping twice (for both express and built-in) was causing problems. In addition, I moved the wrapping down to the request handling phase, which makes the behaviour more correct.
1 parent bdd7fde commit c2cdf92

File tree

3 files changed

+33
-48
lines changed

3 files changed

+33
-48
lines changed

packages/remix/src/utils/instrumentServer.ts

+15-13
Original file line numberDiff line numberDiff line change
@@ -320,22 +320,25 @@ function wrapRequestHandler(origRequestHandler: RequestHandler, build: ServerBui
320320
const routes = createRoutes(build.routes);
321321
const pkg = loadModule<ReactRouterDomPkg>('react-router-dom');
322322
return async function (this: unknown, request: Request, loadContext?: unknown): Promise<Response> {
323-
const hub = getCurrentHub();
324-
const options = hub.getClient()?.getOptions();
323+
const local = domain.create();
324+
return local.bind(async () => {
325+
const hub = getCurrentHub();
326+
const options = hub.getClient()?.getOptions();
325327

326-
if (!options || !hasTracingEnabled(options)) {
327-
return origRequestHandler.call(this, request, loadContext);
328-
}
328+
if (!options || !hasTracingEnabled(options)) {
329+
return origRequestHandler.call(this, request, loadContext);
330+
}
329331

330-
const url = new URL(request.url);
331-
const transaction = startRequestHandlerTransaction(url, request.method, routes, hub, pkg);
332+
const url = new URL(request.url);
333+
const transaction = startRequestHandlerTransaction(url, request.method, routes, hub, pkg);
332334

333-
const res = (await origRequestHandler.call(this, request, loadContext)) as Response;
335+
const res = (await origRequestHandler.call(this, request, loadContext)) as Response;
334336

335-
transaction.setHttpStatus(res.status);
336-
transaction.finish();
337+
transaction.setHttpStatus(res.status);
338+
transaction.finish();
337339

338-
return res;
340+
return res;
341+
})();
339342
};
340343
}
341344

@@ -421,8 +424,7 @@ function makeWrappedCreateRequestHandler(
421424
const newBuild = instrumentBuild(build);
422425
const requestHandler = origCreateRequestHandler.call(this, newBuild, ...args);
423426

424-
const local = domain.create();
425-
return local.bind(() => wrapRequestHandler(requestHandler, newBuild))();
427+
return wrapRequestHandler(requestHandler, newBuild);
426428
};
427429
}
428430

packages/remix/src/utils/serverAdapters/express.ts

+9-16
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { flush } from '@sentry/node';
33
import { hasTracingEnabled } from '@sentry/tracing';
44
import { Transaction } from '@sentry/types';
55
import { extractRequestData, loadModule, logger } from '@sentry/utils';
6-
import * as domain from 'domain';
76

87
import {
98
createRoutes,
@@ -43,23 +42,17 @@ function wrapExpressRequestHandler(
4342
// eslint-disable-next-line @typescript-eslint/unbound-method
4443
res.end = wrapEndMethod(res.end);
4544

46-
const local = domain.create();
47-
local.add(req);
48-
local.add(res);
45+
const request = extractRequestData(req);
46+
const hub = getCurrentHub();
47+
const options = hub.getClient()?.getOptions();
4948

50-
local.run(async () => {
51-
const request = extractRequestData(req);
52-
const hub = getCurrentHub();
53-
const options = hub.getClient()?.getOptions();
49+
if (!options || !hasTracingEnabled(options) || !request.url || !request.method) {
50+
return origRequestHandler.call(this, req, res, next);
51+
}
5452

55-
if (!options || !hasTracingEnabled(options) || !request.url || !request.method) {
56-
return origRequestHandler.call(this, req, res, next);
57-
}
58-
59-
const url = new URL(request.url);
60-
startRequestHandlerTransaction(url, request.method, routes, hub, pkg);
61-
await origRequestHandler.call(this, req, res, next);
62-
});
53+
const url = new URL(request.url);
54+
startRequestHandlerTransaction(url, request.method, routes, hub, pkg);
55+
return origRequestHandler.call(this, req, res, next);
6356
};
6457
}
6558

packages/remix/test/integration/test/server/loader.test.ts

+9-19
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
getMultipleEnvelopeRequest,
66
assertSentryEvent,
77
} from './utils/helpers';
8+
import { Event } from '@sentry/types';
89

910
jest.spyOn(console, 'error').mockImplementation();
1011

@@ -149,25 +150,14 @@ describe.each(['builtin', 'express'])('Remix API Loaders with adapter = %s', ada
149150
scope.persist(false);
150151
await new Promise(resolve => server.close(resolve));
151152

152-
assertSentryTransaction(envelopes[0][2], {
153-
tags: {
154-
tag4: '4',
155-
},
156-
});
157-
assertSentryTransaction(envelopes[1][2], {
158-
tags: {
159-
tag3: '3',
160-
},
161-
});
162-
assertSentryTransaction(envelopes[2][2], {
163-
tags: {
164-
tag2: '2',
165-
},
166-
});
167-
assertSentryTransaction(envelopes[3][2], {
168-
tags: {
169-
tag1: '1',
170-
},
153+
envelopes.forEach(envelope => {
154+
const tags = envelope[2].tags as NonNullable<Event['tags']>;
155+
const customTagArr = Object.keys(tags).filter(t => t.startsWith('tag'));
156+
expect(customTagArr).toHaveLength(1);
157+
158+
const key = customTagArr[0];
159+
const val = key[key.length - 1];
160+
expect(tags[key]).toEqual(val);
171161
});
172162
});
173163
});

0 commit comments

Comments
 (0)