Skip to content

Conversation

mydea
Copy link
Member

@mydea mydea commented Sep 3, 2025

This is a first step to de-compose the node/node-core httpIntegration into multiple composable parts:

  • httpServerIntegration - handles request isolation, sessions, trace continuation, so core Sentry functionality
  • httpServerSpansIntegration - emits http.server spans for incoming requests

The httpIntegration sets these up under the hood, and for now it is not really recommended for users to use these stand-alone (though it is possible if users opt-out of the httpIntegration). The reason is to remain backwards compatible with users using/customizing the httpIntegration. We can revisit this in a later major.

These new integrations have a much slimmer API surface, and also allows us to avoid having to prefix all the options etc. with what they are about (e.g. incomingXXX or outgoingXXX). It also means you can actually tree-shake certain features (span creation) out, in theory.

Outgoing request handling remains the same for the time being, once we decoupled this from the otel http instrumentation we can do something similar there.

The biggest challenge was how to make it possible to de-compose this without having to monkey patch the http server twice. I opted to allow to add callbacks to the httpServerIntegration which it will call on any request. So the httpServerSpansIntegration can register a callback for itself and plug into this with little overhead.


Note

Introduce httpServerIntegration and httpServerSpansIntegration, refactor HTTP composition and add a httpServerRequest client hook; update exports and tests across SDKs.

  • Node-Core:
    • New Integrations: Add httpServerIntegration (request isolation, sessions, body capture) and httpServerSpansIntegration (emit http.server spans; filtering, hooks).
    • Client Hook: Add client.on/emit('httpServerRequest', request, response, normalizedRequest).
    • Refactor: httpIntegration now composes httpServerIntegration + httpServerSpansIntegration + SentryHttpInstrumentation (outgoing breadcrumbs/trace headers only). Remove legacy incoming-requests path.
    • SentryHttpInstrumentation: Drop incoming server handling; keep outgoing request breadcrumbs/propagation.
    • Type/Build: Use WeakRef (tsconfig lib updated).
  • SDKs/Exports:
    • Export httpServerIntegration and httpServerSpansIntegration from @sentry/node-core and re-export via @sentry/node, bun, aws-serverless, google-cloud-serverless, astro, remix, solidstart.
  • Astro:
    • Add event processor to drop transaction events for http.server spans with origin auto.http.otel.http (e.g. prerendered pages).
  • Tests:
    • Update imports to new modules; adjust recordRequestSession usage and promise buffer timeout expectation.

Written by Cursor Bugbot for commit be14b96. This will update automatically on new commits. Configure here.

@mydea mydea self-assigned this Sep 3, 2025
Copy link
Contributor

github-actions bot commented Sep 3, 2025

size-limit report 📦

Path Size % Change Change
@sentry/browser 24.23 kB - -
@sentry/browser - with treeshaking flags 22.75 kB - -
@sentry/browser (incl. Tracing) 40.42 kB - -
@sentry/browser (incl. Tracing, Replay) 78.8 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 68.45 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 83.47 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 95.67 kB - -
@sentry/browser (incl. Feedback) 40.95 kB - -
@sentry/browser (incl. sendFeedback) 28.89 kB - -
@sentry/browser (incl. FeedbackAsync) 33.82 kB +0.01% +1 B 🔺
@sentry/react 25.96 kB - -
@sentry/react (incl. Tracing) 42.39 kB - -
@sentry/vue 28.75 kB - -
@sentry/vue (incl. Tracing) 42.23 kB - -
@sentry/svelte 24.26 kB - -
CDN Bundle 25.75 kB - -
CDN Bundle (incl. Tracing) 40.31 kB - -
CDN Bundle (incl. Tracing, Replay) 76.55 kB -0.01% -1 B 🔽
CDN Bundle (incl. Tracing, Replay, Feedback) 82.06 kB - -
CDN Bundle - uncompressed 75.3 kB - -
CDN Bundle (incl. Tracing) - uncompressed 119.31 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 234.47 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 247.23 kB - -
@sentry/nextjs (client) 44.4 kB - -
@sentry/sveltekit (client) 40.84 kB - -
@sentry/node-core 50.33 kB +0.66% +329 B 🔺
@sentry/node 153.41 kB +0.25% +382 B 🔺
@sentry/node - without tracing 92.18 kB +0.28% +255 B 🔺
@sentry/aws-serverless 105.74 kB +0.36% +374 B 🔺

View base workflow run

Copy link
Contributor

github-actions bot commented Sep 3, 2025

node-overhead report 🧳

Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.

Scenario Requests/s % of Baseline Prev. Requests/s Change %
GET Baseline 8,553 - 9,189 -7%
GET With Sentry 1,289 15% 1,441 -11%
GET With Sentry (error only) 5,850 68% 6,134 -5%
POST Baseline 1,141 - 1,223 -7%
POST With Sentry 453 40% 561 -19%
POST With Sentry (error only) 955 84% 1,078 -11%
MYSQL Baseline 3,217 - 3,370 -5%
MYSQL With Sentry 412 13% 503 -18%
MYSQL With Sentry (error only) 2,591 81% 2,778 -7%

View base workflow run

@mydea mydea force-pushed the fn/extract-http-server-intergation branch 3 times, most recently from b361f67 to 8180ea7 Compare September 8, 2025 09:03
* This integration handles request isolation, trace continuation and other core Sentry functionality around incoming http requests
* handled via the node `http` module.
*/
export const httpServerIntegration = _httpServerIntegration as (
Copy link
Member Author

Choose a reason for hiding this comment

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

exporting the types that we depend on here directly so we can call this in a type-safe way.

@mydea mydea marked this pull request as ready for review September 8, 2025 14:14
@mydea mydea force-pushed the fn/extract-http-server-intergation branch from 8180ea7 to a2bf73c Compare September 8, 2025 14:14
Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

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

Nice, thanks for splitting this up! I think this makes the integrations more readable.

/**
* Register a client callback that will be called when a request is received.
*/
export function registerServerCallback(
Copy link
Member

Choose a reason for hiding this comment

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

I think the callback idea is fine for now but just to confirm: There's no scenario in which users would only register e.g. httpSeverSpansIntegration but NOT httpServerIntegration, right? In that case it wouldn't work I suppose but this is fine if it's out of scope.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll log a warning in this case for now, IMHO that makes sense. I don't think we need to handle this as of now, we can say the one requires the other :)

@mydea mydea force-pushed the fn/extract-http-server-intergation branch 3 times, most recently from a8df443 to cd42f95 Compare September 18, 2025 07:45
@mydea
Copy link
Member Author

mydea commented Sep 18, 2025

FYI I rewrote this to use a hook & non-enumerable property on the request to handle the separation of concerns, vs. keeping this in module scope per-client. I think this is the safer option to go as it means we should be resilient against module scope issues, as well as being more performant because we literally only expect/allow a single callback, not making this generic.

Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

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

I think the client hook refactor is a good idea!


const flushPendingClientAggregates = (): void => {
clearTimeout(timeout);
unregisterClientFlushHook();
Copy link
Member

@Lms24 Lms24 Sep 19, 2025

Choose a reason for hiding this comment

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

I'm not sure if we're listening to more than one 'flush' event but as I learned the hard way inhttps://github.com//pull/17272, synchronously unsubscribing from the hook in the same callback is dangerous. It shouldn't be though, so I'll take a look at #17276 to fix this. If we wanna be extra sure to not cause array mutations here, we can use something like safeUnsubscribe in #16893. Otherwise, we can also ignore this for now and wait for the general fix.

Copy link
Member Author

Choose a reason for hiding this comment

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

huh, interesting! This has not changed here (just moved around) but sounds reasonable to me just fix this generally with your other PR 👍

@mydea mydea force-pushed the fn/extract-http-server-intergation branch 2 times, most recently from 7162c76 to 3154341 Compare September 22, 2025 12:59
@mydea mydea force-pushed the fn/extract-http-server-intergation branch 2 times, most recently from 398c5c0 to f098c0b Compare September 29, 2025 12:09
@mydea mydea force-pushed the fn/extract-http-server-intergation branch from 6732caa to be14b96 Compare September 29, 2025 13:42
@mydea mydea merged commit 7b40a95 into develop Sep 29, 2025
363 of 371 checks passed
@mydea mydea deleted the fn/extract-http-server-intergation branch September 29, 2025 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants