feat(server-utils): Instrument graphql v17 via native tracing channels - #21804

Merged
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels
Jul 7, 2026
Merged

feat(server-utils): Instrument graphql v17 via native tracing channels#21804
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels

Conversation

@logaretm

@logaretmlogaretm commented Jun 25, 2026

Copy link
Copy Markdown
Member

GraphQL v17 uses its native diagnostics_channel for tracing instead of monkey-patching. It publishes lifecycle events on:

  • graphql:parse
  • graphql:validate
  • graphql:execute
  • graphql:subscribe

This PR adds new graphqlIntegration in server-utils that subscribes to these events and builds spans with graphql semantic conventions. The graphqlIntegration node extends this integration and keeps the vendored OTel patcher for graphql < 17. The patcher is gated >=14 <17.

A couple of things worth calling out:

  • The graphql.document value is the original query text with inline literal arguments redacted ("foo""*", 42*) so raw values can't leak, and variable values are never attached.
  • Per-field graphql:resolve spans are off by default because they're very high volume, users can opt in via ignoreResolveSpans just like previous versions.

@github-actions

github-actionsBot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser27.59 kB--
@sentry/browser - with treeshaking flags26.03 kB--
@sentry/browser (incl. Tracing)46.27 kB--
@sentry/browser (incl. Tracing + Span Streaming)48.03 kB--
@sentry/browser (incl. Tracing, Profiling)51.03 kB--
@sentry/browser (incl. Tracing, Replay)85.56 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags75.17 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)90.26 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)102.91 kB--
@sentry/browser (incl. Feedback)44.76 kB--
@sentry/browser (incl. sendFeedback)32.38 kB--
@sentry/browser (incl. FeedbackAsync)37.51 kB--
@sentry/browser (incl. Metrics)28.67 kB--
@sentry/browser (incl. Logs)28.91 kB--
@sentry/browser (incl. Metrics & Logs)29.59 kB--
@sentry/react29.38 kB--
@sentry/react (incl. Tracing)48.53 kB--
@sentry/vue33.03 kB--
@sentry/vue (incl. Tracing)48.16 kB--
@sentry/svelte27.61 kB--
CDN Bundle30 kB--
CDN Bundle (incl. Tracing)48.26 kB--
CDN Bundle (incl. Logs, Metrics)31.57 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)49.57 kB--
CDN Bundle (incl. Replay, Logs, Metrics)70.81 kB--
CDN Bundle (incl. Tracing, Replay)85.73 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)87.04 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)91.55 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)92.83 kB--
CDN Bundle - uncompressed89.35 kB--
CDN Bundle (incl. Tracing) - uncompressed145.99 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed94.05 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed149.96 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed218.75 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed265.16 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed269.12 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed278.86 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed282.81 kB--
@sentry/nextjs (client)50.94 kB--
@sentry/sveltekit (client)46.68 kB--
@sentry/core/server78.38 kB--
@sentry/core/browser64.72 kB--
@sentry/node-core63.21 kB--
@sentry/node124.73 kB+0.67%+830 B 🔺
@sentry/node (incl. diagnostics channel injection)130.64 kB+0.65%+836 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection)69.95 kB--
@sentry/node/light50.72 kB+0.01%+1 B 🔺
@sentry/node - without tracing74.82 kB+0.01%+1 B 🔺
@sentry/aws-serverless85.6 kB--
@sentry/cloudflare (withSentry) - minified181.68 kB--
@sentry/cloudflare (withSentry)449.39 kB--

View base workflow run

@logaretmlogaretm changed the title feat(server-utils): Instrument graphql v17 via native diagnostics_channel tracing channelsfeat(server-utils): Instrument graphql v17 via native tracing channelsJun 25, 2026
@mydea
mydeaforce-pushed the fn/better-integration-extend branch 2 times, most recently from 2407b9e to 31520beCompareJune 26, 2026 08:48
Base automatically changed from fn/better-integration-extend to developJune 26, 2026 09:38
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from c907efa to 3da22d3CompareJune 26, 2026 11:48
@logaretm
logaretm marked this pull request as ready for review June 26, 2026 12:55
@logaretm
logaretm requested a review from a team as a code ownerJune 26, 2026 12:55
@logaretm
logaretm requested review from JPeer264, andreiborza, isaacs and mydea and removed request for a teamJune 26, 2026 12:55
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from abebece to 3f660c0CompareJune 26, 2026 13:01
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@github-actions

Copy link
Copy Markdown
Contributor

👋 @isaacs, @mydea, @JPeer264, @andreiborza — Please review this PR when you get a chance!

Comment threadpackages/server-utils/src/graphql/index.ts Outdated
Comment threadpackages/server-utils/src/graphql/index.ts Outdated
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch 2 times, most recently from 4b397eb to a1e12c5CompareJuly 2, 2026 16:19
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from a1e12c5 to 6e1c439CompareJuly 2, 2026 19:05
@logaretm
logaretm requested a review from mydeaJuly 2, 2026 20:03

@cursorcursorBot 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 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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 93ff31a. Configure here.

Comment threadpackages/node/src/integrations/tracing/graphql/index.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question. Does this behave differently than versions below v16? There seems to be a lot of new code actually for v17

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is mostly great, found a few things that (if I'm reading it correctly) are fixable problems, and if I'm not, could benefit at least from a comment or debug log. The only one I'd gate on is dropping the useOperationNameForRootSpan option, which should at least get a documentation update if it's intentional.

  • Uses conventions
  • Tests etc added
  • Code is easy to follow.

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
@logaretm
logaretm requested a review from isaacsJuly 3, 2026 19:25
@github-actions

Copy link
Copy Markdown
Contributor

👋 @andreiborza — Please review this PR when you get a chance!

@logaretm
logaretm requested a review from JPeer264July 6, 2026 13:51
@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea — Please review this PR when you get a chance!

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM once everything from @isaacs got resolved

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All my concerns look like they've been addressed, so this LGTM!

logaretm added 12 commits July 7, 2026 14:15
…nnel tracing channels
Adds a graphqlChannelIntegration in server-utils that subscribes to graphql >= 17's
native node:diagnostics_channel tracing channels (graphql:parse / :validate / :execute
/ :subscribe) and builds spans with the graphql semantic conventions. The node
graphqlIntegration extends it via extendIntegration so the vendored OTel patcher still
handles graphql < 17. Per-field graphql:resolve spans are omitted (high volume; the OTel
path also defaults them off).
…pans option
Wires the per-field `graphql:resolve` channel into the graphql diagnostics-channel
subscriber, gated behind the existing `ignoreResolveSpans` option (default true, so off
by default). When enabled, `ignoreTrivialResolveSpans` (default true) additionally skips
graphql's default property resolver. Both options now flow through to the channel path,
matching the vendored OTel patcher's behavior on graphql < 17.
…keeping
Split option-matrix tests into process-isolated files instead of resetting
and re-subscribing the process-global channels.
…tion
Runtimes that use the server-utils integration directly expose it to users,
so 'channel' in the name leaks an implementation detail. Node imports it under
an internal alias since it keeps its own composed graphqlIntegration.
Replace the conditional-spread pattern for optional attributes with
`?? undefined`. Undefined-valued keys are dropped by the span backends,
so this is equivalent while keeping the attribute lines consistent.
Replace the ad-hoc `void Promise.resolve().then(...)` deferral with the
shared `waitForTracingChannelBinding` util, matching the mongoose,
vercel-ai and redis integrations. It retries until the async context
binding is available, so it also handles custom OTel setups where the
binding isn't ready on the first tick.
The `?? undefined` on `document` (already `string | undefined`) was a no-op.
Switch `operationName` to `|| undefined` so blank operation names are omitted
rather than recorded as empty-string attributes.
…s-channel path
Ports the legacy OTel useOperationNameForRootSpan behavior (default on) to the
graphql >= 17 diagnostics-channel subscriber, so upgrading graphql no longer drops
root-span renaming. Moves the pure graphql helpers into a utils file.
The internal subscribe function has a single deduped setupOnce caller via
waitForTracingChannelBinding, so the subscribed flag guarded a path that
can't occur. Remove it along with the obsolete idempotency test, mirroring
the mysql2 subscriber.
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from 6395981 to c61c848CompareJuly 7, 2026 18:17
@logaretm
logaretm merged commit c0c2b01 into developJul 7, 2026
214 checks passed
@logaretm
logaretm deleted the awad/graphql-tracing-channels branch July 7, 2026 18:41
Sign up for freeto 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.

4 participants

@logaretm@isaacs@mydea@JPeer264
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(server-utils): Instrument graphql v17 via native tracing channels - #21804

Merged
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels
Jul 7, 2026
Merged

feat(server-utils): Instrument graphql v17 via native tracing channels#21804
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels

Conversation

@logaretm

@logaretmlogaretm commented Jun 25, 2026

Copy link
Copy Markdown
Member

GraphQL v17 uses its native diagnostics_channel for tracing instead of monkey-patching. It publishes lifecycle events on:

  • graphql:parse
  • graphql:validate
  • graphql:execute
  • graphql:subscribe

This PR adds new graphqlIntegration in server-utils that subscribes to these events and builds spans with graphql semantic conventions. The graphqlIntegration node extends this integration and keeps the vendored OTel patcher for graphql < 17. The patcher is gated >=14 <17.

A couple of things worth calling out:

  • The graphql.document value is the original query text with inline literal arguments redacted ("foo""*", 42*) so raw values can't leak, and variable values are never attached.
  • Per-field graphql:resolve spans are off by default because they're very high volume, users can opt in via ignoreResolveSpans just like previous versions.

@github-actions

github-actionsBot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser27.59 kB--
@sentry/browser - with treeshaking flags26.03 kB--
@sentry/browser (incl. Tracing)46.27 kB--
@sentry/browser (incl. Tracing + Span Streaming)48.03 kB--
@sentry/browser (incl. Tracing, Profiling)51.03 kB--
@sentry/browser (incl. Tracing, Replay)85.56 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags75.17 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)90.26 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)102.91 kB--
@sentry/browser (incl. Feedback)44.76 kB--
@sentry/browser (incl. sendFeedback)32.38 kB--
@sentry/browser (incl. FeedbackAsync)37.51 kB--
@sentry/browser (incl. Metrics)28.67 kB--
@sentry/browser (incl. Logs)28.91 kB--
@sentry/browser (incl. Metrics & Logs)29.59 kB--
@sentry/react29.38 kB--
@sentry/react (incl. Tracing)48.53 kB--
@sentry/vue33.03 kB--
@sentry/vue (incl. Tracing)48.16 kB--
@sentry/svelte27.61 kB--
CDN Bundle30 kB--
CDN Bundle (incl. Tracing)48.26 kB--
CDN Bundle (incl. Logs, Metrics)31.57 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)49.57 kB--
CDN Bundle (incl. Replay, Logs, Metrics)70.81 kB--
CDN Bundle (incl. Tracing, Replay)85.73 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)87.04 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)91.55 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)92.83 kB--
CDN Bundle - uncompressed89.35 kB--
CDN Bundle (incl. Tracing) - uncompressed145.99 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed94.05 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed149.96 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed218.75 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed265.16 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed269.12 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed278.86 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed282.81 kB--
@sentry/nextjs (client)50.94 kB--
@sentry/sveltekit (client)46.68 kB--
@sentry/core/server78.38 kB--
@sentry/core/browser64.72 kB--
@sentry/node-core63.21 kB--
@sentry/node124.73 kB+0.67%+830 B 🔺
@sentry/node (incl. diagnostics channel injection)130.64 kB+0.65%+836 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection)69.95 kB--
@sentry/node/light50.72 kB+0.01%+1 B 🔺
@sentry/node - without tracing74.82 kB+0.01%+1 B 🔺
@sentry/aws-serverless85.6 kB--
@sentry/cloudflare (withSentry) - minified181.68 kB--
@sentry/cloudflare (withSentry)449.39 kB--

