dd-trace 3.3.1 → 3.12.1

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 (198) hide show
  1. package/LICENSE-3rdparty.csv +8 -0
  2. package/README.md +108 -43
  3. package/ci/init.js +6 -1
  4. package/ext/exporters.d.ts +2 -1
  5. package/ext/exporters.js +2 -1
  6. package/index.d.ts +129 -36
  7. package/package.json +18 -9
  8. package/packages/datadog-instrumentations/src/body-parser.js +26 -0
  9. package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
  10. package/packages/datadog-instrumentations/src/child-process.js +30 -0
  11. package/packages/datadog-instrumentations/src/connect.js +15 -15
  12. package/packages/datadog-instrumentations/src/cucumber.js +1 -3
  13. package/packages/datadog-instrumentations/src/elasticsearch.js +51 -47
  14. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +1 -1
  15. package/packages/datadog-instrumentations/src/helpers/hooks.js +9 -0
  16. package/packages/datadog-instrumentations/src/helpers/register.js +5 -0
  17. package/packages/datadog-instrumentations/src/http/server.js +20 -12
  18. package/packages/datadog-instrumentations/src/http2/server.js +67 -1
  19. package/packages/datadog-instrumentations/src/jest.js +182 -25
  20. package/packages/datadog-instrumentations/src/koa.js +32 -32
  21. package/packages/datadog-instrumentations/src/ldapjs.js +91 -0
  22. package/packages/datadog-instrumentations/src/mariadb.js +63 -0
  23. package/packages/datadog-instrumentations/src/memcached.js +1 -4
  24. package/packages/datadog-instrumentations/src/mocha.js +135 -24
  25. package/packages/datadog-instrumentations/src/next.js +10 -2
  26. package/packages/datadog-instrumentations/src/opensearch.js +10 -0
  27. package/packages/datadog-instrumentations/src/oracledb.js +8 -8
  28. package/packages/datadog-instrumentations/src/pg.js +7 -3
  29. package/packages/datadog-instrumentations/src/qs.js +24 -0
  30. package/packages/datadog-instrumentations/src/redis.js +12 -3
  31. package/packages/datadog-instrumentations/src/restify.js +5 -1
  32. package/packages/datadog-instrumentations/src/rhea.js +29 -15
  33. package/packages/datadog-instrumentations/src/router.js +23 -23
  34. package/packages/datadog-plugin-amqp10/src/consumer.js +32 -0
  35. package/packages/datadog-plugin-amqp10/src/index.js +11 -101
  36. package/packages/datadog-plugin-amqp10/src/producer.js +34 -0
  37. package/packages/datadog-plugin-amqp10/src/util.js +15 -0
  38. package/packages/datadog-plugin-amqplib/src/client.js +38 -0
  39. package/packages/datadog-plugin-amqplib/src/consumer.js +40 -0
  40. package/packages/datadog-plugin-amqplib/src/index.js +14 -102
  41. package/packages/datadog-plugin-amqplib/src/producer.js +37 -0
  42. package/packages/datadog-plugin-amqplib/src/util.js +14 -0
  43. package/packages/datadog-plugin-cassandra-driver/src/index.js +22 -60
  44. package/packages/datadog-plugin-cucumber/src/index.js +14 -33
  45. package/packages/datadog-plugin-cypress/src/plugin.js +2 -1
  46. package/packages/datadog-plugin-dns/src/index.js +16 -91
  47. package/packages/datadog-plugin-dns/src/lookup.js +40 -0
  48. package/packages/datadog-plugin-dns/src/lookup_service.js +24 -0
  49. package/packages/datadog-plugin-dns/src/resolve.js +24 -0
  50. package/packages/datadog-plugin-dns/src/reverse.js +21 -0
  51. package/packages/datadog-plugin-elasticsearch/src/index.js +24 -60
  52. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +24 -0
  53. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +41 -0
  54. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +14 -99
  55. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +33 -0
  56. package/packages/datadog-plugin-graphql/src/execute.js +73 -0
  57. package/packages/datadog-plugin-graphql/src/index.js +14 -176
  58. package/packages/datadog-plugin-graphql/src/parse.js +32 -0
  59. package/packages/datadog-plugin-graphql/src/resolve.js +70 -76
  60. package/packages/datadog-plugin-graphql/src/validate.js +28 -0
  61. package/packages/datadog-plugin-grpc/src/client.js +46 -55
  62. package/packages/datadog-plugin-grpc/src/index.js +7 -24
  63. package/packages/datadog-plugin-grpc/src/server.js +50 -52
  64. package/packages/datadog-plugin-grpc/src/util.js +15 -14
  65. package/packages/datadog-plugin-http/src/client.js +15 -5
  66. package/packages/datadog-plugin-http/src/index.js +7 -22
  67. package/packages/datadog-plugin-http/src/server.js +19 -3
  68. package/packages/datadog-plugin-http2/src/client.js +20 -1
  69. package/packages/datadog-plugin-http2/src/index.js +8 -26
  70. package/packages/datadog-plugin-http2/src/server.js +44 -0
  71. package/packages/datadog-plugin-jest/src/index.js +41 -65
  72. package/packages/datadog-plugin-kafkajs/src/consumer.js +42 -0
  73. package/packages/datadog-plugin-kafkajs/src/index.js +11 -87
  74. package/packages/datadog-plugin-kafkajs/src/producer.js +31 -0
  75. package/packages/datadog-plugin-mariadb/src/index.js +10 -0
  76. package/packages/datadog-plugin-memcached/src/index.js +17 -52
  77. package/packages/datadog-plugin-mocha/src/index.js +40 -60
  78. package/packages/datadog-plugin-moleculer/src/client.js +22 -36
  79. package/packages/datadog-plugin-moleculer/src/index.js +8 -26
  80. package/packages/datadog-plugin-moleculer/src/server.js +18 -30
  81. package/packages/datadog-plugin-mongodb-core/src/index.js +23 -51
  82. package/packages/datadog-plugin-mysql/src/index.js +23 -52
  83. package/packages/datadog-plugin-mysql2/src/index.js +1 -3
  84. package/packages/datadog-plugin-net/src/index.js +4 -0
  85. package/packages/datadog-plugin-net/src/ipc.js +21 -0
  86. package/packages/datadog-plugin-net/src/tcp.js +46 -0
  87. package/packages/datadog-plugin-next/src/index.js +3 -0
  88. package/packages/datadog-plugin-opensearch/src/index.js +11 -0
  89. package/packages/datadog-plugin-oracledb/src/index.js +29 -55
  90. package/packages/datadog-plugin-pg/src/index.js +27 -51
  91. package/packages/datadog-plugin-redis/src/index.js +29 -60
  92. package/packages/datadog-plugin-rhea/src/consumer.js +55 -0
  93. package/packages/datadog-plugin-rhea/src/index.js +11 -96
  94. package/packages/datadog-plugin-rhea/src/producer.js +45 -0
  95. package/packages/datadog-plugin-router/src/index.js +13 -2
  96. package/packages/datadog-plugin-sharedb/src/index.js +22 -39
  97. package/packages/datadog-plugin-tedious/src/index.js +20 -41
  98. package/packages/dd-trace/src/appsec/addresses.js +3 -1
  99. package/packages/dd-trace/src/appsec/blocking.js +44 -0
  100. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +8 -6
  101. package/packages/dd-trace/src/appsec/gateway/engine/engine.js +1 -1
  102. package/packages/dd-trace/src/appsec/gateway/engine/index.js +7 -2
  103. package/packages/dd-trace/src/appsec/gateway/engine/runner.js +0 -1
  104. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +4 -1
  105. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +11 -0
  106. package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +19 -0
  107. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +11 -0
  108. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +13 -0
  109. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +43 -5
  110. package/packages/dd-trace/src/appsec/iast/iast-context.js +3 -1
  111. package/packages/dd-trace/src/appsec/iast/index.js +24 -8
  112. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +20 -1
  113. package/packages/dd-trace/src/appsec/iast/path-line.js +17 -6
  114. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +17 -0
  115. package/packages/dd-trace/src/appsec/iast/taint-tracking/filter.js +16 -0
  116. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +18 -0
  117. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +98 -0
  118. package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +4 -0
  119. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +38 -0
  120. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +67 -0
  121. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +103 -0
  122. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +98 -30
  123. package/packages/dd-trace/src/appsec/index.js +79 -25
  124. package/packages/dd-trace/src/{plugins/util → appsec}/ip_blocklist.js +0 -0
  125. package/packages/dd-trace/src/appsec/ip_extractor.js +98 -0
  126. package/packages/dd-trace/src/appsec/recommended.json +134 -53
  127. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +7 -0
  128. package/packages/dd-trace/src/appsec/remote_config/index.js +56 -0
  129. package/packages/dd-trace/src/appsec/remote_config/manager.js +264 -0
  130. package/packages/dd-trace/src/{exporters → appsec/remote_config}/scheduler.js +9 -9
  131. package/packages/dd-trace/src/appsec/rule_manager.js +61 -1
  132. package/packages/dd-trace/src/appsec/templates/blocked.html +99 -0
  133. package/packages/dd-trace/src/appsec/templates/blocked.json +8 -0
  134. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +66 -0
  135. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +9 -5
  136. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +19 -51
  137. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +10 -5
  138. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +202 -0
  139. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +51 -62
  140. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +89 -0
  141. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +82 -0
  142. package/packages/dd-trace/src/config.js +119 -35
  143. package/packages/dd-trace/src/constants.js +9 -1
  144. package/packages/dd-trace/src/dogstatsd.js +42 -10
  145. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +10 -2
  146. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
  147. package/packages/dd-trace/src/exporter.js +3 -0
  148. package/packages/dd-trace/src/exporters/agent/index.js +10 -2
  149. package/packages/dd-trace/src/exporters/agent/writer.js +2 -9
  150. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +82 -0
  151. package/packages/dd-trace/src/exporters/common/request.js +51 -1
  152. package/packages/dd-trace/src/exporters/span-stats/index.js +6 -2
  153. package/packages/dd-trace/src/format.js +29 -10
  154. package/packages/dd-trace/src/lambda/handler.js +72 -0
  155. package/packages/dd-trace/src/lambda/index.js +5 -0
  156. package/packages/dd-trace/src/lambda/runtime/errors.js +20 -0
  157. package/packages/dd-trace/src/lambda/runtime/patch.js +74 -0
  158. package/packages/dd-trace/src/lambda/runtime/ritm.js +138 -0
  159. package/packages/dd-trace/src/metrics.js +15 -2
  160. package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -5
  161. package/packages/dd-trace/src/opentracing/span.js +2 -1
  162. package/packages/dd-trace/src/opentracing/span_context.js +9 -0
  163. package/packages/dd-trace/src/plugin_manager.js +11 -17
  164. package/packages/dd-trace/src/plugins/cache.js +9 -0
  165. package/packages/dd-trace/src/plugins/ci_plugin.js +97 -0
  166. package/packages/dd-trace/src/plugins/client.js +9 -0
  167. package/packages/dd-trace/src/plugins/composite.js +26 -0
  168. package/packages/dd-trace/src/plugins/consumer.js +9 -0
  169. package/packages/dd-trace/src/plugins/database.js +55 -0
  170. package/packages/dd-trace/src/plugins/incoming.js +7 -0
  171. package/packages/dd-trace/src/plugins/index.js +3 -0
  172. package/packages/dd-trace/src/plugins/log_plugin.js +2 -2
  173. package/packages/dd-trace/src/plugins/outgoing.js +31 -0
  174. package/packages/dd-trace/src/plugins/plugin.js +3 -0
  175. package/packages/dd-trace/src/plugins/producer.js +9 -0
  176. package/packages/dd-trace/src/plugins/server.js +9 -0
  177. package/packages/dd-trace/src/plugins/storage.js +21 -0
  178. package/packages/dd-trace/src/plugins/tracing.js +94 -0
  179. package/packages/dd-trace/src/plugins/util/ci.js +40 -4
  180. package/packages/dd-trace/src/plugins/util/git.js +58 -18
  181. package/packages/dd-trace/src/plugins/util/test.js +71 -8
  182. package/packages/dd-trace/src/plugins/util/user-provided-git.js +14 -1
  183. package/packages/dd-trace/src/plugins/util/web.js +11 -114
  184. package/packages/dd-trace/src/priority_sampler.js +6 -2
  185. package/packages/dd-trace/src/profiling/config.js +11 -6
  186. package/packages/dd-trace/src/profiling/exporters/agent.js +4 -0
  187. package/packages/dd-trace/src/profiling/index.js +2 -2
  188. package/packages/dd-trace/src/profiling/profiler.js +43 -7
  189. package/packages/dd-trace/src/proxy.js +8 -16
  190. package/packages/dd-trace/src/ritm.js +25 -14
  191. package/packages/dd-trace/src/span_processor.js +17 -0
  192. package/packages/dd-trace/src/span_sampler.js +77 -0
  193. package/packages/dd-trace/src/span_stats.js +2 -2
  194. package/packages/dd-trace/src/telemetry/dependencies.js +21 -7
  195. package/packages/dd-trace/src/telemetry/index.js +7 -1
  196. package/packages/dd-trace/src/telemetry/send-data.js +3 -1
  197. package/packages/dd-trace/src/tracer.js +10 -5
  198. package/packages/dd-trace/src/util.js +43 -1
