diff --git a/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts index 217744e3da..0f60623da3 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/instrumentation.ts @@ -59,6 +59,7 @@ const DEFAULT_CONFIG: GraphQLInstrumentationConfig = { mergeItems: false, depth: -1, allowValues: false, + ignoreResolveSpans: false, }; const supportedVersions = ['>=14']; @@ -474,7 +475,11 @@ export class GraphQLInstrumentation extends InstrumentationBase { if (!contextValue) { contextValue = {}; } - if (contextValue[OTEL_GRAPHQL_DATA_SYMBOL]) { + + if ( + contextValue[OTEL_GRAPHQL_DATA_SYMBOL] || + this._getConfig().ignoreResolveSpans + ) { return { schema, document, diff --git a/plugins/node/opentelemetry-instrumentation-graphql/src/types.ts b/plugins/node/opentelemetry-instrumentation-graphql/src/types.ts index b206b449f4..7cedff14a8 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/src/types.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/src/types.ts @@ -39,6 +39,13 @@ export interface GraphQLInstrumentationConfig extends InstrumentationConfig { */ depth?: number; + /** + * Do not create spans for resolvers. + * + * @default false + */ + ignoreResolveSpans?: boolean; + /** * Don't create spans for the execution of the default resolver on object properties. * diff --git a/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts b/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts index d570a38e1a..ffa186600d 100644 --- a/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts +++ b/plugins/node/opentelemetry-instrumentation-graphql/test/graphql.test.ts @@ -689,6 +689,37 @@ describe('graphql', () => { }); }); + describe('when ignoreResolveSpans is true', () => { + beforeEach(() => { + create({ + ignoreResolveSpans: true, + }); + }); + + afterEach(() => { + exporter.reset(); + graphQLInstrumentation.disable(); + }); + + it('should not create a span for a defined resolver', async () => { + const schema = buildSchema(` + type Query { + hello: String + } + `); + + const rootValue = { + hello: () => 'world', + }; + + await graphql({ schema, source: '{ hello }', rootValue }); + const resolveSpans = exporter + .getFinishedSpans() + .filter(span => span.name === `${SpanNames.RESOLVE} hello`); + assert.deepStrictEqual(resolveSpans.length, 0); + }); + }); + describe('when allowValues is set to true', () => { describe('AND source is query with param', () => { let spans: ReadableSpan[];