View base workflow run

@logaretmlogaretm changed the title feat(server-utils): Instrument graphql v17 via native diagnostics_channel tracing channelsfeat(server-utils): Instrument graphql v17 via native tracing channelsJun 25, 2026
@mydea
mydeaforce-pushed the fn/better-integration-extend branch 2 times, most recently from 2407b9e to 31520beCompareJune 26, 2026 08:48
Base automatically changed from fn/better-integration-extend to developJune 26, 2026 09:38
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from c907efa to 3da22d3CompareJune 26, 2026 11:48
@logaretm
logaretm marked this pull request as ready for review June 26, 2026 12:55
@logaretm
logaretm requested a review from a team as a code ownerJune 26, 2026 12:55
@logaretm
logaretm requested review from JPeer264, andreiborza, isaacs and mydea and removed request for a teamJune 26, 2026 12:55
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from abebece to 3f660c0CompareJune 26, 2026 13:01
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@github-actions

Copy link
Copy Markdown
Contributor

👋 @isaacs, @mydea, @JPeer264, @andreiborza — Please review this PR when you get a chance!

Comment threadpackages/server-utils/src/graphql/index.ts Outdated
Comment threadpackages/server-utils/src/graphql/index.ts Outdated
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch 2 times, most recently from 4b397eb to a1e12c5CompareJuly 2, 2026 16:19
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from a1e12c5 to 6e1c439CompareJuly 2, 2026 19:05
@logaretm
logaretm requested a review from mydeaJuly 2, 2026 20:03

@cursorcursorBot 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 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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 93ff31a. Configure here.

Comment threadpackages/node/src/integrations/tracing/graphql/index.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question. Does this behave differently than versions below v16? There seems to be a lot of new code actually for v17

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is mostly great, found a few things that (if I'm reading it correctly) are fixable problems, and if I'm not, could benefit at least from a comment or debug log. The only one I'd gate on is dropping the useOperationNameForRootSpan option, which should at least get a documentation update if it's intentional.

  • Uses conventions
  • Tests etc added
  • Code is easy to follow.

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
@logaretm
logaretm requested a review from isaacsJuly 3, 2026 19:25
@github-actions

Copy link
Copy Markdown
Contributor

👋 @andreiborza — Please review this PR when you get a chance!

@logaretm
logaretm requested a review from JPeer264July 6, 2026 13:51
@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea — Please review this PR when you get a chance!

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM once everything from @isaacs got resolved

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All my concerns look like they've been addressed, so this LGTM!

logaretm added 12 commits July 7, 2026 14:15
…nnel tracing channels
Adds a graphqlChannelIntegration in server-utils that subscribes to graphql >= 17's
native node:diagnostics_channel tracing channels (graphql:parse / :validate / :execute
/ :subscribe) and builds spans with the graphql semantic conventions. The node
graphqlIntegration extends it via extendIntegration so the vendored OTel patcher still
handles graphql < 17. Per-field graphql:resolve spans are omitted (high volume; the OTel
path also defaults them off).
…pans option
Wires the per-field `graphql:resolve` channel into the graphql diagnostics-channel
subscriber, gated behind the existing `ignoreResolveSpans` option (default true, so off
by default). When enabled, `ignoreTrivialResolveSpans` (default true) additionally skips
graphql's default property resolver. Both options now flow through to the channel path,
matching the vendored OTel patcher's behavior on graphql < 17.
…keeping
Split option-matrix tests into process-isolated files instead of resetting
and re-subscribing the process-global channels.
…tion
Runtimes that use the server-utils integration directly expose it to users,
so 'channel' in the name leaks an implementation detail. Node imports it under
an internal alias since it keeps its own composed graphqlIntegration.
Replace the conditional-spread pattern for optional attributes with
`?? undefined`. Undefined-valued keys are dropped by the span backends,
so this is equivalent while keeping the attribute lines consistent.
Replace the ad-hoc `void Promise.resolve().then(...)` deferral with the
shared `waitForTracingChannelBinding` util, matching the mongoose,
vercel-ai and redis integrations. It retries until the async context
binding is available, so it also handles custom OTel setups where the
binding isn't ready on the first tick.
The `?? undefined` on `document` (already `string | undefined`) was a no-op.
Switch `operationName` to `|| undefined` so blank operation names are omitted
rather than recorded as empty-string attributes.
…s-channel path
Ports the legacy OTel useOperationNameForRootSpan behavior (default on) to the
graphql >= 17 diagnostics-channel subscriber, so upgrading graphql no longer drops
root-span renaming. Moves the pure graphql helpers into a utils file.
The internal subscribe function has a single deduped setupOnce caller via
waitForTracingChannelBinding, so the subscribed flag guarded a path that
can't occur. Remove it along with the obsolete idempotency test, mirroring
the mysql2 subscriber.
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from 6395981 to c61c848CompareJuly 7, 2026 18:17
@logaretm
logaretm merged commit c0c2b01 into developJul 7, 2026
214 checks passed
@logaretm
logaretm deleted the awad/graphql-tracing-channels branch July 7, 2026 18:41
Sign up for freeto 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.

4 participants

@logaretm@isaacs@mydea@JPeer264
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(server-utils): Instrument graphql v17 via native tracing channels - #21804

Merged
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels
Jul 7, 2026
Merged

feat(server-utils): Instrument graphql v17 via native tracing channels#21804
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels

Conversation

@logaretm

@logaretmlogaretm commented Jun 25, 2026

Copy link
Copy Markdown
Member

GraphQL v17 uses its native diagnostics_channel for tracing instead of monkey-patching. It publishes lifecycle events on:

  • graphql:parse
  • graphql:validate
  • graphql:execute
  • graphql:subscribe

This PR adds new graphqlIntegration in server-utils that subscribes to these events and builds spans with graphql semantic conventions. The graphqlIntegration node extends this integration and keeps the vendored OTel patcher for graphql < 17. The patcher is gated >=14 <17.

A couple of things worth calling out:

  • The graphql.document value is the original query text with inline literal arguments redacted ("foo""*", 42*) so raw values can't leak, and variable values are never attached.
  • Per-field graphql:resolve spans are off by default because they're very high volume, users can opt in via ignoreResolveSpans just like previous versions.

@github-actions

github-actionsBot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser27.59 kB--
@sentry/browser - with treeshaking flags26.03 kB--
@sentry/browser (incl. Tracing)46.27 kB--
@sentry/browser (incl. Tracing + Span Streaming)48.03 kB--
@sentry/browser (incl. Tracing, Profiling)51.03 kB--
@sentry/browser (incl. Tracing, Replay)85.56 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags75.17 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)90.26 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)102.91 kB--
@sentry/browser (incl. Feedback)44.76 kB--
@sentry/browser (incl. sendFeedback)32.38 kB--
@sentry/browser (incl. FeedbackAsync)37.51 kB--
@sentry/browser (incl. Metrics)28.67 kB--
@sentry/browser (incl. Logs)28.91 kB--
@sentry/browser (incl. Metrics & Logs)29.59 kB--
@sentry/react29.38 kB--
@sentry/react (incl. Tracing)48.53 kB--
@sentry/vue33.03 kB--
@sentry/vue (incl. Tracing)48.16 kB--
@sentry/svelte27.61 kB--
CDN Bundle30 kB--
CDN Bundle (incl. Tracing)48.26 kB--
CDN Bundle (incl. Logs, Metrics)31.57 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)49.57 kB--
CDN Bundle (incl. Replay, Logs, Metrics)70.81 kB--
CDN Bundle (incl. Tracing, Replay)85.73 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)87.04 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)91.55 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)92.83 kB--
CDN Bundle - uncompressed89.35 kB--
CDN Bundle (incl. Tracing) - uncompressed145.99 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed94.05 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed149.96 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed218.75 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed265.16 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed269.12 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed278.86 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed282.81 kB--
@sentry/nextjs (client)50.94 kB--
@sentry/sveltekit (client)46.68 kB--
@sentry/core/server78.38 kB--
@sentry/core/browser64.72 kB--
@sentry/node-core63.21 kB--
@sentry/node124.73 kB+0.67%+830 B 🔺
@sentry/node (incl. diagnostics channel injection)130.64 kB+0.65%+836 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection)69.95 kB--
@sentry/node/light50.72 kB+0.01%+1 B 🔺
@sentry/node - without tracing74.82 kB+0.01%+1 B 🔺
@sentry/aws-serverless85.6 kB--
@sentry/cloudflare (withSentry) - minified181.68 kB--
@sentry/cloudflare (withSentry)449.39 kB--

