dd-trace 2.28.0 → 2.30.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 (180) hide show
  1. package/LICENSE-3rdparty.csv +2 -2
  2. package/README.md +53 -0
  3. package/ci/init.js +9 -1
  4. package/ext/exporters.d.ts +2 -1
  5. package/ext/exporters.js +2 -1
  6. package/index.d.ts +6 -2
  7. package/package.json +24 -19
  8. package/packages/datadog-esbuild/index.js +104 -0
  9. package/packages/datadog-instrumentations/src/cucumber.js +80 -3
  10. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +100 -27
  11. package/packages/datadog-instrumentations/src/helpers/hook.js +13 -3
  12. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  13. package/packages/datadog-instrumentations/src/helpers/instrument.js +6 -0
  14. package/packages/datadog-instrumentations/src/helpers/register.js +2 -2
  15. package/packages/datadog-instrumentations/src/jest.js +35 -3
  16. package/packages/datadog-instrumentations/src/mariadb.js +130 -11
  17. package/packages/datadog-instrumentations/src/mocha.js +30 -6
  18. package/packages/datadog-instrumentations/src/mongodb-core.js +8 -2
  19. package/packages/datadog-instrumentations/src/mongoose.js +1 -1
  20. package/packages/datadog-instrumentations/src/next.js +32 -4
  21. package/packages/datadog-instrumentations/src/pg.js +16 -11
  22. package/packages/datadog-instrumentations/src/playwright.js +2 -2
  23. package/packages/datadog-plugin-amqp10/src/consumer.js +1 -1
  24. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  25. package/packages/datadog-plugin-amqp10/src/producer.js +3 -2
  26. package/packages/datadog-plugin-amqplib/src/client.js +3 -2
  27. package/packages/datadog-plugin-amqplib/src/consumer.js +1 -1
  28. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  29. package/packages/datadog-plugin-amqplib/src/producer.js +3 -2
  30. package/packages/datadog-plugin-aws-sdk/src/base.js +7 -2
  31. package/packages/datadog-plugin-aws-sdk/src/index.js +1 -1
  32. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +2 -0
  33. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +2 -0
  34. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -0
  35. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -0
  36. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +2 -0
  37. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +2 -0
  38. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +2 -0
  39. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -0
  40. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -0
  41. package/packages/datadog-plugin-bunyan/src/index.js +1 -1
  42. package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -2
  43. package/packages/datadog-plugin-connect/src/index.js +1 -1
  44. package/packages/datadog-plugin-couchbase/src/index.js +1 -1
  45. package/packages/datadog-plugin-cucumber/src/index.js +33 -6
  46. package/packages/datadog-plugin-cypress/src/index.js +1 -1
  47. package/packages/datadog-plugin-cypress/src/plugin.js +40 -33
  48. package/packages/datadog-plugin-dns/src/index.js +1 -1
  49. package/packages/datadog-plugin-dns/src/lookup.js +1 -1
  50. package/packages/datadog-plugin-dns/src/lookup_service.js +1 -1
  51. package/packages/datadog-plugin-dns/src/resolve.js +1 -1
  52. package/packages/datadog-plugin-dns/src/reverse.js +1 -1
  53. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  54. package/packages/datadog-plugin-express/src/index.js +1 -1
  55. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  56. package/packages/datadog-plugin-find-my-way/src/index.js +1 -1
  57. package/packages/datadog-plugin-fs/src/index.js +1 -1
  58. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +5 -5
  59. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -1
  60. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
  61. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +7 -6
  62. package/packages/datadog-plugin-graphql/src/execute.js +1 -1
  63. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  64. package/packages/datadog-plugin-graphql/src/parse.js +1 -1
  65. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  66. package/packages/datadog-plugin-graphql/src/validate.js +1 -1
  67. package/packages/datadog-plugin-grpc/src/client.js +1 -1
  68. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  69. package/packages/datadog-plugin-grpc/src/server.js +1 -1
  70. package/packages/datadog-plugin-hapi/src/index.js +1 -1
  71. package/packages/datadog-plugin-http/src/client.js +2 -2
  72. package/packages/datadog-plugin-http/src/index.js +1 -1
  73. package/packages/datadog-plugin-http/src/server.js +2 -2
  74. package/packages/datadog-plugin-http2/src/client.js +4 -3
  75. package/packages/datadog-plugin-http2/src/index.js +1 -1
  76. package/packages/datadog-plugin-http2/src/server.js +2 -2
  77. package/packages/datadog-plugin-ioredis/src/index.js +1 -1
  78. package/packages/datadog-plugin-jest/src/index.js +53 -19
  79. package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -1
  80. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  81. package/packages/datadog-plugin-kafkajs/src/producer.js +1 -1
  82. package/packages/datadog-plugin-koa/src/index.js +1 -1
  83. package/packages/datadog-plugin-mariadb/src/index.js +18 -1
  84. package/packages/datadog-plugin-memcached/src/index.js +3 -2
  85. package/packages/datadog-plugin-microgateway-core/src/index.js +1 -1
  86. package/packages/datadog-plugin-mocha/src/index.js +13 -9
  87. package/packages/datadog-plugin-moleculer/src/client.js +1 -1
  88. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  89. package/packages/datadog-plugin-moleculer/src/server.js +1 -1
  90. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -1
  91. package/packages/datadog-plugin-mysql/src/index.js +3 -2
  92. package/packages/datadog-plugin-mysql2/src/index.js +1 -1
  93. package/packages/datadog-plugin-net/src/index.js +9 -75
  94. package/packages/datadog-plugin-net/src/ipc.js +1 -1
  95. package/packages/datadog-plugin-net/src/tcp.js +3 -2
  96. package/packages/datadog-plugin-next/src/index.js +3 -3
  97. package/packages/datadog-plugin-opensearch/src/index.js +1 -1
  98. package/packages/datadog-plugin-oracledb/src/index.js +3 -2
  99. package/packages/datadog-plugin-paperplane/src/index.js +1 -1
  100. package/packages/datadog-plugin-paperplane/src/logger.js +1 -1
  101. package/packages/datadog-plugin-paperplane/src/server.js +1 -1
  102. package/packages/datadog-plugin-pg/src/index.js +3 -2
  103. package/packages/datadog-plugin-pino/src/index.js +1 -1
  104. package/packages/datadog-plugin-playwright/src/index.js +5 -4
  105. package/packages/datadog-plugin-redis/src/index.js +3 -2
  106. package/packages/datadog-plugin-restify/src/index.js +1 -1
  107. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  108. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  109. package/packages/datadog-plugin-rhea/src/producer.js +3 -2
  110. package/packages/datadog-plugin-router/src/index.js +8 -8
  111. package/packages/datadog-plugin-sharedb/src/index.js +1 -1
  112. package/packages/datadog-plugin-tedious/src/index.js +3 -2
  113. package/packages/datadog-plugin-web/src/index.js +1 -1
  114. package/packages/datadog-plugin-winston/src/index.js +1 -1
  115. package/packages/dd-trace/src/appsec/{templates/blocked.html → blocked_templates.js} +19 -1
  116. package/packages/dd-trace/src/appsec/blocking.js +9 -24
  117. package/packages/dd-trace/src/appsec/gateway/engine/runner.js +2 -1
  118. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +2 -0
  119. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +12 -0
  120. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  121. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +11 -5
  122. package/packages/dd-trace/src/appsec/iast/iast-log.js +111 -0
  123. package/packages/dd-trace/src/appsec/iast/index.js +8 -4
  124. package/packages/dd-trace/src/appsec/iast/path-line.js +3 -6
  125. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +11 -2
  126. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +11 -0
  127. package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +2 -0
  128. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -0
  129. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -3
  130. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +5 -3
  131. package/packages/dd-trace/src/appsec/iast/telemetry/log_collector.js +96 -0
  132. package/packages/dd-trace/src/appsec/iast/telemetry/logs.js +87 -0
  133. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +27 -2
  134. package/packages/dd-trace/src/appsec/index.js +4 -18
  135. package/packages/dd-trace/src/appsec/recommended.json +43 -14
  136. package/packages/dd-trace/src/appsec/remote_config/index.js +1 -1
  137. package/packages/dd-trace/src/appsec/sdk/index.js +2 -2
  138. package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +27 -0
  139. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +2 -9
  140. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +7 -7
  141. package/packages/dd-trace/src/ci-visibility/exporters/jest-worker/index.js +33 -0
  142. package/packages/dd-trace/src/ci-visibility/exporters/jest-worker/writer.js +37 -0
  143. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +8 -2
  144. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +8 -2
  145. package/packages/dd-trace/src/config.js +44 -22
  146. package/packages/dd-trace/src/constants.js +2 -1
  147. package/packages/dd-trace/src/datastreams/encoding.js +80 -0
  148. package/packages/dd-trace/src/dcitm.js +51 -0
  149. package/packages/dd-trace/src/exporter.js +7 -9
  150. package/packages/dd-trace/src/exporters/common/agents.js +42 -0
  151. package/packages/dd-trace/src/exporters/common/docker.js +4 -1
  152. package/packages/dd-trace/src/exporters/common/request.js +1 -4
  153. package/packages/dd-trace/src/lambda/handler.js +14 -6
  154. package/packages/dd-trace/src/opentracing/propagation/log.js +23 -7
  155. package/packages/dd-trace/src/opentracing/propagation/text_map.js +28 -2
  156. package/packages/dd-trace/src/opentracing/span.js +19 -3
  157. package/packages/dd-trace/src/opentracing/span_context.js +3 -1
  158. package/packages/dd-trace/src/opentracing/tracer.js +3 -1
  159. package/packages/dd-trace/src/plugin_manager.js +7 -7
  160. package/packages/dd-trace/src/plugins/ci_plugin.js +16 -16
  161. package/packages/dd-trace/src/plugins/index.js +1 -0
  162. package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
  163. package/packages/dd-trace/src/plugins/outgoing.js +2 -1
  164. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  165. package/packages/dd-trace/src/plugins/util/ci.js +12 -0
  166. package/packages/dd-trace/src/plugins/util/ip_extractor.js +23 -27
  167. package/packages/dd-trace/src/plugins/util/test.js +26 -7
  168. package/packages/dd-trace/src/profiling/config.js +87 -20
  169. package/packages/dd-trace/src/profiling/constants.js +16 -0
  170. package/packages/dd-trace/src/profiling/exporter_cli.js +62 -0
  171. package/packages/dd-trace/src/profiling/exporters/agent.js +2 -1
  172. package/packages/dd-trace/src/profiling/profiler.js +21 -8
  173. package/packages/dd-trace/src/profiling/profilers/space.js +21 -1
  174. package/packages/dd-trace/src/span_sampler.js +3 -2
  175. package/packages/dd-trace/src/telemetry/index.js +16 -2
  176. package/packages/dd-trace/src/util.js +10 -1
  177. package/scripts/install_plugin_modules.js +5 -1
  178. package/packages/dd-trace/src/appsec/templates/blocked.json +0 -8
  179. package/scripts/junit_report.js +0 -25
  180. package/scripts/tdd.js +0 -34
@@ -3,13 +3,21 @@
3
3
  const path = require('path')
4
4
  const iitm = require('../../../dd-trace/src/iitm')
5
5
  const ritm = require('../../../dd-trace/src/ritm')
6
-
6
+ const dcitm = require('../../../dd-trace/src/dcitm')
7
+
8
+ /**
9
+ * This is called for every module that dd-trace supports instrumentation for.
10
+ * In practice, `modules` is always an array with a single entry.
11
+ *
12
+ * @param {string[]} modules list of modules to hook into
13
+ * @param {Function} onrequire callback to be executed upon encountering module
14
+ */
7
15
  function Hook (modules, onrequire) {
8
16
  if (!(this instanceof Hook)) return new Hook(modules, onrequire)
9
17
 
10
18
  this._patched = Object.create(null)
11
19
 
12
- const safeHook = (moduleExports, moduleName, moduleBaseDir) => {
20
+ const safeHook = (moduleExports, moduleName, moduleBaseDir, moduleVersion) => {
13
21
  const parts = [moduleBaseDir, moduleName].filter(v => v)
14
22
  const filename = path.join(...parts)
15
23
 
@@ -17,7 +25,7 @@ function Hook (modules, onrequire) {
17
25
 
18
26
  this._patched[filename] = true
19
27
 
20
- return onrequire(moduleExports, moduleName, moduleBaseDir)
28
+ return onrequire(moduleExports, moduleName, moduleBaseDir, moduleVersion)
21
29
  }
22
30
 
23
31
  this._ritmHook = ritm(modules, {}, safeHook)
@@ -33,11 +41,13 @@ function Hook (modules, onrequire) {
33
41
  return safeHook(moduleExports, moduleName, moduleBaseDir)
34
42
  }
35
43
  })
44
+ this._dcitmHook = dcitm(modules, {}, safeHook)
36
45
  }
