11import * as diagnosticsChannel from 'node:diagnostics_channel' ;
2- import type { Client , IntegrationFn } from '@sentry/core' ;
3- import { defineIntegration , extendIntegration } from '@sentry/core' ;
4- import { graphqlIntegration as graphqlNativeIntegration } from '../../graphql' ;
5- import type { GraphqlDiagnosticChannelsOptions } from '../../graphql/graphql-dc-subscriber' ;
2+ import type { IntegrationFn } from '@sentry/core' ;
3+ import { defineIntegration , waitForTracingChannelBinding } from '@sentry/core' ;
4+ import { subscribeGraphqlDiagnosticChannels , type GraphQLOptions } from './graphql-dc-subscriber' ;
65import { CHANNELS } from '../../orchestrion/channels' ;
76import { graphqlModuleNames } from '../../orchestrion/config/graphql' ;
87import { invokeOrchestrionInstrumentation } from '../../orchestrion/instrumentation' ;
@@ -28,15 +27,15 @@ interface GraphqlChannelContext {
2827 error ?: unknown ;
2928}
3029
31- function getOptionsWithDefaults ( options : GraphqlDiagnosticChannelsOptions ) : GraphqlResolvedConfig {
30+ function getOptionsWithDefaults ( options : GraphQLOptions ) : GraphqlResolvedConfig {
3231 return {
3332 ignoreResolveSpans : options . ignoreResolveSpans !== false ,
3433 ignoreTrivialResolveSpans : options . ignoreTrivialResolveSpans !== false ,
3534 useOperationNameForRootSpan : options . useOperationNameForRootSpan !== false ,
3635 } ;
3736}
3837
39- const _graphqlIntegration = ( ( options : GraphqlDiagnosticChannelsOptions = { } ) => {
38+ const _graphqlIntegration = ( ( options : GraphQLOptions = { } ) => {
4039 const config = getOptionsWithDefaults ( options ) ;
4140 const getConfig = ( ) : GraphqlResolvedConfig => config ;
4241
@@ -45,6 +44,9 @@ const _graphqlIntegration = ((options: GraphqlDiagnosticChannelsOptions = {}) =>
4544 setup ( client ) {
4645 invokeOrchestrionInstrumentation ( client , graphqlModuleNames , instrumentGraphql , [ config , getConfig ] ) ;
4746 } ,
47+ setupOnce ( ) {
48+ setupNativeGraphQLInstrumentation ( options ) ;
49+ } ,
4850 } ;
4951} ) satisfies IntegrationFn ;
5052
@@ -66,30 +68,20 @@ function instrumentGraphql(config: GraphqlResolvedConfig, getConfig: () => Graph
6668 ) ;
6769}
6870
69- /**
70- * Orchestrion-driven graphql integration for graphql v14–16 (v17 publishes native
71- * `diagnostics_channel` events handled by `@sentry/server-utils`'s graphql integration instead).
72- *
73- * Subscribes to the `orchestrion:graphql:{parse,validate,execute}` channels the orchestrion code
74- * transform injects into `graphql`'s `language/parser.js`, `validation/validate.js` and
75- * `execution/execute.js`, emitting spans identical to the native path. Requires the orchestrion
76- * runtime hook or bundler plugin.
77- */
78- export const graphqlIntegration = defineIntegration ( _graphqlIntegration ) ;
71+ function setupNativeGraphQLInstrumentation ( options : GraphQLOptions ) {
72+ if ( ! diagnosticsChannel . tracingChannel ) {
73+ return ;
74+ }
75+
76+ // Subscribe to graphql's native tracing channels (graphql >= 17).
77+ // This is a no-op on versions that don't publish to the channels, so it is always safe to call.
78+ waitForTracingChannelBinding ( ( ) => {
79+ subscribeGraphqlDiagnosticChannels ( diagnosticsChannel . tracingChannel , options ) ;
80+ } ) ;
81+ }
7982
8083/**
81- * The complete graphql diagnostics-channel integration: the native subscriber (graphql v17) composed
82- * with the orchestrion subscriber (v14–16), so opting into injection instruments every supported
83- * version via diagnostics channels without the OTel patcher. Reuses the OTel `Graphql` name so
84- * enabling injection swaps this in for it.
84+ * Instrument the graphql library.
85+ * This works for graphql v14-v17.
8586 */
86- export const graphqlDiagnosticsIntegration = ( options ?: GraphqlDiagnosticChannelsOptions ) => {
87- const orchestrion = graphqlIntegration ( options ) ;
88- // The native half is the base integration's own `setupOnce`; the orchestrion half
89- // registers lazily via `setup` (only once `graphql` is injected), so it isn't
90- // merged onto the base `setupOnce` — both run.
91- return extendIntegration ( graphqlNativeIntegration ( options ) , {
92- name : INTEGRATION_NAME ,
93- setup : ( client : Client ) => orchestrion . setup ?.( client ) ,
94- } ) ;
95- } ;
87+ export const graphqlIntegration = defineIntegration ( _graphqlIntegration ) ;
0 commit comments