View base workflow run

@logaretmlogaretm changed the title feat(server-utils): Instrument graphql v17 via native diagnostics_channel tracing channelsfeat(server-utils): Instrument graphql v17 via native tracing channelsJun 25, 2026
@mydea
mydeaforce-pushed the fn/better-integration-extend branch 2 times, most recently from 2407b9e to 31520beCompareJune 26, 2026 08:48
Base automatically changed from fn/better-integration-extend to developJune 26, 2026 09:38
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from c907efa to 3da22d3CompareJune 26, 2026 11:48
@logaretm
logaretm marked this pull request as ready for review June 26, 2026 12:55
@logaretm
logaretm requested a review from a team as a code ownerJune 26, 2026 12:55
@logaretm
logaretm requested review from JPeer264, andreiborza, isaacs and mydea and removed request for a teamJune 26, 2026 12:55
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from abebece to 3f660c0CompareJune 26, 2026 13:01
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@github-actions

Copy link
Copy Markdown
Contributor

👋 @isaacs, @mydea, @JPeer264, @andreiborza — Please review this PR when you get a chance!

Comment threadpackages/server-utils/src/graphql/index.ts Outdated
Comment threadpackages/server-utils/src/graphql/index.ts Outdated
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch 2 times, most recently from 4b397eb to a1e12c5CompareJuly 2, 2026 16:19
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from a1e12c5 to 6e1c439CompareJuly 2, 2026 19:05
@logaretm
logaretm requested a review from mydeaJuly 2, 2026 20:03

@cursorcursorBot 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 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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 93ff31a. Configure here.

Comment threadpackages/node/src/integrations/tracing/graphql/index.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question. Does this behave differently than versions below v16? There seems to be a lot of new code actually for v17

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is mostly great, found a few things that (if I'm reading it correctly) are fixable problems, and if I'm not, could benefit at least from a comment or debug log. The only one I'd gate on is dropping the useOperationNameForRootSpan option, which should at least get a documentation update if it's intentional.

  • Uses conventions
  • Tests etc added
  • Code is easy to follow.

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
@logaretm
logaretm requested a review from isaacsJuly 3, 2026 19:25
@github-actions

Copy link
Copy Markdown
Contributor

👋 @andreiborza — Please review this PR when you get a chance!

@logaretm
logaretm requested a review from JPeer264July 6, 2026 13:51
@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea — Please review this PR when you get a chance!

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM once everything from @isaacs got resolved

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All my concerns look like they've been addressed, so this LGTM!

logaretm added 12 commits July 7, 2026 14:15
…nnel tracing channels
Adds a graphqlChannelIntegration in server-utils that subscribes to graphql >= 17's
native node:diagnostics_channel tracing channels (graphql:parse / :validate / :execute
/ :subscribe) and builds spans with the graphql semantic conventions. The node
graphqlIntegration extends it via extendIntegration so the vendored OTel patcher still
handles graphql < 17. Per-field graphql:resolve spans are omitted (high volume; the OTel
path also defaults them off).
…pans option
Wires the per-field `graphql:resolve` channel into the graphql diagnostics-channel
subscriber, gated behind the existing `ignoreResolveSpans` option (default true, so off
by default). When enabled, `ignoreTrivialResolveSpans` (default true) additionally skips
graphql's default property resolver. Both options now flow through to the channel path,
matching the vendored OTel patcher's behavior on graphql < 17.
…keeping
Split option-matrix tests into process-isolated files instead of resetting
and re-subscribing the process-global channels.
…tion
Runtimes that use the server-utils integration directly expose it to users,
so 'channel' in the name leaks an implementation detail. Node imports it under
an internal alias since it keeps its own composed graphqlIntegration.
Replace the conditional-spread pattern for optional attributes with
`?? undefined`. Undefined-valued keys are dropped by the span backends,
so this is equivalent while keeping the attribute lines consistent.
Replace the ad-hoc `void Promise.resolve().then(...)` deferral with the
shared `waitForTracingChannelBinding` util, matching the mongoose,
vercel-ai and redis integrations. It retries until the async context
binding is available, so it also handles custom OTel setups where the
binding isn't ready on the first tick.
The `?? undefined` on `document` (already `string | undefined`) was a no-op.
Switch `operationName` to `|| undefined` so blank operation names are omitted
rather than recorded as empty-string attributes.
…s-channel path
Ports the legacy OTel useOperationNameForRootSpan behavior (default on) to the
graphql >= 17 diagnostics-channel subscriber, so upgrading graphql no longer drops
root-span renaming. Moves the pure graphql helpers into a utils file.
The internal subscribe function has a single deduped setupOnce caller via
waitForTracingChannelBinding, so the subscribed flag guarded a path that
can't occur. Remove it along with the obsolete idempotency test, mirroring
the mysql2 subscriber.
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from 6395981 to c61c848CompareJuly 7, 2026 18:17
@logaretm
logaretm merged commit c0c2b01 into developJul 7, 2026
214 checks passed
@logaretm
logaretm deleted the awad/graphql-tracing-channels branch July 7, 2026 18:41
Sign up for freeto 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.

4 participants

@logaretm@isaacs@mydea@JPeer264
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(server-utils): Instrument graphql v17 via native tracing channels - #21804

Merged
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels
Jul 7, 2026
Merged

feat(server-utils): Instrument graphql v17 via native tracing channels#21804
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels

Conversation

@logaretm

@logaretmlogaretm commented Jun 25, 2026

Copy link
Copy Markdown
Member

GraphQL v17 uses its native diagnostics_channel for tracing instead of monkey-patching. It publishes lifecycle events on:

  • graphql:parse
  • graphql:validate
  • graphql:execute
  • graphql:subscribe

This PR adds new graphqlIntegration in server-utils that subscribes to these events and builds spans with graphql semantic conventions. The graphqlIntegration node extends this integration and keeps the vendored OTel patcher for graphql < 17. The patcher is gated >=14 <17.

A couple of things worth calling out:

  • The graphql.document value is the original query text with inline literal arguments redacted ("foo""*", 42*) so raw values can't leak, and variable values are never attached.
  • Per-field graphql:resolve spans are off by default because they're very high volume, users can opt in via ignoreResolveSpans just like previous versions.

@github-actions

github-actionsBot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser27.59 kB--
@sentry/browser - with treeshaking flags26.03 kB--
@sentry/browser (incl. Tracing)46.27 kB--
@sentry/browser (incl. Tracing + Span Streaming)48.03 kB--
@sentry/browser (incl. Tracing, Profiling)51.03 kB--
@sentry/browser (incl. Tracing, Replay)85.56 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags75.17 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)90.26 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)102.91 kB--
@sentry/browser (incl. Feedback)44.76 kB--
@sentry/browser (incl. sendFeedback)32.38 kB--
@sentry/browser (incl. FeedbackAsync)37.51 kB--
@sentry/browser (incl. Metrics)28.67 kB--
@sentry/browser (incl. Logs)28.91 kB--
@sentry/browser (incl. Metrics & Logs)29.59 kB--
@sentry/react29.38 kB--
@sentry/react (incl. Tracing)48.53 kB--
@sentry/vue33.03 kB--
@sentry/vue (incl. Tracing)48.16 kB--
@sentry/svelte27.61 kB--
CDN Bundle30 kB--
CDN Bundle (incl. Tracing)48.26 kB--
CDN Bundle (incl. Logs, Metrics)31.57 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)49.57 kB--
CDN Bundle (incl. Replay, Logs, Metrics)70.81 kB--
CDN Bundle (incl. Tracing, Replay)85.73 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)87.04 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)91.55 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)92.83 kB--
CDN Bundle - uncompressed89.35 kB--
CDN Bundle (incl. Tracing) - uncompressed145.99 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed94.05 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed149.96 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed218.75 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed265.16 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed269.12 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed278.86 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed282.81 kB--
@sentry/nextjs (client)50.94 kB--
@sentry/sveltekit (client)46.68 kB--
@sentry/core/server78.38 kB--
@sentry/core/browser64.72 kB--
@sentry/node-core63.21 kB--
@sentry/node124.73 kB+0.67%+830 B 🔺
@sentry/node (incl. diagnostics channel injection)130.64 kB+0.65%+836 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection)69.95 kB--
@sentry/node/light50.72 kB+0.01%+1 B 🔺
@sentry/node - without tracing74.82 kB+0.01%+1 B 🔺
@sentry/aws-serverless85.6 kB--
@sentry/cloudflare (withSentry) - minified181.68 kB--
@sentry/cloudflare (withSentry)449.39 kB--

