dd-trace 6.6.0 → 6.8.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 (209) hide show
  1. package/ci/diagnose.js +162 -21
  2. package/ci/init.js +0 -1
  3. package/ci/runbook.md +187 -180
  4. package/ci/test-optimization-validation/approval-artifacts.js +3 -1
  5. package/ci/test-optimization-validation/approval.js +52 -15
  6. package/ci/test-optimization-validation/ci-command-candidate.js +26 -32
  7. package/ci/test-optimization-validation/ci-discovery.js +1 -1
  8. package/ci/test-optimization-validation/ci-package-scripts.js +141 -0
  9. package/ci/test-optimization-validation/ci-remediation.js +112 -39
  10. package/ci/test-optimization-validation/cli.js +516 -681
  11. package/ci/test-optimization-validation/command-blocker.js +188 -33
  12. package/ci/test-optimization-validation/command-output-policy.js +8 -31
  13. package/ci/test-optimization-validation/command-runner.js +189 -245
  14. package/ci/test-optimization-validation/environment.js +90 -0
  15. package/ci/test-optimization-validation/executable.js +159 -388
  16. package/ci/test-optimization-validation/framework-adapters/cucumber.js +119 -0
  17. package/ci/test-optimization-validation/framework-adapters/cypress.js +107 -0
  18. package/ci/test-optimization-validation/framework-adapters/playwright.js +181 -0
  19. package/ci/test-optimization-validation/generated-files.js +84 -22
  20. package/ci/test-optimization-validation/generated-test-contract.js +281 -0
  21. package/ci/test-optimization-validation/generated-verifier.js +49 -16
  22. package/ci/test-optimization-validation/literal-environment.js +57 -0
  23. package/ci/test-optimization-validation/manifest-loader.js +2 -22
  24. package/ci/test-optimization-validation/manifest-scaffold.js +815 -515
  25. package/ci/test-optimization-validation/manifest-schema.js +494 -702
  26. package/ci/test-optimization-validation/offline-fixtures.js +4 -1
  27. package/ci/test-optimization-validation/offline-output.js +6 -6
  28. package/ci/test-optimization-validation/plan-writer.js +243 -984
  29. package/ci/test-optimization-validation/preflight-runner.js +49 -55
  30. package/ci/test-optimization-validation/redaction.js +2 -1
  31. package/ci/test-optimization-validation/report-writer.js +391 -1357
  32. package/ci/test-optimization-validation/result-semantics.js +86 -0
  33. package/ci/test-optimization-validation/runner-command.js +249 -0
  34. package/ci/test-optimization-validation/runner-contract.js +664 -0
  35. package/ci/test-optimization-validation/safe-files.js +4 -4
  36. package/ci/test-optimization-validation/scenarios/auto-test-retries.js +29 -3
  37. package/ci/test-optimization-validation/scenarios/basic-reporting.js +240 -543
  38. package/ci/test-optimization-validation/scenarios/ci-wiring.js +450 -670
  39. package/ci/test-optimization-validation/scenarios/early-flake-detection.js +4 -3
  40. package/ci/test-optimization-validation/scenarios/helpers.js +67 -9
  41. package/ci/test-optimization-validation/scenarios/test-management.js +6 -5
  42. package/ci/test-optimization-validation/source-text.js +87 -0
  43. package/ci/test-optimization-validation/test-output.js +12 -22
  44. package/ci/vitest-no-worker-init-setup.mjs +348 -51
  45. package/ext/tags.d.ts +1 -0
  46. package/index.d.ts +84 -13
  47. package/package.json +10 -4
  48. package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
  49. package/packages/datadog-esbuild/index.js +4 -2
  50. package/packages/datadog-esbuild/src/utils.js +1 -1
  51. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +4 -4
  52. package/packages/datadog-instrumentations/src/cucumber.js +9 -6
  53. package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
  54. package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
  55. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
  56. package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
  57. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +1 -0
  58. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
  59. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/openai-agents.js +31 -0
  60. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +57 -0
  61. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
  62. package/packages/datadog-instrumentations/src/helpers/router-helper.js +1 -1
  63. package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
  64. package/packages/datadog-instrumentations/src/http/client.js +1 -3
  65. package/packages/datadog-instrumentations/src/jest.js +8 -14
  66. package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
  67. package/packages/datadog-instrumentations/src/mocha/main.js +2 -42
  68. package/packages/datadog-instrumentations/src/mocha/utils.js +68 -2
  69. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +19 -0
  70. package/packages/datadog-instrumentations/src/mocha/worker.js +446 -42
  71. package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
  72. package/packages/datadog-instrumentations/src/openai-agents.js +159 -0
  73. package/packages/datadog-instrumentations/src/playwright.js +3 -2
  74. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  75. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +525 -56
  76. package/packages/datadog-instrumentations/src/vitest-main.js +90 -10
  77. package/packages/datadog-instrumentations/src/webdriverio.js +914 -0
  78. package/packages/datadog-plugin-aerospike/src/index.js +1 -3
  79. package/packages/datadog-plugin-amqplib/src/client.js +1 -1
  80. package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
  81. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  82. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
  83. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
  84. package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
  85. package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
  86. package/packages/datadog-plugin-child_process/src/index.js +3 -3
  87. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +5 -8
  88. package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
  89. package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
  90. package/packages/datadog-plugin-fs/src/index.js +0 -4
  91. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
  92. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
  93. package/packages/datadog-plugin-graphql/src/execute.js +1 -0
  94. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
  95. package/packages/datadog-plugin-http/src/client.js +2 -1
  96. package/packages/datadog-plugin-jest/src/index.js +2 -3
  97. package/packages/datadog-plugin-jest/src/util.js +2 -1
  98. package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
  99. package/packages/datadog-plugin-mocha/src/index.js +25 -6
  100. package/packages/datadog-plugin-openai-agents/src/index.js +74 -0
  101. package/packages/datadog-plugin-openai-agents/src/integration.js +503 -0
  102. package/packages/datadog-plugin-openai-agents/src/processor.js +108 -0
  103. package/packages/datadog-plugin-openai-agents/src/util.js +60 -0
  104. package/packages/datadog-plugin-prisma/src/index.js +5 -1
  105. package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
  106. package/packages/datadog-plugin-rhea/src/producer.js +1 -1
  107. package/packages/datadog-plugin-undici/src/index.js +2 -1
  108. package/packages/datadog-plugin-vitest/src/index.js +84 -11
  109. package/packages/datadog-webpack/index.js +2 -2
  110. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
  111. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
  112. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
  113. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  114. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
  115. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
  116. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
  117. package/packages/dd-trace/src/appsec/sdk/track_event.js +1 -1
  118. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  119. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
  120. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +50 -51
  121. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -1
  122. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +4 -0
  123. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
  124. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
  125. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +161 -33
  126. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
  127. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +7 -5
  128. package/packages/dd-trace/src/config/defaults.js +14 -6
  129. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
  130. package/packages/dd-trace/src/config/index.js +15 -0
  131. package/packages/dd-trace/src/config/parsers.js +19 -1
  132. package/packages/dd-trace/src/config/supported-configurations.json +12 -6
  133. package/packages/dd-trace/src/datastreams/encoding.js +3 -4
  134. package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
  135. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
  136. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
  137. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
  138. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
  139. package/packages/dd-trace/src/encode/span-stats.js +7 -1
  140. package/packages/dd-trace/src/encode/tags-processors.js +2 -2
  141. package/packages/dd-trace/src/exporter.js +16 -9
  142. package/packages/dd-trace/src/exporters/common/url.js +3 -5
  143. package/packages/dd-trace/src/exporters/electron/index.js +4 -1
  144. package/packages/dd-trace/src/external-logger/src/index.js +1 -2
  145. package/packages/dd-trace/src/flare/index.js +2 -2
  146. package/packages/dd-trace/src/id.js +1 -1
  147. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
  148. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
  149. package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
  150. package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
  151. package/packages/dd-trace/src/llmobs/experiments/index.js +51 -12
  152. package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
  153. package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
  154. package/packages/dd-trace/src/llmobs/experiments/util.js +218 -0
  155. package/packages/dd-trace/src/llmobs/index.js +9 -1
  156. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +104 -22
  157. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
  158. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
  159. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
  160. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
  161. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +5 -9
  162. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +20 -0
  163. package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +321 -0
  164. package/packages/dd-trace/src/llmobs/sdk.js +6 -12
  165. package/packages/dd-trace/src/llmobs/span_processor.js +14 -7
  166. package/packages/dd-trace/src/llmobs/tagger.js +24 -5
  167. package/packages/dd-trace/src/llmobs/util.js +56 -3
  168. package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
  169. package/packages/dd-trace/src/noop/proxy.js +2 -2
  170. package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +3 -6
  171. package/packages/dd-trace/src/openfeature/configuration_source.js +5 -8
  172. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +5 -1
  173. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
  174. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
  175. package/packages/dd-trace/src/opentracing/span.js +1 -1
  176. package/packages/dd-trace/src/opentracing/span_context.js +1 -1
  177. package/packages/dd-trace/src/plugins/ci_plugin.js +114 -23
  178. package/packages/dd-trace/src/plugins/index.js +2 -0
  179. package/packages/dd-trace/src/plugins/outbound.js +4 -1
  180. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  181. package/packages/dd-trace/src/plugins/tracing.js +1 -0
  182. package/packages/dd-trace/src/plugins/util/ci.js +7 -6
  183. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  184. package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +1 -1
  185. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  186. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  187. package/packages/dd-trace/src/plugins/util/test.js +38 -12
  188. package/packages/dd-trace/src/plugins/util/url.js +5 -5
  189. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
  190. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  191. package/packages/dd-trace/src/priority_sampler.js +6 -3
  192. package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
  193. package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
  194. package/packages/dd-trace/src/ritm.js +5 -20
  195. package/packages/dd-trace/src/span_processor.js +1 -1
  196. package/packages/dd-trace/src/span_stats.js +22 -4
  197. package/packages/dd-trace/src/startup-log.js +3 -0
  198. package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
  199. package/packages/dd-trace/src/util.js +16 -0
  200. package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
  201. package/vendor/dist/pprof-format/index.js +1 -1
  202. package/vendor/dist/source-map/index.js +1 -1
  203. package/ci/test-optimization-validation/command-suitability.js +0 -471
  204. package/ci/test-optimization-validation/init-probe-preload.js +0 -163
  205. package/ci/test-optimization-validation/init-probe.js +0 -246
  206. package/ci/test-optimization-validation/late-initialization.js +0 -63
  207. package/ci/test-optimization-validation/local-command.js +0 -163
  208. package/ci/test-optimization-validation/setup-runner.js +0 -97
  209. package/ci/test-optimization-validation-manifest.schema.json +0 -1
@@ -15,12 +15,27 @@ class RheaConsumerPlugin extends ConsumerPlugin {
15
15
  })
16
16
  }
17
17
 
18
+ start (ctx) {
19
+ if (!this.config.dsmEnabled) return
20
+ const { msgObj } = ctx
21
+ if (!msgObj?.message?.delivery_annotations) return
22
+
23
+ const { span } = ctx.currentStore
24
+ const name = getResourceNameFromMessage(msgObj)
25
+ const payloadSize = getAmqpMessageSize(
26
+ { headers: msgObj.message.delivery_annotations, content: msgObj.message.body }
27
+ )
28
+ this.tracer.decodeDataStreamsContext(msgObj.message.delivery_annotations)
29
+ this.tracer
30
+ .setCheckpoint(['direction:in', `topic:${name}`, 'type:rabbitmq'], span, payloadSize)
31
+ }
32
+
18
33
  bindStart (ctx) {
19
34
  const { msgObj } = ctx
20
35
  const name = getResourceNameFromMessage(msgObj)
21
36
  const childOf = extractTextMap(msgObj, this.tracer)
22
37
 
23
- const span = this.startSpan({
38
+ this.startSpan({
24
39
  childOf,
25
40
  resource: name,
26
41
  type: 'worker',
@@ -31,18 +46,6 @@ class RheaConsumerPlugin extends ConsumerPlugin {
31
46
  },
32
47
  }, ctx)
33
48
 
34
- if (
35
- this.config.dsmEnabled &&
36
- msgObj?.message?.delivery_annotations
37
- ) {
38
- const payloadSize = getAmqpMessageSize(
39
- { headers: msgObj.message.delivery_annotations, content: msgObj.message.body }
40
- )
41
- this.tracer.decodeDataStreamsContext(msgObj.message.delivery_annotations)
42
- this.tracer
43
- .setCheckpoint(['direction:in', `topic:${name}`, 'type:rabbitmq'], span, payloadSize)
44
- }
45
-
46
49
  return ctx.currentStore
47
50
  }
48
51
  }
@@ -37,7 +37,7 @@ class RheaProducerPlugin extends ProducerPlugin {
37
37
 
38
38
  function addDeliveryAnnotations (msg, tracer, span) {
39
39
  if (msg) {
40
- msg.delivery_annotations = msg.delivery_annotations || {}
40
+ msg.delivery_annotations ||= {}
41
41
 
42
42
  tracer.inject(span, 'text_map', msg.delivery_annotations)
43
43
 
@@ -7,6 +7,7 @@ const formats = require('../../../ext/formats')
7
7
  const HTTP_HEADERS = formats.HTTP_HEADERS
8
8
  const log = require('../../dd-trace/src/log')
9
9
  const { buildClientHttpUrl } = require('../../dd-trace/src/plugins/util/url')
10
+ const { stripQueryAndFragment } = require('../../dd-trace/src/util')
10
11
  const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
11
12
 
12
13
  const {
@@ -62,7 +63,7 @@ class UndiciPlugin extends HttpClientPlugin {
62
63
 
63
64
  const host = port ? `${hostname}:${port}` : hostname
64
65
  const base = `${protocol}//${host}`
65
- const pathname = path.split(/[?#]/)[0]
66
+ const pathname = stripQueryAndFragment(path)
66
67
  const uri = `${base}${pathname}`
67
68
 
68
69
  const allowed = this.config.filter(uri)
@@ -5,6 +5,7 @@ const { storage } = require('../../datadog-core')
5
5
 
6
6
  const {
7
7
  TEST_STATUS,
8
+ TEST_TYPE,
8
9
  VITEST_POOL,
9
10
  finishAllTraceSpans,
10
11
  getTestSuitePath,
@@ -36,6 +37,10 @@ const {
36
37
  TEST_HAS_DYNAMIC_NAME,
37
38
  TEST_FINAL_STATUS,
38
39
  TEST_IS_TEST_FRAMEWORK_WORKER,
40
+ TEST_BROWSER_DRIVER,
41
+ TEST_BROWSER_NAME,
42
+ TEST_IS_RUM_ACTIVE,
43
+ TEST_PARAMETERS,
39
44
  } = require('../../dd-trace/src/plugins/util/test')
40
45
  const { COMPONENT } = require('../../dd-trace/src/constants')
41
46
  const {
@@ -50,6 +55,28 @@ const { DD_MAJOR } = require('../../../version')
50
55
  // This is because there's some loss of resolution.
51
56
  const MILLISECONDS_TO_SUBTRACT_FROM_FAILED_TEST_DURATION = 5
52
57
 
58
+ function setBrowserTags (tags, browserEnvironment, includeParameters) {
59
+ if (!browserEnvironment.isBrowserMode) return
60
+
61
+ tags[TEST_TYPE] = 'browser'
62
+ if (browserEnvironment.browserDriver) {
63
+ tags[TEST_BROWSER_DRIVER] = browserEnvironment.browserDriver
64
+ }
65
+ if (browserEnvironment.browserName) {
66
+ tags[TEST_BROWSER_NAME] = browserEnvironment.browserName
67
+ }
68
+ if (includeParameters && (browserEnvironment.browserName || browserEnvironment.browserProjectName)) {
69
+ const parameters = {}
70
+ if (browserEnvironment.browserName) {
71
+ parameters.browser = browserEnvironment.browserName
72
+ }
73
+ if (browserEnvironment.browserProjectName) {
74
+ parameters.project = browserEnvironment.browserProjectName
75
+ }
76
+ tags[TEST_PARAMETERS] = JSON.stringify({ arguments: parameters, metadata: {} })
77
+ }
78
+ }
79
+
53
80
  class VitestPlugin extends CiPlugin {
54
81
  static id = 'vitest'
55
82
 
@@ -100,6 +127,14 @@ class VitestPlugin extends CiPlugin {
100
127
  isModified,
101
128
  isTestFrameworkWorker,
102
129
  requestErrorTags,
130
+ isBrowserMode,
131
+ browserDriver,
132
+ browserName,
133
+ browserProjectName,
134
+ isRumActive,
135
+ testExecutionId,
136
+ testStartLine,
137
+ startTime,
103
138
  } = ctx
104
139
 
105
140
  const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
@@ -109,6 +144,7 @@ class VitestPlugin extends CiPlugin {
109
144
  const extraTags = {
110
145
  ...requestErrorTags,
111
146
  [TEST_SOURCE_FILE]: testSuite,
147
+ [TEST_SOURCE_START]: testStartLine || 1,
112
148
  }
113
149
  if (isRetry) {
114
150
  extraTags[TEST_IS_RETRY] = 'true'
@@ -143,12 +179,23 @@ class VitestPlugin extends CiPlugin {
143
179
  if (isTestFrameworkWorker) {
144
180
  extraTags[TEST_IS_TEST_FRAMEWORK_WORKER] = 'true'
145
181
  }
182
+ if (isRumActive) {
183
+ extraTags[TEST_IS_RUM_ACTIVE] = 'true'
184
+ }
185
+ setBrowserTags(extraTags, {
186
+ browserDriver,
187
+ browserName,
188
+ browserProjectName,
189
+ isBrowserMode,
190
+ }, true)
146
191
 
147
192
  const span = this.startTestSpan(
148
193
  testName,
149
194
  testSuite,
150
195
  testSuiteSpan,
151
- extraTags
196
+ extraTags,
197
+ testExecutionId,
198
+ startTime
152
199
  )
153
200
 
154
201
  ctx.parentStore = store
@@ -297,25 +344,41 @@ class VitestPlugin extends CiPlugin {
297
344
  testSuiteAbsolutePath,
298
345
  isNew,
299
346
  isDisabled,
347
+ isRumActive,
300
348
  isTestFrameworkWorker,
301
349
  requestErrorTags,
302
350
  testSuiteSpan,
351
+ isBrowserMode,
352
+ browserDriver,
353
+ browserName,
354
+ browserProjectName,
355
+ testExecutionId,
356
+ testStartLine,
303
357
  }) => {
304
358
  const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot)
359
+ const extraTags = {
360
+ ...requestErrorTags,
361
+ [TEST_SOURCE_FILE]: testSuite,
362
+ [TEST_SOURCE_START]: testStartLine || 1,
363
+ [TEST_STATUS]: 'skip',
364
+ [TEST_FINAL_STATUS]: 'skip',
365
+ ...(isDisabled ? { [TEST_MANAGEMENT_IS_DISABLED]: 'true' } : {}),
366
+ ...(isNew ? { [TEST_IS_NEW]: 'true' } : {}),
367
+ ...(isRumActive ? { [TEST_IS_RUM_ACTIVE]: 'true' } : {}),
368
+ ...(isTestFrameworkWorker ? { [TEST_IS_TEST_FRAMEWORK_WORKER]: 'true' } : {}),
369
+ }
370
+ setBrowserTags(extraTags, {
371
+ browserDriver,
372
+ browserName,
373
+ browserProjectName,
374
+ isBrowserMode,
375
+ }, true)
305
376
  const testSpan = this.startTestSpan(
306
377
  testName,
307
378
  testSuite,
308
379
  testSuiteSpan || this.testSuiteSpan,
309
- {
310
- ...requestErrorTags,
311
- [TEST_SOURCE_FILE]: testSuite,
312
- [TEST_SOURCE_START]: 1, // we can't get the proper start line in vitest
313
- [TEST_STATUS]: 'skip',
314
- [TEST_FINAL_STATUS]: 'skip',
315
- ...(isDisabled ? { [TEST_MANAGEMENT_IS_DISABLED]: 'true' } : {}),
316
- ...(isNew ? { [TEST_IS_NEW]: 'true' } : {}),
317
- ...(isTestFrameworkWorker ? { [TEST_IS_TEST_FRAMEWORK_WORKER]: 'true' } : {}),
318
- }
380
+ extraTags,
381
+ testExecutionId
319
382
  )
320
383
  this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'test', this.getTestTelemetryTags(testSpan))
321
384
  testSpan.finish()
@@ -330,6 +393,10 @@ class VitestPlugin extends CiPlugin {
330
393
  frameworkVersion,
331
394
  isTestFrameworkWorker,
332
395
  isVitestNoWorkerInitActive,
396
+ isBrowserMode,
397
+ browserDriver,
398
+ browserName,
399
+ browserProjectName,
333
400
  } = ctx
334
401
 
335
402
  const testCommand = ctx.testCommand || 'vitest run'
@@ -377,6 +444,12 @@ class VitestPlugin extends CiPlugin {
377
444
  if (isTestFrameworkWorker) {
378
445
  testSuiteMetadata[TEST_IS_TEST_FRAMEWORK_WORKER] = 'true'
379
446
  }
447
+ setBrowserTags(testSuiteMetadata, {
448
+ browserDriver,
449
+ browserName,
450
+ browserProjectName,
451
+ isBrowserMode,
452
+ }, false)
380
453
 
381
454
  const codeOwners = this.getCodeOwners(testSuiteMetadata)
382
455
  if (codeOwners) {
@@ -141,7 +141,7 @@ class DatadogWebpackPlugin {
141
141
  // (#8980); absent peers stay opaque, so a build that does not opt into the feature does
142
142
  // not follow their dependency chain (#8635).
143
143
  if (matchesOptionalPeerFile(normalizedResource)) {
144
- createData.loaders = createData.loaders || []
144
+ createData.loaders ||= []
145
145
  createData.loaders.push({ loader: require.resolve('./src/optional-peer-loader') })
146
146
  log.debug('INLINE: optional-peer loader applied to %s', normalizedResource)
147
147
  return
@@ -188,7 +188,7 @@ class DatadogWebpackPlugin {
188
188
  const version = packageJson.version
189
189
  const pkgPath = request === pkg ? pkg : `${pkg}/${modulePath}`
190
190
 
191
- createData.loaders = createData.loaders || []
191
+ createData.loaders ||= []
192
192
  createData.loaders.unshift({
193
193
  loader: require.resolve('./src/loader'),
194
194
  options: { pkg, version, path: pkgPath },
@@ -307,7 +307,7 @@ function parseBody (body, contentType) {
307
307
  const formBody = Buffer.isBuffer(body) ? body.toString('utf8') : String(body)
308
308
  const params = new URLSearchParams(formBody)
309
309
  const result = {}
310
- for (const [key, value] of params.entries()) {
310
+ for (const [key, value] of params) {
311
311
  if (key in result) {
312
312
  const existing = result[key]
313
313
  if (Array.isArray(existing)) {
@@ -56,7 +56,7 @@ class HardcodedBaseAnalyzer extends Analyzer {
56
56
  }
57
57
 
58
58
  _getEvidence (value) {
59
- return { value: `${value.data}` }
59
+ return { value: value.data }
60
60
  }
61
61
 
62
62
  _getLocation (value) {
@@ -11,7 +11,7 @@ class HardcodedPasswordAnalyzer extends HardcodedBaseAnalyzer {
11
11
  }
12
12
 
13
13
  _getEvidence (value) {
14
- return { value: `${value.ident}` }
14
+ return { value: value.ident }
15
15
  }
16
16
  }
17
17
 
@@ -74,7 +74,7 @@ class SqlInjectionAnalyzer extends StoredInjectionAnalyzer {
74
74
  }
75
75
 
76
76
  analyze (value, store, dialect) {
77
- store = store || storage('legacy').getStore()
77
+ store ||= storage('legacy').getStore()
78
78
  if (!(store && store.sqlAnalyzed)) {
79
79
  super.analyze(value, store, dialect)
80
80
  }
@@ -215,9 +215,7 @@ function getTaintTrackingImpl (telemetryVerbosity, dummy = false) {
215
215
  if (dummy) return TaintTrackingNoop
216
216
 
217
217
  // with Verbosity.DEBUG every invocation of a TaintedUtils method increases the EXECUTED_PROPAGATION metric
218
- return isDebugAllowed(telemetryVerbosity)
219
- ? createImplWith(getContextDebug)
220
- : createImplWith(getContextDefault)
218
+ return createImplWith(isDebugAllowed(telemetryVerbosity) ? getContextDebug : getContextDefault)
221
219
  }
222
220
 
223
221
  function getTaintTrackingNoop () {
@@ -35,7 +35,7 @@ function stringifyWithRanges (obj, objRanges, loadSensitiveRanges = false) {
35
35
  let value
36
36
  const ranges = []
37
37
  const sensitiveRanges = []
38
- objRanges = objRanges || {}
38
+ objRanges ||= {}
39
39
 
40
40
  if (objRanges || loadSensitiveRanges) {
41
41
  const cloneObj = Array.isArray(obj) ? [] : {}
@@ -21,7 +21,7 @@ let stackTraceMaxDepth
21
21
  let maxStackTraces
22
22
 
23
23
  function canAddVulnerability (vulnerability) {
24
- const hasRequiredFields = vulnerability?.evidence && vulnerability?.type && vulnerability?.location
24
+ const hasRequiredFields = vulnerability?.evidence && vulnerability.type && vulnerability.location
25
25
  if (!hasRequiredFields) return false
26
26
 
27
27
  const isDuplicated = deduplicationEnabled && isDuplicatedVulnerability(vulnerability)
@@ -64,7 +64,7 @@ function addVulnerability (iastContext, vulnerability, callSiteFrames) {
64
64
  }
65
65
 
66
66
  if (iastContext?.rootSpan) {
67
- iastContext[VULNERABILITIES_KEY] = iastContext[VULNERABILITIES_KEY] || []
67
+ iastContext[VULNERABILITIES_KEY] ||= []
68
68
  iastContext[VULNERABILITIES_KEY].push(vulnerability)
69
69
  } else {
70
70
  sendVulnerabilities([vulnerability], span)
@@ -160,7 +160,7 @@ function flattenFields (fields, depth = 0) {
160
160
 
161
161
  if (value && typeof value === 'object') {
162
162
  const { result: flatValue, truncated: inheritTruncated } = flattenFields(value, depth + 1)
163
- truncated = truncated || inheritTruncated
163
+ truncated ||= inheritTruncated
164
164
 
165
165
  if (flatValue) {
166
166
  for (const flatKey of Object.keys(flatValue)) {
@@ -39,7 +39,7 @@ class WAFManager {
39
39
  const { obfuscatorKeyRegex, obfuscatorValueRegex } = this.config
40
40
  return new DDWAF(rules, WAFManager.defaultWafConfigPath, { obfuscatorKeyRegex, obfuscatorValueRegex })
41
41
  } catch (err) {
42
- this.ddwafVersion = this.ddwafVersion || 'unknown'
42
+ this.ddwafVersion ||= 'unknown'
43
43
  Reporter.reportWafInit(this.ddwafVersion, 'unknown')
44
44
 
45
45
  log.error('[ASM] AppSec could not load native package. In-app WAF features will not be available.', err)
@@ -303,10 +303,11 @@ function writeNewFile (filename, payload) {
303
303
  *
304
304
  * @param {string} directory directory path
305
305
  * @param {string} label directory label
306
- * @returns {{dev: number, ino: number}} stable directory identity
306
+ * @returns {{dev: bigint, ino: bigint}} stable directory identity
307
307
  */
308
308
  function captureDirectory (directory, label) {
309
- const stat = fs.lstatSync(directory)
309
+ // Windows file reference numbers exceed 2^53, where distinct directories round to one number.
310
+ const stat = fs.lstatSync(directory, { bigint: true })
310
311
  if (!stat.isDirectory() || stat.isSymbolicLink()) {
311
312
  throw new Error(`Offline Test Optimization validation ${label} must be a regular directory.`)
312
313
  }
@@ -317,10 +318,10 @@ function captureDirectory (directory, label) {
317
318
  * Creates or validates one child directory without accepting symbolic links.
318
319
  *
319
320
  * @param {string} parent parent directory path
320
- * @param {{dev: number, ino: number}} parentIdentity expected parent identity
321
+ * @param {{dev: bigint, ino: bigint}} parentIdentity expected parent identity
321
322
  * @param {string} directory child directory path
322
323
  * @param {string} label directory label
323
- * @returns {{dev: number, ino: number}} stable child identity
324
+ * @returns {{dev: bigint, ino: bigint}} stable child identity
324
325
  */
325
326
  function createDirectory (parent, parentIdentity, directory, label) {
326
327
  assertDirectoryUnchanged(parent, parentIdentity, 'parent output')
@@ -336,7 +337,7 @@ function createDirectory (parent, parentIdentity, directory, label) {
336
337
  * Rejects a directory that changed after sink construction.
337
338
  *
338
339
  * @param {string} directory directory path
339
- * @param {{dev: number, ino: number}} identity expected directory identity
340
+ * @param {{dev: bigint, ino: bigint}} identity expected directory identity
340
341
  * @param {string} label directory label
341
342
  */
342
343
  function assertDirectoryUnchanged (directory, identity, label) {
@@ -351,7 +352,7 @@ function assertDirectoryUnchanged (directory, identity, label) {
351
352
  *
352
353
  * @param {string} filename partial payload path
353
354
  * @param {string} directory expected parent directory
354
- * @param {{dev: number, ino: number}} identity expected parent identity
355
+ * @param {{dev: bigint, ino: bigint}} identity expected parent identity
355
356
  */
356
357
  function removePartialFile (filename, directory, identity) {
357
358
  try {
@@ -15,11 +15,13 @@ const { uploadCoverageReport: uploadCoverageReportRequest } = require('../reques
15
15
  const { uploadTestScreenshot: uploadTestScreenshotRequest } = require('../requests/upload-test-screenshot')
16
16
  const { parsers } = require('../../config/parsers')
17
17
  const log = require('../../log')
18
+ const { getSegment } = require('../../util')
18
19
  const BufferingExporter = require('../../exporters/common/buffering-exporter')
19
20
  const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../../plugins/util/tags')
20
21
  const { sendGitMetadata: sendGitMetadataRequest } = require('./git/git_metadata')
21
22
 
22
23
  const hostname = getHostname()
24
+ const EMPTY_SETTINGS = Object.freeze({})
23
25
 
24
26
  function getTestConfigurationTags (tags) {
25
27
  if (!tags) {
@@ -27,8 +29,7 @@ function getTestConfigurationTags (tags) {
27
29
  }
28
30
  return Object.keys(tags).reduce((acc, key) => {
29
31
  if (key.startsWith('test.configuration.')) {
30
- const [, configKey] = key.split('test.configuration.')
31
- acc[configKey] = tags[key]
32
+ acc[getSegment(key, 'test.configuration.', 1)] = tags[key]
32
33
  }
33
34
  return acc
34
35
  }, {})
@@ -308,60 +309,58 @@ class CiVisibilityExporter extends BufferingExporter {
308
309
  }
309
310
 
310
311
  // Takes into account potential kill switches
311
- filterConfiguration (remoteConfiguration) {
312
- if (!remoteConfiguration) {
313
- return {}
314
- }
312
+ filterConfiguration (remoteConfiguration = EMPTY_SETTINGS) {
313
+ const { testOptimization } = this._config
315
314
  const {
316
- isCodeCoverageEnabled,
317
- isSuitesSkippingEnabled,
318
- isItrEnabled,
319
- requireGit,
320
- isEarlyFlakeDetectionEnabled,
315
+ DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED: isEarlyFlakeDetectionAllowed,
316
+ DD_CIVISIBILITY_FLAKY_RETRY_COUNT: flakyTestRetriesCount = 0,
317
+ DD_CIVISIBILITY_FLAKY_RETRY_ENABLED: isFlakyTestRetriesAllowed,
318
+ DD_CIVISIBILITY_IMPACTED_TESTS_DETECTION_ENABLED: isImpactedTestsAllowed,
319
+ DD_TEST_EARLY_FLAKE_DETECTION_RETRY_COUNT: earlyFlakeDetectionRetryCount,
320
+ DD_TEST_FAILED_TEST_REPLAY_ENABLED: isFailedTestReplayAllowed,
321
+ DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES: configuredAttemptToFixRetries = 0,
322
+ DD_TEST_MANAGEMENT_ENABLED: isTestManagementAllowed,
323
+ } = testOptimization
324
+ const hasEarlyFlakeDetectionRetryCount = earlyFlakeDetectionRetryCount !== undefined
325
+ const configuredSlowTestRetries = remoteConfiguration.earlyFlakeDetectionSlowTestRetries ?? EMPTY_SETTINGS
326
+ const earlyFlakeDetectionSlowTestRetries = hasEarlyFlakeDetectionRetryCount
327
+ ? Object.freeze({
328
+ '5s': earlyFlakeDetectionRetryCount,
329
+ '10s': earlyFlakeDetectionRetryCount,
330
+ '30s': earlyFlakeDetectionRetryCount,
331
+ '5m': earlyFlakeDetectionRetryCount,
332
+ })
333
+ : Object.isFrozen(configuredSlowTestRetries)
334
+ ? configuredSlowTestRetries
335
+ : Object.freeze({ ...configuredSlowTestRetries })
336
+ const earlyFlakeDetectionNumRetries = hasEarlyFlakeDetectionRetryCount
337
+ ? earlyFlakeDetectionRetryCount
338
+ : remoteConfiguration.earlyFlakeDetectionNumRetries ?? 0
339
+ const testManagementAttemptToFixRetries =
340
+ remoteConfiguration.testManagementAttemptToFixRetries ?? configuredAttemptToFixRetries
341
+
342
+ return Object.freeze({
343
+ isCodeCoverageEnabled: remoteConfiguration.isCodeCoverageEnabled === true,
344
+ isSuitesSkippingEnabled: remoteConfiguration.isSuitesSkippingEnabled === true,
345
+ isItrEnabled: remoteConfiguration.isItrEnabled === true,
346
+ requireGit: remoteConfiguration.requireGit === true,
347
+ isEarlyFlakeDetectionEnabled:
348
+ remoteConfiguration.isEarlyFlakeDetectionEnabled === true && isEarlyFlakeDetectionAllowed === true,
321
349
  earlyFlakeDetectionNumRetries,
322
350
  earlyFlakeDetectionSlowTestRetries,
323
- earlyFlakeDetectionFaultyThreshold,
324
- isFlakyTestRetriesEnabled,
325
- isDiEnabled,
326
- isKnownTestsEnabled,
327
- isTestManagementEnabled,
351
+ earlyFlakeDetectionFaultyThreshold: remoteConfiguration.earlyFlakeDetectionFaultyThreshold ?? 30,
352
+ isFlakyTestRetriesEnabled:
353
+ remoteConfiguration.isFlakyTestRetriesEnabled === true && isFlakyTestRetriesAllowed === true,
354
+ flakyTestRetriesCount,
355
+ isDiEnabled: remoteConfiguration.isDiEnabled === true && isFailedTestReplayAllowed === true,
356
+ isKnownTestsEnabled: remoteConfiguration.isKnownTestsEnabled === true,
357
+ isTestManagementEnabled:
358
+ remoteConfiguration.isTestManagementEnabled === true && isTestManagementAllowed === true,
328
359
  testManagementAttemptToFixRetries,
329
- isImpactedTestsEnabled,
330
- isCoverageReportUploadEnabled,
331
- } = remoteConfiguration
332
- const { testOptimization } = this._config
333
- const earlyFlakeDetectionRetryCount =
334
- testOptimization.DD_TEST_EARLY_FLAKE_DETECTION_RETRY_COUNT
335
- const hasEarlyFlakeDetectionRetryCount = earlyFlakeDetectionRetryCount !== undefined
336
- return {
337
- isCodeCoverageEnabled,
338
- isSuitesSkippingEnabled,
339
- isItrEnabled,
340
- requireGit,
341
- isEarlyFlakeDetectionEnabled:
342
- isEarlyFlakeDetectionEnabled && testOptimization.DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED,
343
- earlyFlakeDetectionNumRetries:
344
- hasEarlyFlakeDetectionRetryCount ? earlyFlakeDetectionRetryCount : earlyFlakeDetectionNumRetries,
345
- earlyFlakeDetectionSlowTestRetries: hasEarlyFlakeDetectionRetryCount
346
- ? {
347
- '5s': earlyFlakeDetectionRetryCount,
348
- '10s': earlyFlakeDetectionRetryCount,
349
- '30s': earlyFlakeDetectionRetryCount,
350
- '5m': earlyFlakeDetectionRetryCount,
351
- }
352
- : earlyFlakeDetectionSlowTestRetries,
353
- earlyFlakeDetectionFaultyThreshold,
354
- isFlakyTestRetriesEnabled: isFlakyTestRetriesEnabled && testOptimization.DD_CIVISIBILITY_FLAKY_RETRY_ENABLED,
355
- flakyTestRetriesCount: testOptimization.DD_CIVISIBILITY_FLAKY_RETRY_COUNT,
356
- isDiEnabled: isDiEnabled && testOptimization.DD_TEST_FAILED_TEST_REPLAY_ENABLED,
357
- isKnownTestsEnabled,
358
- isTestManagementEnabled: isTestManagementEnabled && testOptimization.DD_TEST_MANAGEMENT_ENABLED,
359
- testManagementAttemptToFixRetries:
360
- testManagementAttemptToFixRetries ?? testOptimization.DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES,
361
360
  isImpactedTestsEnabled:
362
- isImpactedTestsEnabled && testOptimization.DD_CIVISIBILITY_IMPACTED_TESTS_DETECTION_ENABLED,
363
- isCoverageReportUploadEnabled,
364
- }
361
+ remoteConfiguration.isImpactedTestsEnabled === true && isImpactedTestsAllowed === true,
362
+ isCoverageReportUploadEnabled: remoteConfiguration.isCoverageReportUploadEnabled === true,
363
+ })
365
364
  }
366
365
 
367
366
  sendGitMetadata (repositoryUrl) {
@@ -8,6 +8,7 @@ const FormData = require('../../../exporters/common/form-data')
8
8
  const request = require('../../../exporters/common/request')
9
9
 
10
10
  const log = require('../../../log')
11
+ const { getSegment } = require('../../../util')
11
12
  const {
12
13
  getLatestCommits,
13
14
  getRepositoryUrl,
@@ -145,7 +146,7 @@ function uploadPackFile ({ url, isEvpProxy, evpProxyPrefix, packFileToUpload, re
145
146
  try {
146
147
  const packFileContent = fs.readFileSync(packFileToUpload)
147
148
  // The original filename includes a random prefix, so we remove it here
148
- const [, filename] = path.basename(packFileToUpload).split('-')
149
+ const filename = getSegment(path.basename(packFileToUpload), '-', 1)
149
150
  form.append('packfile', packFileContent, {
150
151
  filename,
151
152
  contentType: 'application/octet-stream',
@@ -5,6 +5,7 @@ const {
5
5
  JEST_WORKER_TRACE_PAYLOAD_CODE,
6
6
  JEST_WORKER_TELEMETRY_PAYLOAD_CODE,
7
7
  CUCUMBER_WORKER_TRACE_PAYLOAD_CODE,
8
+ MOCHA_WORKER_LOGS_PAYLOAD_CODE,
8
9
  MOCHA_WORKER_TRACE_PAYLOAD_CODE,
9
10
  JEST_WORKER_LOGS_PAYLOAD_CODE,
10
11
  PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE,
@@ -50,6 +51,9 @@ function getInterprocessLogsCode () {
50
51
  if (getEnvironmentVariable('JEST_WORKER_ID')) {
51
52
  return JEST_WORKER_LOGS_PAYLOAD_CODE
52
53
  }
54
+ if (getEnvironmentVariable('MOCHA_WORKER_ID') === 'webdriverio') {
55
+ return MOCHA_WORKER_LOGS_PAYLOAD_CODE
56
+ }
53
57
  if (getEnvironmentVariable('TINYPOOL_WORKER_ID')) {
54
58
  return VITEST_WORKER_LOGS_PAYLOAD_CODE
55
59
  }
@@ -0,0 +1,26 @@
1
+ 'use strict'
2
+
3
+ const WEBDRIVERIO_WORKER_ENV = '_DD_TEST_OPTIMIZATION_WEBDRIVERIO_WORKER'
4
+ const WEBDRIVERIO_WORKER_EVENT = 'workerEvent'
5
+ const WEBDRIVERIO_WORKER_ORIGIN = 'datadog'
6
+
7
+ /**
8
+ * Wraps an internal worker payload in the event WebdriverIO reserves for worker messages.
9
+ *
10
+ * @param {unknown} args
11
+ * @returns {{args: unknown, name: string, origin: string}}
12
+ */
13
+ function createWebdriverioWorkerMessage (args) {
14
+ return {
15
+ origin: WEBDRIVERIO_WORKER_ORIGIN,
16
+ name: WEBDRIVERIO_WORKER_EVENT,
17
+ args,
18
+ }
19
+ }
20
+
21
+ module.exports = {
22
+ createWebdriverioWorkerMessage,
23
+ WEBDRIVERIO_WORKER_ENV,
24
+ WEBDRIVERIO_WORKER_EVENT,
25
+ WEBDRIVERIO_WORKER_ORIGIN,
26
+ }
@@ -2,6 +2,10 @@
2
2
  const { JSONEncoder } = require('../../encode/json-encoder')
3
3
  const { getEnvironmentVariable } = require('../../../config/helper')
4
4
  const log = require('../../../log')
5
+ const {
6
+ createWebdriverioWorkerMessage,
7
+ WEBDRIVERIO_WORKER_ENV,
8
+ } = require('./webdriverio')
5
9
 
6
10
  function getVitestWorkerPort () {
7
11
  const port = globalThis.__vitest_worker__?.ctx?.port
@@ -13,6 +17,7 @@ class Writer {
13
17
  this._encoder = new JSONEncoder()
14
18
  // Code used to identify the type of payload being sent to the main process
15
19
  this._interprocessCode = interprocessCode
20
+ this._isWebdriverioWorker = !!getEnvironmentVariable(WEBDRIVERIO_WORKER_ENV)
16
21
  }
17
22
 
18
23
  /**
@@ -43,9 +48,12 @@ class Writer {
43
48
  // Old because vitest@>=4 uses `DD_VITEST_WORKER` and reports arrays just like other frameworks
44
49
  // Before vitest@>=4, we need the `__tinypool_worker_message__` property, or tinypool will crash
45
50
  const isVitestWorkerOld = !!getEnvironmentVariable('TINYPOOL_WORKER_ID')
46
- const payload = isVitestWorkerOld
51
+ let payload = isVitestWorkerOld
47
52
  ? { __tinypool_worker_message__: true, interprocessCode: this._interprocessCode, data }
48
53
  : [this._interprocessCode, data]
54
+ if (this._isWebdriverioWorker) {
55
+ payload = createWebdriverioWorkerMessage(payload)
56
+ }
49
57
 
50
58
  const vitestWorkerPort = getVitestWorkerPort()
51
59
  if (vitestWorkerPort) {