Skip to content

Commit ba1fa7e

Browse files
authored
fix support for graphql 16 (#1670)
1 parent 13c23bb commit ba1fa7e

File tree

2 files changed

+87
-38
lines changed

2 files changed

+87
-38
lines changed

packages/datadog-plugin-graphql/src/index.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,17 @@ let tools
99
function createWrapExecute (tracer, config, defaultFieldResolver) {
1010
return function wrapExecute (execute) {
1111
return function executeWithTrace () {
12-
const args = normalizeArgs(arguments)
12+
const args = normalizeArgs(arguments, tracer, config, defaultFieldResolver)
1313
const schema = args.schema
1414
const document = args.document
1515
const source = document && document._datadog_source
16-
const fieldResolver = args.fieldResolver || defaultFieldResolver
17-
const contextValue = args.contextValue = args.contextValue || {}
16+
const contextValue = args.contextValue
1817
const operation = getOperation(document, args.operationName)
1918

2019
if (contextValue._datadog_graphql) {
2120
return execute.apply(this, arguments)
2221
}
2322

24-
args.fieldResolver = wrapResolve(fieldResolver, tracer, config)
25-
2623
if (schema) {
2724
wrapFields(schema._queryType, tracer, config)
2825
wrapFields(schema._mutationType, tracer, config)
@@ -32,7 +29,7 @@ function createWrapExecute (tracer, config, defaultFieldResolver) {
3229

3330
contextValue._datadog_graphql = { source, span, fields: {} }
3431

35-
return call(execute, span, this, [args], (err, res) => {
32+
return call(execute, span, this, arguments, (err, res) => {
3633
finishResolvers(contextValue, config)
3734

3835
setError(span, err || (res && res.errors && res.errors[0]))
@@ -212,10 +209,19 @@ function getField (contextValue, path) {
212209
return contextValue._datadog_graphql.fields[path.join('.')]
213210
}
214211

215-
function normalizeArgs (args) {
216-
if (args.length === 1) {
217-
return args[0]
218-
}
212+
function normalizeArgs (args, tracer, config, defaultFieldResolver) {
213+
if (args.length !== 1) return normalizePositional(args, tracer, config, defaultFieldResolver)
214+
215+
args[0].contextValue = args[0].contextValue || {}
216+
args[0].fieldResolver = wrapResolve(args[0].fieldResolver || defaultFieldResolver, tracer, config)
217+
218+
return args[0]
219+
}
220+
221+
function normalizePositional (args, tracer, config, defaultFieldResolver) {
222+
args[3] = args[3] || {} // contextValue
223+
args[6] = wrapResolve(args[6] || defaultFieldResolver, tracer, config) // fieldResolver
224+
args.length = Math.max(args.length, 7)
219225

220226
return {
221227
schema: args[0],

packages/datadog-plugin-graphql/test/index.spec.js

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict'
22

3+
const { expect } = require('chai')
4+
const semver = require('semver')
35
const agent = require('../../dd-trace/test/plugins/agent')
46
const plugin = require('../src')
57

@@ -175,6 +177,7 @@ describe('Plugin', () => {
175177

176178
it('should instrument parsing', done => {
177179
const source = `query MyQuery { hello(name: "world") }`
180+
const variableValues = { who: 'world' }
178181

179182
agent
180183
.use(traces => {
@@ -189,11 +192,12 @@ describe('Plugin', () => {
189192
.then(done)
190193
.catch(done)
191194

192-
graphql.graphql(schema, source, null, null, { who: 'world' }).catch(done)
195+
graphql.graphql({ schema, source, variableValues }).catch(done)
193196
})
194197

195198
it('should instrument validation', done => {
196199
const source = `query MyQuery { hello(name: "world") }`
200+
const variableValues = { who: 'world' }
197201

198202
agent
199203
.use(traces => {
@@ -208,11 +212,12 @@ describe('Plugin', () => {
208212
.then(done)
209213
.catch(done)
210214

211-
graphql.graphql(schema, source, null, null, { who: 'world' }).catch(done)
215+
graphql.graphql({ schema, source, variableValues }).catch(done)
212216
})
213217

214218
it('should instrument execution', done => {
215219
const source = `query MyQuery { hello(name: "world") }`
220+
const variableValues = { who: 'world' }
216221

217222
agent
218223
.use(traces => {
@@ -229,11 +234,12 @@ describe('Plugin', () => {
229234
.then(done)
230235
.catch(done)
231236

232-
graphql.graphql(schema, source, null, null, { who: 'world' }).catch(done)
237+
graphql.graphql({ schema, source, variableValues }).catch(done)
233238
})
234239

235240
it('should not include variables by default', done => {
236241
const source = `query MyQuery($who: String!) { hello(name: $who) }`
242+
const variableValues = { who: 'world' }
237243

238244
agent
239245
.use(traces => {
@@ -243,7 +249,7 @@ describe('Plugin', () => {
243249
.then(done)
244250
.catch(done)
245251

246-
graphql.graphql(schema, source, null, null, { who: 'world' }).catch(done)
252+
graphql.graphql({ schema, source, variableValues }).catch(done)
247253
})
248254

249255
it('should instrument schema resolvers', done => {
@@ -267,7 +273,7 @@ describe('Plugin', () => {
267273
.then(done)
268274
.catch(done)
269275

270-
graphql.graphql(schema, source).catch(done)
276+
graphql.graphql({ schema, source }).catch(done)
271277
})
272278

273279
it('should instrument nested field resolvers', done => {
@@ -325,7 +331,7 @@ describe('Plugin', () => {
325331
.then(done)
326332
.catch(done)
327333

328-
graphql.graphql(schema, source).catch(done)
334+
graphql.graphql({ schema, source }).catch(done)
329335
})
330336

331337
it('should instrument list field resolvers', done => {
@@ -375,7 +381,7 @@ describe('Plugin', () => {
375381
.then(done)
376382
.catch(done)
377383

378-
graphql.graphql(schema, source).catch(done)
384+
graphql.graphql({ schema, source }).catch(done)
379385
})
380386

381387
it('should instrument mutations', done => {
@@ -390,7 +396,7 @@ describe('Plugin', () => {
390396
.then(done)
391397
.catch(done)
392398

393-
graphql.graphql(schema, source).catch(done)
399+
graphql.graphql({ schema, source }).catch(done)
394400
})
395401

396402
it('should instrument subscriptions', done => {
@@ -405,13 +411,13 @@ describe('Plugin', () => {
405411
.then(done)
406412
.catch(done)
407413

408-
graphql.graphql(schema, source).catch(done)
414+
graphql.graphql({ schema, source }).catch(done)
409415
})
410416

411417
it('should handle a circular schema', done => {
412418
const source = `{ human { pets { owner { name } } } }`
413419

414-
graphql.graphql(schema, source)
420+
graphql.graphql({ schema, source })
415421
.then((result) => {
416422
expect(result.data.human.pets[0].owner.name).to.equal('test')
417423
})
@@ -427,6 +433,7 @@ describe('Plugin', () => {
427433
`)
428434

429435
const source = `{ hello }`
436+
const rootValue = { hello: 'world' }
430437

431438
agent
432439
.use(traces => {
@@ -439,7 +446,7 @@ describe('Plugin', () => {
439446
.then(done)
440447
.catch(done)
441448

442-
graphql.graphql(schema, source, { hello: 'world' }).catch(done)
449+
graphql.graphql({ schema, source, rootValue }).catch(done)
443450
})
444451

445452
it('should instrument the execution field resolver without a rootValue resolver', done => {
@@ -484,14 +491,15 @@ describe('Plugin', () => {
484491
.then(done)
485492
.catch(done)
486493

487-
graphql.graphql(schema, source).catch(done)
494+
graphql.graphql({ schema, source }).catch(done)
488495
})
489496

490-
graphql.graphql(schema, source).catch(done)
497+
graphql.graphql({ schema, source }).catch(done)
491498
})
492499

493500
it('should run parsing, validation and execution in the current context', done => {
494501
const source = `query MyQuery { hello(name: "world") }`
502+
const variableValues = { who: 'world' }
495503
const span = tracer.startSpan('test.request')
496504

497505
agent
@@ -520,7 +528,7 @@ describe('Plugin', () => {
520528
.catch(done)
521529

522530
tracer.scope().activate(span, () => {
523-
graphql.graphql(schema, source, null, null, { who: 'world' })
531+
graphql.graphql({ schema, source, variableValues })
524532
.then(() => span.finish())
525533
.catch(done)
526534
})
@@ -576,11 +584,11 @@ describe('Plugin', () => {
576584
})
577585

578586
it('should handle unsupported operations', () => {
579-
const query = `query MyQuery { hello(name: "world") }`
587+
const source = `query MyQuery { hello(name: "world") }`
580588
const subscription = `subscription { human { name } }`
581589

582-
return graphql.graphql(schema, query)
583-
.then(() => graphql.graphql(schema, subscription))
590+
return graphql.graphql({ schema, source })
591+
.then(() => graphql.graphql({ schema, source: subscription }))
584592
.then(result => {
585593
expect(result).to.not.have.property('errors')
586594
})
@@ -631,7 +639,7 @@ describe('Plugin', () => {
631639
.then(done)
632640
.catch(done)
633641

634-
graphql.execute(schema, document)
642+
graphql.execute({ schema, document })
635643
})
636644

637645
it('should handle parsing exceptions', done => {
@@ -767,7 +775,7 @@ describe('Plugin', () => {
767775
.then(done)
768776
.catch(done)
769777

770-
Promise.resolve(graphql.execute(schema, document, rootValue))
778+
Promise.resolve(graphql.execute({ schema, document, rootValue }))
771779
.then(res => {
772780
error = res.errors[0]
773781
})
@@ -934,7 +942,7 @@ describe('Plugin', () => {
934942
.then(done)
935943
.catch(done)
936944

937-
graphql.graphql(schema, source).catch(done)
945+
graphql.graphql({ schema, source }).catch(done)
938946
})
939947

940948
it('should handle single fragment definitions', done => {
@@ -958,9 +966,42 @@ describe('Plugin', () => {
958966
.then(done)
959967
.catch(done)
960968

961-
graphql.graphql(schema, source).catch(done)
969+
graphql.graphql({ schema, source }).catch(done)
962970
})
963971

972+
// https://github.com/graphql/graphql-js/pull/2904
973+
if (!semver.intersects(version, '>=16')) {
974+
it('should instrument using positional arguments', done => {
975+
const source = `query MyQuery { hello(name: "world") }`
976+
const variableValues = { who: 'world' }
977+
978+
agent
979+
.use(traces => {
980+
const spans = sort(traces[0])
981+
982+
expect(spans[0]).to.have.property('service', 'test')
983+
expect(spans[0]).to.have.property('name', 'graphql.execute')
984+
expect(spans[0]).to.have.property('resource', 'query MyQuery{hello(name:"")}')
985+
expect(spans[0]).to.have.property('type', 'graphql')
986+
expect(spans[0].meta).to.not.have.property('graphql.source')
987+
expect(spans[0].meta).to.have.property('graphql.operation.type', 'query')
988+
expect(spans[0].meta).to.have.property('graphql.operation.name', 'MyQuery')
989+
})
990+
.then(done)
991+
.catch(done)
992+
993+
graphql.graphql(schema, source, null, null, variableValues).catch(done)
994+
})
995+
} else {
996+
it('should not support positional arguments', done => {
997+
const source = `query MyQuery { hello(name: "world") }`
998+
const variableValues = { who: 'world' }
999+
1000+
graphql.graphql(schema, source, null, null, variableValues)
1001+
.then(() => done(new Error('Expected error.')), () => done())
1002+
})
1003+
}
1004+
9641005
// it('should not disable signature with invalid arguments', done => {
9651006
// agent
9661007
// .use(traces => {
@@ -1035,7 +1076,7 @@ describe('Plugin', () => {
10351076
.then(done)
10361077
.catch(done)
10371078

1038-
graphql.graphql(schema, source).catch(done)
1079+
graphql.graphql({ schema, source }).catch(done)
10391080
})
10401081

10411082
it('should apply the filter callback to the variables', done => {
@@ -1044,6 +1085,7 @@ describe('Plugin', () => {
10441085
hello(title: $title, name: $who)
10451086
}
10461087
`
1088+
const variableValues = { title: 'planet', who: 'world' }
10471089

10481090
agent
10491091
.use(traces => {
@@ -1057,7 +1099,7 @@ describe('Plugin', () => {
10571099
.then(done)
10581100
.catch(done)
10591101

1060-
graphql.graphql(schema, source, null, null, { title: 'planet', who: 'world' }).catch(done)
1102+
graphql.graphql({ schema, source, variableValues }).catch(done)
10611103
})
10621104
})
10631105

@@ -1085,6 +1127,7 @@ describe('Plugin', () => {
10851127
hello(title: $title, name: $who)
10861128
}
10871129
`
1130+
const variableValues = { title: 'planet', who: 'world' }
10881131

10891132
agent
10901133
.use(traces => {
@@ -1096,7 +1139,7 @@ describe('Plugin', () => {
10961139
.then(done)
10971140
.catch(done)
10981141

1099-
graphql.graphql(schema, source, null, null, { title: 'planet', who: 'world' }).catch(done)
1142+
graphql.graphql({ schema, source, variableValues }).catch(done)
11001143
})
11011144
})
11021145

@@ -1139,7 +1182,7 @@ describe('Plugin', () => {
11391182
.then(done)
11401183
.catch(done)
11411184

1142-
graphql.graphql(schema, source).catch(done)
1185+
graphql.graphql({ schema, source }).catch(done)
11431186
})
11441187

11451188
it('should run the resolvers in the execution scope', done => {
@@ -1217,7 +1260,7 @@ describe('Plugin', () => {
12171260
.then(done)
12181261
.catch(done)
12191262

1220-
graphql.graphql(schema, source).catch(done)
1263+
graphql.graphql({ schema, source }).catch(done)
12211264
})
12221265
})
12231266

@@ -1271,7 +1314,7 @@ describe('Plugin', () => {
12711314
.then(done)
12721315
.catch(done)
12731316

1274-
graphql.graphql(schema, source).catch(done)
1317+
graphql.graphql({ schema, source }).catch(done)
12751318
})
12761319
})
12771320

@@ -1304,7 +1347,7 @@ describe('Plugin', () => {
13041347
.then(done)
13051348
.catch(done)
13061349

1307-
graphql.graphql(schema, source).catch(done)
1350+
graphql.graphql({ schema, source }).catch(done)
13081351
})
13091352
})
13101353

0 commit comments

Comments
 (0)