View base workflow run

@logaretmlogaretm changed the title feat(server-utils): Instrument graphql v17 via native diagnostics_channel tracing channelsfeat(server-utils): Instrument graphql v17 via native tracing channelsJun 25, 2026
@mydea
mydeaforce-pushed the fn/better-integration-extend branch 2 times, most recently from 2407b9e to 31520beCompareJune 26, 2026 08:48
Base automatically changed from fn/better-integration-extend to developJune 26, 2026 09:38
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from c907efa to 3da22d3CompareJune 26, 2026 11:48
@logaretm
logaretm marked this pull request as ready for review June 26, 2026 12:55
@logaretm
logaretm requested a review from a team as a code ownerJune 26, 2026 12:55
@logaretm
logaretm requested review from JPeer264, andreiborza, isaacs and mydea and removed request for a teamJune 26, 2026 12:55
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from abebece to 3f660c0CompareJune 26, 2026 13:01
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@github-actions

Copy link
Copy Markdown
Contributor

👋 @isaacs, @mydea, @JPeer264, @andreiborza — Please review this PR when you get a chance!

Comment threadpackages/server-utils/src/graphql/index.ts Outdated
Comment threadpackages/server-utils/src/graphql/index.ts Outdated
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch 2 times, most recently from 4b397eb to a1e12c5CompareJuly 2, 2026 16:19
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from a1e12c5 to 6e1c439CompareJuly 2, 2026 19:05
@logaretm
logaretm requested a review from mydeaJuly 2, 2026 20:03

@cursorcursorBot 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 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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 93ff31a. Configure here.

Comment threadpackages/node/src/integrations/tracing/graphql/index.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question. Does this behave differently than versions below v16? There seems to be a lot of new code actually for v17

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is mostly great, found a few things that (if I'm reading it correctly) are fixable problems, and if I'm not, could benefit at least from a comment or debug log. The only one I'd gate on is dropping the useOperationNameForRootSpan option, which should at least get a documentation update if it's intentional.

  • Uses conventions
  • Tests etc added
  • Code is easy to follow.

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
@logaretm
logaretm requested a review from isaacsJuly 3, 2026 19:25
@github-actions

Copy link
Copy Markdown
Contributor

👋 @andreiborza — Please review this PR when you get a chance!

@logaretm
logaretm requested a review from JPeer264July 6, 2026 13:51
@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea — Please review this PR when you get a chance!

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM once everything from @isaacs got resolved

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All my concerns look like they've been addressed, so this LGTM!

logaretm added 12 commits July 7, 2026 14:15
…nnel tracing channels
Adds a graphqlChannelIntegration in server-utils that subscribes to graphql >= 17's
native node:diagnostics_channel tracing channels (graphql:parse / :validate / :execute
/ :subscribe) and builds spans with the graphql semantic conventions. The node
graphqlIntegration extends it via extendIntegration so the vendored OTel patcher still
handles graphql < 17. Per-field graphql:resolve spans are omitted (high volume; the OTel
path also defaults them off).
…pans option
Wires the per-field `graphql:resolve` channel into the graphql diagnostics-channel
subscriber, gated behind the existing `ignoreResolveSpans` option (default true, so off
by default). When enabled, `ignoreTrivialResolveSpans` (default true) additionally skips
graphql's default property resolver. Both options now flow through to the channel path,
matching the vendored OTel patcher's behavior on graphql < 17.
…keeping
Split option-matrix tests into process-isolated files instead of resetting
and re-subscribing the process-global channels.
…tion
Runtimes that use the server-utils integration directly expose it to users,
so 'channel' in the name leaks an implementation detail. Node imports it under
an internal alias since it keeps its own composed graphqlIntegration.
Replace the conditional-spread pattern for optional attributes with
`?? undefined`. Undefined-valued keys are dropped by the span backends,
so this is equivalent while keeping the attribute lines consistent.
Replace the ad-hoc `void Promise.resolve().then(...)` deferral with the
shared `waitForTracingChannelBinding` util, matching the mongoose,
vercel-ai and redis integrations. It retries until the async context
binding is available, so it also handles custom OTel setups where the
binding isn't ready on the first tick.
The `?? undefined` on `document` (already `string | undefined`) was a no-op.
Switch `operationName` to `|| undefined` so blank operation names are omitted
rather than recorded as empty-string attributes.
…s-channel path
Ports the legacy OTel useOperationNameForRootSpan behavior (default on) to the
graphql >= 17 diagnostics-channel subscriber, so upgrading graphql no longer drops
root-span renaming. Moves the pure graphql helpers into a utils file.
The internal subscribe function has a single deduped setupOnce caller via
waitForTracingChannelBinding, so the subscribed flag guarded a path that
can't occur. Remove it along with the obsolete idempotency test, mirroring
the mysql2 subscriber.
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from 6395981 to c61c848CompareJuly 7, 2026 18:17
@logaretm
logaretm merged commit c0c2b01 into developJul 7, 2026
214 checks passed
@logaretm
logaretm deleted the awad/graphql-tracing-channels branch July 7, 2026 18:41
Sign up for freeto 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.

4 participants

@logaretm@isaacs@mydea@JPeer264
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(server-utils): Instrument graphql v17 via native tracing channels - #21804

Merged
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels
Jul 7, 2026
Merged

feat(server-utils): Instrument graphql v17 via native tracing channels#21804
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels

Conversation

@logaretm

@logaretmlogaretm commented Jun 25, 2026

Copy link
Copy Markdown
Member

GraphQL v17 uses its native diagnostics_channel for tracing instead of monkey-patching. It publishes lifecycle events on:

  • graphql:parse
  • graphql:validate
  • graphql:execute
  • graphql:subscribe

This PR adds new graphqlIntegration in server-utils that subscribes to these events and builds spans with graphql semantic conventions. The graphqlIntegration node extends this integration and keeps the vendored OTel patcher for graphql < 17. The patcher is gated >=14 <17.

A couple of things worth calling out:

  • The graphql.document value is the original query text with inline literal arguments redacted ("foo""*", 42*) so raw values can't leak, and variable values are never attached.
  • Per-field graphql:resolve spans are off by default because they're very high volume, users can opt in via ignoreResolveSpans just like previous versions.

@github-actions

github-actionsBot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser27.59 kB--
@sentry/browser - with treeshaking flags26.03 kB--
@sentry/browser (incl. Tracing)46.27 kB--
@sentry/browser (incl. Tracing + Span Streaming)48.03 kB--
@sentry/browser (incl. Tracing, Profiling)51.03 kB--
@sentry/browser (incl. Tracing, Replay)85.56 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags75.17 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)90.26 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)102.91 kB--
@sentry/browser (incl. Feedback)44.76 kB--
@sentry/browser (incl. sendFeedback)32.38 kB--
@sentry/browser (incl. FeedbackAsync)37.51 kB--
@sentry/browser (incl. Metrics)28.67 kB--
@sentry/browser (incl. Logs)28.91 kB--
@sentry/browser (incl. Metrics & Logs)29.59 kB--
@sentry/react29.38 kB--
@sentry/react (incl. Tracing)48.53 kB--
@sentry/vue33.03 kB--
@sentry/vue (incl. Tracing)48.16 kB--
@sentry/svelte27.61 kB--
CDN Bundle30 kB--
CDN Bundle (incl. Tracing)48.26 kB--
CDN Bundle (incl. Logs, Metrics)31.57 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)49.57 kB--
CDN Bundle (incl. Replay, Logs, Metrics)70.81 kB--
CDN Bundle (incl. Tracing, Replay)85.73 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)87.04 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)91.55 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)92.83 kB--
CDN Bundle - uncompressed89.35 kB--
CDN Bundle (incl. Tracing) - uncompressed145.99 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed94.05 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed149.96 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed218.75 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed265.16 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed269.12 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed278.86 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed282.81 kB--
@sentry/nextjs (client)50.94 kB--
@sentry/sveltekit (client)46.68 kB--
@sentry/core/server78.38 kB--
@sentry/core/browser64.72 kB--
@sentry/node-core63.21 kB--
@sentry/node124.73 kB+0.67%+830 B 🔺
@sentry/node (incl. diagnostics channel injection)130.64 kB+0.65%+836 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection)69.95 kB--
@sentry/node/light50.72 kB+0.01%+1 B 🔺
@sentry/node - without tracing74.82 kB+0.01%+1 B 🔺
@sentry/aws-serverless85.6 kB--
@sentry/cloudflare (withSentry) - minified181.68 kB--
@sentry/cloudflare (withSentry)449.39 kB--

View base workflow run

@logaretmlogaretm changed the title feat(server-utils): Instrument graphql v17 via native diagnostics_channel tracing channelsfeat(server-utils): Instrument graphql v17 via native tracing channelsJun 25, 2026
@mydea
mydeaforce-pushed the fn/better-integration-extend branch 2 times, most recently from 2407b9e to 31520beCompareJune 26, 2026 08:48
Base automatically changed from fn/better-integration-extend to developJune 26, 2026 09:38
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from c907efa to 3da22d3CompareJune 26, 2026 11:48
@logaretm
logaretm marked this pull request as ready for review June 26, 2026 12:55
@logaretm
logaretm requested a review from a team as a code ownerJune 26, 2026 12:55
@logaretm
logaretm requested review from JPeer264, andreiborza, isaacs and mydea and removed request for a teamJune 26, 2026 12:55
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from abebece to 3f660c0CompareJune 26, 2026 13:01
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@github-actions

Copy link
Copy Markdown
Contributor

👋 @isaacs, @mydea, @JPeer264, @andreiborza — Please review this PR when you get a chance!

Comment threadpackages/server-utils/src/graphql/index.ts Outdated
Comment threadpackages/server-utils/src/graphql/index.ts Outdated
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch 2 times, most recently from 4b397eb to a1e12c5CompareJuly 2, 2026 16:19
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from a1e12c5 to 6e1c439CompareJuly 2, 2026 19:05
@logaretm
logaretm requested a review from mydeaJuly 2, 2026 20:03

@cursorcursorBot 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 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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 93ff31a. Configure here.

Comment threadpackages/node/src/integrations/tracing/graphql/index.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question. Does this behave differently than versions below v16? There seems to be a lot of new code actually for v17

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is mostly great, found a few things that (if I'm reading it correctly) are fixable problems, and if I'm not, could benefit at least from a comment or debug log. The only one I'd gate on is dropping the useOperationNameForRootSpan option, which should at least get a documentation update if it's intentional.

  • Uses conventions
  • Tests etc added
  • Code is easy to follow.

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
@logaretm
logaretm requested a review from isaacsJuly 3, 2026 19:25
@github-actions

Copy link
Copy Markdown
Contributor

👋 @andreiborza — Please review this PR when you get a chance!

@logaretm
logaretm requested a review from JPeer264July 6, 2026 13:51
@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea — Please review this PR when you get a chance!

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM once everything from @isaacs got resolved

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All my concerns look like they've been addressed, so this LGTM!

logaretm added 12 commits July 7, 2026 14:15
…nnel tracing channels
Adds a graphqlChannelIntegration in server-utils that subscribes to graphql >= 17's
native node:diagnostics_channel tracing channels (graphql:parse / :validate / :execute
/ :subscribe) and builds spans with the graphql semantic conventions. The node
graphqlIntegration extends it via extendIntegration so the vendored OTel patcher still
handles graphql < 17. Per-field graphql:resolve spans are omitted (high volume; the OTel
path also defaults them off).
…pans option
Wires the per-field `graphql:resolve` channel into the graphql diagnostics-channel
subscriber, gated behind the existing `ignoreResolveSpans` option (default true, so off
by default). When enabled, `ignoreTrivialResolveSpans` (default true) additionally skips
graphql's default property resolver. Both options now flow through to the channel path,
matching the vendored OTel patcher's behavior on graphql < 17.
…keeping
Split option-matrix tests into process-isolated files instead of resetting
and re-subscribing the process-global channels.
…tion
Runtimes that use the server-utils integration directly expose it to users,
so 'channel' in the name leaks an implementation detail. Node imports it under
an internal alias since it keeps its own composed graphqlIntegration.
Replace the conditional-spread pattern for optional attributes with
`?? undefined`. Undefined-valued keys are dropped by the span backends,
so this is equivalent while keeping the attribute lines consistent.
Replace the ad-hoc `void Promise.resolve().then(...)` deferral with the
shared `waitForTracingChannelBinding` util, matching the mongoose,
vercel-ai and redis integrations. It retries until the async context
binding is available, so it also handles custom OTel setups where the
binding isn't ready on the first tick.
The `?? undefined` on `document` (already `string | undefined`) was a no-op.
Switch `operationName` to `|| undefined` so blank operation names are omitted
rather than recorded as empty-string attributes.
…s-channel path
Ports the legacy OTel useOperationNameForRootSpan behavior (default on) to the
graphql >= 17 diagnostics-channel subscriber, so upgrading graphql no longer drops
root-span renaming. Moves the pure graphql helpers into a utils file.
The internal subscribe function has a single deduped setupOnce caller via
waitForTracingChannelBinding, so the subscribed flag guarded a path that
can't occur. Remove it along with the obsolete idempotency test, mirroring
the mysql2 subscriber.
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from 6395981 to c61c848CompareJuly 7, 2026 18:17
@logaretm
logaretm merged commit c0c2b01 into developJul 7, 2026
214 checks passed
@logaretm
logaretm deleted the awad/graphql-tracing-channels branch July 7, 2026 18:41
Sign up for freeto 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.

4 participants

@logaretm@isaacs@mydea@JPeer264
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(server-utils): Instrument graphql v17 via native tracing channels - #21804

Merged
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels
Jul 7, 2026
Merged

feat(server-utils): Instrument graphql v17 via native tracing channels#21804
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels

Conversation

@logaretm

@logaretmlogaretm commented Jun 25, 2026

Copy link
Copy Markdown
Member

GraphQL v17 uses its native diagnostics_channel for tracing instead of monkey-patching. It publishes lifecycle events on:

  • graphql:parse
  • graphql:validate
  • graphql:execute
  • graphql:subscribe

This PR adds new graphqlIntegration in server-utils that subscribes to these events and builds spans with graphql semantic conventions. The graphqlIntegration node extends this integration and keeps the vendored OTel patcher for graphql < 17. The patcher is gated >=14 <17.

A couple of things worth calling out:

  • The graphql.document value is the original query text with inline literal arguments redacted ("foo""*", 42*) so raw values can't leak, and variable values are never attached.
  • Per-field graphql:resolve spans are off by default because they're very high volume, users can opt in via ignoreResolveSpans just like previous versions.

@github-actions

github-actionsBot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser27.59 kB--
@sentry/browser - with treeshaking flags26.03 kB--
@sentry/browser (incl. Tracing)46.27 kB--
@sentry/browser (incl. Tracing + Span Streaming)48.03 kB--
@sentry/browser (incl. Tracing, Profiling)51.03 kB--
@sentry/browser (incl. Tracing, Replay)85.56 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags75.17 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)90.26 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)102.91 kB--
@sentry/browser (incl. Feedback)44.76 kB--
@sentry/browser (incl. sendFeedback)32.38 kB--
@sentry/browser (incl. FeedbackAsync)37.51 kB--
@sentry/browser (incl. Metrics)28.67 kB--
@sentry/browser (incl. Logs)28.91 kB--
@sentry/browser (incl. Metrics & Logs)29.59 kB--
@sentry/react29.38 kB--
@sentry/react (incl. Tracing)48.53 kB--
@sentry/vue33.03 kB--
@sentry/vue (incl. Tracing)48.16 kB--
@sentry/svelte27.61 kB--
CDN Bundle30 kB--
CDN Bundle (incl. Tracing)48.26 kB--
CDN Bundle (incl. Logs, Metrics)31.57 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)49.57 kB--
CDN Bundle (incl. Replay, Logs, Metrics)70.81 kB--
CDN Bundle (incl. Tracing, Replay)85.73 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)87.04 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)91.55 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)92.83 kB--
CDN Bundle - uncompressed89.35 kB--
CDN Bundle (incl. Tracing) - uncompressed145.99 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed94.05 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed149.96 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed218.75 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed265.16 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed269.12 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed278.86 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed282.81 kB--
@sentry/nextjs (client)50.94 kB--
@sentry/sveltekit (client)46.68 kB--
@sentry/core/server78.38 kB--
@sentry/core/browser64.72 kB--
@sentry/node-core63.21 kB--
@sentry/node124.73 kB+0.67%+830 B 🔺
@sentry/node (incl. diagnostics channel injection)130.64 kB+0.65%+836 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection)69.95 kB--
@sentry/node/light50.72 kB+0.01%+1 B 🔺
@sentry/node - without tracing74.82 kB+0.01%+1 B 🔺
@sentry/aws-serverless85.6 kB--
@sentry/cloudflare (withSentry) - minified181.68 kB--
@sentry/cloudflare (withSentry)449.39 kB--

View base workflow run

@logaretmlogaretm changed the title feat(server-utils): Instrument graphql v17 via native diagnostics_channel tracing channelsfeat(server-utils): Instrument graphql v17 via native tracing channelsJun 25, 2026
@mydea
mydeaforce-pushed the fn/better-integration-extend branch 2 times, most recently from 2407b9e to 31520beCompareJune 26, 2026 08:48
Base automatically changed from fn/better-integration-extend to developJune 26, 2026 09:38
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from c907efa to 3da22d3CompareJune 26, 2026 11:48
@logaretm
logaretm marked this pull request as ready for review June 26, 2026 12:55
@logaretm
logaretm requested a review from a team as a code ownerJune 26, 2026 12:55
@logaretm
logaretm requested review from JPeer264, andreiborza, isaacs and mydea and removed request for a teamJune 26, 2026 12:55
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from abebece to 3f660c0CompareJune 26, 2026 13:01
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@github-actions

Copy link
Copy Markdown
Contributor

👋 @isaacs, @mydea, @JPeer264, @andreiborza — Please review this PR when you get a chance!

Comment threadpackages/server-utils/src/graphql/index.ts Outdated
Comment threadpackages/server-utils/src/graphql/index.ts Outdated
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch 2 times, most recently from 4b397eb to a1e12c5CompareJuly 2, 2026 16:19
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from a1e12c5 to 6e1c439CompareJuly 2, 2026 19:05
@logaretm
logaretm requested a review from mydeaJuly 2, 2026 20:03

@cursorcursorBot 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 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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 93ff31a. Configure here.

Comment threadpackages/node/src/integrations/tracing/graphql/index.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question. Does this behave differently than versions below v16? There seems to be a lot of new code actually for v17

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is mostly great, found a few things that (if I'm reading it correctly) are fixable problems, and if I'm not, could benefit at least from a comment or debug log. The only one I'd gate on is dropping the useOperationNameForRootSpan option, which should at least get a documentation update if it's intentional.

  • Uses conventions
  • Tests etc added
  • Code is easy to follow.

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
@logaretm
logaretm requested a review from isaacsJuly 3, 2026 19:25
@github-actions

Copy link
Copy Markdown
Contributor

👋 @andreiborza — Please review this PR when you get a chance!

@logaretm
logaretm requested a review from JPeer264July 6, 2026 13:51
@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea — Please review this PR when you get a chance!

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM once everything from @isaacs got resolved

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All my concerns look like they've been addressed, so this LGTM!

logaretm added 12 commits July 7, 2026 14:15
…nnel tracing channels
Adds a graphqlChannelIntegration in server-utils that subscribes to graphql >= 17's
native node:diagnostics_channel tracing channels (graphql:parse / :validate / :execute
/ :subscribe) and builds spans with the graphql semantic conventions. The node
graphqlIntegration extends it via extendIntegration so the vendored OTel patcher still
handles graphql < 17. Per-field graphql:resolve spans are omitted (high volume; the OTel
path also defaults them off).
…pans option
Wires the per-field `graphql:resolve` channel into the graphql diagnostics-channel
subscriber, gated behind the existing `ignoreResolveSpans` option (default true, so off
by default). When enabled, `ignoreTrivialResolveSpans` (default true) additionally skips
graphql's default property resolver. Both options now flow through to the channel path,
matching the vendored OTel patcher's behavior on graphql < 17.
…keeping
Split option-matrix tests into process-isolated files instead of resetting
and re-subscribing the process-global channels.
…tion
Runtimes that use the server-utils integration directly expose it to users,
so 'channel' in the name leaks an implementation detail. Node imports it under
an internal alias since it keeps its own composed graphqlIntegration.
Replace the conditional-spread pattern for optional attributes with
`?? undefined`. Undefined-valued keys are dropped by the span backends,
so this is equivalent while keeping the attribute lines consistent.
Replace the ad-hoc `void Promise.resolve().then(...)` deferral with the
shared `waitForTracingChannelBinding` util, matching the mongoose,
vercel-ai and redis integrations. It retries until the async context
binding is available, so it also handles custom OTel setups where the
binding isn't ready on the first tick.
The `?? undefined` on `document` (already `string | undefined`) was a no-op.
Switch `operationName` to `|| undefined` so blank operation names are omitted
rather than recorded as empty-string attributes.
…s-channel path
Ports the legacy OTel useOperationNameForRootSpan behavior (default on) to the
graphql >= 17 diagnostics-channel subscriber, so upgrading graphql no longer drops
root-span renaming. Moves the pure graphql helpers into a utils file.
The internal subscribe function has a single deduped setupOnce caller via
waitForTracingChannelBinding, so the subscribed flag guarded a path that
can't occur. Remove it along with the obsolete idempotency test, mirroring
the mysql2 subscriber.
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from 6395981 to c61c848CompareJuly 7, 2026 18:17
@logaretm
logaretm merged commit c0c2b01 into developJul 7, 2026
214 checks passed
@logaretm
logaretm deleted the awad/graphql-tracing-channels branch July 7, 2026 18:41
Sign up for freeto 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.

4 participants

@logaretm@isaacs@mydea@JPeer264
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(server-utils): Instrument graphql v17 via native tracing channels - #21804

Merged
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels
Jul 7, 2026
Merged

feat(server-utils): Instrument graphql v17 via native tracing channels#21804
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels

Conversation

@logaretm

@logaretmlogaretm commented Jun 25, 2026

Copy link
Copy Markdown
Member

GraphQL v17 uses its native diagnostics_channel for tracing instead of monkey-patching. It publishes lifecycle events on:

  • graphql:parse
  • graphql:validate
  • graphql:execute
  • graphql:subscribe

This PR adds new graphqlIntegration in server-utils that subscribes to these events and builds spans with graphql semantic conventions. The graphqlIntegration node extends this integration and keeps the vendored OTel patcher for graphql < 17. The patcher is gated >=14 <17.

A couple of things worth calling out:

  • The graphql.document value is the original query text with inline literal arguments redacted ("foo""*", 42*) so raw values can't leak, and variable values are never attached.
  • Per-field graphql:resolve spans are off by default because they're very high volume, users can opt in via ignoreResolveSpans just like previous versions.

@github-actions

github-actionsBot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser27.59 kB--
@sentry/browser - with treeshaking flags26.03 kB--
@sentry/browser (incl. Tracing)46.27 kB--
@sentry/browser (incl. Tracing + Span Streaming)48.03 kB--
@sentry/browser (incl. Tracing, Profiling)51.03 kB--
@sentry/browser (incl. Tracing, Replay)85.56 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags75.17 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)90.26 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)102.91 kB--
@sentry/browser (incl. Feedback)44.76 kB--
@sentry/browser (incl. sendFeedback)32.38 kB--
@sentry/browser (incl. FeedbackAsync)37.51 kB--
@sentry/browser (incl. Metrics)28.67 kB--
@sentry/browser (incl. Logs)28.91 kB--
@sentry/browser (incl. Metrics & Logs)29.59 kB--
@sentry/react29.38 kB--
@sentry/react (incl. Tracing)48.53 kB--
@sentry/vue33.03 kB--
@sentry/vue (incl. Tracing)48.16 kB--
@sentry/svelte27.61 kB--
CDN Bundle30 kB--
CDN Bundle (incl. Tracing)48.26 kB--
CDN Bundle (incl. Logs, Metrics)31.57 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)49.57 kB--
CDN Bundle (incl. Replay, Logs, Metrics)70.81 kB--
CDN Bundle (incl. Tracing, Replay)85.73 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)87.04 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)91.55 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)92.83 kB--
CDN Bundle - uncompressed89.35 kB--
CDN Bundle (incl. Tracing) - uncompressed145.99 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed94.05 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed149.96 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed218.75 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed265.16 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed269.12 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed278.86 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed282.81 kB--
@sentry/nextjs (client)50.94 kB--
@sentry/sveltekit (client)46.68 kB--
@sentry/core/server78.38 kB--
@sentry/core/browser64.72 kB--
@sentry/node-core63.21 kB--
@sentry/node124.73 kB+0.67%+830 B 🔺
@sentry/node (incl. diagnostics channel injection)130.64 kB+0.65%+836 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection)69.95 kB--
@sentry/node/light50.72 kB+0.01%+1 B 🔺
@sentry/node - without tracing74.82 kB+0.01%+1 B 🔺
@sentry/aws-serverless85.6 kB--
@sentry/cloudflare (withSentry) - minified181.68 kB--
@sentry/cloudflare (withSentry)449.39 kB--

