Skip to content

Instantly share code, notes, and snippets.

@trentm
Created June 8, 2022 20:20
Show Gist options
  • Save trentm/ee7d2d5f7c7a98917b362c405830c84b to your computer and use it in GitHub Desktop.
Save trentm/ee7d2d5f7c7a98917b362c405830c84b to your computer and use it in GitHub Desktop.
diff --git a/lib/instrumentation/modules/graphql.js b/lib/instrumentation/modules/graphql.js
index 4c680f2f..a59b4ba7 100644
--- a/lib/instrumentation/modules/graphql.js
+++ b/lib/instrumentation/modules/graphql.js
@@ -41,19 +41,36 @@ module.exports = function (graphql, agent, { version, enabled }) {
})
function wrapGraphql (orig) {
- return function wrappedGraphql (schema, requestString, rootValue, contextValue, variableValues, operationName) {
+ return function wrappedGraphql (args) {
agent.logger.debug('intercepted call to graphql.graphql')
const span = ins.createSpan('GraphQL: Unknown Query', 'db', 'graphql', 'execute')
if (!span) {
return orig.apply(this, arguments)
}
- var source = new graphql.Source(requestString || '', 'GraphQL request')
- if (source) {
+ let schema
+ let source
+ let operationName
+ if (arguments.length === 1) {
+ schema = args.schema
+ source = args.source
+ operationName = args.operationName
+ } else {
+ // graphql <=v15 supported positional arguments:
+ // function (schema, source, rootValue, contextValue, variableValues, operationName)
+ schema = arguments[0]
+ source = arguments[1]
+ operationName = arguments[5]
+ }
+
+ const sourceObj = (typeof source === 'string'
+ ? new graphql.Source(source || '', 'GraphQL request')
+ : source)
+ if (sourceObj) {
var documentAST
try {
- documentAST = graphql.parse(source)
+ documentAST = graphql.parse(sourceObj)
} catch (syntaxError) {
agent.logger.debug('graphql.parse(source) failed - skipping graphql query extraction')
}
@@ -79,9 +96,7 @@ module.exports = function (graphql, agent, { version, enabled }) {
}
function wrapExecute (orig) {
- return function wrappedExecute () {
- var { document, operationName } = extractArgs(...arguments)
-
+ return function wrappedExecute (args) {
agent.logger.debug('intercepted call to graphql.execute')
const span = ins.createSpan('GraphQL: Unknown Query', 'db', 'graphql', 'execute')
if (!span) {
@@ -89,6 +104,18 @@ module.exports = function (graphql, agent, { version, enabled }) {
return orig.apply(this, arguments)
}
+ let document
+ let operationName
+ if (arguments.length === 1) {
+ document = args.document
+ operationName = args.operationName
+ } else {
+ // graphql <=v15 supported positional arguments:
+ // function (schema, document, rootValue, contextValue, variableValues, operationName)
+ document = arguments[1]
+ operationName = arguments[5]
+ }
+
var details = extractDetails(document, operationName)
var queries = details.queries
operationName = operationName || (details.operation && details.operation.name && details.operation.name.value)
@@ -123,20 +150,6 @@ module.exports = function (graphql, agent, { version, enabled }) {
}
}
- function extractArgs (argsOrSchema, document, rootValue, contextValue, variableValues, operationName) {
- // Arg object
- if (arguments.length === 1) {
- return {
- document: argsOrSchema.document,
- operationName: argsOrSchema.operationName
- }
- }
- return {
- document,
- operationName
- }
- }
-
function extractDetails (document, operationName) {
var queries = []
var operation
diff --git a/package-lock.json b/package-lock.json
index 97b52487..6e0d019d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -83,7 +83,7 @@
"generic-pool": "^3.7.1",
"get-port": "^5.1.1",
"got": "^9.6.0",
- "graphql": "^15.8.0",
+ "graphql": "^16.5.0",
"handlebars": "^4.7.3",
"https-pem": "^3.0.0",
"ioredis": "^4.28.0",
@@ -8346,12 +8346,12 @@
"dev": true
},
"node_modules/graphql": {
- "version": "15.8.0",
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz",
- "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==",
+ "version": "16.5.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz",
+ "integrity": "sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA==",
"dev": true,
"engines": {
- "node": ">= 10.x"
+ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
},
"node_modules/graphql-tag": {
@@ -22766,9 +22766,9 @@
"dev": true
},
"graphql": {
- "version": "15.8.0",
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz",
- "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==",
+ "version": "16.5.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz",
+ "integrity": "sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA==",
"dev": true
},
"graphql-tag": {
diff --git a/package.json b/package.json
index 75129a3e..2105cfdf 100644
--- a/package.json
+++ b/package.json
@@ -153,7 +153,7 @@
"generic-pool": "^3.7.1",
"get-port": "^5.1.1",
"got": "^9.6.0",
- "graphql": "^15.8.0",
+ "graphql": "^16.5.0",
"handlebars": "^4.7.3",
"https-pem": "^3.0.0",
"ioredis": "^4.28.0",
diff --git a/test/instrumentation/modules/graphql.test.js b/test/instrumentation/modules/graphql.test.js
index 9aa3e51a..d8ea1ab3 100644
--- a/test/instrumentation/modules/graphql.test.js
+++ b/test/instrumentation/modules/graphql.test.js
@@ -9,17 +9,42 @@ var agent = require('../../..').start({
})
var graphql = require('graphql')
-var pkg = require('graphql/package.json')
+const graphqlVer = require('graphql/package.json').version
var semver = require('semver')
var test = require('tape')
var mockClient = require('../../_mock_http_client')
-test('graphql.graphql', function (t) {
+if (semver.lt(graphqlVer, '16.0.0')) {
+ // graphql@16 dropped support for positional arguments.
+ test('graphql.graphql(...) - positional args', function (t) {
+ resetAgent(done(t))
+
+ var schema = graphql.buildSchema('type Query { hello: String }')
+ var rootValue = {
+ hello () {
+ return 'Hello world!'
+ }
+ }
+ var query = '{ hello }'
+
+ agent.startTransaction('foo')
+
+ graphql.graphql(schema, query, rootValue).then(function (response) {
+ t.ok(agent.currentSpan === null, 'no currentSpan .graphql().then(...)')
+ agent.endTransaction()
+ t.deepLooseEqual(response, { data: { hello: 'Hello world!' } })
+ agent.flush()
+ })
+ t.ok(agent.currentSpan === null, 'no currentSpan in sync code after .graphql(...)')
+ })
+}
+
+test('graphql.graphql(...) - single GraphQLArgs arg', function (t) {
resetAgent(done(t))
var schema = graphql.buildSchema('type Query { hello: String }')
- var root = {
+ var rootValue = {
hello () {
return 'Hello world!'
}
@@ -28,7 +53,7 @@ test('graphql.graphql', function (t) {
agent.startTransaction('foo')
- graphql.graphql(schema, query, root).then(function (response) {
+ graphql.graphql({ schema, source: query, rootValue }).then(function (response) {
t.ok(agent.currentSpan === null, 'no currentSpan .graphql().then(...)')
agent.endTransaction()
t.deepLooseEqual(response, { data: { hello: 'Hello world!' } })
@@ -41,7 +66,7 @@ test('graphql.graphql - invalid query', function (t) {
resetAgent(done(t, 'Unknown Query'))
var schema = graphql.buildSchema('type Query { hello: String }')
- var root = {
+ var rootValue = {
hello () {
return 'Hello world!'
}
@@ -50,7 +75,7 @@ test('graphql.graphql - invalid query', function (t) {
agent.startTransaction('foo')
- graphql.graphql(schema, query, root).then(function (response) {
+ graphql.graphql({ schema, source: query, rootValue }).then(function (response) {
t.ok(agent.currentSpan === null, 'no currentSpan .graphql().then(...)')
agent.endTransaction()
t.deepEqual(Object.keys(response), ['errors'])
@@ -75,7 +100,7 @@ test('graphql.graphql - transaction ended', function (t) {
})
var schema = graphql.buildSchema('type Query { hello: String }')
- var root = {
+ var rootValue = {
hello () {
return 'Hello world!'
}
@@ -84,36 +109,39 @@ test('graphql.graphql - transaction ended', function (t) {
agent.startTransaction('foo').end()
- graphql.graphql(schema, query, root).then(function (response) {
+ graphql.graphql({ schema, source: query, rootValue }).then(function (response) {
t.ok(agent.currentSpan === null, 'no currentSpan .graphql().then(...)')
t.deepLooseEqual(response, { data: { hello: 'Hello world!' } })
})
t.ok(agent.currentSpan === null, 'no currentSpan in sync code after .graphql(...)')
})
-test('graphql.execute', function (t) {
- resetAgent(done(t))
+if (semver.lt(graphqlVer, '16.0.0')) {
+ // graphql@16 dropped support for positional arguments.
+ test('graphql.execute(...) - positional args', function (t) {
+ resetAgent(done(t))
- var schema = graphql.buildSchema('type Query { hello: String }')
- var root = {
- hello () {
- return Promise.resolve('Hello world!')
+ var schema = graphql.buildSchema('type Query { hello: String }')
+ var rootValue = {
+ hello () {
+ return Promise.resolve('Hello world!')
+ }
}
- }
- var query = '{ hello }'
- var source = new graphql.Source(query)
- var documentAST = graphql.parse(source)
+ var query = '{ hello }'
+ var source = new graphql.Source(query)
+ var documentAST = graphql.parse(source)
- agent.startTransaction('foo')
+ agent.startTransaction('foo')
- graphql.execute(schema, documentAST, root).then(function (response) {
- t.ok(agent.currentSpan === null, 'no currentSpan .execute().then(...)')
- agent.endTransaction()
- t.deepLooseEqual(response, { data: { hello: 'Hello world!' } })
- agent.flush()
+ graphql.execute(schema, documentAST, rootValue).then(function (response) {
+ t.ok(agent.currentSpan === null, 'no currentSpan .execute().then(...)')
+ agent.endTransaction()
+ t.deepLooseEqual(response, { data: { hello: 'Hello world!' } })
+ agent.flush()
+ })
+ t.ok(agent.currentSpan === null, 'no currentSpan in sync code after .execute(...)')
})
- t.ok(agent.currentSpan === null, 'no currentSpan in sync code after .execute(...)')
-})
+}
test('graphql.execute - transaction ended', function (t) {
t.plan(7)
@@ -129,29 +157,29 @@ test('graphql.execute - transaction ended', function (t) {
})
var schema = graphql.buildSchema('type Query { hello: String }')
- var root = {
+ var rootValue = {
hello () {
return Promise.resolve('Hello world!')
}
}
var query = '{ hello }'
var source = new graphql.Source(query)
- var documentAST = graphql.parse(source)
+ var document = graphql.parse(source)
agent.startTransaction('foo').end()
- graphql.execute(schema, documentAST, root).then(function (response) {
+ graphql.execute({ schema, document, rootValue }).then(function (response) {
t.ok(agent.currentSpan === null, 'no currentSpan .execute().then(...)')
t.deepLooseEqual(response, { data: { hello: 'Hello world!' } })
})
t.ok(agent.currentSpan === null, 'no currentSpan in sync code after .execute(...)')
})
-test('graphql.execute args object', function (t) {
+test('graphql.execute(...) - single ExecutionArgs arg', function (t) {
resetAgent(done(t))
var schema = graphql.buildSchema('type Query { hello: String }')
- var root = {
+ var rootValue = {
hello () {
return Promise.resolve('Hello world!')
}
@@ -162,7 +190,7 @@ test('graphql.execute args object', function (t) {
var args = {
schema: schema,
document: documentAST,
- rootValue: root
+ rootValue: rootValue
}
agent.startTransaction('foo')
@@ -176,23 +204,23 @@ test('graphql.execute args object', function (t) {
t.ok(agent.currentSpan === null, 'no currentSpan in sync code after .execute(...)')
})
-if (semver.satisfies(pkg.version, '>=0.12')) {
+if (semver.satisfies(graphqlVer, '>=0.12')) {
test('graphql.execute sync', function (t) {
resetAgent(done(t))
var schema = graphql.buildSchema('type Query { hello: String }')
- var root = {
+ var rootValue = {
hello () {
return 'Hello world!'
}
}
var query = '{ hello }'
var source = new graphql.Source(query)
- var documentAST = graphql.parse(source)
+ var document = graphql.parse(source)
agent.startTransaction('foo')
- var response = graphql.execute(schema, documentAST, root)
+ var response = graphql.execute({ schema, document, rootValue })
t.ok(agent.currentSpan === null, 'no currentSpan in sync code after .execute(...)')
agent.endTransaction()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment