Skip to content

fix(node): Avoid double-wrapping http module #16177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
May 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

### Important Changes

- **fix(node): Avoid double-wrapping http module ([#16177](https://github.com/getsentry/sentry-javascript/pull/16177))**

When running your application in ESM mode, there have been scenarios that resulted in the `http`/`https` emitting duplicate spans for incoming requests. This was apparently caused by us double-wrapping the modules for incoming request isolation.

In order to solve this problem, the modules are no longer monkey patched by us for request isolation. Instead, we register diagnostics*channel hooks to handle request isolation now.
While this is generally not expected to break anything, there is one tiny change that \_may* affect you if you have been relying on very specific functionality:
Comment on lines +19 to +20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l: Markdown formatting here seems odd, is that on purpose?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, no!


The `ignoreOutgoingRequests` option of `httpIntegration` receives the `RequestOptions` as second argument. This type is not changed, however due to how the wrapping now works, we no longer pass through the full RequestOptions, but re-construct this partially based on the generated request. For the vast majority of cases, this should be fine, but for the sake of completeness, these are the only fields that may be available there going forward - other fields that _may_ have existed before may no longer be set:

```ts
ignoreOutgoingRequests(url: string, {
method: string;
protocol: string;
host: string;
hostname: string; // same as host
path: string;
headers: OutgoingHttpHeaders;
})
```

## 9.15.0

### Important Changes
Expand Down
2 changes: 1 addition & 1 deletion dev-packages/e2e-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"clean": "rimraf tmp node_modules && yarn clean:test-applications && yarn clean:pnpm",
"ci:build-matrix": "ts-node ./lib/getTestMatrix.ts",
"ci:build-matrix-optional": "ts-node ./lib/getTestMatrix.ts --optional=true",
"clean:test-applications": "rimraf --glob test-applications/**/{node_modules,dist,build,.next,.nuxt,.sveltekit,.react-router,pnpm-lock.yaml,.last-run.json,test-results}",
"clean:test-applications": "rimraf --glob test-applications/**/{node_modules,dist,build,.next,.nuxt,.sveltekit,.react-router,.astro,.output,pnpm-lock.yaml,.last-run.json,test-results}",
"clean:pnpm": "pnpm store prune"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ test.describe('tracing in dynamically rendered (ssr) routes', () => {
});

expect(serverPageRequestTxn).toMatchObject({
breadcrumbs: expect.any(Array),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this used to be the breadcrumbs of other errors from other tests.. which seems wrong to me, actually? So I wonder if this actually fixes something with astro, which is possible as now this is unrelated to when this is initialized, I guess..

Copy link
Member

@Lms24 Lms24 May 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this could fix some kind of isolation problem since request isolation in Astro was limited to the middleware lifecycle previously. Maybe something didn't work as expected in there or there was a timing issue. Gonna say it's finde until proven otherwise :D

contexts: {
app: expect.any(Object),
cloud_resource: expect.any(Object),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,28 @@ describe('express with http import', () => {
cleanupChildProcesses();
});

createEsmAndCjsTests(
__dirname,
'scenario.mjs',
'instrument.mjs',
(createRunner, test) => {
test('it works when importing the http module', async () => {
const runner = createRunner()
.expect({
transaction: {
transaction: 'GET /test2',
},
})
.expect({
transaction: {
transaction: 'GET /test',
},
})
.expect({
transaction: {
transaction: 'GET /test3',
},
})
.start();
await runner.makeRequest('get', '/test');
await runner.makeRequest('get', '/test3');
await runner.completed();
});
// TODO: This is failing on ESM because importing http is triggering the http spans twice :(
// We need to fix this!
},
{ failsOnEsm: true },
);
createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => {
test('it works when importing the http module', async () => {
const runner = createRunner()
.expect({
transaction: {
transaction: 'GET /test2',
},
})
.expect({
transaction: {
transaction: 'GET /test',
},
})
.expect({
transaction: {
transaction: 'GET /test3',
},
})
.start();
await runner.makeRequest('get', '/test');
await runner.makeRequest('get', '/test3');
await runner.completed();
});
});
});
Loading
Loading