dd-trace 2.1.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/LICENSE-3rdparty.csv +0 -2
  2. package/index.d.ts +28 -12
  3. package/package.json +3 -5
  4. package/packages/datadog-instrumentations/index.js +14 -3
  5. package/packages/datadog-instrumentations/src/bunyan.js +22 -0
  6. package/packages/datadog-instrumentations/src/couchbase.js +143 -0
  7. package/packages/datadog-instrumentations/src/cucumber.js +116 -0
  8. package/packages/datadog-instrumentations/src/elasticsearch.js +84 -0
  9. package/packages/datadog-instrumentations/src/generic-pool.js +48 -0
  10. package/packages/datadog-instrumentations/src/ioredis.js +52 -0
  11. package/packages/datadog-instrumentations/src/mongoose.js +30 -0
  12. package/packages/datadog-instrumentations/src/pino.js +105 -0
  13. package/packages/datadog-instrumentations/src/redis.js +118 -0
  14. package/packages/datadog-instrumentations/src/sharedb.js +78 -0
  15. package/packages/datadog-instrumentations/src/winston.js +57 -0
  16. package/packages/datadog-plugin-bunyan/src/index.js +5 -22
  17. package/packages/datadog-plugin-couchbase/src/index.js +51 -148
  18. package/packages/datadog-plugin-cucumber/src/index.js +83 -128
  19. package/packages/datadog-plugin-elasticsearch/src/index.js +41 -82
  20. package/packages/datadog-plugin-fastify/src/fastify.js +22 -1
  21. package/packages/datadog-plugin-fastify/src/find-my-way.js +0 -1
  22. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +8 -6
  23. package/packages/datadog-plugin-graphql/src/index.js +34 -28
  24. package/packages/datadog-plugin-grpc/src/client.js +20 -6
  25. package/packages/datadog-plugin-http2/src/server.js +2 -0
  26. package/packages/datadog-plugin-ioredis/src/index.js +5 -35
  27. package/packages/datadog-plugin-jest/src/jest-environment.js +26 -30
  28. package/packages/datadog-plugin-koa/src/index.js +6 -2
  29. package/packages/datadog-plugin-microgateway-core/src/index.js +1 -3
  30. package/packages/datadog-plugin-mocha/src/index.js +5 -3
  31. package/packages/datadog-plugin-mongodb-core/src/util.js +31 -7
  32. package/packages/datadog-plugin-next/src/index.js +9 -4
  33. package/packages/datadog-plugin-oracledb/src/index.js +10 -7
  34. package/packages/datadog-plugin-pino/src/index.js +5 -158
  35. package/packages/datadog-plugin-redis/src/index.js +96 -80
  36. package/packages/datadog-plugin-restify/src/index.js +18 -3
  37. package/packages/datadog-plugin-rhea/src/index.js +8 -5
  38. package/packages/datadog-plugin-router/src/index.js +23 -14
  39. package/packages/datadog-plugin-sharedb/src/index.js +47 -87
  40. package/packages/datadog-plugin-winston/src/index.js +5 -110
  41. package/packages/datadog-shimmer/src/shimmer.js +1 -1
  42. package/packages/dd-trace/lib/version.js +1 -1
  43. package/packages/dd-trace/src/appsec/index.js +6 -1
  44. package/packages/dd-trace/src/appsec/reporter.js +3 -2
  45. package/packages/dd-trace/src/config.js +7 -1
  46. package/packages/dd-trace/src/constants.js +1 -6
  47. package/packages/dd-trace/src/opentracing/propagation/text_map.js +0 -34
  48. package/packages/dd-trace/src/opentracing/tracer.js +1 -1
  49. package/packages/dd-trace/src/plugins/index.js +0 -2
  50. package/packages/dd-trace/src/plugins/log_plugin.js +49 -0
  51. package/packages/dd-trace/src/plugins/plugin.js +7 -0
  52. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  53. package/packages/dd-trace/src/plugins/util/web.js +102 -84
  54. package/packages/dd-trace/src/priority_sampler.js +1 -49
  55. package/packages/dd-trace/src/scope.js +47 -23
  56. package/packages/dd-trace/src/span_processor.js +22 -7
  57. package/packages/dd-trace/src/tagger.js +14 -21
  58. package/packages/dd-trace/src/tracer.js +1 -1
  59. package/NOTICE +0 -4
  60. package/packages/datadog-plugin-generic-pool/src/index.js +0 -52
  61. package/packages/datadog-plugin-mongoose/src/index.js +0 -51
  62. package/scripts/tracer-runner.js +0 -13
