dd-trace 5.52.0 → 5.54.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 (332) hide show
  1. package/LICENSE-3rdparty.csv +2 -1
  2. package/README.md +5 -0
  3. package/index.d.ts +87 -22
  4. package/initialize.mjs +3 -4
  5. package/package.json +36 -34
  6. package/packages/datadog-core/src/utils/src/get.js +1 -1
  7. package/packages/datadog-core/src/utils/src/has.js +1 -1
  8. package/packages/datadog-core/src/utils/src/kebabcase.js +4 -6
  9. package/packages/datadog-core/src/utils/src/parse-tags.js +1 -1
  10. package/packages/datadog-core/src/utils/src/pick.js +2 -2
  11. package/packages/datadog-core/src/utils/src/set.js +1 -1
  12. package/packages/datadog-core/src/utils/src/uniq.js +1 -1
  13. package/packages/datadog-instrumentations/src/amqp10.js +19 -17
  14. package/packages/datadog-instrumentations/src/amqplib.js +57 -37
  15. package/packages/datadog-instrumentations/src/apollo.js +2 -2
  16. package/packages/datadog-instrumentations/src/aws-sdk.js +1 -1
  17. package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -4
  18. package/packages/datadog-instrumentations/src/child_process.js +3 -3
  19. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +92 -62
  20. package/packages/datadog-instrumentations/src/couchbase.js +5 -4
  21. package/packages/datadog-instrumentations/src/cucumber.js +126 -84
  22. package/packages/datadog-instrumentations/src/cypress.js +2 -1
  23. package/packages/datadog-instrumentations/src/dns.js +1 -1
  24. package/packages/datadog-instrumentations/src/express.js +2 -6
  25. package/packages/datadog-instrumentations/src/fs.js +7 -6
  26. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +28 -34
  27. package/packages/datadog-instrumentations/src/graphql.js +7 -10
  28. package/packages/datadog-instrumentations/src/grpc/client.js +11 -23
  29. package/packages/datadog-instrumentations/src/grpc/server.js +7 -20
  30. package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +16 -10
  31. package/packages/datadog-instrumentations/src/helpers/hook.js +1 -1
  32. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -1
  33. package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -41
  34. package/packages/datadog-instrumentations/src/helpers/register.js +21 -18
  35. package/packages/datadog-instrumentations/src/http/client.js +16 -21
  36. package/packages/datadog-instrumentations/src/iovalkey.js +51 -0
  37. package/packages/datadog-instrumentations/src/jest.js +184 -87
  38. package/packages/datadog-instrumentations/src/kafkajs.js +65 -44
  39. package/packages/datadog-instrumentations/src/knex.js +4 -4
  40. package/packages/datadog-instrumentations/src/ldapjs.js +3 -4
  41. package/packages/datadog-instrumentations/src/mariadb.js +38 -61
  42. package/packages/datadog-instrumentations/src/mocha/main.js +85 -59
  43. package/packages/datadog-instrumentations/src/mocha/utils.js +103 -82
  44. package/packages/datadog-instrumentations/src/mocha/worker.js +6 -0
  45. package/packages/datadog-instrumentations/src/mongodb-core.js +1 -1
  46. package/packages/datadog-instrumentations/src/mysql.js +20 -36
  47. package/packages/datadog-instrumentations/src/mysql2.js +55 -47
  48. package/packages/datadog-instrumentations/src/net.js +4 -2
  49. package/packages/datadog-instrumentations/src/next.js +7 -14
  50. package/packages/datadog-instrumentations/src/nyc.js +1 -1
  51. package/packages/datadog-instrumentations/src/openai.js +21 -23
  52. package/packages/datadog-instrumentations/src/oracledb.js +1 -1
  53. package/packages/datadog-instrumentations/src/pg.js +6 -13
  54. package/packages/datadog-instrumentations/src/playwright.js +170 -136
  55. package/packages/datadog-instrumentations/src/redis.js +3 -3
  56. package/packages/datadog-instrumentations/src/restify.js +2 -2
  57. package/packages/datadog-instrumentations/src/rhea.js +42 -54
  58. package/packages/datadog-instrumentations/src/router.js +22 -25
  59. package/packages/datadog-instrumentations/src/tedious.js +1 -1
  60. package/packages/datadog-instrumentations/src/url.js +9 -17
  61. package/packages/datadog-instrumentations/src/vitest.js +126 -97
  62. package/packages/datadog-plugin-amqp10/src/consumer.js +7 -3
  63. package/packages/datadog-plugin-amqp10/src/producer.js +7 -3
  64. package/packages/datadog-plugin-amqplib/src/client.js +6 -2
  65. package/packages/datadog-plugin-amqplib/src/consumer.js +7 -3
  66. package/packages/datadog-plugin-amqplib/src/producer.js +7 -3
  67. package/packages/datadog-plugin-amqplib/src/util.js +1 -1
  68. package/packages/datadog-plugin-apollo/src/gateway/request.js +5 -6
  69. package/packages/datadog-plugin-apollo/src/gateway/validate.js +2 -3
  70. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
  71. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +2 -2
  72. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +13 -13
  73. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +24 -31
  74. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  75. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +6 -6
  76. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
  77. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -1
  78. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +4 -5
  79. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
  80. package/packages/datadog-plugin-aws-sdk/src/util.js +5 -6
  81. package/packages/datadog-plugin-cassandra-driver/src/index.js +1 -1
  82. package/packages/datadog-plugin-child_process/src/index.js +4 -4
  83. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +23 -23
  84. package/packages/datadog-plugin-cucumber/src/index.js +86 -20
  85. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +97 -27
  86. package/packages/datadog-plugin-cypress/src/plugin.js +11 -1
  87. package/packages/datadog-plugin-cypress/src/support.js +24 -5
  88. package/packages/datadog-plugin-express/src/code_origin.js +30 -0
  89. package/packages/datadog-plugin-express/src/index.js +10 -12
  90. package/packages/datadog-plugin-express/src/tracing.js +19 -0
  91. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +7 -3
  92. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +12 -7
  93. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +6 -2
  94. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +26 -9
  95. package/packages/datadog-plugin-graphql/src/execute.js +2 -2
  96. package/packages/datadog-plugin-graphql/src/index.js +7 -6
  97. package/packages/datadog-plugin-graphql/src/resolve.js +2 -2
  98. package/packages/datadog-plugin-graphql/src/tools/index.js +1 -0
  99. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -0
  100. package/packages/datadog-plugin-graphql/src/tools/transforms.js +1 -0
  101. package/packages/datadog-plugin-grpc/src/client.js +2 -2
  102. package/packages/datadog-plugin-grpc/src/util.js +2 -2
  103. package/packages/datadog-plugin-http/src/client.js +18 -7
  104. package/packages/datadog-plugin-http2/src/client.js +20 -20
  105. package/packages/datadog-plugin-iovalkey/src/index.js +18 -0
  106. package/packages/datadog-plugin-jest/src/index.js +36 -28
  107. package/packages/datadog-plugin-jest/src/util.js +8 -8
  108. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +3 -1
  109. package/packages/datadog-plugin-kafkajs/src/consumer.js +9 -5
  110. package/packages/datadog-plugin-kafkajs/src/producer.js +15 -7
  111. package/packages/datadog-plugin-kafkajs/src/utils.js +1 -1
  112. package/packages/datadog-plugin-langchain/src/handlers/chain.js +7 -7
  113. package/packages/datadog-plugin-langchain/src/handlers/embedding.js +2 -2
  114. package/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js +6 -4
  115. package/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js +5 -4
  116. package/packages/datadog-plugin-langchain/src/tracing.js +11 -10
  117. package/packages/datadog-plugin-mariadb/src/index.js +3 -9
  118. package/packages/datadog-plugin-mocha/src/index.js +88 -48
  119. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -1
  120. package/packages/datadog-plugin-mysql/src/index.js +11 -9
  121. package/packages/datadog-plugin-mysql2/src/index.js +16 -0
  122. package/packages/datadog-plugin-net/src/tcp.js +1 -1
  123. package/packages/datadog-plugin-next/src/index.js +6 -5
  124. package/packages/datadog-plugin-openai/src/services.js +6 -10
  125. package/packages/datadog-plugin-openai/src/tracing.js +10 -14
  126. package/packages/datadog-plugin-oracledb/src/index.js +1 -1
  127. package/packages/datadog-plugin-playwright/src/index.js +48 -22
  128. package/packages/datadog-plugin-redis/src/index.js +9 -4
  129. package/packages/datadog-plugin-rhea/src/consumer.js +8 -6
  130. package/packages/datadog-plugin-rhea/src/producer.js +5 -2
  131. package/packages/datadog-plugin-router/src/index.js +1 -1
  132. package/packages/datadog-plugin-selenium/src/index.js +1 -6
  133. package/packages/datadog-plugin-vitest/src/index.js +99 -72
  134. package/packages/datadog-shimmer/src/shimmer.js +163 -36
  135. package/packages/dd-trace/src/appsec/api_security_sampler.js +2 -2
  136. package/packages/dd-trace/src/appsec/blocked_templates.js +1 -1
  137. package/packages/dd-trace/src/appsec/blocking.js +6 -20
  138. package/packages/dd-trace/src/appsec/graphql.js +2 -2
  139. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
  140. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +1 -1
  141. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +1 -1
  142. package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +4 -6
  143. package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +7 -12
  144. package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +4 -6
  145. package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +4 -0
  146. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +9 -12
  147. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +5 -4
  148. package/packages/dd-trace/src/appsec/iast/context/context-plugin.js +2 -3
  149. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +3 -3
  150. package/packages/dd-trace/src/appsec/iast/index.js +1 -0
  151. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +102 -7
  152. package/packages/dd-trace/src/appsec/iast/path-line.js +7 -8
  153. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +6 -13
  154. package/packages/dd-trace/src/appsec/iast/security-controls/parser.js +6 -6
  155. package/packages/dd-trace/src/appsec/iast/taint-tracking/filter.js +2 -2
  156. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +3 -3
  157. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +4 -28
  158. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -7
  159. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +3 -4
  160. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -1
  161. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -7
  162. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -2
  163. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +6 -6
  164. package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +1 -1
  165. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +1 -1
  166. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +1 -1
  167. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +7 -7
  168. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +23 -24
  169. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +3 -3
  170. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +4 -4
  171. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +6 -11
  172. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +9 -11
  173. package/packages/dd-trace/src/appsec/index.js +15 -12
  174. package/packages/dd-trace/src/appsec/rasp/index.js +19 -17
  175. package/packages/dd-trace/src/appsec/rasp/lfi.js +2 -1
  176. package/packages/dd-trace/src/appsec/rasp/utils.js +11 -6
  177. package/packages/dd-trace/src/appsec/reporter.js +233 -40
  178. package/packages/dd-trace/src/appsec/rule_manager.js +2 -2
  179. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
  180. package/packages/dd-trace/src/appsec/stack_trace.js +2 -4
  181. package/packages/dd-trace/src/appsec/telemetry/index.js +1 -2
  182. package/packages/dd-trace/src/appsec/telemetry/rasp.js +3 -14
  183. package/packages/dd-trace/src/appsec/telemetry/waf.js +3 -5
  184. package/packages/dd-trace/src/appsec/user_tracking.js +3 -5
  185. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +8 -8
  186. package/packages/dd-trace/src/azure_metadata.js +2 -7
  187. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +1 -1
  188. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +2 -2
  189. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
  190. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +3 -3
  191. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
  192. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
  193. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -1
  194. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +6 -4
  195. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -2
  196. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +0 -2
  197. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +1 -1
  198. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +1 -1
  199. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +8 -5
  200. package/packages/dd-trace/src/ci-visibility/telemetry.js +4 -0
  201. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
  202. package/packages/dd-trace/src/config.js +82 -51
  203. package/packages/dd-trace/src/config_stable.js +3 -3
  204. package/packages/dd-trace/src/datastreams/encoding.js +9 -9
  205. package/packages/dd-trace/src/datastreams/fnv.js +1 -1
  206. package/packages/dd-trace/src/datastreams/pathway.js +4 -4
  207. package/packages/dd-trace/src/datastreams/processor.js +5 -7
  208. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -1
  209. package/packages/dd-trace/src/datastreams/schemas/schema_sampler.js +4 -6
  210. package/packages/dd-trace/src/datastreams/size.js +1 -1
  211. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +131 -72
  212. package/packages/dd-trace/src/debugger/devtools_client/condition.js +6 -8
  213. package/packages/dd-trace/src/debugger/devtools_client/defaults.js +1 -1
  214. package/packages/dd-trace/src/debugger/devtools_client/index.js +17 -27
  215. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +18 -38
  216. package/packages/dd-trace/src/debugger/devtools_client/send.js +8 -7
  217. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +16 -8
  218. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +8 -10
  219. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +3 -3
  220. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +2 -10
  221. package/packages/dd-trace/src/debugger/devtools_client/state.js +31 -4
  222. package/packages/dd-trace/src/dogstatsd.js +7 -4
  223. package/packages/dd-trace/src/encode/0.4.js +9 -9
  224. package/packages/dd-trace/src/encode/0.5.js +1 -1
  225. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +3 -3
  226. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +1 -1
  227. package/packages/dd-trace/src/encode/tags-processors.js +1 -1
  228. package/packages/dd-trace/src/exporter.js +6 -6
  229. package/packages/dd-trace/src/exporters/agent/writer.js +1 -5
  230. package/packages/dd-trace/src/exporters/common/docker.js +1 -1
  231. package/packages/dd-trace/src/exporters/common/form-data.js +6 -4
  232. package/packages/dd-trace/src/exporters/common/request.js +1 -1
  233. package/packages/dd-trace/src/exporters/common/util.js +1 -1
  234. package/packages/dd-trace/src/external-logger/src/index.js +5 -5
  235. package/packages/dd-trace/src/flare/file.js +1 -5
  236. package/packages/dd-trace/src/format.js +1 -1
  237. package/packages/dd-trace/src/git_properties.js +1 -1
  238. package/packages/dd-trace/src/id.js +12 -6
  239. package/packages/dd-trace/src/iitm.js +10 -22
  240. package/packages/dd-trace/src/lambda/handler.js +6 -6
  241. package/packages/dd-trace/src/lambda/runtime/patch.js +4 -4
  242. package/packages/dd-trace/src/lambda/runtime/ritm.js +1 -1
  243. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +6 -6
  244. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +2 -6
  245. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +3 -3
  246. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +6 -6
  247. package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -1
  248. package/packages/dd-trace/src/llmobs/sdk.js +2 -2
  249. package/packages/dd-trace/src/llmobs/tagger.js +113 -99
  250. package/packages/dd-trace/src/llmobs/util.js +9 -9
  251. package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
  252. package/packages/dd-trace/src/llmobs/writers/util.js +1 -1
  253. package/packages/dd-trace/src/log/index.js +4 -4
  254. package/packages/dd-trace/src/log/log.js +1 -1
  255. package/packages/dd-trace/src/log/writer.js +2 -2
  256. package/packages/dd-trace/src/msgpack/chunk.js +3 -3
  257. package/packages/dd-trace/src/msgpack/encoder.js +28 -28
  258. package/packages/dd-trace/src/noop/dogstatsd.js +6 -6
  259. package/packages/dd-trace/src/noop/span.js +3 -5
  260. package/packages/dd-trace/src/noop/tracer.js +1 -2
  261. package/packages/dd-trace/src/opentelemetry/span_processor.js +2 -2
  262. package/packages/dd-trace/src/opentelemetry/tracer.js +6 -5
  263. package/packages/dd-trace/src/opentracing/propagation/log.js +6 -8
  264. package/packages/dd-trace/src/opentracing/propagation/text_map.js +27 -23
  265. package/packages/dd-trace/src/opentracing/propagation/tracestate.js +8 -4
  266. package/packages/dd-trace/src/opentracing/span.js +9 -14
  267. package/packages/dd-trace/src/opentracing/tracer.js +9 -6
  268. package/packages/dd-trace/src/payload-tagging/index.js +1 -1
  269. package/packages/dd-trace/src/payload-tagging/tagging.js +6 -6
  270. package/packages/dd-trace/src/pkg.js +1 -1
  271. package/packages/dd-trace/src/plugins/ci_plugin.js +62 -10
  272. package/packages/dd-trace/src/plugins/consumer.js +2 -2
  273. package/packages/dd-trace/src/plugins/inbound.js +5 -1
  274. package/packages/dd-trace/src/plugins/index.js +1 -1
  275. package/packages/dd-trace/src/plugins/outbound.js +4 -5
  276. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  277. package/packages/dd-trace/src/plugins/producer.js +2 -2
  278. package/packages/dd-trace/src/plugins/storage.js +2 -2
  279. package/packages/dd-trace/src/plugins/util/ci.js +23 -15
  280. package/packages/dd-trace/src/plugins/util/git.js +165 -11
  281. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -1
  282. package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
  283. package/packages/dd-trace/src/plugins/util/llm.js +27 -10
  284. package/packages/dd-trace/src/plugins/util/stacktrace.js +1 -1
  285. package/packages/dd-trace/src/plugins/util/test.js +311 -48
  286. package/packages/dd-trace/src/plugins/util/url.js +1 -1
  287. package/packages/dd-trace/src/plugins/util/urlfilter.js +13 -17
  288. package/packages/dd-trace/src/plugins/util/user-provided-git.js +12 -3
  289. package/packages/dd-trace/src/plugins/util/web.js +5 -4
  290. package/packages/dd-trace/src/priority_sampler.js +22 -22
  291. package/packages/dd-trace/src/profiling/config.js +44 -8
  292. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +5 -5
  293. package/packages/dd-trace/src/profiling/exporters/file.js +2 -1
  294. package/packages/dd-trace/src/profiling/profiler.js +37 -2
  295. package/packages/dd-trace/src/profiling/profilers/events.js +14 -17
  296. package/packages/dd-trace/src/profiling/profilers/shared.js +6 -1
  297. package/packages/dd-trace/src/profiling/profilers/space.js +3 -3
  298. package/packages/dd-trace/src/profiling/profilers/wall.js +6 -7
  299. package/packages/dd-trace/src/profiling/ssi-heuristics.js +3 -5
  300. package/packages/dd-trace/src/profiling/tagger.js +3 -5
  301. package/packages/dd-trace/src/profiling/webspan-utils.js +1 -1
  302. package/packages/dd-trace/src/proxy.js +7 -13
  303. package/packages/dd-trace/src/random_sampler.js +40 -0
  304. package/packages/dd-trace/src/rate_limiter.js +4 -4
  305. package/packages/dd-trace/src/remote_config/index.js +3 -7
  306. package/packages/dd-trace/src/remote_config/manager.js +25 -13
  307. package/packages/dd-trace/src/require-package-json.js +1 -1
  308. package/packages/dd-trace/src/ritm.js +4 -4
  309. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +2 -2
  310. package/packages/dd-trace/src/sampler.js +33 -4
  311. package/packages/dd-trace/src/sampling_rule.js +12 -3
  312. package/packages/dd-trace/src/scope.js +1 -1
  313. package/packages/dd-trace/src/serverless.js +0 -48
  314. package/packages/dd-trace/src/service-naming/schemas/util.js +1 -1
  315. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +8 -0
  316. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +2 -3
  317. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
  318. package/packages/dd-trace/src/span_processor.js +3 -3
  319. package/packages/dd-trace/src/span_sampler.js +4 -1
  320. package/packages/dd-trace/src/standalone/tracesource.js +1 -1
  321. package/packages/dd-trace/src/startup-log.js +2 -2
  322. package/packages/dd-trace/src/telemetry/dependencies.js +4 -4
  323. package/packages/dd-trace/src/telemetry/logs/log-collector.js +9 -10
  324. package/packages/dd-trace/src/telemetry/metrics.js +10 -5
  325. package/packages/dd-trace/src/telemetry/send-data.js +1 -1
  326. package/packages/dd-trace/src/telemetry/telemetry.js +23 -24
  327. package/packages/dd-trace/src/util.js +1 -1
  328. package/version.js +1 -0
  329. package/packages/datadog-instrumentations/src/paperplane.js +0 -77
  330. package/packages/datadog-plugin-paperplane/src/index.js +0 -25
  331. package/packages/datadog-plugin-paperplane/src/logger.js +0 -11
  332. package/packages/datadog-plugin-paperplane/src/server.js +0 -24
