dd-trace 5.102.0 → 5.104.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 (201) hide show
  1. package/ext/exporters.js +1 -0
  2. package/index.d.ts +25 -3
  3. package/package.json +15 -13
  4. package/packages/datadog-esbuild/src/utils.js +2 -2
  5. package/packages/datadog-instrumentations/src/ai.js +1 -1
  6. package/packages/datadog-instrumentations/src/aws-sdk.js +2 -2
  7. package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -2
  8. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +32 -15
  9. package/packages/datadog-instrumentations/src/couchbase.js +69 -220
  10. package/packages/datadog-instrumentations/src/cucumber.js +104 -31
  11. package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
  12. package/packages/datadog-instrumentations/src/electron/preload.js +42 -0
  13. package/packages/datadog-instrumentations/src/electron.js +240 -0
  14. package/packages/datadog-instrumentations/src/fetch.js +5 -5
  15. package/packages/datadog-instrumentations/src/graphql.js +13 -17
  16. package/packages/datadog-instrumentations/src/grpc/client.js +48 -32
  17. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +2 -2
  18. package/packages/datadog-instrumentations/src/helpers/hook.js +4 -1
  19. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  20. package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
  21. package/packages/datadog-instrumentations/src/helpers/kafka.js +58 -0
  22. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +3 -2
  23. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +19 -5
  24. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +14 -13
  25. package/packages/datadog-instrumentations/src/http/client.js +2 -2
  26. package/packages/datadog-instrumentations/src/ioredis.js +18 -14
  27. package/packages/datadog-instrumentations/src/jest.js +382 -84
  28. package/packages/datadog-instrumentations/src/kafkajs.js +184 -174
  29. package/packages/datadog-instrumentations/src/mariadb.js +1 -1
  30. package/packages/datadog-instrumentations/src/memcached.js +2 -1
  31. package/packages/datadog-instrumentations/src/mocha/main.js +309 -56
  32. package/packages/datadog-instrumentations/src/mocha/utils.js +48 -8
  33. package/packages/datadog-instrumentations/src/mongodb-core.js +34 -9
  34. package/packages/datadog-instrumentations/src/mongoose.js +10 -12
  35. package/packages/datadog-instrumentations/src/mysql.js +2 -2
  36. package/packages/datadog-instrumentations/src/mysql2.js +1 -1
  37. package/packages/datadog-instrumentations/src/pg.js +25 -11
  38. package/packages/datadog-instrumentations/src/playwright.js +449 -60
  39. package/packages/datadog-instrumentations/src/redis.js +19 -10
  40. package/packages/datadog-instrumentations/src/router.js +4 -2
  41. package/packages/datadog-instrumentations/src/vitest.js +246 -149
  42. package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -21
  43. package/packages/datadog-plugin-aws-sdk/src/base.js +18 -24
  44. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  45. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -1
  46. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
  47. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
  48. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  49. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
  50. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -2
  51. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -1
  52. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
  53. package/packages/datadog-plugin-couchbase/src/index.js +58 -52
  54. package/packages/datadog-plugin-cucumber/src/index.js +1 -0
  55. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +239 -40
  56. package/packages/datadog-plugin-cypress/src/support.js +13 -1
  57. package/packages/datadog-plugin-elasticsearch/src/index.js +28 -8
  58. package/packages/datadog-plugin-electron/src/index.js +17 -0
  59. package/packages/datadog-plugin-electron/src/ipc.js +143 -0
  60. package/packages/datadog-plugin-electron/src/net.js +82 -0
  61. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +27 -18
  62. package/packages/datadog-plugin-graphql/src/execute.js +6 -28
  63. package/packages/datadog-plugin-graphql/src/resolve.js +30 -35
  64. package/packages/datadog-plugin-graphql/src/tools/signature.js +32 -7
  65. package/packages/datadog-plugin-graphql/src/tools/transforms.js +118 -100
  66. package/packages/datadog-plugin-graphql/src/utils.js +33 -1
  67. package/packages/datadog-plugin-grpc/src/client.js +6 -7
  68. package/packages/datadog-plugin-grpc/src/util.js +57 -22
  69. package/packages/datadog-plugin-http/src/client.js +2 -2
  70. package/packages/datadog-plugin-jest/src/index.js +92 -50
  71. package/packages/datadog-plugin-kafkajs/src/producer.js +32 -0
  72. package/packages/datadog-plugin-mocha/src/index.js +1 -0
  73. package/packages/datadog-plugin-mongodb-core/src/index.js +70 -69
  74. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  75. package/packages/datadog-plugin-openai/src/services.js +2 -1
  76. package/packages/datadog-plugin-pg/src/index.js +3 -3
  77. package/packages/datadog-plugin-playwright/src/index.js +4 -0
  78. package/packages/datadog-plugin-redis/src/index.js +54 -24
  79. package/packages/datadog-plugin-undici/src/index.js +19 -0
  80. package/packages/datadog-plugin-vitest/src/index.js +19 -7
  81. package/packages/datadog-shimmer/src/shimmer.js +35 -0
  82. package/packages/dd-trace/src/aiguard/index.js +3 -1
  83. package/packages/dd-trace/src/aiguard/sdk.js +36 -30
  84. package/packages/dd-trace/src/aiguard/tags.js +20 -11
  85. package/packages/dd-trace/src/appsec/blocking.js +2 -2
  86. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -2
  87. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
  88. package/packages/dd-trace/src/appsec/index.js +10 -3
  89. package/packages/dd-trace/src/appsec/reporter.js +19 -5
  90. package/packages/dd-trace/src/azure_metadata.js +17 -6
  91. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +4 -4
  92. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -2
  93. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +6 -4
  94. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +1 -1
  95. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -1
  96. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +5 -3
  97. package/packages/dd-trace/src/config/defaults.js +3 -14
  98. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
  99. package/packages/dd-trace/src/config/helper.js +4 -0
  100. package/packages/dd-trace/src/config/index.js +2 -2
  101. package/packages/dd-trace/src/config/major-overrides.js +98 -0
  102. package/packages/dd-trace/src/config/parsers.js +7 -1
  103. package/packages/dd-trace/src/config/supported-configurations.json +60 -38
  104. package/packages/dd-trace/src/crashtracking/crashtracker.js +15 -3
  105. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
  106. package/packages/dd-trace/src/datastreams/context.js +4 -2
  107. package/packages/dd-trace/src/datastreams/manager.js +1 -1
  108. package/packages/dd-trace/src/datastreams/processor.js +2 -2
  109. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +2 -2
  110. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
  111. package/packages/dd-trace/src/debugger/devtools_client/state.js +2 -1
  112. package/packages/dd-trace/src/debugger/index.js +7 -7
  113. package/packages/dd-trace/src/dogstatsd.js +2 -2
  114. package/packages/dd-trace/src/encode/0.4.js +45 -54
  115. package/packages/dd-trace/src/encode/0.5.js +34 -3
  116. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +26 -19
  117. package/packages/dd-trace/src/encode/agentless-json.js +1 -1
  118. package/packages/dd-trace/src/exporter.js +2 -0
  119. package/packages/dd-trace/src/exporters/agent/index.js +2 -1
  120. package/packages/dd-trace/src/exporters/agentless/index.js +3 -2
  121. package/packages/dd-trace/src/exporters/agentless/writer.js +2 -2
  122. package/packages/dd-trace/src/exporters/common/agents.js +3 -1
  123. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -1
  124. package/packages/dd-trace/src/exporters/common/request.js +4 -2
  125. package/packages/dd-trace/src/exporters/electron/index.js +49 -0
  126. package/packages/dd-trace/src/external-logger/src/index.js +2 -1
  127. package/packages/dd-trace/src/git_metadata.js +10 -8
  128. package/packages/dd-trace/src/id.js +17 -4
  129. package/packages/dd-trace/src/lambda/handler-paths.js +52 -0
  130. package/packages/dd-trace/src/lambda/handler.js +2 -4
  131. package/packages/dd-trace/src/lambda/index.js +62 -14
  132. package/packages/dd-trace/src/lambda/runtime/patch.js +21 -46
  133. package/packages/dd-trace/src/llmobs/index.js +13 -2
  134. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +45 -15
  135. package/packages/dd-trace/src/llmobs/sdk.js +10 -0
  136. package/packages/dd-trace/src/llmobs/writers/base.js +2 -1
  137. package/packages/dd-trace/src/log/writer.js +3 -1
  138. package/packages/dd-trace/src/noop/span.js +3 -1
  139. package/packages/dd-trace/src/openfeature/writers/base.js +2 -1
  140. package/packages/dd-trace/src/openfeature/writers/exposures.js +51 -20
  141. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
  142. package/packages/dd-trace/src/opentracing/propagation/text_map.js +20 -9
  143. package/packages/dd-trace/src/payload-tagging/config/index.js +2 -2
  144. package/packages/dd-trace/src/plugins/apollo.js +3 -1
  145. package/packages/dd-trace/src/plugins/ci_plugin.js +52 -17
  146. package/packages/dd-trace/src/plugins/database.js +54 -12
  147. package/packages/dd-trace/src/plugins/index.js +1 -0
  148. package/packages/dd-trace/src/plugins/log_plugin.js +3 -1
  149. package/packages/dd-trace/src/plugins/plugin.js +2 -4
  150. package/packages/dd-trace/src/plugins/tracing.js +5 -3
  151. package/packages/dd-trace/src/plugins/util/ci.js +8 -8
  152. package/packages/dd-trace/src/plugins/util/git-cache.js +20 -18
  153. package/packages/dd-trace/src/plugins/util/git.js +3 -1
  154. package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -2
  155. package/packages/dd-trace/src/plugins/util/test.js +119 -5
  156. package/packages/dd-trace/src/plugins/util/user-provided-git.js +17 -15
  157. package/packages/dd-trace/src/plugins/util/web.js +11 -0
  158. package/packages/dd-trace/src/priority_sampler.js +1 -1
  159. package/packages/dd-trace/src/profiling/profiler.js +1 -1
  160. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
  161. package/packages/dd-trace/src/profiling/ssi-heuristics.js +1 -1
  162. package/packages/dd-trace/src/rate_limiter.js +1 -1
  163. package/packages/dd-trace/src/remote_config/scheduler.js +1 -1
  164. package/packages/dd-trace/src/ritm.js +2 -1
  165. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -8
  166. package/packages/dd-trace/src/scope.js +7 -5
  167. package/packages/dd-trace/src/serverless.js +5 -2
  168. package/packages/dd-trace/src/service-naming/extra-services.js +14 -0
  169. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +20 -0
  170. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
  171. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +20 -0
  172. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
  173. package/packages/dd-trace/src/span_stats.js +1 -1
  174. package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
  175. package/packages/dd-trace/src/telemetry/endpoints.js +1 -1
  176. package/packages/dd-trace/src/telemetry/telemetry.js +2 -2
  177. package/packages/dd-trace/src/lambda/runtime/ritm.js +0 -133
  178. package/vendor/dist/opentracing/LICENSE +0 -201
  179. package/vendor/dist/opentracing/binary_carrier.d.ts +0 -11
  180. package/vendor/dist/opentracing/constants.d.ts +0 -61
  181. package/vendor/dist/opentracing/examples/demo/demo.d.ts +0 -2
  182. package/vendor/dist/opentracing/ext/tags.d.ts +0 -90
  183. package/vendor/dist/opentracing/functions.d.ts +0 -20
  184. package/vendor/dist/opentracing/global_tracer.d.ts +0 -14
  185. package/vendor/dist/opentracing/index.d.ts +0 -12
  186. package/vendor/dist/opentracing/index.js +0 -1
  187. package/vendor/dist/opentracing/mock_tracer/index.d.ts +0 -5
  188. package/vendor/dist/opentracing/mock_tracer/mock_context.d.ts +0 -13
  189. package/vendor/dist/opentracing/mock_tracer/mock_report.d.ts +0 -16
  190. package/vendor/dist/opentracing/mock_tracer/mock_span.d.ts +0 -50
  191. package/vendor/dist/opentracing/mock_tracer/mock_tracer.d.ts +0 -26
  192. package/vendor/dist/opentracing/noop.d.ts +0 -8
  193. package/vendor/dist/opentracing/reference.d.ts +0 -33
  194. package/vendor/dist/opentracing/span.d.ts +0 -147
  195. package/vendor/dist/opentracing/span_context.d.ts +0 -26
  196. package/vendor/dist/opentracing/test/api_compatibility.d.ts +0 -16
  197. package/vendor/dist/opentracing/test/mocktracer_implemenation.d.ts +0 -3
  198. package/vendor/dist/opentracing/test/noop_implementation.d.ts +0 -4
  199. package/vendor/dist/opentracing/test/opentracing_api.d.ts +0 -3
  200. package/vendor/dist/opentracing/test/unittest.d.ts +0 -2
  201. package/vendor/dist/opentracing/tracer.d.ts +0 -127
@@ -13,6 +13,7 @@ const errorCh = channel('apm:redis:command:error')
13
13
  let createClientUrl
14
14
  let createClientName
15
15
  const instanceInfo = new WeakMap()
16
+ const connectionInfoCache = new WeakMap()
16
17
 
17
18
  function wrapAddCommand (addCommand) {
18
19
  return function (command) {
@@ -20,10 +21,7 @@ function wrapAddCommand (addCommand) {
20
21
  return addCommand.apply(this, arguments)
21
22
  }
22
23
 
23
- const name = command[0]
24
- const args = command.slice(1)
25
-
26
- const ctx = getStartCtx(this, name, args)
24
+ const ctx = getStartCtx(this, command[0], command, 1)
27
25
  return startCh.runStores(ctx, () => {
28
26
  const res = addCommand.apply(this, arguments)
29
27
 
@@ -136,22 +134,33 @@ addHook({ name: 'redis', versions: ['>=0.12 <2.6'] }, redis => {
136
134
  return redis
137
135
  })
138
136
 
139
- function getStartCtx (client, command, args) {
140
- const { url, connectionName } = instanceInfo.get(client) || {}
137
+ function getStartCtx (client, command, args, argsStartIndex) {
138
+ let cached = connectionInfoCache.get(client)
139
+ if (cached === undefined) {
140
+ const info = instanceInfo.get(client)
141
+ cached = {
142
+ connectionOptions:
143
+ client.connection_options || client.connection_option || client.connectionOption || info?.url,
144
+ connectionName: info?.connectionName,
145
+ }
146
+ connectionInfoCache.set(client, cached)
147
+ }
141
148
 
142
149
  return {
143
150
  db: client.selected_db,
144
151
  command,
145
152
  args,
146
- connectionOptions: client.connection_options || client.connection_option || client.connectionOption || url,
147
- connectionName,
153
+ argsStartIndex,
154
+ connectionOptions: cached.connectionOptions,
155
+ connectionName: cached.connectionName,
148
156
  }
149
157
  }
150
158
 
151
159
  function wrapCallback (finishCh, errorCh, ctx, callback) {
152
- return shimmer.wrapFunction(callback, callback => function (err) {
160
+ if (typeof callback !== 'function') return callback
161
+ return function (err) {
153
162
  return finish(finishCh, errorCh, ctx, err, callback, this, arguments)
154
- })
163
+ }
155
164
  }
156
165
 
157
166
  function finish (finishCh, errorCh, ctx, error, callback, thisArg, args) {
@@ -112,8 +112,10 @@ function createWrapRouterMethod (name, compile) {
112
112
  }
113
113
  }
114
114
 
115
- function wrapNext (req, next) {
116
- return shimmer.wrapFunction(next, next => function (error) {
115
+ function wrapNext (req, originalNext) {
116
+ // Per layer dispatch, N per request. `shimmer.wrapCallback` preserves
117
+ // only `name` + `length`; see its JSDoc for the full contract.
118
+ return shimmer.wrapCallback(originalNext, next => function (error) {
117
119
  if (error && error !== 'route' && error !== 'router') {
118
120
  errorChannel.publish({ req, error })
119
121
  }
@@ -19,6 +19,7 @@ const {
19
19
  collectTestOptimizationSummariesFromTraces,
20
20
  logAttemptToFixTestExecution,
21
21
  logTestOptimizationSummary,
22
+ getTestOptimizationRequestResults,
22
23
  } = require('../../dd-trace/src/plugins/util/test')
23
24
  const { addHook, channel } = require('./helpers/instrument')
24
25
 
@@ -43,6 +44,7 @@ const testSuiteErrorCh = channel('ci:vitest:test-suite:error')
43
44
  // test session hooks
44
45
  const testSessionStartCh = channel('ci:vitest:session:start')
45
46
  const testSessionFinishCh = channel('ci:vitest:session:finish')
47
+ const testSessionConfigurationCh = channel('ci:vitest:session:configuration')
46
48
  const libraryConfigurationCh = channel('ci:vitest:library-configuration')
47
49
  const knownTestsCh = channel('ci:vitest:known-tests')
48
50
  const isEarlyFlakeDetectionFaultyCh = channel('ci:vitest:is-early-flake-detection-faulty')
@@ -74,6 +76,9 @@ let isRetryReasonEfd = false
74
76
  let isRetryReasonAttemptToFix = false
75
77
  const switchedStatuses = new WeakSet()
76
78
  const workerProcesses = new WeakSet()
79
+ const mainProcessSetupPromises = new WeakMap()
80
+ const coverageWrappedProviders = new WeakSet()
81
+ const finishWrappedContexts = new WeakSet()
77
82
  let isFlakyTestRetriesEnabled = false
78
83
  let flakyTestRetriesCount = 0
79
84
  let isEarlyFlakeDetectionEnabled = false
@@ -134,6 +139,9 @@ function getProvidedContext () {
134
139
  _ddFlakyTestRetriesCount: flakyTestRetriesCount,
135
140
  _ddIsImpactedTestsEnabled: isImpactedTestsEnabled,
136
141
  _ddModifiedFiles: modifiedFiles,
142
+ _ddTestSessionId: testSessionId,
143
+ _ddTestModuleId: testModuleId,
144
+ _ddTestCommand: testCommand,
137
145
  } = globalThis.__vitest_worker__.providedContext
138
146
 
139
147
  return {
@@ -150,6 +158,9 @@ function getProvidedContext () {
150
158
  flakyTestRetriesCount: flakyTestRetriesCount ?? 0,
151
159
  isImpactedTestsEnabled,
152
160
  modifiedFiles,
161
+ testSessionId,
162
+ testModuleId,
163
+ testCommand,
153
164
  }
154
165
  } catch {
155
166
  log.error('Vitest workers could not parse provided context, so some features will not work.')
@@ -167,6 +178,9 @@ function getProvidedContext () {
167
178
  flakyTestRetriesCount: 0,
168
179
  isImpactedTestsEnabled: false,
169
180
  modifiedFiles: {},
181
+ testSessionId: undefined,
182
+ testModuleId: undefined,
183
+ testCommand: undefined,
170
184
  }
171
185
  }
172
186
  }
@@ -217,6 +231,10 @@ function getTestRunnerExport (testPackage) {
217
231
  return findExportByName(testPackage, 'VitestTestRunner') || findExportByName(testPackage, 'TestRunner')
218
232
  }
219
233
 
234
+ function getVitestExport (vitestPackage) {
235
+ return findExportByName(vitestPackage, 'Vitest')
236
+ }
237
+
220
238
  function getForksPoolWorkerExport (vitestPackage) {
221
239
  return findExportByName(vitestPackage, 'ForksPoolWorker')
222
240
  }
@@ -329,170 +347,223 @@ function wrapBeforeEachCleanupResult (task, result) {
329
347
  return result
330
348
  }
331
349
 
332
- function getSortWrapper (sort, frameworkVersion) {
333
- return async function () {
334
- if (!testSessionFinishCh.hasSubscribers) {
335
- return sort.apply(this, arguments)
336
- }
337
- // There isn't any other async function that we seem to be able to hook into
338
- // So we will use the sort from BaseSequencer. This means that a custom sequencer
339
- // will not work. This will be a known limitation.
350
+ function getWorkspaceProject (ctx) {
351
+ return ctx.getCoreWorkspaceProject
352
+ ? ctx.getCoreWorkspaceProject()
353
+ : ctx.getRootProject()
354
+ }
355
+
356
+ function setProvidedContext (ctx, values, warningMessage) {
357
+ try {
358
+ Object.assign(getWorkspaceProject(ctx)._provided, values)
359
+ } catch {
360
+ log.warn(warningMessage)
361
+ }
362
+ }
363
+
364
+ function getTestFilepathsFromSpecifications (testSpecifications) {
365
+ if (!Array.isArray(testSpecifications) || !testSpecifications.length) {
366
+ return
367
+ }
368
+
369
+ return testSpecifications.map(testSpecification => {
370
+ const testFile = Array.isArray(testSpecification) ? testSpecification[1] : testSpecification
371
+ return testFile?.moduleId || testFile?.filepath || testFile
372
+ })
373
+ }
374
+
375
+ function getTestFilepaths (ctx, testSpecifications) {
376
+ const testFilepaths = getTestFilepathsFromSpecifications(testSpecifications)
377
+ if (testFilepaths) {
378
+ return testFilepaths
379
+ }
380
+
381
+ const getFilePaths = ctx.getTestFilepaths || ctx._globTestFilepaths
382
+ return getFilePaths.call(ctx)
383
+ }
384
+
385
+ function wrapCoverageProvider (ctx) {
386
+ const { coverageProvider } = ctx
387
+ if (!coverageProvider?.generateCoverage || coverageWrappedProviders.has(coverageProvider)) {
388
+ return
389
+ }
390
+ coverageWrappedProviders.add(coverageProvider)
391
+
392
+ // Capture coverage root directory from config (default is 'coverage' in cwd)
393
+ try {
394
+ const coverageConfig = ctx.config?.coverage
395
+ const reportsDirectory = coverageConfig?.reportsDirectory || 'coverage'
396
+ const rootDir = ctx.config?.root || process.cwd()
397
+ coverageRootDir = path.isAbsolute(reportsDirectory) ? reportsDirectory : path.join(rootDir, reportsDirectory)
398
+ } catch {
399
+ // Fallback to cwd if we can't get config
400
+ coverageRootDir = process.cwd()
401
+ }
402
+
403
+ shimmer.wrap(coverageProvider, 'generateCoverage', generateCoverage => async function () {
404
+ const totalCodeCoverage = await generateCoverage.apply(this, arguments)
340
405
 
341
406
  try {
342
- const { err, libraryConfig } = await getChannelPromise(libraryConfigurationCh, frameworkVersion)
343
- if (!err) {
344
- isFlakyTestRetriesEnabled = libraryConfig.isFlakyTestRetriesEnabled
345
- flakyTestRetriesCount = libraryConfig.flakyTestRetriesCount
346
- isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
347
- earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
348
- earlyFlakeDetectionSlowTestRetries = libraryConfig.earlyFlakeDetectionSlowTestRetries ?? {}
349
- isDiEnabled = libraryConfig.isDiEnabled
350
- isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
351
- isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
352
- testManagementAttemptToFixRetries = libraryConfig.testManagementAttemptToFixRetries
353
- isImpactedTestsEnabled = libraryConfig.isImpactedTestsEnabled
354
- }
407
+ testCodeCoverageLinesTotal = totalCodeCoverage.getCoverageSummary().lines.pct
355
408
  } catch {
356
- isFlakyTestRetriesEnabled = false
357
- isEarlyFlakeDetectionEnabled = false
358
- isDiEnabled = false
359
- isKnownTestsEnabled = false
360
- isImpactedTestsEnabled = false
409
+ // ignore errors
361
410
  }
411
+ return totalCodeCoverage
412
+ })
413
+ }
362
414
 
363
- if (isFlakyTestRetriesEnabled && !this.ctx.config.retry && flakyTestRetriesCount > 0) {
364
- this.ctx.config.retry = flakyTestRetriesCount
365
- try {
366
- const workspaceProject = this.ctx.getCoreWorkspaceProject
367
- ? this.ctx.getCoreWorkspaceProject()
368
- : this.ctx.getRootProject()
369
- workspaceProject._provided._ddIsFlakyTestRetriesEnabled = isFlakyTestRetriesEnabled
370
- workspaceProject._provided._ddFlakyTestRetriesCount = flakyTestRetriesCount
371
- } catch {
372
- log.warn('Could not send library configuration to workers.')
373
- }
374
- }
415
+ function wrapSessionFinish (ctx) {
416
+ if (finishWrappedContexts.has(ctx)) {
417
+ return
418
+ }
419
+ finishWrappedContexts.add(ctx)
375
420
 
376
- if (isKnownTestsEnabled) {
377
- const knownTestsResponse = await getChannelPromise(knownTestsCh)
378
- if (knownTestsResponse.err) {
379
- isEarlyFlakeDetectionEnabled = false
380
- } else {
381
- const knownTests = knownTestsResponse.knownTests
382
- const getFilePaths = this.ctx.getTestFilepaths || this.ctx._globTestFilepaths
383
-
384
- const testFilepaths = await getFilePaths.call(this.ctx)
385
-
386
- if (isValidKnownTests(knownTests)) {
387
- isEarlyFlakeDetectionFaultyCh.publish({
388
- knownTests: knownTests.vitest,
389
- testFilepaths,
390
- onDone: (isFaulty) => {
391
- isEarlyFlakeDetectionFaulty = isFaulty
392
- },
393
- })
394
- if (isEarlyFlakeDetectionFaulty) {
395
- isEarlyFlakeDetectionEnabled = false
396
- log.warn('New test detection is disabled because the number of new tests is too high.')
397
- } else {
398
- // TODO: use this to pass session and module IDs to the worker, instead of polluting process.env
399
- // Note: setting this.ctx.config.provide directly does not work because it's cached
400
- try {
401
- const workspaceProject = this.ctx.getCoreWorkspaceProject
402
- ? this.ctx.getCoreWorkspaceProject()
403
- : this.ctx.getRootProject()
404
- workspaceProject._provided._ddIsKnownTestsEnabled = isKnownTestsEnabled
405
- workspaceProject._provided._ddKnownTests = knownTests
406
- workspaceProject._provided._ddIsEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
407
- workspaceProject._provided._ddEarlyFlakeDetectionNumRetries =
408
- getConfiguredEfdRetryCount(earlyFlakeDetectionSlowTestRetries, earlyFlakeDetectionNumRetries)
409
- workspaceProject._provided._ddEarlyFlakeDetectionSlowTestRetries = earlyFlakeDetectionSlowTestRetries
410
- } catch {
411
- log.warn('Could not send known tests to workers so Early Flake Detection will not work.')
412
- }
413
- }
414
- } else {
415
- isEarlyFlakeDetectionFaulty = true
416
- isEarlyFlakeDetectionEnabled = false
417
- }
418
- }
419
- }
421
+ shimmer.wrap(ctx, 'exit', getFinishWrapper)
422
+ shimmer.wrap(ctx, 'close', getFinishWrapper)
423
+ }
420
424
 
421
- if (isDiEnabled) {
422
- try {
423
- const workspaceProject = this.ctx.getCoreWorkspaceProject
424
- ? this.ctx.getCoreWorkspaceProject()
425
- : this.ctx.getRootProject()
426
- workspaceProject._provided._ddIsDiEnabled = isDiEnabled
427
- } catch {
428
- log.warn('Could not send Dynamic Instrumentation configuration to workers.')
429
- }
430
- }
425
+ async function runMainProcessSetup (ctx, frameworkVersion, testSpecifications) {
426
+ if (!testSessionFinishCh.hasSubscribers) {
427
+ return
428
+ }
431
429
 
432
- if (isTestManagementTestsEnabled) {
433
- const { err, testManagementTests: receivedTestManagementTests } = await getChannelPromise(testManagementTestsCh)
434
- if (err) {
435
- isTestManagementTestsEnabled = false
436
- log.error('Could not get test management tests.')
437
- } else {
438
- const testManagementTests = receivedTestManagementTests
439
- try {
440
- const workspaceProject = this.ctx.getCoreWorkspaceProject
441
- ? this.ctx.getCoreWorkspaceProject()
442
- : this.ctx.getRootProject()
443
- workspaceProject._provided._ddIsTestManagementTestsEnabled = isTestManagementTestsEnabled
444
- workspaceProject._provided._ddTestManagementAttemptToFixRetries = testManagementAttemptToFixRetries
445
- workspaceProject._provided._ddTestManagementTests = testManagementTests
446
- } catch {
447
- log.warn('Could not send test management tests to workers so Test Management will not work.')
448
- }
449
- }
430
+ try {
431
+ const { err, libraryConfig } = await getChannelPromise(libraryConfigurationCh, frameworkVersion)
432
+ if (!err) {
433
+ isFlakyTestRetriesEnabled = libraryConfig.isFlakyTestRetriesEnabled
434
+ flakyTestRetriesCount = libraryConfig.flakyTestRetriesCount
435
+ isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
436
+ earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
437
+ earlyFlakeDetectionSlowTestRetries = libraryConfig.earlyFlakeDetectionSlowTestRetries ?? {}
438
+ isDiEnabled = libraryConfig.isDiEnabled
439
+ isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
440
+ isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
441
+ testManagementAttemptToFixRetries = libraryConfig.testManagementAttemptToFixRetries
442
+ isImpactedTestsEnabled = libraryConfig.isImpactedTestsEnabled
450
443
  }
444
+ } catch {
445
+ isFlakyTestRetriesEnabled = false
446
+ isEarlyFlakeDetectionEnabled = false
447
+ isDiEnabled = false
448
+ isKnownTestsEnabled = false
449
+ isImpactedTestsEnabled = false
450
+ }
451
451
 
452
- if (isImpactedTestsEnabled) {
453
- const { err, modifiedFiles } = await getChannelPromise(modifiedFilesCh)
454
- if (err) {
455
- log.error('Could not get modified tests.')
456
- } else {
457
- try {
458
- const workspaceProject = this.ctx.getCoreWorkspaceProject
459
- ? this.ctx.getCoreWorkspaceProject()
460
- : this.ctx.getRootProject()
461
- workspaceProject._provided._ddIsImpactedTestsEnabled = isImpactedTestsEnabled
462
- workspaceProject._provided._ddModifiedFiles = modifiedFiles
463
- } catch {
464
- log.warn('Could not send modified tests to workers so Impacted Tests will not work.')
452
+ if (testSessionConfigurationCh.hasSubscribers) {
453
+ const { testSessionId, testModuleId, testCommand } = await getChannelPromise(
454
+ testSessionConfigurationCh,
455
+ frameworkVersion
456
+ )
457
+ setProvidedContext(ctx, {
458
+ _ddTestSessionId: testSessionId,
459
+ _ddTestModuleId: testModuleId,
460
+ _ddTestCommand: testCommand,
461
+ }, 'Could not send test session configuration to workers.')
462
+ }
463
+
464
+ const {
465
+ knownTestsResponse,
466
+ testManagementTestsResponse,
467
+ } = await getTestOptimizationRequestResults({
468
+ isKnownTestsEnabled,
469
+ isTestManagementTestsEnabled,
470
+ getKnownTests: () => getChannelPromise(knownTestsCh),
471
+ getTestManagementTests: () => getChannelPromise(testManagementTestsCh),
472
+ })
473
+
474
+ if (isFlakyTestRetriesEnabled && !ctx.config.retry && flakyTestRetriesCount > 0) {
475
+ ctx.config.retry = flakyTestRetriesCount
476
+ setProvidedContext(ctx, {
477
+ _ddIsFlakyTestRetriesEnabled: isFlakyTestRetriesEnabled,
478
+ _ddFlakyTestRetriesCount: flakyTestRetriesCount,
479
+ }, 'Could not send library configuration to workers.')
480
+ }
481
+
482
+ if (isKnownTestsEnabled) {
483
+ const currentKnownTestsResponse = knownTestsResponse || await getChannelPromise(knownTestsCh)
484
+ if (currentKnownTestsResponse.err) {
485
+ isEarlyFlakeDetectionEnabled = false
486
+ } else {
487
+ const knownTests = currentKnownTestsResponse.knownTests
488
+ const testFilepaths = await getTestFilepaths(ctx, testSpecifications)
489
+
490
+ if (isValidKnownTests(knownTests)) {
491
+ isEarlyFlakeDetectionFaultyCh.publish({
492
+ knownTests: knownTests.vitest,
493
+ testFilepaths,
494
+ onDone: (isFaulty) => {
495
+ isEarlyFlakeDetectionFaulty = isFaulty
496
+ },
497
+ })
498
+ if (isEarlyFlakeDetectionFaulty) {
499
+ isEarlyFlakeDetectionEnabled = false
500
+ log.warn('New test detection is disabled because the number of new tests is too high.')
501
+ } else {
502
+ setProvidedContext(ctx, {
503
+ _ddIsKnownTestsEnabled: isKnownTestsEnabled,
504
+ _ddKnownTests: knownTests,
505
+ _ddIsEarlyFlakeDetectionEnabled: isEarlyFlakeDetectionEnabled,
506
+ _ddEarlyFlakeDetectionNumRetries:
507
+ getConfiguredEfdRetryCount(earlyFlakeDetectionSlowTestRetries, earlyFlakeDetectionNumRetries),
508
+ _ddEarlyFlakeDetectionSlowTestRetries: earlyFlakeDetectionSlowTestRetries,
509
+ }, 'Could not send known tests to workers so Early Flake Detection will not work.')
465
510
  }
511
+ } else {
512
+ isEarlyFlakeDetectionFaulty = true
513
+ isEarlyFlakeDetectionEnabled = false
466
514
  }
467
515
  }
516
+ }
468
517
 
469
- if (this.ctx.coverageProvider?.generateCoverage) {
470
- // Capture coverage root directory from config (default is 'coverage' in cwd)
471
- try {
472
- const coverageConfig = this.ctx.config?.coverage
473
- const reportsDirectory = coverageConfig?.reportsDirectory || 'coverage'
474
- const rootDir = this.ctx.config?.root || process.cwd()
475
- coverageRootDir = path.isAbsolute(reportsDirectory) ? reportsDirectory : path.join(rootDir, reportsDirectory)
476
- } catch {
477
- // Fallback to cwd if we can't get config
478
- coverageRootDir = process.cwd()
479
- }
518
+ if (isDiEnabled) {
519
+ setProvidedContext(ctx, {
520
+ _ddIsDiEnabled: isDiEnabled,
521
+ }, 'Could not send Dynamic Instrumentation configuration to workers.')
522
+ }
480
523
 
481
- shimmer.wrap(this.ctx.coverageProvider, 'generateCoverage', generateCoverage => async function () {
482
- const totalCodeCoverage = await generateCoverage.apply(this, arguments)
524
+ if (isTestManagementTestsEnabled) {
525
+ const { err, testManagementTests: receivedTestManagementTests } =
526
+ testManagementTestsResponse || await getChannelPromise(testManagementTestsCh)
527
+ if (err) {
528
+ isTestManagementTestsEnabled = false
529
+ log.error('Could not get test management tests.')
530
+ } else {
531
+ setProvidedContext(ctx, {
532
+ _ddIsTestManagementTestsEnabled: isTestManagementTestsEnabled,
533
+ _ddTestManagementAttemptToFixRetries: testManagementAttemptToFixRetries,
534
+ _ddTestManagementTests: receivedTestManagementTests,
535
+ }, 'Could not send test management tests to workers so Test Management will not work.')
536
+ }
537
+ }
483
538
 
484
- try {
485
- testCodeCoverageLinesTotal = totalCodeCoverage.getCoverageSummary().lines.pct
486
- } catch {
487
- // ignore errors
488
- }
489
- return totalCodeCoverage
490
- })
539
+ if (isImpactedTestsEnabled) {
540
+ const { err, modifiedFiles } = await getChannelPromise(modifiedFilesCh)
541
+ if (err) {
542
+ log.error('Could not get modified tests.')
543
+ } else {
544
+ setProvidedContext(ctx, {
545
+ _ddIsImpactedTestsEnabled: isImpactedTestsEnabled,
546
+ _ddModifiedFiles: modifiedFiles,
547
+ }, 'Could not send modified tests to workers so Impacted Tests will not work.')
491
548
  }
549
+ }
492
550
 
493
- shimmer.wrap(this.ctx, 'exit', getFinishWrapper)
494
- shimmer.wrap(this.ctx, 'close', getFinishWrapper)
551
+ wrapCoverageProvider(ctx)
552
+ wrapSessionFinish(ctx)
553
+ }
495
554
 
555
+ function ensureMainProcessSetup (ctx, frameworkVersion, testSpecifications) {
556
+ let setupPromise = mainProcessSetupPromises.get(ctx)
557
+ if (!setupPromise) {
558
+ setupPromise = runMainProcessSetup(ctx, frameworkVersion, testSpecifications)
559
+ mainProcessSetupPromises.set(ctx, setupPromise)
560
+ }
561
+ return setupPromise
562
+ }
563
+
564
+ function getSortWrapper (sort, frameworkVersion) {
565
+ return async function () {
566
+ await ensureMainProcessSetup(this.ctx, frameworkVersion, arguments[0])
496
567
  return sort.apply(this, arguments)
497
568
  }
498
569
  }
@@ -504,6 +575,11 @@ function getFinishWrapper (exitOrClose) {
504
575
  return exitOrClose.apply(this, arguments)
505
576
  }
506
577
  isClosed = true
578
+
579
+ if (!testSessionFinishCh.hasSubscribers) {
580
+ return exitOrClose.apply(this, arguments)
581
+ }
582
+
507
583
  let onFinish
508
584
 
509
585
  const flushPromise = new Promise(resolve => {
@@ -555,6 +631,17 @@ function getCliOrStartVitestWrapper (frameworkVersion) {
555
631
  }
556
632
  }
557
633
 
634
+ function wrapVitestRunFiles (Vitest, frameworkVersion) {
635
+ if (!Vitest?.prototype?.runFiles) {
636
+ return
637
+ }
638
+
639
+ shimmer.wrap(Vitest.prototype, 'runFiles', runFiles => async function (testSpecifications) {
640
+ await ensureMainProcessSetup(this, frameworkVersion, testSpecifications)
641
+ return runFiles.apply(this, arguments)
642
+ })
643
+ }
644
+
558
645
  function getCreateCliWrapper (vitestPackage, frameworkVersion) {
559
646
  const createCliExport = findExportByName(vitestPackage, 'createCLI')
560
647
  if (!createCliExport) {
@@ -658,6 +745,11 @@ function getStartVitestWrapper (cliApiPackage, frameworkVersion) {
658
745
  const startVitestExport = findExportByName(cliApiPackage, 'startVitest')
659
746
  shimmer.wrap(cliApiPackage, startVitestExport.key, getCliOrStartVitestWrapper(frameworkVersion))
660
747
 
748
+ const vitest = getVitestExport(cliApiPackage)
749
+ if (vitest) {
750
+ wrapVitestRunFiles(vitest.value, frameworkVersion)
751
+ }
752
+
661
753
  const forksPoolWorker = getForksPoolWorkerExport(cliApiPackage)
662
754
  if (forksPoolWorker) {
663
755
  // function is async
@@ -921,7 +1013,6 @@ function wrapVitestTestRunner (VitestTestRunner) {
921
1013
  // Here we finish the earlier iteration,
922
1014
  // as long as it's not the _last_ iteration (which will be finished normally)
923
1015
 
924
- // TODO: check test duration (not to repeat if it's too slow)
925
1016
  const ctx = taskToCtx.get(task)
926
1017
  if (ctx) {
927
1018
  if (lastExecutionStatus === 'fail') {
@@ -1269,8 +1360,15 @@ addHook({
1269
1360
  }
1270
1361
  // From >=3.0.1, the first arguments changes from a string to an object containing the filepath
1271
1362
  const testSuiteAbsolutePath = testPaths[0]?.filepath || testPaths[0]
1272
-
1273
- const testSuiteCtx = { testSuiteAbsolutePath, frameworkVersion }
1363
+ const providedContext = getProvidedContext()
1364
+
1365
+ const testSuiteCtx = {
1366
+ testSuiteAbsolutePath,
1367
+ frameworkVersion,
1368
+ testSessionId: providedContext.testSessionId,
1369
+ testModuleId: providedContext.testModuleId,
1370
+ testCommand: providedContext.testCommand,
1371
+ }
1274
1372
  testSuiteStartCh.runStores(testSuiteCtx, () => {})
1275
1373
  const startTestsResponse = await startTests.apply(this, arguments)
1276
1374
 
@@ -1288,7 +1386,6 @@ addHook({
1288
1386
  // We have to trick vitest into thinking that the test has passed
1289
1387
  // but we want to report it as failed if it did fail
1290
1388
  const isSwitchedStatus = switchedStatuses.has(task)
1291
- const providedContext = getProvidedContext()
1292
1389
 
1293
1390
  if (result) {
1294
1391
  const { state, duration, errors } = result
@@ -2,8 +2,7 @@
2
2
 
3
3
  const { storage } = require('../../../datadog-core')
4
4
  const ApolloBasePlugin = require('../../../dd-trace/src/plugins/apollo')
5
-
6
- let tools
5
+ const { getSignature } = require('../../../datadog-plugin-graphql/src/utils')
7
6
 
8
7
  const OPERATION_DEFINITION = 'OperationDefinition'
9
8
  const FRAGMENT_DEFINITION = 'FragmentDefinition'
@@ -100,23 +99,4 @@ function buildOperationContext (schema, operationDocument, operationName) {
100
99
  }
101
100
  }
102
101
 
103
- function getSignature (document, operationName, operationType, calculate) {
104
- if (calculate !== false && tools !== false) {
105
- try {
106
- try {
107
- tools = tools || require('../../../datadog-plugin-graphql/src/tools')
108
- } catch (e) {
109
- tools = false
110
- throw e
111
- }
112
-
113
- return tools.defaultEngineReportingSignature(document, operationName)
114
- } catch {
115
- // safety net
116
- }
117
- }
118
-
119
- return [operationType, operationName].filter(Boolean).join(' ')
120
- }
121
-
122
102
  module.exports = ApolloGatewayRequestPlugin