View base workflow run

@logaretmlogaretm changed the title feat(server-utils): Instrument graphql v17 via native diagnostics_channel tracing channelsfeat(server-utils): Instrument graphql v17 via native tracing channelsJun 25, 2026
@mydea
mydeaforce-pushed the fn/better-integration-extend branch 2 times, most recently from 2407b9e to 31520beCompareJune 26, 2026 08:48
Base automatically changed from fn/better-integration-extend to developJune 26, 2026 09:38
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from c907efa to 3da22d3CompareJune 26, 2026 11:48
@logaretm
logaretm marked this pull request as ready for review June 26, 2026 12:55
@logaretm
logaretm requested a review from a team as a code ownerJune 26, 2026 12:55
@logaretm
logaretm requested review from JPeer264, andreiborza, isaacs and mydea and removed request for a teamJune 26, 2026 12:55
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from abebece to 3f660c0CompareJune 26, 2026 13:01
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@github-actions

Copy link
Copy Markdown
Contributor

👋 @isaacs, @mydea, @JPeer264, @andreiborza — Please review this PR when you get a chance!

Comment threadpackages/server-utils/src/graphql/index.ts Outdated
Comment threadpackages/server-utils/src/graphql/index.ts Outdated
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch 2 times, most recently from 4b397eb to a1e12c5CompareJuly 2, 2026 16:19
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from a1e12c5 to 6e1c439CompareJuly 2, 2026 19:05
@logaretm
logaretm requested a review from mydeaJuly 2, 2026 20:03

@cursorcursorBot 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 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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 93ff31a. Configure here.

Comment threadpackages/node/src/integrations/tracing/graphql/index.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question. Does this behave differently than versions below v16? There seems to be a lot of new code actually for v17

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is mostly great, found a few things that (if I'm reading it correctly) are fixable problems, and if I'm not, could benefit at least from a comment or debug log. The only one I'd gate on is dropping the useOperationNameForRootSpan option, which should at least get a documentation update if it's intentional.

  • Uses conventions
  • Tests etc added
  • Code is easy to follow.

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
@logaretm
logaretm requested a review from isaacsJuly 3, 2026 19:25
@github-actions

Copy link
Copy Markdown
Contributor

👋 @andreiborza — Please review this PR when you get a chance!

@logaretm
logaretm requested a review from JPeer264July 6, 2026 13:51
@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea — Please review this PR when you get a chance!

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM once everything from @isaacs got resolved

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All my concerns look like they've been addressed, so this LGTM!

logaretm added 12 commits July 7, 2026 14:15
…nnel tracing channels
Adds a graphqlChannelIntegration in server-utils that subscribes to graphql >= 17's
native node:diagnostics_channel tracing channels (graphql:parse / :validate / :execute
/ :subscribe) and builds spans with the graphql semantic conventions. The node
graphqlIntegration extends it via extendIntegration so the vendored OTel patcher still
handles graphql < 17. Per-field graphql:resolve spans are omitted (high volume; the OTel
path also defaults them off).
…pans option
Wires the per-field `graphql:resolve` channel into the graphql diagnostics-channel
subscriber, gated behind the existing `ignoreResolveSpans` option (default true, so off
by default). When enabled, `ignoreTrivialResolveSpans` (default true) additionally skips
graphql's default property resolver. Both options now flow through to the channel path,
matching the vendored OTel patcher's behavior on graphql < 17.
…keeping
Split option-matrix tests into process-isolated files instead of resetting
and re-subscribing the process-global channels.
…tion
Runtimes that use the server-utils integration directly expose it to users,
so 'channel' in the name leaks an implementation detail. Node imports it under
an internal alias since it keeps its own composed graphqlIntegration.
Replace the conditional-spread pattern for optional attributes with
`?? undefined`. Undefined-valued keys are dropped by the span backends,
so this is equivalent while keeping the attribute lines consistent.
Replace the ad-hoc `void Promise.resolve().then(...)` deferral with the
shared `waitForTracingChannelBinding` util, matching the mongoose,
vercel-ai and redis integrations. It retries until the async context
binding is available, so it also handles custom OTel setups where the
binding isn't ready on the first tick.
The `?? undefined` on `document` (already `string | undefined`) was a no-op.
Switch `operationName` to `|| undefined` so blank operation names are omitted
rather than recorded as empty-string attributes.
…s-channel path
Ports the legacy OTel useOperationNameForRootSpan behavior (default on) to the
graphql >= 17 diagnostics-channel subscriber, so upgrading graphql no longer drops
root-span renaming. Moves the pure graphql helpers into a utils file.
The internal subscribe function has a single deduped setupOnce caller via
waitForTracingChannelBinding, so the subscribed flag guarded a path that
can't occur. Remove it along with the obsolete idempotency test, mirroring
the mysql2 subscriber.
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from 6395981 to c61c848CompareJuly 7, 2026 18:17
@logaretm
logaretm merged commit c0c2b01 into developJul 7, 2026
214 checks passed
@logaretm
logaretm deleted the awad/graphql-tracing-channels branch July 7, 2026 18:41
Sign up for freeto 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.

4 participants

@logaretm@isaacs@mydea@JPeer264
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(server-utils): Instrument graphql v17 via native tracing channels - #21804

Merged
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels
Jul 7, 2026
Merged

feat(server-utils): Instrument graphql v17 via native tracing channels#21804
logaretm merged 12 commits into
developfrom
awad/graphql-tracing-channels

Conversation

@logaretm

@logaretmlogaretm commented Jun 25, 2026

Copy link
Copy Markdown
Member

GraphQL v17 uses its native diagnostics_channel for tracing instead of monkey-patching. It publishes lifecycle events on:

  • graphql:parse
  • graphql:validate
  • graphql:execute
  • graphql:subscribe

This PR adds new graphqlIntegration in server-utils that subscribes to these events and builds spans with graphql semantic conventions. The graphqlIntegration node extends this integration and keeps the vendored OTel patcher for graphql < 17. The patcher is gated >=14 <17.

A couple of things worth calling out:

  • The graphql.document value is the original query text with inline literal arguments redacted ("foo""*", 42*) so raw values can't leak, and variable values are never attached.
  • Per-field graphql:resolve spans are off by default because they're very high volume, users can opt in via ignoreResolveSpans just like previous versions.

@github-actions

github-actionsBot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser27.59 kB--
@sentry/browser - with treeshaking flags26.03 kB--
@sentry/browser (incl. Tracing)46.27 kB--
@sentry/browser (incl. Tracing + Span Streaming)48.03 kB--
@sentry/browser (incl. Tracing, Profiling)51.03 kB--
@sentry/browser (incl. Tracing, Replay)85.56 kB--
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags75.17 kB--
@sentry/browser (incl. Tracing, Replay with Canvas)90.26 kB--
@sentry/browser (incl. Tracing, Replay, Feedback)102.91 kB--
@sentry/browser (incl. Feedback)44.76 kB--
@sentry/browser (incl. sendFeedback)32.38 kB--
@sentry/browser (incl. FeedbackAsync)37.51 kB--
@sentry/browser (incl. Metrics)28.67 kB--
@sentry/browser (incl. Logs)28.91 kB--
@sentry/browser (incl. Metrics & Logs)29.59 kB--
@sentry/react29.38 kB--
@sentry/react (incl. Tracing)48.53 kB--
@sentry/vue33.03 kB--
@sentry/vue (incl. Tracing)48.16 kB--
@sentry/svelte27.61 kB--
CDN Bundle30 kB--
CDN Bundle (incl. Tracing)48.26 kB--
CDN Bundle (incl. Logs, Metrics)31.57 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)49.57 kB--
CDN Bundle (incl. Replay, Logs, Metrics)70.81 kB--
CDN Bundle (incl. Tracing, Replay)85.73 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)87.04 kB--
CDN Bundle (incl. Tracing, Replay, Feedback)91.55 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)92.83 kB--
CDN Bundle - uncompressed89.35 kB--
CDN Bundle (incl. Tracing) - uncompressed145.99 kB--
CDN Bundle (incl. Logs, Metrics) - uncompressed94.05 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed149.96 kB--
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed218.75 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed265.16 kB--
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed269.12 kB--
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed278.86 kB--
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed282.81 kB--
@sentry/nextjs (client)50.94 kB--
@sentry/sveltekit (client)46.68 kB--
@sentry/core/server78.38 kB--
@sentry/core/browser64.72 kB--
@sentry/node-core63.21 kB--
@sentry/node124.73 kB+0.67%+830 B 🔺
@sentry/node (incl. diagnostics channel injection)130.64 kB+0.65%+836 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection)69.95 kB--
@sentry/node/light50.72 kB+0.01%+1 B 🔺
@sentry/node - without tracing74.82 kB+0.01%+1 B 🔺
@sentry/aws-serverless85.6 kB--
@sentry/cloudflare (withSentry) - minified181.68 kB--
@sentry/cloudflare (withSentry)449.39 kB--