@@ -26,7 +26,7 @@ const {
26
26
  getOnHookEndHandler,
27
27
  getOnFailHandler,
28
28
  getOnPendingHandler,
29
- testFileToSuiteAr,
29
+ testFileToSuiteCtx,
30
30
  newTests,
31
31
  testsQuarantined,
32
32
  getTestFullName,
@@ -53,7 +53,7 @@ const originalCoverageMap = createCoverageMap()
53
53
  let untestedCoverage
54
54
 
55
55
  // test channels
56
- const testStartCh = channel('ci:mocha:test:start')
56
+ const testFinishCh = channel('ci:mocha:test:finish')
57
57
 
58
58
  // test suite channels
59
59
  const testSuiteStartCh = channel('ci:mocha:test-suite:start')
@@ -66,6 +66,7 @@ const libraryConfigurationCh = channel('ci:mocha:library-configuration')
66
66
  const knownTestsCh = channel('ci:mocha:known-tests')
67
67
  const skippableSuitesCh = channel('ci:mocha:test-suite:skippable')
68
68
  const testManagementTestsCh = channel('ci:mocha:test-management-tests')
69
+ const impactedTestsCh = channel('ci:mocha:modified-tests')
69
70
  const workerReportTraceCh = channel('ci:mocha:worker-report:trace')
70
71
  const testSessionStartCh = channel('ci:mocha:session:start')
71
72
  const testSessionFinishCh = channel('ci:mocha:session:finish')
@@ -166,7 +167,7 @@ function getOnEndHandler (isParallel) {
166
167
  error = new Error(`Failed tests: ${this.failures}.`)
167
168
  }
168
169
 
169
- testFileToSuiteAr.clear()
170
+ testFileToSuiteCtx.clear()
170
171
 
171
172
  let testCodeCoverageLinesTotal
172
173
  if (global.__coverage__) {
@@ -175,7 +176,7 @@ function getOnEndHandler (isParallel) {
175
176
  originalCoverageMap.merge(fromCoverageMapToCoverage(untestedCoverage))
176
177
  }
177
178
  testCodeCoverageLinesTotal = originalCoverageMap.getCoverageSummary().lines.pct
178
- } catch (e) {
179
+ } catch {
179
180
  // ignore errors
180
181
  }
181
182
  // restore the original coverage
@@ -209,6 +210,26 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
209
210
  } else {
210
211
  config.testManagementTests = receivedTestManagementTests
211
212
  }