37
46
 
38
47
  Hook.prototype.unhook = function () {
39
48
  this._ritmHook.unhook()
40
49
  this._iitmHook.unhook()
50
+ this._dcitmHook.unhook()
41
51
  this._patched = Object.create(null)
42
52
  }
43
53
 
@@ -47,6 +47,7 @@ module.exports = {
47
47
  'jest-environment-node': () => require('../jest'),
48
48
  'jest-environment-jsdom': () => require('../jest'),
49
49
  'jest-jasmine2': () => require('../jest'),
50
+ 'jest-worker': () => require('../jest'),
50
51
  'koa': () => require('../koa'),
51
52
  'koa-router': () => require('../koa'),
52
53
  'kafkajs': () => require('../kafkajs'),
@@ -14,6 +14,12 @@ exports.channel = function (name) {
14
14
  return ch
15
15
  }
16
16
 
17
+ /**
18
+ * @param {string} args.name module name
19
+ * @param {string[]} args.versions array of semver range strings
20
+ * @param {string} args.file path to file within package to instrument?
21
+ * @param Function hook
22
+ */
17
23
  exports.addHook = function addHook ({ name, versions, file }, hook) {
18
24
  if (!instrumentations[name]) {
19
25
  instrumentations[name] = []
@@ -17,7 +17,7 @@ const loadChannel = channel('dd-trace:instrumentation:load')
17
17
  // TODO: make this more efficient
18
18
 
19
19
  for (const packageName of names) {
20
- Hook([packageName], (moduleExports, moduleName, moduleBaseDir) => {
20
+ Hook([packageName], (moduleExports, moduleName, moduleBaseDir, moduleVersion) => {
21
21
  moduleName = moduleName.replace(pathSepExpr, '/')
22
22
 
23
23
  hooks[packageName]()
@@ -26,7 +26,7 @@ for (const packageName of names) {
26
26
  const fullFilename = filename(name, file)
27
27
 
28
28
  if (moduleName === fullFilename) {
29
- const version = getVersion(moduleBaseDir)
29
+ const version = moduleVersion || getVersion(moduleBaseDir)
30
30
 
31
31
  if (matchVersion(version, versions)) {
32
32
  try {
@@ -2,7 +2,11 @@
2
2
  const { addHook, channel, AsyncResource } = require('./helpers/instrument')
3
3
  const shimmer = require('../../datadog-shimmer')
4
4
  const log = require('../../dd-trace/src/log')
5
- const { getCoveredFilenamesFromCoverage } = require('../../dd-trace/src/plugins/util/test')
5
+ const {
6
+ getCoveredFilenamesFromCoverage,
7
+ JEST_WORKER_TRACE_PAYLOAD_CODE,
8
+ JEST_WORKER_COVERAGE_PAYLOAD_CODE
9
+ } = require('../../dd-trace/src/plugins/util/test')
6
10
 
7
11
  const testSessionStartCh = channel('ci:jest:session:start')
8
12
  const testSessionFinishCh = channel('ci:jest:session:finish')
@@ -11,6 +15,10 @@ const testSessionConfigurationCh = channel('ci:jest:session:configuration')
11
15
 
12
16
  const testSuiteStartCh = channel('ci:jest:test-suite:start')
13
17
  const testSuiteFinishCh = channel('ci:jest:test-suite:finish')
18
+
19
+ const workerReportTraceCh = channel('ci:jest:worker-report:trace')
20
+ const workerReportCoverageCh = channel('ci:jest:worker-report:coverage')
21
+
14
22
  const testSuiteCodeCoverageCh = channel('ci:jest:test-suite:code-coverage')
15
23
 
16
24
  const testStartCh = channel('ci:jest:test:start')
@@ -214,7 +222,6 @@ function cliWrapper (cli, jestVersion) {
214
222
  log.error(err)
215
223
  }
216
224
  }
217
-
218
225
  const isSuitesSkipped = !!skippableSuites.length
219
226
 
220
227
  const processArgv = process.argv.slice(2).join(' ')
@@ -309,7 +316,6 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
309
316
  } else if (numFailingTests !== 0) {
310
317
  status = 'fail'
311
318
  }
312
- testSuiteFinishCh.publish({ status, errorMessage })
313
319
 
314
320
  const coverageFiles = getCoveredFilenamesFromCoverage(environment.global.__coverage__)
315
321
  .map(filename => getTestSuitePath(filename, environment.rootDir))
@@ -326,6 +332,7 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
326
332
  testSuiteCodeCoverageCh.publish([...coverageFiles, environment.testSuite])
327
333
  })
328
334
  }
335
+ testSuiteFinishCh.publish({ status, errorMessage })
329
336
  return suiteResults
330
337
  })
331
338
  })
@@ -475,3 +482,28 @@ addHook({
475
482
  versions: ['>=24.8.0'],
476
483
  file: 'build/jasmineAsyncInstall.js'
477
484
  }, jasmineAsyncInstallWraper)
485
+
486
+ addHook({
487
+ name: 'jest-worker',
488
+ versions: ['>=24.9.0'],
489
+ file: 'build/workers/ChildProcessWorker.js'
490
+ }, (childProcessWorker) => {
491
+ const ChildProcessWorker = childProcessWorker.default
492
+ shimmer.wrap(ChildProcessWorker.prototype, '_onMessage', _onMessage => function () {
493
+ const [code, data] = arguments[0]
494
+ if (code === JEST_WORKER_TRACE_PAYLOAD_CODE) { // datadog trace payload
495
+ sessionAsyncResource.runInAsyncScope(() => {
496
+ workerReportTraceCh.publish(data)
497
+ })
498
+ return
499
+ }
500
+ if (code === JEST_WORKER_COVERAGE_PAYLOAD_CODE) { // datadog coverage payload
501
+ sessionAsyncResource.runInAsyncScope(() => {
502
+ workerReportCoverageCh.publish(data)
503
+ })
504
+ return
505
+ }
506
+ return _onMessage.apply(this, arguments)
507
+ })
508
+ return childProcessWorker
509
+ })
@@ -7,17 +7,17 @@ const shimmer = require('../../datadog-shimmer')
7
7
  const startCh = channel('apm:mariadb:query:start')
8
8
  const finishCh = channel('apm:mariadb:query:finish')
9
9
  const errorCh = channel('apm:mariadb:query:error')
10
+ const skipCh = channel('apm:mariadb:pool:skip')
11
+ const unskipCh = channel('apm:mariadb:pool:unskip')
10
12
 
11
- function wrapCommandStart (start) {
13
+ function wrapCommandStart (start, callbackResource) {
12
14
  return function () {
13
15
  if (!startCh.hasSubscribers) return start.apply(this, arguments)
14
16
 
15
- const callbackResource = new AsyncResource('bound-anonymous-fn')
16
-
17
17
  const resolve = callbackResource.bind(this.resolve)
18
18
  const reject = callbackResource.bind(this.reject)
19
19
 
20
- const asyncResource = new AsyncResource('bound-anonymous-fn')
20
+ const asyncResource = callbackResource.runInAsyncScope(() => new AsyncResource('bound-anonymous-fn'))
21
21
 
22
22
  shimmer.wrap(this, 'resolve', function wrapResolve () {
23
23
  return function () {
@@ -47,17 +47,136 @@ function wrapCommandStart (start) {
47
47
  }
48
48
  }
49
49
 
50
+ function wrapCommand (Command) {
51
+ return class extends Command {
52
+ constructor (...args) {
53
+ super(...args)
54
+
55
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
56
+
57
+ if (this.start) {
58
+ this.start = wrapCommandStart(this.start, callbackResource)
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ function createWrapQuery (options) {
65
+ return function wrapQuery (query) {
66
+ return function (sql) {
67
+ if (!startCh.hasSubscribers) return query.apply(this, arguments)
68
+
69
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
70
+
71
+ return asyncResource.runInAsyncScope(() => {
72
+ startCh.publish({ sql, conf: options })
73
+
74
+ return query.apply(this, arguments)
75
+ .then(result => {
76
+ finishCh.publish()
77
+ return result
78
+ }, error => {
79
+ errorCh.publish(error)
80
+ finishCh.publish()
81
+ throw error
82
+ })
83
+ }, 'bound-anonymous-fn')
84
+ }
85
+ }
86
+ }
87
+
88
+ function createWrapQueryCallback (options) {
89
+ return function wrapQuery (query) {
90
+ return function (sql) {
91
+ if (!startCh.hasSubscribers) return query.apply(this, arguments)
92
+
93
+ const cb = arguments[arguments.length - 1]
94
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
95
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
96
+
97
+ if (typeof cb !== 'function') {
98
+ arguments.length = arguments.length + 1
99
+ }
100
+
101
+ arguments[arguments.length - 1] = asyncResource.bind(function (err) {
102
+ if (err) {
103
+ errorCh.publish(err)
104
+ }
105
+
106
+ finishCh.publish()
107
+
108
+ if (typeof cb === 'function') {
109
+ return callbackResource.runInAsyncScope(() => cb.apply(this, arguments))
110
+ }
111
+ })
112
+
113
+ return asyncResource.runInAsyncScope(() => {
114
+ startCh.publish({ sql, conf: options })
115
+
116
+ return query.apply(this, arguments)
117
+ }, 'bound-anonymous-fn')
118
+ }
119
+ }
120
+ }
121
+
122
+ function wrapConnection (Connection, promiseMethod) {
123
+ return function (options) {
124
+ Connection.apply(this, arguments)
125
+
126
+ shimmer.wrap(this, promiseMethod, createWrapQuery(options))
127
+ shimmer.wrap(this, '_queryCallback', createWrapQueryCallback(options))
128
+ }
129
+ }
130
+
131
+ function wrapPoolBase (PoolBase) {
132
+ return function (options, processTask, createConnectionPool, pingPromise) {
133
+ arguments[1] = wrapPoolMethod(processTask)
134
+ arguments[2] = wrapPoolMethod(createConnectionPool)
135
+
136
+ PoolBase.apply(this, arguments)
137
+
138
+ shimmer.wrap(this, 'query', createWrapQuery(options.connOptions))
139
+ }
140
+ }
141
+
142
+ // It's not possible to prevent connection pools from leaking across queries,
143
+ // so instead we just skip instrumentation completely to avoid memory leaks
144
+ // and/or orphan spans.
145
+ function wrapPoolMethod (createConnection) {
146
+ return function () {
147
+ skipCh.publish()
148
+ try {
149
+ return createConnection.apply(this, arguments)
150
+ } finally {
151
+ unskipCh.publish()
152
+ }
153
+ }
154
+ }
155
+
50
156
  const name = 'mariadb'
51
- const versions = ['>=2.0.3']
52
157
 
53
- addHook({ name, file: 'lib/cmd/query.js', versions }, (Query) => {
54
- shimmer.wrap(Query.prototype, 'start', wrapCommandStart)
158
+ addHook({ name, file: 'lib/cmd/query.js', versions: ['>=3'] }, (Query) => {
159
+ return wrapCommand(Query)
160
+ })
161
+
162
+ addHook({ name, file: 'lib/cmd/execute.js', versions: ['>=3'] }, (Execute) => {
163
+ return wrapCommand(Execute)
164
+ })
165
+
166
+ addHook({ name, file: 'lib/pool.js', versions: ['>=3'] }, (Pool) => {
167
+ shimmer.wrap(Pool.prototype, '_createConnection', wrapPoolMethod)
55
168
 
56
- return Query
169
+ return Pool
57
170
  })
58
171
 
59
- addHook({ name, file: 'lib/cmd/execute.js', versions }, (Query) => {
60
- shimmer.wrap(Query.prototype, 'start', wrapCommandStart)
172
+ addHook({ name, file: 'lib/connection.js', versions: ['>=2.5.2 <3'] }, (Connection) => {
173
+ return shimmer.wrap(Connection, wrapConnection(Connection, '_queryPromise'))
174
+ })
175
+
176
+ addHook({ name, file: 'lib/connection.js', versions: ['>=2.0.4 <=2.5.1'] }, (Connection) => {
177
+ return shimmer.wrap(Connection, wrapConnection(Connection, 'query'))
178
+ })
61
179
 
62
- return Query
180
+ addHook({ name, file: 'lib/pool-base.js', versions: ['>=2.0.4 <3'] }, (PoolBase) => {
181
+ return shimmer.wrap(PoolBase, wrapPoolBase(PoolBase))
63
182
  })
@@ -2,6 +2,8 @@ const { createCoverageMap } = require('istanbul-lib-coverage')
2
2
 
3
3
  const { addHook, channel, AsyncResource } = require('./helpers/instrument')
4
4
  const shimmer = require('../../datadog-shimmer')
5
+ const log = require('../../dd-trace/src/log')
6
+
5
7
  const {
6
8
  getCoveredFilenamesFromCoverage,
7
9
  resetCoverage,
@@ -34,6 +36,9 @@ const testToAr = new WeakMap()
34
36
  const originalFns = new WeakMap()
35
37
  const testFileToSuiteAr = new Map()
36
38
 
39
+ // `isWorker` is true if it's a Mocha worker
40
+ let isWorker = false
41
+
37
42
  // We'll preserve the original coverage here
38
43
  const originalCoverageMap = createCoverageMap()
39
44
 
@@ -101,7 +106,7 @@ function mochaHook (Runner) {
101
106
  patched.add(Runner)
102
107
 
103
108
  shimmer.wrap(Runner.prototype, 'run', run => function () {
104
- if (!testStartCh.hasSubscribers) {
109
+ if (!testStartCh.hasSubscribers || isWorker) {
105
110
  return run.apply(this, arguments)
106
111
  }
107
112
 
@@ -120,9 +125,18 @@ function mochaHook (Runner) {
120
125
 
121
126
  const isSuitesSkipped = !!suitesToSkip.length
122
127
 
123
- testSessionFinishCh.publish({ status, isSuitesSkipped })
124
- // restore the original coverage
125
- global.__coverage__ = fromCoverageMapToCoverage(originalCoverageMap)
128
+ let testCodeCoverageLinesTotal
129
+ if (global.__coverage__) {
130
+ try {
131
+ testCodeCoverageLinesTotal = originalCoverageMap.getCoverageSummary().lines.pct
132
+ } catch (e) {
133
+ // ignore errors
134
+ }
135
+ // restore the original coverage
136
+ global.__coverage__ = fromCoverageMapToCoverage(originalCoverageMap)
137
+ }
138
+
139
+ testSessionFinishCh.publish({ status, isSuitesSkipped, testCodeCoverageLinesTotal })
126
140
  }))
127
141
 
128
142
  this.once('start', testRunAsyncResource.bind(function () {
@@ -321,7 +335,15 @@ addHook({
321
335
  * If ITR is disabled, `onDone` is called immediately on the subscriber
322
336
  */
323
337
  shimmer.wrap(Mocha.prototype, 'run', run => function () {
324
- if (!itrConfigurationCh.hasSubscribers) {
338
+ if (this.options.parallel) {
339
+ log.warn(`Unable to initialize CI Visibility because Mocha is running in parallel mode.`)
340
+ return run.apply(this, arguments)
341
+ }
342
+
343
+ if (!itrConfigurationCh.hasSubscribers || this.isWorker) {
344
+ if (this.isWorker) {
345
+ isWorker = true
346
+ }
325
347
  return run.apply(this, arguments)
326
348
  }
327
349
  this.options.delay = true
@@ -379,7 +401,9 @@ addHook({
379
401
  * This attaches `run` to the global context, which we'll call after
380
402
  * our configuration and skippable suites requests
381
403
  */
382
- mocha.options.delay = true
404
+ if (!mocha.options.parallel) {
405
+ mocha.options.delay = true
406
+ }
383
407
  return runMocha.apply(this, arguments)
384
408
  })
385
409
  return run
@@ -25,13 +25,19 @@ addHook({ name: 'mongodb-core', versions: ['2 - 3.1.9'] }, Server => {
25
25
  return Server
26
26
  })
27
27
 
28
- addHook({ name: 'mongodb', versions: ['>=4'], file: 'lib/cmap/connection.js' }, Connection => {
28
+ addHook({ name: 'mongodb', versions: ['>=4 <4.6.0'], file: 'lib/cmap/connection.js' }, Connection => {
29
29
  const proto = Connection.Connection.prototype
30
30
  shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command'))
31
31
  shimmer.wrap(proto, 'query', query => wrapConnectionCommand(query, 'query'))
32
32
  return Connection
33
33
  })
34
34
 
35
+ addHook({ name: 'mongodb', versions: ['>=4.6.0'], file: 'lib/cmap/connection.js' }, Connection => {
36
+ const proto = Connection.Connection.prototype
37
+ shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command'))
38
+ return Connection
39
+ })
40
+
35
41
  addHook({ name: 'mongodb', versions: ['>=3.3 <4'], file: 'lib/core/wireprotocol/index.js' }, wp => wrapWp(wp))
36
42
 
37
43
  addHook({ name: 'mongodb-core', versions: ['>=3.2'], file: 'lib/wireprotocol/index.js' }, wp => wrapWp(wp))
@@ -46,7 +52,7 @@ addHook({ name: 'mongodb-core', versions: ['~3.1.10'], file: 'lib/wireprotocol/2
46
52
  return WireProtocol
47
53
  })
48
54
 
49
- addHook({ name: 'mongodb', versions: ['>=3.5.4'], file: 'lib/utils.js' }, util => {
55
+ addHook({ name: 'mongodb', versions: ['>=3.5.4 <4.11.0'], file: 'lib/utils.js' }, util => {
50
56
  shimmer.wrap(util, 'maybePromise', maybePromise => function (parent, callback, fn) {
51
57
  const asyncResource = new AsyncResource('bound-anonymous-fn')
52
58
  const callbackIndex = arguments.length - 2
@@ -19,7 +19,7 @@ function wrapAddQueue (addQueue) {
19
19
 
20
20
  addHook({
21
21
  name: 'mongoose',
22
- versions: ['>=4.6.4 <7'] // TODO: Mongoose v7 compat
22
+ versions: ['>=4.6.4 <5', '5', '6', '>=7']
23
23
  }, mongoose => {
24
24
  if (mongoose.Promise !== global.Promise) {
25
25
  shimmer.wrap(mongoose.Promise.prototype, 'then', wrapThen)
@@ -26,16 +26,33 @@ function wrapHandleApiRequest (handleApiRequest) {
26
26
  return promise.then(handled => {
27
27
  if (!handled) return handled
28
28
 
29
- const page = getPageFromPath(pathname, this.dynamicRoutes)
29
+ return this.hasPage(pathname).then(pageFound => {
30
+ const page = pageFound ? pathname : getPageFromPath(pathname, this.dynamicRoutes)
30
31
 
31
- pageLoadChannel.publish({ page })
32
+ pageLoadChannel.publish({ page })
32
33
 
33
- return handled
34
+ return handled
35
+ })
34
36
  })
35
37
  })
36
38
  }
37
39
  }
38
40
 
41
+ // next 13.2 handleApiRequest uses a different set of parameters
42
+ function wrapHandleApiRequestWithMatch (handleApiRequest) {
43
+ return function (req, res, query, match) {
44
+ return instrument(req, res, () => {
45
+ const page = (typeof match === 'object' && typeof match.definition === 'object')
46
+ ? match.definition.pathname
47
+ : undefined
48
+
49
+ pageLoadChannel.publish({ page })
50
+
51
+ return handleApiRequest.apply(this, arguments)
52
+ })
53
+ }
54
+ }
55
+
39
56
  function wrapRenderToResponse (renderToResponse) {
40
57
  return function (ctx) {
41
58
  return instrument(ctx.req, ctx.res, () => renderToResponse.apply(this, arguments))
@@ -127,7 +144,18 @@ function finish (req, res, result, err) {
127
144
  return result
128
145
  }
129
146
 
130
- // TODO: 13.2 support
147
+ addHook({ name: 'next', versions: ['>=13.2'], file: 'dist/server/next-server.js' }, nextServer => {
148
+ const Server = nextServer.default
149
+
150
+ shimmer.wrap(Server.prototype, 'handleRequest', wrapHandleRequest)
151
+ shimmer.wrap(Server.prototype, 'handleApiRequest', wrapHandleApiRequestWithMatch)
152
+ shimmer.wrap(Server.prototype, 'renderToResponse', wrapRenderToResponse)
153
+ shimmer.wrap(Server.prototype, 'renderErrorToResponse', wrapRenderErrorToResponse)
154
+ shimmer.wrap(Server.prototype, 'findPageComponents', wrapFindPageComponents)
155
+
156
+ return nextServer
157
+ })
158
+
131
159
  addHook({ name: 'next', versions: ['>=11.1 <13.2'], file: 'dist/server/next-server.js' }, nextServer => {
132
160
  const Server = nextServer.default
133
161
 
@@ -27,27 +27,22 @@ function wrapQuery (query) {
27
27
  return query.apply(this, arguments)
28
28
  }
29
29
 
30
- const retval = query.apply(this, arguments)
31
-
32
- const queryQueue = this.queryQueue || this._queryQueue
33
- const activeQuery = this.activeQuery || this._activeQuery
34
- const pgQuery = queryQueue[queryQueue.length - 1] || activeQuery
35
-
36
- if (!pgQuery) {
37
- return retval
38
- }
39
-
40
30
  const callbackResource = new AsyncResource('bound-anonymous-fn')
41
31
  const asyncResource = new AsyncResource('bound-anonymous-fn')
42
32
  const processId = this.processID
33
+ let pgQuery = {
34
+ text: arguments[0]
35
+ }
36
+
43
37
  return asyncResource.runInAsyncScope(() => {
44
38
  startCh.publish({
45
39
  params: this.connectionParameters,
46
- originalQuery: pgQuery.text,
47
40
  query: pgQuery,
48
41
  processId
49
42
  })
50
43
 
44
+ arguments[0] = pgQuery.text
45
+
51
46
  const finish = asyncResource.bind(function (error) {
52
47
  if (error) {
53
48
  errorCh.publish(error)
@@ -55,6 +50,16 @@ function wrapQuery (query) {
55
50
  finishCh.publish()
56
51
  })
57
52
 
53
+ const retval = query.apply(this, arguments)
54
+ const queryQueue = this.queryQueue || this._queryQueue
55
+ const activeQuery = this.activeQuery || this._activeQuery
56
+
57
+ pgQuery = queryQueue[queryQueue.length - 1] || activeQuery
58
+
59
+ if (!pgQuery) {
60
+ return retval
61
+ }
62
+
58
63
  if (pgQuery.callback) {
59
64
  const originalCallback = callbackResource.bind(pgQuery.callback)
60
65
  pgQuery.callback = function (err, res) {
@@ -76,7 +76,7 @@ function getRootDir (playwrightRunner) {
76
76
  }
77
77
 
78
78
  function testBeginHandler (test) {
79
- const { title: testName, location: { file: testSuiteAbsolutePath }, _type } = test
79
+ const { _requireFile: testSuiteAbsolutePath, title: testName, _type } = test
80
80
 
81
81
  if (_type === 'beforeAll' || _type === 'afterAll') {
82
82
  return
@@ -101,7 +101,7 @@ function testBeginHandler (test) {
101
101
  }
102
102
 
103
103
  function testEndHandler (test, testStatus, error) {
104
- const { location: { file: testSuiteAbsolutePath }, results, _type } = test
104
+ const { _requireFile: testSuiteAbsolutePath, results, _type } = test
105
105
 
106
106
  if (_type === 'beforeAll' || _type === 'afterAll') {
107
107
  return
@@ -4,7 +4,7 @@ const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
4
4
  const { getAddress, getShortName } = require('./util')
5
5
 
6
6
  class Amqp10ConsumerPlugin extends ConsumerPlugin {
7
- static get name () { return 'amqp10' }
7
+ static get id () { return 'amqp10' }
8
8
  static get system () { return 'amqp' }
9
9
 
10
10
  start ({ link }) {
@@ -5,7 +5,7 @@ const ConsumerPlugin = require('./consumer')
5
5
  const CompositePlugin = require('../../dd-trace/src/plugins/composite')
6
6
 
7
7
  class Amqp10Plugin extends CompositePlugin {
8
- static get name () { return 'amqp10' }
8
+ static get id () { return 'amqp10' }
9
9
  static get plugins () {
10
10
  return {
11
11
  producer: ProducerPlugin,
@@ -1,10 +1,11 @@
1
1
  'use strict'
2
2
 
3
3
  const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
4
+ const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
4
5
  const { getAddress, getShortName } = require('./util')
5
6
 
6
7
  class Amqp10ProducerPlugin extends ProducerPlugin {
7
- static get name () { return 'amqp10' }
8
+ static get id () { return 'amqp10' }
8
9
  static get operation () { return 'send' }
9
10
  static get system () { return 'amqp' }
10
11
 
@@ -20,7 +21,7 @@ class Amqp10ProducerPlugin extends ProducerPlugin {
20
21
  'amqp.link.target.address': target,
21
22
  'amqp.link.role': 'sender',
22
23
  'out.host': address.host,
23
- 'out.port': address.port,
24
+ [CLIENT_PORT_KEY]: address.port,
24
25
  'amqp.link.name': link.name,
25
26
  'amqp.link.handle': link.handle,
26
27
  'amqp.connection.host': address.host,
@@ -1,11 +1,12 @@
1
1
  'use strict'
2
2
 
3
3
  const { TEXT_MAP } = require('../../../ext/formats')
4
+ const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
4
5
  const ClientPlugin = require('../../dd-trace/src/plugins/client')
5
6
  const { getResourceName } = require('./util')
6
7
 
7
8
  class AmqplibClientPlugin extends ClientPlugin {
8
- static get name () { return 'amqplib' }
9
+ static get id () { return 'amqplib' }
9
10
  static get operation () { return 'command' }
10
11
 
11
12
  start ({ channel = {}, method, fields }) {
@@ -19,7 +20,7 @@ class AmqplibClientPlugin extends ClientPlugin {
19
20
  kind: 'client',
20
21
  meta: {
21
22
  'out.host': stream._host,
22
- 'out.port': stream.remotePort,
23
+ [CLIENT_PORT_KEY]: stream.remotePort,
23
24
  'amqp.queue': fields.queue,
24
25
  'amqp.exchange': fields.exchange,
25
26
  'amqp.routingKey': fields.routingKey,
@@ -5,7 +5,7 @@ const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
5
5
  const { getResourceName } = require('./util')
6
6
 
7
7
  class AmqplibConsumerPlugin extends ConsumerPlugin {
8
- static get name () { return 'amqplib' }
8
+ static get id () { return 'amqplib' }
9
9
  static get operation () { return 'command' }
10
10
 
11
11
  start ({ method, fields, message }) {
@@ -7,7 +7,7 @@ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
7
7
 
8
8
  // TODO: Consider splitting channels for publish/receive in the instrumentation.
9
9
  class AmqplibPlugin extends CompositePlugin {
10
- static get name () { return 'amqplib' }
10
+ static get id () { return 'amqplib' }
11
11
  static get plugins () {
12
12
  return {
13
13
  producer: ProducerPlugin,