@@ -1,150 +1,105 @@
1
- const { SAMPLING_RULE_DECISION } = require('../../dd-trace/src/constants')
1
+ 'use strict'
2
+
3
+ const Plugin = require('../../dd-trace/src/plugins/plugin')
4
+ const { storage } = require('../../datadog-core')
2
5
 
3
6
  const {
7
+ CI_APP_ORIGIN,
4
8
  TEST_TYPE,
5
9
  TEST_NAME,
6
10
  TEST_SUITE,
7
- TEST_STATUS,
8
- TEST_FRAMEWORK_VERSION,
9
11
  TEST_SKIP_REASON,
10
- CI_APP_ORIGIN,
12
+ TEST_FRAMEWORK_VERSION,
11
13
  ERROR_MESSAGE,
12
- getTestEnvironmentMetadata,
14
+ TEST_STATUS,
13
15
  finishAllTraceSpans,
16
+ getTestEnvironmentMetadata,
14
17
  getTestSuitePath
15
18
  } = require('../../dd-trace/src/plugins/util/test')
19
+ const { SPAN_TYPE, RESOURCE_NAME } = require('../../../ext/tags')
20
+ const { SAMPLING_RULE_DECISION } = require('../../dd-trace/src/constants')
16
21
 
17
- function setStatusFromResult (span, result, tag) {
18
- if (result.status === 1) {
19
- span.setTag(tag, 'pass')
20
- } else if (result.status === 2) {
21
- span.setTag(tag, 'skip')
22
- } else if (result.status === 4) {
23
- span.setTag(tag, 'skip')
24
- span.setTag(TEST_SKIP_REASON, 'not implemented')
25
- } else {
26
- span.setTag(tag, 'fail')
27
- span.setTag(ERROR_MESSAGE, result.message)
22
+ class CucumberPlugin extends Plugin {
23
+ static get name () {
24
+ return 'cucumber'
28
25
  }
29
- }
30
26
 
31
- function setStatusFromResultLatest (span, result, tag) {
32
- if (result.status === 'PASSED') {
33
- span.setTag(tag, 'pass')
34
- } else if (result.status === 'SKIPPED' || result.status === 'PENDING') {
35
- span.setTag(tag, 'skip')
36
- } else if (result.status === 'UNDEFINED') {
37
- span.setTag(tag, 'skip')
38
- span.setTag(TEST_SKIP_REASON, 'not implemented')
39
- } else {
40
- span.setTag(tag, 'fail')
41
- span.setTag(ERROR_MESSAGE, result.message)
42
- }
43
- }
27
+ constructor (...args) {
28
+ super(...args)
44
29
 
45
- function createWrapRun (tracer, testEnvironmentMetadata, sourceRoot, setStatus) {
46
- return function wrapRun (run) {
47
- return function handleRun () {
48
- const testName = this.pickle.name
49
- const testSuite = getTestSuitePath(this.pickle.uri, sourceRoot)
50
-
51
- const commonSpanTags = {
52
- [TEST_TYPE]: 'test',
53
- [TEST_NAME]: testName,
54
- [TEST_SUITE]: testSuite,
55
- [SAMPLING_RULE_DECISION]: 1,
56
- [TEST_FRAMEWORK_VERSION]: tracer._version,
57
- ...testEnvironmentMetadata
58
- }
30
+ const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber', this.config)
31
+ const sourceRoot = process.cwd()
32
+
33
+ this.addSub('ci:cucumber:run:start', ({ pickleName, pickleUri }) => {
34
+ const store = storage.getStore()
35
+ const childOf = store ? store.span : store
36
+ const testSuite = getTestSuitePath(pickleUri, sourceRoot)
59
37
 
60
- return tracer.trace(
61
- 'cucumber.test',
62
- {
63
- type: 'test',
64
- resource: testName,
65
- tags: commonSpanTags
66
- },
67
- (testSpan) => {
68
- testSpan.context()._trace.origin = CI_APP_ORIGIN
69
- const promise = run.apply(this, arguments)
70
- promise.then(() => {
71
- setStatus(testSpan, this.getWorstStepResult(), TEST_STATUS)
72
- }).finally(() => {
73
- finishAllTraceSpans(testSpan)
74
- })
75
- return promise
38
+ const span = this.tracer.startSpan('cucumber.test', {
39
+ childOf,
40
+ tags: {
41
+ [SPAN_TYPE]: 'test',
42
+ [RESOURCE_NAME]: pickleName,
43
+ [TEST_TYPE]: 'test',
44
+ [TEST_NAME]: pickleName,
45
+ [TEST_SUITE]: testSuite,
46
+ [SAMPLING_RULE_DECISION]: 1,
47
+ [TEST_FRAMEWORK_VERSION]: this.tracer._version,
48
+ ...testEnvironmentMetadata
76
49
  }
77
- )
78
- }
79
- }
80
- }
50
+ })
51
+ span.context()._trace.origin = CI_APP_ORIGIN
52
+ this.enter(span, store)
53
+ })
81
54
 
82
- function createWrapRunStep (tracer, getResourceName, setStatus) {
83
- return function wrapRunStep (runStep) {
84
- return function handleRunStep () {
85
- const resource = getResourceName(arguments[0])
86
- return tracer.trace(
87
- 'cucumber.step',
88
- { resource, tags: { 'cucumber.step': resource } },
89
- (span) => {
90
- const promise = runStep.apply(this, arguments)
91
- promise.then((result) => {
92
- setStatus(span, result, 'step.status')
93
- })
94
- return promise
55
+ this.addSub('ci:cucumber:run:end', () => {
56
+ this.exit()
57
+ })
58
+
59
+ this.addSub('ci:cucumber:run-step:start', ({ resource }) => {
60
+ const store = storage.getStore()
61
+ const childOf = store ? store.span : store
62
+ const span = this.tracer.startSpan('cucumber.step', {
63
+ childOf,
64
+ tags: {
65
+ 'cucumber.step': resource,
66
+ [RESOURCE_NAME]: resource
95
67
  }
96
- )
97
- }
98
- }
99
- }
68
+ })
69
+ this.enter(span, store)
70
+ })
71
+
72
+ this.addSub('ci:cucumber:run-step:end', () => {
73
+ this.exit()
74
+ })
75
+
76
+ this.addSub('ci:cucumber:run:async-end', ({ isStep, status, skipReason, errorMessage }) => {
77
+ const span = storage.getStore().span
78
+ const statusTag = isStep ? 'step.status' : TEST_STATUS
79
+
80
+ span.setTag(statusTag, status)
100
81
 
101
- module.exports = [
102
- {
103
- name: '@cucumber/cucumber',
104
- versions: ['7.0.0 - 7.2.1'],
105
- file: 'lib/runtime/pickle_runner.js',
106
- patch (PickleRunner, tracer, config) {
107
- const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber', config)
108
- const sourceRoot = process.cwd()
109
- const pl = PickleRunner.default
110
- this.wrap(
111
- pl.prototype,
112
- 'run',
113
- createWrapRun(tracer, testEnvironmentMetadata, sourceRoot, setStatusFromResult)
114
- )
115
- const getResourceName = (testStep) => {
116
- return testStep.isHook ? 'hook' : testStep.pickleStep.text
82
+ if (skipReason) {
83
+ span.setTag(TEST_SKIP_REASON, skipReason)
117
84
  }
118
- this.wrap(pl.prototype, 'runStep', createWrapRunStep(tracer, getResourceName, setStatusFromResult))
119
- },
120
- unpatch (PickleRunner) {
121
- const pl = PickleRunner.default
122
- this.unwrap(pl.prototype, 'run')
123
- this.unwrap(pl.prototype, 'runStep')
124
- }
125
- },
126
- {
127
- name: '@cucumber/cucumber',
128
- versions: ['>=7.3.0'],
129
- file: 'lib/runtime/test_case_runner.js',
130
- patch (TestCaseRunner, tracer, config) {
131
- const testEnvironmentMetadata = getTestEnvironmentMetadata('cucumber', config)
132
- const sourceRoot = process.cwd()
133
- const pl = TestCaseRunner.default
134
- this.wrap(
135
- pl.prototype,
136
- 'run',
137
- createWrapRun(tracer, testEnvironmentMetadata, sourceRoot, setStatusFromResultLatest)
138
- )
139
- const getResourceName = (testStep) => {
140
- return testStep.text
85
+
86
+ if (errorMessage) {
87
+ span.setTag(ERROR_MESSAGE, errorMessage)
88
+ }
89
+
90
+ span.finish()
91
+ if (!isStep) {
92
+ finishAllTraceSpans(span)
141
93
  }
142
- this.wrap(pl.prototype, 'runStep', createWrapRunStep(tracer, getResourceName, setStatusFromResultLatest))
143
- },
144
- unpatch (TestCaseRunner) {
145
- const pl = TestCaseRunner.default
146
- this.unwrap(pl.prototype, 'run')
147
- this.unwrap(pl.prototype, 'runStep')
148
- }
94
+ })
95
+
96
+ this.addSub('ci:cucumber:error', (err) => {
97
+ if (err) {
98
+ const span = storage.getStore().span
99
+ span.setTag('error', err)
100
+ }
101
+ })
149
102
  }
150
- ]
103
+ }
104
+
105
+ module.exports = CucumberPlugin
@@ -1,23 +1,29 @@
1
1
  'use strict'
2
2
 
3
- const Tags = require('opentracing').Tags
3
+ const Plugin = require('../../dd-trace/src/plugins/plugin')
4
+ const { storage } = require('../../datadog-core')
4
5
  const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
5
6
 
6
- function createWrapRequest (tracer, config) {
7
- config = normalizeConfig(config)
8
- return function wrapRequest (request) {
9
- return function requestWithTrace (params, options, cb) {
10
- if (!params) return request.apply(this, arguments)
7
+ class ElasticsearchPlugin extends Plugin {
8
+ static get name () {
9
+ return 'elasticsearch'
10
+ }
11
+
12
+ constructor (...args) {
13
+ super(...args)
14
+
15
+ this.addSub('apm:elasticsearch:query:start', ({ params }) => {
16
+ this.config = normalizeConfig(this.config)
11
17
 
12
- const lastIndex = arguments.length - 1
18
+ const store = storage.getStore()
19
+ const childOf = store ? store.span : store
13
20
  const body = getBody(params.body || params.bulkBody)
14
- const childOf = tracer.scope().active()
15
- const span = tracer.startSpan('elasticsearch.query', {
21
+ const span = this.tracer.startSpan('elasticsearch.query', {
16
22
  childOf,
17
23
  tags: {
18
- [Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT,
19
- [Tags.DB_TYPE]: 'elasticsearch',
20
- 'service.name': config.service || `${tracer._service}-elasticsearch`,
24
+ 'db.type': 'elasticsearch',
25
+ 'span.kind': 'client',
26
+ 'service.name': this.config.service || `${this.tracer._service}-elasticsearch`,
21
27
  'resource.name': `${params.method} ${quantizePath(params.path)}`,
22
28
  'span.type': 'elasticsearch',
23
29
  'elasticsearch.url': params.path,
@@ -26,57 +32,25 @@ function createWrapRequest (tracer, config) {
26
32
  'elasticsearch.params': JSON.stringify(params.querystring || params.query)
27
33
  }
28
34
  })
35
+ analyticsSampler.sample(span, this.config.measured)
36
+ this.enter(span, store)
37
+ })
29
38
 
30
- analyticsSampler.sample(span, config.measured)
31
-
32
- cb = arguments[lastIndex]
33
-
34
- if (typeof cb === 'function') {
35
- arguments[lastIndex] = wrapCallback(tracer, span, params, config, cb)
36
-
37
- return tracer.scope().activate(span, () => request.apply(this, arguments))
38
- } else {
39
- const promise = request.apply(this, arguments)
40
-
41
- if (promise && typeof promise.then === 'function') {
42
- promise.then(() => finish(span, params, config), e => finish(span, params, config, e))
43
- } else {
44
- finish(span, params, config)
45
- }
46
-
47
- return promise
48
- }
49
- }
50
- }
51
- }
39
+ this.addSub('apm:elasticsearch:query:end', () => {
40
+ this.exit()
41
+ })
52
42
 
53
- function wrapCallback (tracer, span, params, config, done) {
54
- return tracer.scope().bind(function (err) {
55
- finish(span, params, config, err)
56
- done.apply(null, arguments)
57
- })
58
- }
43
+ this.addSub('apm:elasticsearch:query:error', err => {
44
+ const span = storage.getStore().span
45
+ span.setTag('error', err)
46
+ })
59
47
 
60
- function finish (span, params, config, err) {
61
- if (err) {
62
- span.addTags({
63
- 'error.type': err.name,
64
- 'error.msg': err.message,
65
- 'error.stack': err.stack
48
+ this.addSub('apm:elasticsearch:query:async-end', ({ params }) => {
49
+ const span = storage.getStore().span
50
+ this.config.hooks.query(span, params)
51
+ span.finish()
66
52
  })
67
53
  }
68
-
69
- config.hooks.query(span, params)
70
-
71
- span.finish()
72
- }
73
-
74
- function quantizePath (path) {
75
- return path && path.replace(/[0-9]+/g, '?')
76
- }
77
-
78
- function getBody (body) {
79
- return body && JSON.stringify(body)
80
54
  }
81
55
 
82
56
  function normalizeConfig (config) {
@@ -94,27 +68,12 @@ function getHooks (config) {
94
68
  return { query }
95
69
  }
96
70
 
97
- module.exports = [
98
- {
99
- name: 'elasticsearch',
100
- file: 'src/lib/transport.js',
101
- versions: ['>=10'],
102
- patch (Transport, tracer, config) {
103
- this.wrap(Transport.prototype, 'request', createWrapRequest(tracer, config))
104
- },
105
- unpatch (Transport) {
106
- this.unwrap(Transport.prototype, 'request')
107
- }
108
- },
109
- {
110
- name: '@elastic/elasticsearch',
111
- file: 'lib/Transport.js',
112
- versions: ['>=5.6.16'], // initial version of this module
113
- patch (Transport, tracer, config) {
114
- this.wrap(Transport.prototype, 'request', createWrapRequest(tracer, config))
115
- },
116
- unpatch (Transport) {
117
- this.unwrap(Transport.prototype, 'request')
118
- }
119
- }
120
- ]
71
+ function getBody (body) {
72
+ return body && JSON.stringify(body)
73
+ }
74
+
75
+ function quantizePath (path) {
76
+ return path && path.replace(/[0-9]+/g, '?')
77
+ }
78
+
79
+ module.exports = ElasticsearchPlugin
@@ -165,7 +165,28 @@ function getRes (reply) {
165
165
  module.exports = [
166
166
  {
167
167
  name: 'fastify',
168
- versions: ['>=1'],
168
+ versions: ['>=3'],
169
+ patch (fastify, tracer, config) {
170
+ // `fastify` is a function so we return a wrapper that will replace its export.
171
+ const wrapped = this.wrapExport(fastify, createWrapFastify(tracer, config)(fastify))
172
+
173
+ wrapped.fastify = wrapped
174
+ wrapped.default = wrapped
175
+
176
+ return wrapped
177
+ },
178
+ unpatch (fastify) {
179
+ const unwrapped = this.unwrapExport(fastify)
180
+
181
+ unwrapped.fastify = unwrapped
182
+ unwrapped.default = unwrapped
183
+
184
+ return unwrapped
185
+ }
186
+ },
187
+ {
188
+ name: 'fastify',
189
+ versions: ['1 - 2'],
169
190
  patch (fastify, tracer, config) {
170
191
  // `fastify` is a function so we return a wrapper that will replace its export.
171
192
  return this.wrapExport(fastify, createWrapFastify(tracer, config)(fastify))
@@ -10,7 +10,6 @@ function createWrapOn () {
10
10
  const wrapper = function (req) {
11
11
  web.patch(req)
12
12
  web.enterRoute(req, path)
13
- req._datadog.routeEntered = true
14
13
 
15
14
  return handler.apply(this, arguments)
16
15
  }
@@ -2,6 +2,8 @@
2
2
 
3
3
  const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
4
4
 
5
+ const messageSpans = new WeakMap()
6
+
5
7
  function createWrapRequest (tracer, config) {
6
8
  return function wrapRequest (request) {
7
9
  return function requestWithTrace (cfg = { reqOpts: {} }, cb) {
@@ -45,11 +47,11 @@ function createWrapRequest (tracer, config) {
45
47
  function createWrapSubscriptionEmit (tracer, config) {
46
48
  return function wrapSubscriptionEmit (emit) {
47
49
  return function emitWithTrace (eventName, message) {
48
- if (eventName !== 'message' || !message || !message._datadog_span) {
49
- return emit.apply(this, arguments)
50
- }
50
+ if (eventName !== 'message' || !message) return emit.apply(this, arguments)
51
+
52
+ const span = messageSpans.get(message)
51
53
 
52
- const span = message._datadog_span
54
+ if (!span) return emit.apply(this, arguments)
53
55
 
54
56
  return tracer.scope().activate(span, () => {
55
57
  try {
@@ -83,7 +85,7 @@ function createWrapLeaseDispense (tracer, config) {
83
85
 
84
86
  analyticsSampler.sample(span, config.measured, true)
85
87
 
86
- message._datadog_span = span
88
+ messageSpans.set(message, span)
87
89
 
88
90
  return dispense.apply(this, arguments)
89
91
  }
@@ -119,7 +121,7 @@ function getTopic (cfg) {
119
121
  }
120
122
 
121
123
  function finish (message) {
122
- const span = message._datadog_span
124
+ const span = messageSpans.get(message)
123
125
 
124
126
  if (!span) return
125
127
 
@@ -4,6 +4,11 @@ const pick = require('lodash.pick')
4
4
  const log = require('../../dd-trace/src/log')
5
5
  const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
6
6
 
7
+ const contexts = new WeakMap()
8
+ const documentSources = new WeakMap()
9
+ const patchedTypes = new WeakSet()
10
+ const patchedResolvers = new WeakSet()
11
+
7
12
  let tools
8
13
 
9
14
  function createWrapExecute (tracer, config, defaultFieldResolver) {
@@ -12,11 +17,11 @@ function createWrapExecute (tracer, config, defaultFieldResolver) {
12
17
  const args = normalizeArgs(arguments, tracer, config, defaultFieldResolver)
13
18
  const schema = args.schema
14
19
  const document = args.document
15
- const source = document && document._datadog_source
20
+ const source = documentSources.get(document)
16
21
  const contextValue = args.contextValue
17
22
  const operation = getOperation(document, args.operationName)
18
23
 
19
- if (contextValue._datadog_graphql) {
24
+ if (contexts.has(contextValue)) {
20
25
  return execute.apply(this, arguments)
21
26
  }
22
27
 
@@ -26,11 +31,12 @@ function createWrapExecute (tracer, config, defaultFieldResolver) {
26
31
  }
27
32
 
28
33
  const span = startExecutionSpan(tracer, config, operation, args)
34
+ const context = { source, span, fields: {} }
29
35
 
30
- contextValue._datadog_graphql = { source, span, fields: {} }
36
+ contexts.set(contextValue, context)
31
37
 
32
38
  return call(execute, span, this, arguments, (err, res) => {
33
- finishResolvers(contextValue, config)
39
+ finishResolvers(context)
34
40
 
35
41
  setError(span, err || (res && res.errors && res.errors[0]))
36
42
  config.hooks.execute(span, args, res)
@@ -55,7 +61,7 @@ function createWrapParse (tracer, config) {
55
61
  if (!operation) return document // skip schema parsing
56
62
 
57
63
  if (source) {
58
- document._datadog_source = source.body || source
64
+ documentSources.set(document, source.body || source)
59
65
  }
60
66
 
61
67
  addDocumentTags(span, document, config)
@@ -103,11 +109,11 @@ function createWrapValidate (tracer, config) {
103
109
  }
104
110
 
105
111
  function wrapFields (type, tracer, config) {
106
- if (!type || !type._fields || type._datadog_patched) {
112
+ if (!type || !type._fields || patchedTypes.has(type)) {
107
113
  return
108
114
  }
109
115
 
110
- type._datadog_patched = true
116
+ patchedTypes.add(type)
111
117
 
112
118
  Object.keys(type._fields).forEach(key => {
113
119
  const field = type._fields[key]
@@ -136,14 +142,16 @@ function wrapFieldType (field, tracer, config) {
136
142
  }
137
143
 
138
144
  function wrapResolve (resolve, tracer, config) {
139
- if (resolve._datadog_patched || typeof resolve !== 'function') return resolve
145
+ if (typeof resolve !== 'function' || patchedResolvers.has(resolve)) return resolve
140
146
 
141
147
  const responsePathAsArray = config.collapse
142
148
  ? withCollapse(pathToArray)
143
149
  : pathToArray
144
150
 
145
151
  function resolveWithTrace (source, args, contextValue, info) {
146
- if (!contextValue._datadog_graphql) return resolve.apply(this, arguments)
152
+ const context = contexts.get(contextValue)
153
+
154
+ if (!context) return resolve.apply(this, arguments)
147
155
 
148
156
  const path = responsePathAsArray(info && info.path)
149
157
 
@@ -151,18 +159,18 @@ function wrapResolve (resolve, tracer, config) {
151
159
  const depth = path.filter(item => typeof item === 'string').length
152
160
 
153
161
  if (config.depth < depth) {
154
- const parent = getParentField(tracer, contextValue, path)
162
+ const parent = getParentField(tracer, context, path)
155
163
 
156
164
  return call(resolve, parent.span, this, arguments)
157
165
  }
158
166
  }
159
167
 
160
- const field = assertField(tracer, config, contextValue, info, path)
168
+ const field = assertField(tracer, config, context, info, path)
161
169
 
162
170
  return call(resolve, field.span, this, arguments, err => updateField(field, err))
163
171
  }
164
172
 
165
- resolveWithTrace._datadog_patched = true
173
+ patchedResolvers.add(resolveWithTrace)
166
174
 
167
175
  return resolveWithTrace
168
176
  }
@@ -191,9 +199,9 @@ function call (fn, span, thisArg, args, callback) {
191
199
  }
192
200
  }
193
201
 
194
- function getParentField (tracer, contextValue, path) {
202
+ function getParentField (tracer, context, path) {
195
203
  for (let i = path.length - 1; i > 0; i--) {
196
- const field = getField(contextValue, path.slice(0, i))
204
+ const field = getField(context, path.slice(0, i))
197
205
 
198
206
  if (field) {
199
207
  return field
@@ -201,12 +209,12 @@ function getParentField (tracer, contextValue, path) {
201
209
  }
202
210
 
203
211
  return {
204
- span: contextValue._datadog_graphql.span
212
+ span: context.span
205
213
  }
206
214
  }
207
215
 
208
- function getField (contextValue, path) {
209
- return contextValue._datadog_graphql.fields[path.join('.')]
216
+ function getField (context, path) {
217
+ return context.fields[path.join('.')]
210
218
  }
211
219
 
212
220
  function normalizeArgs (args, tracer, config, defaultFieldResolver) {
@@ -267,8 +275,8 @@ function addExecutionTags (span, config, operation, document, operationName) {
267
275
  function addDocumentTags (span, document, config) {
268
276
  const tags = {}
269
277
 
270
- if (config.source && document && document._datadog_source) {
271
- tags['graphql.source'] = document._datadog_source
278
+ if (config.source && document) {
279
+ tags['graphql.source'] = documentSources.get(document)
272
280
  }
273
281
 
274
282
  span.addTags(tags)
@@ -300,9 +308,9 @@ function startSpan (tracer, config, name, options) {
300
308
  })
301
309
  }
302
310
 
303
- function startResolveSpan (tracer, config, childOf, path, info, contextValue) {
311
+ function startResolveSpan (tracer, config, childOf, path, info, { source }) {
304
312
  const span = startSpan(tracer, config, 'resolve', { childOf })
305
- const document = contextValue._datadog_graphql.source
313
+ const document = source
306
314
  const fieldNode = info.fieldNodes.find(fieldNode => fieldNode.kind === 'Field')
307
315
 
308
316
  analyticsSampler.sample(span, config.measured)
@@ -345,9 +353,7 @@ function finish (span, finishTime) {
345
353
  span.finish(finishTime)
346
354
  }
347
355
 
348
- function finishResolvers (contextValue) {
349
- const fields = contextValue._datadog_graphql.fields
350
-
356
+ function finishResolvers ({ fields }) {
351
357
  Object.keys(fields).reverse().forEach(key => {
352
358
  const field = fields[key]
353
359
 
@@ -369,18 +375,18 @@ function withCollapse (responsePathAsArray) {
369
375
  }
370
376
  }
371
377
 
372
- function assertField (tracer, config, contextValue, info, path) {
378
+ function assertField (tracer, config, context, info, path) {
373
379
  const pathString = path.join('.')
374
- const fields = contextValue._datadog_graphql.fields
380
+ const fields = context.fields
375
381
 
376
382
  let field = fields[pathString]
377
383
 
378
384
  if (!field) {
379
- const parent = getParentField(tracer, contextValue, path)
385
+ const parent = getParentField(tracer, context, path)
380
386
 
381
387
  field = fields[pathString] = {
382
388
  parent,
383
- span: startResolveSpan(tracer, config, parent.span, path, info, contextValue),
389
+ span: startResolveSpan(tracer, config, parent.span, path, info, context),
384
390
  error: null
385
391
  }
386
392
  }