Skip to content

test(e2e): Verify bundler plugins instrument a bundled graphql at runtime - #23670

Open
mydea wants to merge 2 commits into
fn/graphql-esm-instrumentfrom
fn/bundler-graphql-runtime
Open

test(e2e): Verify bundler plugins instrument a bundled graphql at runtime#23670
mydea wants to merge 2 commits into
fn/graphql-esm-instrumentfrom
fn/bundler-graphql-runtime

Conversation

@mydea

@mydea mydea commented Aug 27, 2026

Copy link
Copy Markdown
Member

Extends the five node bundler apps (node-webpack, node-vite, node-rollup, node-rolldown, node-esbuild) from a static banner-grep into a real runtime test, in the spirit of orchestrion-treeshake-repro: actually run the bundled service against a real package and verify what gets injected.

Each app now bundles a real graphql workload (inlined; only node builtins external) twice — plain (no plugin) and plugin (Sentry bundler plugin) — then runs both built bundles and asserts:

  • both builds: the graphql query still returns data (the plugin doesn't break the app or crash the bundle at boot),
  • plugin build: graphql auto-spans appear with origin auto.graphql.diagnostic_channel,
  • plain build: they do not (negative control).

This guards the fix beneath it (#23669) and catches the whole class of "bundle looks instrumented but emits no spans" regressions the static grep couldn't.

Decisions

  • Isolate the build-time path. The entry sets enableRuntimeChannelInjection: false and the bundles run with a plain node (no --import), so the bundler plugin is the only possible injector — making the plain build a true negative rather than something the runtime hook could rescue.
  • Capture via the spanEnd hook (+ spanToJSON) rather than beforeSendSpan, so collection is independent of transport and trace lifecycle. Transport is a no-op and the DSN fake — nothing hits the network.
  • Entry is an async function, not top-level await, so the same source bundles to both ESM and esbuild's CJS node output.
  • esbuild emits CJS, the other four emit ESM. esbuild's ESM output can't perform the CJS require('node:async_hooks') that @sentry/server-utils does once inlined (an esbuild CJS-in-ESM interop limit, the "separate bug" the repro noted); CJS output is the normal esbuild node target and sidesteps it. This also means esbuild resolves graphql's CJS build, so the suite covers both the .js and .mjs orchestrion paths.
  • Dropped the banner-grep assertion: the runtime span check is a strictly stronger proof that build-time injection ran, and the banner's new Set() formatting varies by bundler.

@mydea
mydea force-pushed the fn/bundler-graphql-runtime branch from 28dc52a to 36b76fb Compare August 27, 2026 08:26
@mydea
mydea force-pushed the fn/bundler-graphql-runtime branch from 36b76fb to 04d550b Compare August 27, 2026 08:26
@mydea
mydea force-pushed the fn/bundler-graphql-runtime branch from 04d550b to 0e12cc0 Compare August 27, 2026 08:29

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0e12cc0. Configure here.

Comment thread dev-packages/e2e-tests/test-applications/node-esbuild/src/entry.mjs
Comment thread dev-packages/e2e-tests/test-applications/node-esbuild/src/entry.mjs
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 28.57 kB - -
@sentry/browser - with treeshaking flags 26.92 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 26.82 kB - -
@sentry/browser (incl. Tracing) 48.63 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 48.65 kB - -
@sentry/browser (incl. Tracing, Profiling) 51.56 kB - -
@sentry/browser (incl. Tracing, Replay) 88.11 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 77.51 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 92.82 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 105.51 kB - -
@sentry/browser (incl. Feedback) 45.79 kB - -
@sentry/browser (incl. sendFeedback) 33.35 kB - -
@sentry/browser (incl. FeedbackAsync) 38.46 kB - -
@sentry/browser (incl. Metrics) 29.51 kB - -
@sentry/browser (incl. Logs) 29.8 kB - -
@sentry/browser (incl. Metrics & Logs) 30.43 kB - -
@sentry/react 30.31 kB - -
@sentry/react (incl. Tracing) 50.84 kB - -
@sentry/vue 35.69 kB - -
@sentry/vue (incl. Tracing) 50.88 kB - -
@sentry/svelte 28.59 kB - -
CDN Bundle 30.36 kB - -
CDN Bundle (incl. Tracing) 49.12 kB - -
CDN Bundle (incl. Logs, Metrics) 32.56 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 51.01 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 73 kB - -
CDN Bundle (incl. Tracing, Replay) 86.62 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 88.52 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 92.4 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 94.33 kB - -
CDN Bundle - uncompressed 89.97 kB - -
CDN Bundle (incl. Tracing) - uncompressed 146.82 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 96.26 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 152.51 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 225.42 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 266.32 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 272 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 280.01 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 285.68 kB - -
@sentry/nextjs (client) 53.41 kB - -
@sentry/sveltekit (client) 49.08 kB - -
@sentry/core/server 65.3 kB - -
@sentry/core/browser 52.37 kB - -
@sentry/node 122.37 kB +0.04% +41 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 85.23 kB +0.03% +19 B 🔺
@sentry/node - without tracing 87.69 kB +0.06% +46 B 🔺
@sentry/node - without channel injection 102.06 kB +0.04% +32 B 🔺
@sentry/aws-serverless 95.85 kB +0.05% +47 B 🔺
@sentry/cloudflare (withSentry) - minified 199.57 kB - -
@sentry/cloudflare (withSentry) 495.71 kB - -

View base workflow run

mydea and others added 2 commits August 27, 2026 11:35
…nstrumentation

Extends the node webpack/vite/rollup/rolldown/esbuild bundler apps from a static
banner-grep into a runtime test: each app bundles a real `graphql` workload (inlined,
only node builtins external) twice — `plain` (no plugin) and `plugin` (Sentry bundler
plugin) — then runs both built bundles and asserts the query still returns data and
that only the `plugin` build emits `auto.graphql.diagnostic_channel` spans.

The entry disables `enableRuntimeChannelInjection` and runs without `--import`, so the
bundler plugin is the only possible injector, making the `plain` build a true negative.
Spans are captured via the `spanEnd` hook (transport/lifecycle-independent). The entry
body is an async function (not top-level await) so it bundles to both ESM and esbuild's
CJS node output.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n set

Adds two more variants per bundler app that keep graphql external and run the built
bundle with `node --import @sentry/node/import`, so the runtime diagnostics-channel
hook instruments graphql at load time (the inlined variants exercise the build-time
transform instead). Each app now runs four scenarios:

  - plain            (inlined,  no plugin, no --import): no graphql spans (control)
  - plugin           (inlined,  plugin,    no --import): one set, build-time
  - plain-external   (external, no plugin, --import):    one set, runtime hook
  - plugin-external  (external, plugin,    --import):    one set, runtime hook only

The assert defines "one set" relative to the build-time run and checks every
instrumented scenario emits exactly that count — never zero, never double. The
plugin-external + --import case in particular proves the build-time plugin and the
runtime hook don't both instrument the same module (the plugin can't touch an
external dep, so the runtime hook is the sole injector).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mydea
mydea force-pushed the fn/bundler-graphql-runtime branch from e5bf0b9 to 07f694a Compare August 27, 2026 09:36
@mydea
mydea marked this pull request as ready for review August 27, 2026 11:37
@mydea
mydea requested review from Lms24, andreiborza and isaacs August 27, 2026 13:37
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.

1 participant