View base workflow run

@logaretmlogaretm changed the title feat(server-utils): Instrument graphql v17 via native diagnostics_channel tracing channelsfeat(server-utils): Instrument graphql v17 via native tracing channelsJun 25, 2026
@mydea
mydeaforce-pushed the fn/better-integration-extend branch 2 times, most recently from 2407b9e to 31520beCompareJune 26, 2026 08:48
Base automatically changed from fn/better-integration-extend to developJune 26, 2026 09:38
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from c907efa to 3da22d3CompareJune 26, 2026 11:48
@logaretm
logaretm marked this pull request as ready for review June 26, 2026 12:55
@logaretm
logaretm requested a review from a team as a code ownerJune 26, 2026 12:55
@logaretm
logaretm requested review from JPeer264, andreiborza, isaacs and mydea and removed request for a teamJune 26, 2026 12:55
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from abebece to 3f660c0CompareJune 26, 2026 13:01
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@github-actions

Copy link
Copy Markdown
Contributor

👋 @isaacs, @mydea, @JPeer264, @andreiborza — Please review this PR when you get a chance!

Comment threadpackages/server-utils/src/graphql/index.ts Outdated
Comment threadpackages/server-utils/src/graphql/index.ts Outdated
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch 2 times, most recently from 4b397eb to a1e12c5CompareJuly 2, 2026 16:19
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from a1e12c5 to 6e1c439CompareJuly 2, 2026 19:05
@logaretm
logaretm requested a review from mydeaJuly 2, 2026 20:03

@cursorcursorBot 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 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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 93ff31a. Configure here.

Comment threadpackages/node/src/integrations/tracing/graphql/index.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question. Does this behave differently than versions below v16? There seems to be a lot of new code actually for v17

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is mostly great, found a few things that (if I'm reading it correctly) are fixable problems, and if I'm not, could benefit at least from a comment or debug log. The only one I'd gate on is dropping the useOperationNameForRootSpan option, which should at least get a documentation update if it's intentional.

  • Uses conventions
  • Tests etc added
  • Code is easy to follow.

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated
@logaretm
logaretm requested a review from isaacsJuly 3, 2026 19:25
@github-actions

Copy link
Copy Markdown
Contributor

👋 @andreiborza — Please review this PR when you get a chance!

@logaretm
logaretm requested a review from JPeer264July 6, 2026 13:51
@github-actions

Copy link
Copy Markdown
Contributor

👋 @mydea — Please review this PR when you get a chance!

@JPeer264JPeer264 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM once everything from @isaacs got resolved

Comment threadpackages/server-utils/src/graphql/graphql-dc-subscriber.ts Outdated

@isaacsisaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All my concerns look like they've been addressed, so this LGTM!

logaretm added 12 commits July 7, 2026 14:15
…nnel tracing channels
Adds a graphqlChannelIntegration in server-utils that subscribes to graphql >= 17's
native node:diagnostics_channel tracing channels (graphql:parse / :validate / :execute
/ :subscribe) and builds spans with the graphql semantic conventions. The node
graphqlIntegration extends it via extendIntegration so the vendored OTel patcher still
handles graphql < 17. Per-field graphql:resolve spans are omitted (high volume; the OTel
path also defaults them off).
…pans option
Wires the per-field `graphql:resolve` channel into the graphql diagnostics-channel
subscriber, gated behind the existing `ignoreResolveSpans` option (default true, so off
by default). When enabled, `ignoreTrivialResolveSpans` (default true) additionally skips
graphql's default property resolver. Both options now flow through to the channel path,
matching the vendored OTel patcher's behavior on graphql < 17.
…keeping
Split option-matrix tests into process-isolated files instead of resetting
and re-subscribing the process-global channels.
…tion
Runtimes that use the server-utils integration directly expose it to users,
so 'channel' in the name leaks an implementation detail. Node imports it under
an internal alias since it keeps its own composed graphqlIntegration.
Replace the conditional-spread pattern for optional attributes with
`?? undefined`. Undefined-valued keys are dropped by the span backends,
so this is equivalent while keeping the attribute lines consistent.
Replace the ad-hoc `void Promise.resolve().then(...)` deferral with the
shared `waitForTracingChannelBinding` util, matching the mongoose,
vercel-ai and redis integrations. It retries until the async context
binding is available, so it also handles custom OTel setups where the
binding isn't ready on the first tick.
The `?? undefined` on `document` (already `string | undefined`) was a no-op.
Switch `operationName` to `|| undefined` so blank operation names are omitted
rather than recorded as empty-string attributes.
…s-channel path
Ports the legacy OTel useOperationNameForRootSpan behavior (default on) to the
graphql >= 17 diagnostics-channel subscriber, so upgrading graphql no longer drops
root-span renaming. Moves the pure graphql helpers into a utils file.
The internal subscribe function has a single deduped setupOnce caller via
waitForTracingChannelBinding, so the subscribed flag guarded a path that
can't occur. Remove it along with the obsolete idempotency test, mirroring
the mysql2 subscriber.
@logaretm
logaretmforce-pushed the awad/graphql-tracing-channels branch from 6395981 to c61c848CompareJuly 7, 2026 18:17
@logaretm
logaretm merged commit c0c2b01 into developJul 7, 2026
214 checks passed
@logaretm
logaretm deleted the awad/graphql-tracing-channels branch July 7, 2026 18:41
Sign up for freeto 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.

4 participants

@logaretm@isaacs@mydea@JPeer264