213
+ if (config.isImpactedTestsEnabled) {
214
+ impactedTestsCh.publish({
215
+ onDone: mochaRunAsyncResource.bind(onReceivedImpactedTests)
216
+ })
217
+ } else if (config.isSuitesSkippingEnabled) {
218
+ skippableSuitesCh.publish({
219
+ onDone: mochaRunAsyncResource.bind(onReceivedSkippableSuites)
220
+ })
221
+ } else {
222
+ onFinishRequest()
223
+ }
224
+ }
225
+
226
+ const onReceivedImpactedTests = ({ err, modifiedTests: receivedModifiedTests }) => {
227
+ if (err) {
228
+ config.modifiedTests = []
229
+ config.isImpactedTestsEnabled = false
230
+ } else {
231
+ config.modifiedTests = receivedModifiedTests
232
+ }
212
233
  if (config.isSuitesSkippingEnabled) {
213
234
  skippableSuitesCh.publish({
214
235
  onDone: mochaRunAsyncResource.bind(onReceivedSkippableSuites)
@@ -237,7 +258,7 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
237
258
 
238
259
  runner.suite.suites = suitesToRun
239
260
 
240
- skippedSuites = Array.from(filteredSuites.skippedSuites)
261
+ skippedSuites = [...filteredSuites.skippedSuites]
241
262
 
242
263
  onFinishRequest()
243
264
  }
@@ -254,6 +275,10 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
254
275
  testManagementTestsCh.publish({
255
276
  onDone: mochaRunAsyncResource.bind(onReceivedTestManagementTests)
256
277
  })
278
+ } if (config.isImpactedTestsEnabled) {
279
+ impactedTestsCh.publish({
280
+ onDone: mochaRunAsyncResource.bind(onReceivedImpactedTests)
281
+ })
257
282
  } else if (config.isSuitesSkippingEnabled) {
258
283
  skippableSuitesCh.publish({
259
284
  onDone: mochaRunAsyncResource.bind(onReceivedSkippableSuites)
@@ -274,6 +299,7 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
274
299
  config.isKnownTestsEnabled = libraryConfig.isKnownTestsEnabled
275
300
  config.isTestManagementTestsEnabled = libraryConfig.isTestManagementEnabled
276
301
  config.testManagementAttemptToFixRetries = libraryConfig.testManagementAttemptToFixRetries
302
+ config.isImpactedTestsEnabled = libraryConfig.isImpactedTestsEnabled
277
303
  // ITR and auto test retries are not supported in parallel mode yet
278
304
  config.isSuitesSkippingEnabled = !isParallel && libraryConfig.isSuitesSkippingEnabled
279
305
  config.isFlakyTestRetriesEnabled = !isParallel && libraryConfig.isFlakyTestRetriesEnabled
@@ -287,6 +313,10 @@ function getExecutionConfiguration (runner, isParallel, onFinishRequest) {
287
313
  testManagementTestsCh.publish({
288
314
  onDone: mochaRunAsyncResource.bind(onReceivedTestManagementTests)
289
315
  })
316
+ } else if (config.isImpactedTestsEnabled) {
317
+ impactedTestsCh.publish({
318
+ onDone: mochaRunAsyncResource.bind(onReceivedImpactedTests)
319
+ })
290
320
  } else if (config.isSuitesSkippingEnabled) {
291
321
  skippableSuitesCh.publish({
292
322
  onDone: mochaRunAsyncResource.bind(onReceivedSkippableSuites)
@@ -312,7 +342,7 @@ addHook({
312
342
  }, (Mocha) => {
313
343
  shimmer.wrap(Mocha.prototype, 'run', run => function () {
314
344
  // Workers do not need to request any data, just run the tests
315
- if (!testStartCh.hasSubscribers || process.env.MOCHA_WORKER_ID || this.options.parallel) {
345
+ if (!testFinishCh.hasSubscribers || process.env.MOCHA_WORKER_ID || this.options.parallel) {
316
346
  return run.apply(this, arguments)
317
347
  }
318
348
 
@@ -367,7 +397,7 @@ addHook({
367
397
  }, (run) => {
368
398
  // `runMocha` is an async function
369
399
  shimmer.wrap(run, 'runMocha', runMocha => function () {
370
- if (!testStartCh.hasSubscribers) {
400
+ if (!testFinishCh.hasSubscribers) {
371
401
  return runMocha.apply(this, arguments)
372
402
  }
373
403
  const mocha = arguments[0]
@@ -403,7 +433,7 @@ addHook({
403
433
  shimmer.wrap(Runner.prototype, 'runTests', runTests => getRunTestsWrapper(runTests, config))
404
434
 
405
435
  shimmer.wrap(Runner.prototype, 'run', run => function () {
406
- if (!testStartCh.hasSubscribers) {
436
+ if (!testFinishCh.hasSubscribers) {
407
437
  return run.apply(this, arguments)
408
438
  }
409
439
 
@@ -430,20 +460,18 @@ addHook({
430
460
  if (suite.root || !suite.tests.length) {
431
461
  return
432
462
  }
433
- let asyncResource = testFileToSuiteAr.get(suite.file)
434
- if (!asyncResource) {
435
- asyncResource = new AsyncResource('bound-anonymous-fn')
436
- testFileToSuiteAr.set(suite.file, asyncResource)
463
+ let ctx = testFileToSuiteCtx.get(suite.file)
464
+ if (!ctx) {
437
465
  const isUnskippable = unskippableSuites.includes(suite.file)
438
466
  isForcedToRun = isUnskippable && suitesToSkip.includes(getTestSuitePath(suite.file, process.cwd()))
439
- asyncResource.runInAsyncScope(() => {
440
- testSuiteStartCh.publish({
441
- testSuiteAbsolutePath: suite.file,
442
- isUnskippable,
443
- isForcedToRun,
444
- itrCorrelationId
445
- })
446
- })
467
+ ctx = {
468
+ testSuiteAbsolutePath: suite.file,
469
+ isUnskippable,
470
+ isForcedToRun,
471
+ itrCorrelationId
472
+ }
473
+ testFileToSuiteCtx.set(suite.file, ctx)
474
+ testSuiteStartCh.runStores(ctx, () => {})
447
475
  }
448
476
  })
449
477
 
@@ -485,11 +513,9 @@ addHook({
485
513
  resetCoverage(global.__coverage__)
486
514
  }
487
515
 
488
- const asyncResource = testFileToSuiteAr.get(suite.file)
489
- if (asyncResource) {
490
- asyncResource.runInAsyncScope(() => {
491
- testSuiteFinishCh.publish(status)
492
- })
516
+ const ctx = testFileToSuiteCtx.get(suite.file)
517
+ if (ctx) {
518
+ testSuiteFinishCh.publish({ status, ...ctx.currentStore }, () => {})
493
519
  } else {
494
520
  log.warn(() => `No AsyncResource found for suite ${suite.file}`)
495
521
  }
@@ -509,6 +535,15 @@ addHook({
509
535
  file: 'lib/runnable.js'
510
536
  }, (runnablePackage) => runnableWrapper(runnablePackage, config))
511
537
 
538
+ function onMessage (message) {
539
+ if (Array.isArray(message)) {
540
+ const [messageCode, payload] = message
541
+ if (messageCode === MOCHA_WORKER_TRACE_PAYLOAD_CODE) {
542
+ workerReportTraceCh.publish(payload)
543
+ }
544
+ }
545
+ }
546
+
512
547
  // Only used in parallel mode (--parallel flag is passed)
513
548
  // Used to generate suite events and receive test payloads from workers
514
549
  addHook({
@@ -520,58 +555,40 @@ addHook({
520
555
  file: 'src/WorkerHandler.js'
521
556
  }, (workerHandlerPackage) => {
522
557
  shimmer.wrap(workerHandlerPackage.prototype, 'exec', exec => function (_, path) {
523
- if (!testStartCh.hasSubscribers) {
558
+ if (!testFinishCh.hasSubscribers) {
524
559
  return exec.apply(this, arguments)
525
560
  }
526
561
  if (!path?.length) {
527
562
  return exec.apply(this, arguments)
528
563
  }
529
564
  const [testSuiteAbsolutePath] = path
530
- const testSuiteAsyncResource = new AsyncResource('bound-anonymous-fn')
531
-
532
- function onMessage (message) {
533
- if (Array.isArray(message)) {
534
- const [messageCode, payload] = message
535
- if (messageCode === MOCHA_WORKER_TRACE_PAYLOAD_CODE) {
536
- testSuiteAsyncResource.runInAsyncScope(() => {
537
- workerReportTraceCh.publish(payload)
538
- })
539
- }
540
- }
541
- }
565
+ const testSuiteContext = {}
542
566
 
543
567
  this.worker.on('message', onMessage)
544
568
 
545
- testSuiteAsyncResource.runInAsyncScope(() => {
546
- testSuiteStartCh.publish({
547
- testSuiteAbsolutePath
548
- })
549
- })
569
+ testSuiteContext.testSuiteAbsolutePath = testSuiteAbsolutePath
570
+ testSuiteStartCh.runStores(testSuiteContext, () => {})
550
571
 
551
572
  try {
552
573
  const promise = exec.apply(this, arguments)
553
574
  promise.then(
554
575
  (result) => {
555
576
  const status = result.failureCount === 0 ? 'pass' : 'fail'
556
- testSuiteAsyncResource.runInAsyncScope(() => {
557
- testSuiteFinishCh.publish(status)
558
- })
577
+ testSuiteFinishCh.publish({ status, ...testSuiteContext.currentStore }, () => {})
559
578
  this.worker.off('message', onMessage)
560
579
  },
561
580
  (err) => {
562
- testSuiteAsyncResource.runInAsyncScope(() => {
563
- testSuiteErrorCh.publish(err)
564
- testSuiteFinishCh.publish('fail')
565
- })
581
+ testSuiteContext.error = err
582
+ testSuiteErrorCh.runStores(testSuiteContext, () => {})
583
+ testSuiteFinishCh.publish({ status: 'fail', ...testSuiteContext.currentStore }, () => {})
566
584
  this.worker.off('message', onMessage)
567
585
  }
568
586
  )
569
587
  return promise
570
588
  } catch (err) {
571
- testSuiteAsyncResource.runInAsyncScope(() => {
572
- testSuiteErrorCh.publish(err)
573
- testSuiteFinishCh.publish('fail')
574
- })
589
+ testSuiteContext.error = err
590
+ testSuiteErrorCh.runStores(testSuiteContext, () => {})
591
+ testSuiteFinishCh.publish({ status: 'fail', ...testSuiteContext.currentStore }, () => {})
575
592
  this.worker.off('message', onMessage)
576
593
  throw err
577
594
  }
@@ -588,7 +605,7 @@ addHook({
588
605
  file: 'lib/nodejs/parallel-buffered-runner.js'
589
606
  }, (ParallelBufferedRunner, frameworkVersion) => {
590
607
  shimmer.wrap(ParallelBufferedRunner.prototype, 'run', run => function (cb, { files }) {
591
- if (!testStartCh.hasSubscribers) {
608
+ if (!testFinishCh.hasSubscribers) {
592
609
  return run.apply(this, arguments)
593
610
  }
594
611
 
@@ -629,7 +646,10 @@ addHook({
629
646
  const { BufferedWorkerPool } = BufferedWorkerPoolPackage
630
647
 
631
648
  shimmer.wrap(BufferedWorkerPool.prototype, 'run', run => async function (testSuiteAbsolutePath, workerArgs) {
632
- if (!testStartCh.hasSubscribers || (!config.isKnownTestsEnabled && !config.isTestManagementTestsEnabled)) {
649
+ if (!testFinishCh.hasSubscribers ||
650
+ (!config.isKnownTestsEnabled &&
651
+ !config.isTestManagementTestsEnabled &&
652
+ !config.isImpactedTestsEnabled)) {
633
653
  return run.apply(this, arguments)
634
654
  }
635
655
 
@@ -662,6 +682,12 @@ addHook({
662
682
  }
663
683
  }
664
684
 
685
+ if (config.isImpactedTestsEnabled) {
686
+ const testSuiteImpactedTests = config.modifiedTests || {}
687
+ newWorkerArgs._ddIsImpactedTestsEnabled = true
688
+ newWorkerArgs._ddModifiedTests = testSuiteImpactedTests
689
+ }
690
+
665
691
  // We pass the known tests for the test file to the worker
666
692
  const testFileResult = await run.apply(
667
693
  this,
@@ -682,10 +708,10 @@ addHook({
682
708
  const testFullName = getTestFullName(test)
683
709
  const tests = newTests[testFullName]
684
710
 
685
- if (!tests) {
686
- newTests[testFullName] = [test]
687
- } else {
711
+ if (tests) {
688
712
  tests.push(test)
713
+ } else {
714
+ newTests[testFullName] = [test]
689
715
  }
690
716
  }
691
717
  // `testsQuarantined` is filled in the worker process, so we need to use the test results to fill it here too.
@@ -7,7 +7,7 @@ const {
7
7
  addAttemptToFixStringToTestName,
8
8
  removeAttemptToFixStringFromTestName
9
9
  } = require('../../../dd-trace/src/plugins/util/test')
10
- const { channel, AsyncResource } = require('../helpers/instrument')
10
+ const { channel } = require('../helpers/instrument')
11
11
  const shimmer = require('../../../datadog-shimmer')
12
12
 
13
13
  // test channels
@@ -17,15 +17,16 @@ const testFinishCh = channel('ci:mocha:test:finish')
17
17
  const testRetryCh = channel('ci:mocha:test:retry')
18
18
  const errorCh = channel('ci:mocha:test:error')
19
19
  const skipCh = channel('ci:mocha:test:skip')
20
-
20
+ const testFnCh = channel('ci:mocha:test:fn')
21
+ const isModifiedCh = channel('ci:mocha:test:is-modified')
21
22
  // suite channels
22
23
  const testSuiteErrorCh = channel('ci:mocha:test-suite:error')
23
24
 
24
25
  const BREAKPOINT_HIT_GRACE_PERIOD_MS = 200
25
- const testToAr = new WeakMap()
26
+ const testToContext = new WeakMap()
26
27
  const originalFns = new WeakMap()
27
28
  const testToStartLine = new WeakMap()
28
- const testFileToSuiteAr = new Map()
29
+ const testFileToSuiteCtx = new Map()
29
30
  const wrappedFunctions = new WeakSet()
30
31
  const newTests = {}
31
32
  const testsAttemptToFix = new Set()
@@ -125,7 +126,7 @@ function getTestStatus (test) {
125
126
  return 'pass'
126
127
  }
127
128
 
128
- function getTestToArKey (test) {
129
+ function getTestToContextKey (test) {
129
130
  if (!test.fn) {
130
131
  return test
131
132
  }
@@ -136,14 +137,14 @@ function getTestToArKey (test) {
136
137
  return originalFn
137
138
  }
138
139
 
139
- function getTestAsyncResource (test) {
140
- const key = getTestToArKey(test)
141
- return testToAr.get(key)
140
+ function getTestContext (test) {
141
+ const key = getTestToContextKey(test)
142
+ return testToContext.get(key)
142
143
  }
143
144
 
144
145
  function runnableWrapper (RunnablePackage, libraryConfig) {
145
146
  shimmer.wrap(RunnablePackage.prototype, 'run', run => function () {
146
- if (!testStartCh.hasSubscribers) {
147
+ if (!testFinishCh.hasSubscribers) {
147
148
  return run.apply(this, arguments)
148
149
  }
149
150
  // Flaky test retries does not work in parallel mode
@@ -167,14 +168,17 @@ function runnableWrapper (RunnablePackage, libraryConfig) {
167
168
 
168
169
  if (isTestHook || this.type === 'test') {
169
170
  const test = isTestHook ? this.ctx.currentTest : this
170
- const asyncResource = getTestAsyncResource(test)
171
+ const ctx = getTestContext(test)
171
172
 
172
- if (asyncResource) {
173
- // we bind the test fn to the correct async resource
174
- const newFn = asyncResource.bind(this.fn)
173
+ if (ctx) {
174
+ const originalFn = this.fn
175
+ // we bind the test fn to the correct context
176
+ const newFn = function () {
177
+ return testFnCh.runStores(ctx, () => originalFn.apply(this, arguments))
178
+ }
175
179
 
176
180
  // we store the original function, not to lose it
177
- originalFns.set(newFn, this.fn)
181
+ originalFns.set(newFn, originalFn)
178
182
  this.fn = newFn
179
183
 
180
184
  wrappedFunctions.add(this.fn)
@@ -189,7 +193,6 @@ function runnableWrapper (RunnablePackage, libraryConfig) {
189
193
  function getOnTestHandler (isMain) {
190
194
  return function (test) {
191
195
  const testStartLine = testToStartLine.get(test)
192
- const asyncResource = new AsyncResource('bound-anonymous-fn')
193
196
 
194
197
  // This may be a retry. If this is the case, `test.fn` is already wrapped,
195
198
  // so we need to restore it.
@@ -198,7 +201,6 @@ function getOnTestHandler (isMain) {
198
201
  test.fn = originalFn
199
202
  wrappedFunctions.delete(test.fn)
200
203
  }
201
- testToAr.set(test.fn, asyncResource)
202
204
 
203
205
  const {
204
206
  file: testSuiteAbsolutePath,
@@ -207,7 +209,8 @@ function getOnTestHandler (isMain) {
207
209
  _ddIsEfdRetry: isEfdRetry,
208
210
  _ddIsAttemptToFix: isAttemptToFix,
209
211
  _ddIsDisabled: isDisabled,
210
- _ddIsQuarantined: isQuarantined
212
+ _ddIsQuarantined: isQuarantined,
213
+ _ddIsModified: isModified
211
214
  } = test
212
215
 
213
216
  const testName = removeEfdStringFromTestName(removeAttemptToFixStringFromTestName(test.fullTitle()))
@@ -228,6 +231,7 @@ function getOnTestHandler (isMain) {
228
231
  testInfo.isAttemptToFix = isAttemptToFix
229
232
  testInfo.isDisabled = isDisabled
230
233
  testInfo.isQuarantined = isQuarantined
234
+ testInfo.isModified = isModified
231
235
  // We want to store the result of the new tests
232
236
  if (isNew) {
233
237
  const testFullName = getTestFullName(test)
@@ -242,15 +246,15 @@ function getOnTestHandler (isMain) {
242
246
  test.pending = true
243
247
  }
244
248
 
245
- asyncResource.runInAsyncScope(() => {
246
- testStartCh.publish(testInfo)
247
- })
249
+ const ctx = testInfo
250
+ testToContext.set(test.fn, ctx)
251
+ testStartCh.runStores(ctx, () => {})
248
252
  }
249
253
  }
250
254
 
251
255
  function getOnTestEndHandler (config) {
252
256
  return async function (test) {
253
- const asyncResource = getTestAsyncResource(test)
257
+ const ctx = getTestContext(test)
254
258
  const status = getTestStatus(test)
255
259
 
256
260
  // After finishing it might take a bit for the snapshot to be handled.
@@ -269,17 +273,17 @@ function getOnTestEndHandler (config) {
269
273
 
270
274
  const testName = getTestFullName(test)
271
275
 
272
- if (!testsStatuses.get(testName)) {
273
- testsStatuses.set(testName, [status])
274
- } else {
276
+ if (testsStatuses.get(testName)) {
275
277
  testsStatuses.get(testName).push(status)
278
+ } else {
279
+ testsStatuses.set(testName, [status])
276
280
  }
277
281
  const testStatuses = testsStatuses.get(testName)
278
282
 
279
283
  const isLastAttempt = testStatuses.length === config.testManagementAttemptToFixRetries + 1
280
284
 
281
285
  if (test._ddIsAttemptToFix && isLastAttempt) {
282
- if (testStatuses.some(status => status === 'fail')) {
286
+ if (testStatuses.includes('fail')) {
283
287
  attemptToFixFailed = true
284
288
  }
285
289
  if (testStatuses.every(status => status === 'fail')) {
@@ -295,18 +299,17 @@ function getOnTestEndHandler (config) {
295
299
  !test._ddIsEfdRetry
296
300
 
297
301
  // if there are afterEach to be run, we don't finish the test yet
298
- if (asyncResource && !getAfterEachHooks(test).length) {
299
- asyncResource.runInAsyncScope(() => {
300
- testFinishCh.publish({
301
- status,
302
- hasBeenRetried: isMochaRetry(test),
303
- isLastRetry: getIsLastRetry(test),
304
- hasFailedAllRetries,
305
- attemptToFixPassed,
306
- attemptToFixFailed,
307
- isAttemptToFixRetry,
308
- isAtrRetry
309
- })
302
+ if (ctx && !getAfterEachHooks(test).length) {
303
+ testFinishCh.publish({
304
+ status,
305
+ hasBeenRetried: isMochaRetry(test),
306
+ isLastRetry: getIsLastRetry(test),
307
+ hasFailedAllRetries,
308
+ attemptToFixPassed,
309
+ attemptToFixFailed,
310
+ isAttemptToFixRetry,
311
+ isAtrRetry,
312
+ ...ctx.currentStore
310
313
  })
311
314
  }
312
315
  }
@@ -320,10 +323,13 @@ function getOnHookEndHandler () {
320
323
  const isLastAfterEach = afterEachHooks.indexOf(hook) === afterEachHooks.length - 1
321
324
  if (isLastAfterEach) {
322
325
  const status = getTestStatus(test)
323
- const asyncResource = getTestAsyncResource(test)
324
- if (asyncResource) {
325
- asyncResource.runInAsyncScope(() => {
326
- testFinishCh.publish({ status, hasBeenRetried: isMochaRetry(test), isLastRetry: getIsLastRetry(test) })
326
+ const ctx = getTestContext(test)
327
+ if (ctx) {
328
+ testFinishCh.publish({
329
+ status,
330
+ hasBeenRetried: isMochaRetry(test),
331
+ isLastRetry: getIsLastRetry(test),
332
+ ...ctx.currentStore
327
333
  })
328
334
  }
329
335
  }
@@ -339,35 +345,34 @@ function getOnFailHandler (isMain) {
339
345
  if (isHook && testOrHook.ctx) {
340
346
  test = testOrHook.ctx.currentTest
341
347
  }
342
- let testAsyncResource
348
+ let testContext
343
349
  if (test) {
344
- testAsyncResource = getTestAsyncResource(test)
350
+ testContext = getTestContext(test)
345
351
  }
346
- if (testAsyncResource) {
347
- testAsyncResource.runInAsyncScope(() => {
348
- if (isHook) {
349
- err.message = `${testOrHook.fullTitle()}: ${err.message}`
350
- errorCh.publish(err)
351
- // if it's a hook and it has failed, 'test end' will not be called
352
- testFinishCh.publish({ status: 'fail', hasBeenRetried: isMochaRetry(test) })
353
- } else {
354
- errorCh.publish(err)
355
- }
356
- })
352
+ if (testContext) {
353
+ if (isHook) {
354
+ err.message = `${testOrHook.fullTitle()}: ${err.message}`
355
+ testContext.err = err
356
+ errorCh.runStores(testContext, () => {})
357
+ // if it's a hook and it has failed, 'test end' will not be called
358
+ testFinishCh.publish({ status: 'fail', hasBeenRetried: isMochaRetry(test), ...testContext.currentStore })
359
+ } else {
360
+ testContext.err = err
361
+ errorCh.runStores(testContext, () => {})
362
+ }
357
363
  }
358
364
 
359
365
  if (isMain) {
360
- const testSuiteAsyncResource = testFileToSuiteAr.get(testFile)
366
+ const testSuiteContext = testFileToSuiteCtx.get(testFile)
361
367
 
362
- if (testSuiteAsyncResource) {
368
+ if (testSuiteContext) {
363
369
  // we propagate the error to the suite
364
370
  const testSuiteError = new Error(
365
371
  `"${testOrHook.parent.fullTitle()}" failed with message "${err.message}"`
366
372
  )
367
373
  testSuiteError.stack = err.stack
368
- testSuiteAsyncResource.runInAsyncScope(() => {
369
- testSuiteErrorCh.publish(testSuiteError)
370
- })
374
+ testSuiteContext.error = testSuiteError
375
+ testSuiteErrorCh.runStores(testSuiteContext, () => {})
371
376
  }
372
377
  }
373
378
  }
@@ -375,20 +380,18 @@ function getOnFailHandler (isMain) {
375
380
 
376
381
  function getOnTestRetryHandler (config) {
377
382
  return function (test, err) {
378
- const asyncResource = getTestAsyncResource(test)
379
- if (asyncResource) {
383
+ const ctx = getTestContext(test)
384
+ if (ctx) {
380
385
  const isFirstAttempt = test._currentRetry === 0
381
386
  const willBeRetried = test._currentRetry < test._retries
382
387
  const isAtrRetry = !isFirstAttempt &&
383
388
  config.isFlakyTestRetriesEnabled &&
384
389
  !test._ddIsAttemptToFix &&
385
390
  !test._ddIsEfdRetry
386
- asyncResource.runInAsyncScope(() => {
387
- testRetryCh.publish({ isFirstAttempt, err, willBeRetried, test, isAtrRetry })
388
- })
391
+ testRetryCh.publish({ isFirstAttempt, err, willBeRetried, test, isAtrRetry, ...ctx.currentStore })
389
392
  }
390
- const key = getTestToArKey(test)
391
- testToAr.delete(key)
393
+ const key = getTestToContextKey(test)
394
+ testToContext.delete(key)
392
395
  }
393
396
  }
394
397
 
@@ -407,23 +410,19 @@ function getOnPendingHandler () {
407
410
  testStartLine
408
411
  }
409
412
 
410
- const asyncResource = getTestAsyncResource(test)
411
- if (asyncResource) {
412
- asyncResource.runInAsyncScope(() => {
413
- skipCh.publish(testInfo)
414
- })
413
+ const ctx = getTestContext(test)
414
+ if (ctx) {
415
+ skipCh.publish(testInfo)
415
416
  } else {
416
- // if there is no async resource, the test has been skipped through `test.skip`
417
+ // if there is no context, the test has been skipped through `test.skip`
417
418
  // or the parent suite is skipped
418
- const skippedTestAsyncResource = new AsyncResource('bound-anonymous-fn')
419
+ const testCtx = testInfo
419
420
  if (test.fn) {
420
- testToAr.set(test.fn, skippedTestAsyncResource)
421
+ testToContext.set(test.fn, testCtx)
421
422
  } else {
422
- testToAr.set(test, skippedTestAsyncResource)
423
+ testToContext.set(test, testCtx)
423
424
  }
424
- skippedTestAsyncResource.runInAsyncScope(() => {
425
- skipCh.publish(testInfo)
426
- })
425
+ skipCh.runStores(testCtx, () => {})
427
426
  }
428
427
  }
429
428
  }
@@ -455,12 +454,34 @@ function getRunTestsWrapper (runTests, config) {
455
454
  })
456
455
  }
457
456
 
457
+ if (config.isImpactedTestsEnabled) {
458
+ suite.tests.forEach((test) => {
459
+ isModifiedCh.publish({
460
+ modifiedTests: config.modifiedTests,
461
+ file: suite.file,
462
+ onDone: (isModified) => {
463
+ if (isModified) {
464
+ test._ddIsModified = true
465
+ if (!test.isPending() && !test._ddIsAttemptToFix && config.isEarlyFlakeDetectionEnabled) {
466
+ retryTest(
467
+ test,
468
+ config.earlyFlakeDetectionNumRetries,
469
+ addEfdStringToTestName,
470
+ ['_ddIsModified', '_ddIsEfdRetry']
471
+ )
472
+ }
473
+ }
474
+ }
475
+ })
476
+ })
477
+ }
478
+
458
479
  if (config.isKnownTestsEnabled) {
459
480
  // by the time we reach `this.on('test')`, it is too late. We need to add retries here
460
481
  suite.tests.forEach(test => {
461
482
  if (!test.isPending() && isNewTest(test, config.knownTests)) {
462
483
  test._ddIsNew = true
463
- if (config.isEarlyFlakeDetectionEnabled) {
484
+ if (config.isEarlyFlakeDetectionEnabled && !test._ddIsAttemptToFix && !test._ddIsModified) {
464
485
  retryTest(
465
486
  test,
466
487
  config.earlyFlakeDetectionNumRetries,
@@ -484,9 +505,9 @@ module.exports = {
484
505
  getTestFullName,
485
506
  getTestStatus,
486
507
  runnableWrapper,
487
- testToAr,
508
+ testToContext,
488
509
  originalFns,
489
- getTestAsyncResource,
510
+ getTestContext,
490
511
  testToStartLine,
491
512
  getOnTestHandler,
492
513
  getOnTestEndHandler,
@@ -494,7 +515,7 @@ module.exports = {
494
515
  getOnHookEndHandler,
495
516
  getOnFailHandler,
496
517
  getOnPendingHandler,
497
- testFileToSuiteAr,
518
+ testFileToSuiteCtx,
498
519
  getRunTestsWrapper,
499
520
  newTests,
500
521
  testsQuarantined,