@@ -1,104 +1,19 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../dd-trace/src/plugins/plugin')
4
- const { storage } = require('../../datadog-core')
5
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
6
-
7
- const messageSpans = new WeakMap()
8
- class GoogleCloudPubsubPlugin extends Plugin {
9
- static get name () {
10
- return 'google-cloud-pubsub'
11
- }
12
-
13
- constructor (...args) {
14
- super(...args)
15
-
16
- this.addSub(`apm:google-cloud-pubsub:request:start`, ({ cfg, projectId, messages }) => {
17
- const store = storage.getStore()
18
- const childOf = store ? store.span : store
19
- const topic = getTopic(cfg)
20
- const tags = {
21
- component: '@google-cloud/pubsub',
22
- 'resource.name': [cfg.method, topic].filter(x => x).join(' '),
23
- 'service.name': this.config.service || `${this.tracer._service}-pubsub`,
24
- 'span.kind': 'client',
25
- 'pubsub.method': cfg.method,
26
- 'gcloud.project_id': projectId,
27
- 'pubsub.topic': topic
28
- }
29
- if (cfg.method === 'publish') {
30
- tags['span.kind'] = 'producer'
31
- }
32
- const span = this.tracer.startSpan('pubsub.request', {
33
- childOf,
34
- tags
35
- })
36
-
37
- analyticsSampler.sample(span, this.config.measured)
38
- this.enter(span, store)
39
-
40
- for (const msg of messages) {
41
- if (!msg.attributes) {
42
- msg.attributes = {}
43
- }
44
- this.tracer.inject(span, 'text_map', msg.attributes)
45
- }
46
- })
47
-
48
- this.addSub(`apm:google-cloud-pubsub:receive:start`, ({ message }) => {
49
- const store = storage.getStore()
50
- const subscription = message._subscriber._subscription
51
- const topic = subscription.metadata && subscription.metadata.topic
52
- const childOf = this.tracer.extract('text_map', message.attributes)
53
- const tags = {
54
- component: '@google-cloud/pubsub',
55
- 'resource.name': topic,
56
- 'service.name': this.config.service || this.tracer._service,
57
- 'gcloud.project_id': subscription.pubsub.projectId,
58
- 'pubsub.topic': topic,
59
- 'span.kind': 'consumer',
60
- 'span.type': 'worker'
61
- }
62
-
63
- const span = this.tracer.startSpan('pubsub.receive', {
64
- childOf,
65
- tags
66
- })
67
-
68
- analyticsSampler.sample(span, this.config.measured, true)
69
- this.enter(span, store)
70
-
71
- messageSpans.set(message, span)
72
- })
73
-
74
- this.addSub(`apm:google-cloud-pubsub:request:error`, err => {
75
- const span = storage.getStore().span
76
- span.setTag('error', err)
77
- })
78
-
79
- this.addSub(`apm:google-cloud-pubsub:request:finish`, () => {
80
- const span = storage.getStore().span
81
- span.finish()
82
- })
83
-
84
- this.addSub(`apm:google-cloud-pubsub:receive:error`, ({ err, message }) => {
85
- const span = messageSpans.get(message)
86
- if (!span) return undefined
87
- span.setTag('error', err)
88
- })
89
-
90
- this.addSub(`apm:google-cloud-pubsub:receive:finish`, ({ message }) => {
91
- const span = messageSpans.get(message)
92
- if (!span) return
93
- span.setTag('pubsub.ack', message._handled ? 1 : 0)
94
- span.finish()
95
- })
96
- }
97
- }
98
-
99
- function getTopic (cfg) {
100
- if (cfg.reqOpts) {
101
- return cfg.reqOpts[cfg.method === 'createTopic' ? 'name' : 'topic']
3
+ const ProducerPlugin = require('./producer')
4
+ const ConsumerPlugin = require('./consumer')
5
+ const ClientPlugin = require('./client')
6
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
7
+
8
+ // TODO: Consider splitting channels for publish/receive in the instrumentation.
9
+ class GoogleCloudPubsubPlugin extends CompositePlugin {
10
+ static get name () { return 'google-cloud-pubsub' }
11
+ static get plugins () {
12
+ return {
13
+ producer: ProducerPlugin,
14
+ consumer: ConsumerPlugin,
15
+ client: ClientPlugin
16
+ }
102
17
  }
103
18
  }
104
19
 
@@ -0,0 +1,33 @@
1
+ 'use strict'
2
+
3
+ const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
4
+
5
+ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
6
+ static get name () { return 'google-cloud-pubsub' }
7
+ static get operation () { return 'request' }
8
+
9
+ start ({ cfg, projectId, messages }) {
10
+ if (cfg.method !== 'publish') return
11
+
12
+ const topic = cfg.reqOpts.topic
13
+ const span = this.startSpan('pubsub.request', { // TODO: rename
14
+ service: this.config.service || `${this.tracer._service}-pubsub`,
15
+ resource: `${cfg.method} ${topic}`,
16
+ kind: 'producer',
17
+ meta: {
18
+ 'gcloud.project_id': projectId,
19
+ 'pubsub.method': cfg.method, // TODO: remove
20
+ 'pubsub.topic': topic
21
+ }
22
+ })
23
+
24
+ for (const msg of messages) {
25
+ if (!msg.attributes) {
26
+ msg.attributes = {}
27
+ }
28
+ this.tracer.inject(span, 'text_map', msg.attributes)
29
+ }
30
+ }
31
+ }
32
+
33
+ module.exports = GoogleCloudPubsubProducerPlugin
@@ -0,0 +1,73 @@
1
+ 'use strict'
2
+
3
+ const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
4
+
5
+ let tools
6
+
7
+ class GraphQLExecutePlugin extends TracingPlugin {
8
+ static get name () { return 'graphql' }
9
+ static get operation () { return 'execute' }
10
+
11
+ start ({ operation, args, docSource }) {
12
+ const type = operation && operation.operation
13
+ const name = operation && operation.name && operation.name.value
14
+ const document = args.document
15
+ const source = this.config.source && document && docSource
16
+
17
+ const span = this.startSpan('graphql.execute', {
18
+ service: this.config.service,
19
+ resource: getSignature(document, name, type, this.config.signature),
20
+ kind: 'server',
21
+ type: 'graphql',
22
+ meta: {
23
+ 'graphql.operation.type': type,
24
+ 'graphql.operation.name': name,
25
+ 'graphql.source': source
26
+ }
27
+ })
28
+
29
+ addVariableTags(this.config, span, args.variableValues)
30
+ }
31
+
32
+ finish ({ res, args }) {
33
+ const span = this.activeSpan
34
+ this.config.hooks.execute(span, args, res)
35
+ span.finish()
36
+ }
37
+ }
38
+
39
+ // span-related
40
+
41
+ function addVariableTags (config, span, variableValues) {
42
+ const tags = {}
43
+
44
+ if (variableValues && config.variables) {
45
+ const variables = config.variables(variableValues)
46
+ for (const param in variables) {
47
+ tags[`graphql.variables.${param}`] = variables[param]
48
+ }
49
+ }
50
+
51
+ span.addTags(tags)
52
+ }
53
+
54
+ function getSignature (document, operationName, operationType, calculate) {
55
+ if (calculate !== false && tools !== false) {
56
+ try {
57
+ try {
58
+ tools = tools || require('./tools')
59
+ } catch (e) {
60
+ tools = false
61
+ throw e
62
+ }
63
+
64
+ return tools.defaultEngineReportingSignature(document, operationName)
65
+ } catch (e) {
66
+ // safety net
67
+ }
68
+ }
69
+
70
+ return [operationType, operationName].filter(val => val).join(' ')
71
+ }
72
+
73
+ module.exports = GraphQLExecutePlugin
@@ -1,111 +1,25 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../dd-trace/src/plugins/plugin')
4
- const { storage } = require('../../datadog-core')
5
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
3
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
6
4
  const log = require('../../dd-trace/src/log')
5
+ const GraphQLExecutePlugin = require('./execute')
6
+ const GraphQLParsePlugin = require('./parse')
7
+ const GraphQLValidatePlugin = require('./validate')
7
8
  const GraphQLResolvePlugin = require('./resolve')
8
9
 
9
- let tools
10
- class GraphQLPlugin extends Plugin {
11
- static get name () {
12
- return 'graphql'
13
- }
14
-
15
- constructor (...args) {
16
- super(...args)
17
-
18
- /** Execute Subs */
19
-
20
- // resolve plugin separated for disabling purposes
21
- this.resolve = new GraphQLResolvePlugin(...args)
22
-
23
- this.addSub('apm:graphql:execute:start', ({ operation, args, docSource }) => {
24
- const store = storage.getStore()
25
- const span = startSpan('execute', this.config, this.tracer, store)
26
-
27
- // process add tags
28
- addExecutionTags(span, this.config, operation, args.document)
29
- addDocumentTags(span, args.document, this.config, docSource)
30
- addVariableTags(this.config, span, args.variableValues)
31
-
32
- analyticsSampler.sample(span, this.config.measured, true)
33
-
34
- this.enter(span, store)
35
- })
36
-
37
- this.addSub('apm:graphql:execute:error', this.addError)
38
-
39
- this.addSub('apm:graphql:execute:finish', ({ res, args }) => {
40
- const span = storage.getStore().span
41
- this.config.hooks.execute(span, args, res)
42
- span.finish()
43
- })
44
-
45
- /** Parser Subs */
46
-
47
- this.addSub('apm:graphql:parser:start', () => {
48
- const store = storage.getStore()
49
- const span = startSpan('parse', this.config, this.tracer, store)
50
-
51
- analyticsSampler.sample(span, this.config.measured, true)
52
- this.enter(span, store)
53
- })
54
-
55
- this.addSub('apm:graphql:parser:finish', ({ source, document, docSource }) => {
56
- const span = storage.getStore().span
57
-
58
- const tags = {}
59
- if (this.config.source && document) {
60
- tags['graphql.source'] = docSource
61
- }
62
-
63
- span.addTags(tags)
64
-
65
- this.config.hooks.parse(span, source, document)
66
-
67
- span.finish()
68
- })
69
-
70
- this.addSub('apm:graphql:parser:error', this.addError)
71
-
72
- /** Validate Subs */
73
-
74
- this.addSub('apm:graphql:validate:start', ({ docSource, document }) => {
75
- const store = storage.getStore()
76
- const span = startSpan('validate', this.config, this.tracer, store)
77
-
78
- analyticsSampler.sample(span, this.config.measured, true)
79
-
80
- if (document && document.loc) {
81
- const tags = {}
82
- if (this.config.source && document) {
83
- tags['graphql.source'] = docSource
84
- }
85
-
86
- span.addTags(tags)
87
- }
88
-
89
- this.enter(span, store)
90
- })
91
-
92
- this.addSub('apm:graphql:validate:finish', ({ document, errors }) => {
93
- const span = storage.getStore().span
94
- this.config.hooks.validate(span, document, errors)
95
- span.finish()
96
- })
97
-
98
- this.addSub('apm:graphql:validate:error', this.addError)
10
+ class GraphQLPlugin extends CompositePlugin {
11
+ static get name () { return 'graphql' }
12
+ static get plugins () {
13
+ return {
14
+ execute: GraphQLExecutePlugin,
15
+ parse: GraphQLParsePlugin,
16
+ validate: GraphQLValidatePlugin,
17
+ resolve: GraphQLResolvePlugin
18
+ }
99
19
  }
100
20
 
101
21
  configure (config) {
102
- const validated = validateConfig(config)
103
-
104
- // this will disable resolve subscribers if `config.depth` is set to 0
105
- const resolveConfig = validated.depth === 0 ? false : validated
106
- this.resolve.configure(resolveConfig)
107
-
108
- return super.configure(validated)
22
+ return super.configure(validateConfig(config))
109
23
  }
110
24
  }
111
25
 
@@ -155,80 +69,4 @@ function pick (obj, selectors) {
155
69
  return Object.fromEntries(Object.entries(obj).filter(([key]) => selectors.includes(key)))
156
70
  }
157
71
 
158
- // span-related
159
-
160
- function startSpan (name, conf, tracer, store, options) {
161
- const service = conf.service || tracer._service
162
- const childOf = store ? store.span : store
163
- options = options || {}
164
- return tracer.startSpan(`graphql.${name}`, {
165
- childOf: options.childOf || childOf,
166
- startTime: options.startTime,
167
- tags: {
168
- 'service.name': service,
169
- 'span.type': 'graphql'
170
- }
171
- })
172
- }
173
-
174
- function addExecutionTags (span, config, operation, document) {
175
- const type = operation && operation.operation
176
- const name = operation && operation.name && operation.name.value
177
- const tags = {
178
- 'resource.name': getSignature(document, name, type, config.signature)
179
- }
180
-
181
- if (type) {
182
- tags['graphql.operation.type'] = type
183
- }
184
-
185
- if (name) {
186
- tags['graphql.operation.name'] = name
187
- }
188
-
189
- span.addTags(tags)
190
- }
191
-
192
- function addDocumentTags (span, document, config, docSource) {
193
- const tags = {}
194
-
195
- if (config.source && document) {
196
- tags['graphql.source'] = docSource
197
- }
198
-
199
- span.addTags(tags)
200
- }
201
-
202
- function addVariableTags (config, span, variableValues) {
203
- const tags = {}
204
-
205
- if (variableValues && config.variables) {
206
- const variables = config.variables(variableValues)
207
- for (const param in variables) {
208
- tags[`graphql.variables.${param}`] = variables[param]
209
- }
210
- }
211
-
212
- span.addTags(tags)
213
- }
214
-
215
- function getSignature (document, operationName, operationType, calculate) {
216
- if (calculate !== false && tools !== false) {
217
- try {
218
- try {
219
- tools = tools || require('./tools')
220
- } catch (e) {
221
- tools = false
222
- throw e
223
- }
224
-
225
- return tools.defaultEngineReportingSignature(document, operationName)
226
- } catch (e) {
227
- // safety net
228
- }
229
- }
230
-
231
- return [operationType, operationName].filter(val => val).join(' ')
232
- }
233
-
234
72
  module.exports = GraphQLPlugin
@@ -0,0 +1,32 @@
1
+ 'use strict'
2
+
3
+ const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
4
+
5
+ class GraphQLParsePlugin extends TracingPlugin {
6
+ static get name () { return 'graphql' }
7
+ static get operation () { return 'parser' }
8
+
9
+ start () {
10
+ this.startSpan('graphql.parse', {
11
+ service: this.config.service,
12
+ type: 'graphql',
13
+ meta: {
14
+ 'graphql.source': ''
15
+ }
16
+ })
17
+ }
18
+
19
+ finish ({ source, document, docSource }) {
20
+ const span = this.activeSpan
21
+
22
+ if (this.config.source && document) {
23
+ span.setTag('graphql.source', docSource)
24
+ }
25
+
26
+ this.config.hooks.parse(span, source, document)
27
+
28
+ span.finish()
29
+ }
30
+ }
31
+
32
+ module.exports = GraphQLParsePlugin
@@ -1,98 +1,92 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../dd-trace/src/plugins/plugin')
4
- const { storage } = require('../../datadog-core')
5
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
3
+ const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
6
4
 
7
5
  const collapsedPathSym = Symbol('collapsedPaths')
8
6
 
9
- class GraphQLResolvePlugin extends Plugin {
10
- static get name () {
11
- return 'graphql'
7
+ class GraphQLResolvePlugin extends TracingPlugin {
8
+ static get name () { return 'graphql' }
9
+ static get operation () { return 'resolve' }
10
+
11
+ start ({ info, context }) {
12
+ const path = getPath(info, this.config)
13
+
14
+ if (!shouldInstrument(this.config, path)) return
15
+
16
+ const computedPathString = path.join('.')
17
+
18
+ if (this.config.collapse) {
19
+ if (!context[collapsedPathSym]) {
20
+ context[collapsedPathSym] = {}
21
+ }
22
+
23
+ if (context.fields[computedPathString]) return
24
+ if (context[collapsedPathSym][computedPathString]) return
25
+
26
+ context[collapsedPathSym][computedPathString] = true
27
+ }
28
+
29
+ const document = context.source
30
+ const fieldNode = info.fieldNodes.find(fieldNode => fieldNode.kind === 'Field')
31
+ const loc = this.config.source && document && fieldNode && fieldNode.loc
32
+ const source = loc && document.substring(loc.start, loc.end)
33
+
34
+ const span = this.startSpan('graphql.resolve', {
35
+ service: this.config.service,
36
+ resource: `${info.fieldName}:${info.returnType}`,
37
+ type: 'graphql',
38
+ meta: {
39
+ 'graphql.field.name': info.fieldName,
40
+ 'graphql.field.path': computedPathString,
41
+ 'graphql.field.type': info.returnType.name,
42
+ 'graphql.source': source
43
+ }
44
+ })
45
+
46
+ if (fieldNode && this.config.variables && fieldNode.arguments) {
47
+ const variables = this.config.variables(info.variableValues)
48
+
49
+ fieldNode.arguments
50
+ .filter(arg => arg.value && arg.value.kind === 'Variable')
51
+ .filter(arg => arg.value.name && variables[arg.value.name.value])
52
+ .map(arg => arg.value.name.value)
53
+ .forEach(name => {
54
+ span.setTag(`graphql.variables.${name}`, variables[name])
55
+ })
56
+ }
57
+ }
58
+
59
+ finish (finishTime) {
60
+ const span = this.activeSpan
61
+ span.finish(finishTime)
12
62
  }
13
63
 
14
64
  constructor (...args) {
15
65
  super(...args)
16
66
 
17
- this.addSub('apm:graphql:resolve:start', ({ info, context }) => {
18
- const store = storage.getStore()
19
- depthPredicate(info, this.config, (computedPath) => {
20
- const computedPathString = computedPath.join('.')
21
- if ((!this.config.collapse && !context.fields[computedPathString]) ||
22
- (!context[collapsedPathSym] || !context[collapsedPathSym][computedPathString])) {
23
- // cache the collapsed string here
24
- if (this.config.collapse) {
25
- if (!context[collapsedPathSym]) context[collapsedPathSym] = {}
26
- context[collapsedPathSym][computedPathString] = true
27
- }
28
-
29
- const service = this.config.service || this.tracer._service
30
- const childOf = store ? store.span : store
31
- const span = this.tracer.startSpan(`graphql.resolve`, {
32
- childOf: childOf,
33
- tags: {
34
- 'service.name': service,
35
- 'span.type': 'graphql'
36
- }
37
- })
38
- const document = context.source
39
- const fieldNode = info.fieldNodes.find(fieldNode => fieldNode.kind === 'Field')
40
-
41
- analyticsSampler.sample(span, this.config.measured)
42
-
43
- span.addTags({
44
- 'resource.name': `${info.fieldName}:${info.returnType}`,
45
- 'graphql.field.name': info.fieldName,
46
- 'graphql.field.path': computedPathString,
47
- 'graphql.field.type': info.returnType.name
48
- })
49
-
50
- if (fieldNode) {
51
- if (this.config.source && document && fieldNode.loc) {
52
- span.setTag('graphql.source', document.substring(fieldNode.loc.start, fieldNode.loc.end))
53
- }
54
-
55
- if (this.config.variables && fieldNode.arguments) {
56
- const variables = this.config.variables(info.variableValues)
57
-
58
- fieldNode.arguments
59
- .filter(arg => arg.value && arg.value.kind === 'Variable')
60
- .filter(arg => arg.value.name && variables[arg.value.name.value])
61
- .map(arg => arg.value.name.value)
62
- .forEach(name => {
63
- span.setTag(`graphql.variables.${name}`, variables[name])
64
- })
65
- }
66
- }
67
- this.enter(span, store)
68
- }
69
- })
70
- })
67
+ this.addTraceSub('updateField', ({ field, info, err }) => {
68
+ const path = getPath(info, this.config)
71
69
 
72
- this.addSub('apm:graphql:resolve:updateField', ({ field, info, err }) => {
73
- depthPredicate(info, this.config, () => {
74
- const span = storage.getStore().span
75
- field.finishTime = span._getTime ? span._getTime() : 0
76
- field.error = field.error || err
77
- })
78
- })
70
+ if (!shouldInstrument(this.config, path)) return
79
71
 
80
- this.addSub('apm:graphql:resolve:error', this.addError)
81
-
82
- this.addSub('apm:graphql:resolve:finish', finishTime => {
83
- const span = storage.getStore().span
84
- span.finish(finishTime)
72
+ const span = this.activeSpan
73
+ field.finishTime = span._getTime ? span._getTime() : 0
74
+ field.error = field.error || err
85
75
  })
86
76
  }
77
+
78
+ configure (config) {
79
+ // this will disable resolve subscribers if `config.depth` is set to 0
80
+ super.configure(config.depth === 0 ? false : config)
81
+ }
87
82
  }
88
83
 
89
84
  // helpers
90
85
 
91
- function depthPredicate (info, config, func) {
92
- func = func || (() => {})
93
- const path = getPath(info, config)
86
+ function shouldInstrument (config, path) {
94
87
  const depth = path.filter(item => typeof item === 'string').length
95
- if (config.depth < 0 || config.depth >= depth) func(path)
88
+
89
+ return config.depth < 0 || config.depth >= depth
96
90
  }
97
91
 
98
92
  function getPath (info, config) {
@@ -0,0 +1,28 @@
1
+ 'use strict'
2
+
3
+ const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
4
+
5
+ class GraphQLValidatePlugin extends TracingPlugin {
6
+ static get name () { return 'graphql' }
7
+ static get operation () { return 'validate' }
8
+
9
+ start ({ docSource, document }) {
10
+ const source = this.config.source && document && docSource
11
+
12
+ this.startSpan('graphql.validate', {
13
+ service: this.config.service,
14
+ type: 'graphql',
15
+ meta: {
16
+ 'graphql.source': source
17
+ }
18
+ })
19
+ }
20
+
21
+ finish ({ document, errors }) {
22
+ const span = this.activeSpan
23
+ this.config.hooks.validate(span, document, errors)
24
+ span.finish()
25
+ }
26
+ }
27
+
28
+ module.exports = GraphQLValidatePlugin