dd-trace 6.12.0 → 6.14.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 (251) hide show
  1. package/LICENSE-3rdparty.csv +3 -1
  2. package/ci/init.js +8 -3
  3. package/ci/test-optimization-validation/ci-package-scripts.js +2 -2
  4. package/ci/test-optimization-validation/ci-remediation.js +6 -6
  5. package/ci/test-optimization-validation/command-blocker.js +7 -5
  6. package/ci/test-optimization-validation/framework-adapters/cucumber.js +1 -1
  7. package/ci/test-optimization-validation/framework-adapters/cypress.js +9 -11
  8. package/ci/test-optimization-validation/framework-adapters/vitest.js +3 -3
  9. package/ci/test-optimization-validation/package-check.js +1 -1
  10. package/ci/test-optimization-validation/report-writer.js +7 -5
  11. package/ci/test-optimization-validation/scenarios/ci-wiring.js +5 -4
  12. package/ci/vitest-no-worker-init-runner-setup.mjs +8 -0
  13. package/ci/vitest-no-worker-init-setup.mjs +13 -13
  14. package/ci/vitest-no-worker-init-v5-setup.mjs +4 -0
  15. package/index.d.ts +127 -26
  16. package/package.json +22 -19
  17. package/packages/datadog-esbuild/index.js +3 -1
  18. package/packages/datadog-instrumentations/src/bunyan.js +4 -2
  19. package/packages/datadog-instrumentations/src/cypress-config.js +19 -17
  20. package/packages/datadog-instrumentations/src/fs.js +24 -20
  21. package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +2 -2
  22. package/packages/datadog-instrumentations/src/graphql.js +16 -16
  23. package/packages/datadog-instrumentations/src/helpers/bunyan.js +12 -3
  24. package/packages/datadog-instrumentations/src/helpers/graphql-jit-runtime.js +504 -0
  25. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
  26. package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +266 -0
  27. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +1 -2
  28. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +95 -30
  29. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +0 -25
  30. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +83 -0
  31. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +85 -1
  32. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  33. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/mercurius.js +30 -12
  34. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +13 -0
  35. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +279 -0
  36. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +12 -1
  37. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +562 -27
  38. package/packages/datadog-instrumentations/src/jest.js +165 -38
  39. package/packages/datadog-instrumentations/src/knex.js +76 -0
  40. package/packages/datadog-instrumentations/src/mariadb-bundle.js +1597 -0
  41. package/packages/datadog-instrumentations/src/mariadb.js +13 -0
  42. package/packages/datadog-instrumentations/src/mocha/common.js +59 -2
  43. package/packages/datadog-instrumentations/src/mocha/main.js +25 -15
  44. package/packages/datadog-instrumentations/src/mocha/utils.js +2 -1
  45. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +98 -0
  46. package/packages/datadog-instrumentations/src/mocha/worker.js +12 -8
  47. package/packages/datadog-instrumentations/src/net.js +14 -17
  48. package/packages/datadog-instrumentations/src/next.js +212 -62
  49. package/packages/datadog-instrumentations/src/openai.js +42 -40
  50. package/packages/datadog-instrumentations/src/pg.js +15 -0
  51. package/packages/datadog-instrumentations/src/pino.js +15 -4
  52. package/packages/datadog-instrumentations/src/playwright.js +137 -27
  53. package/packages/datadog-instrumentations/src/rum-browser-scripts.js +40 -0
  54. package/packages/datadog-instrumentations/src/sequelize.js +94 -2
  55. package/packages/datadog-instrumentations/src/undici.js +53 -4
  56. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +44 -7
  57. package/packages/datadog-instrumentations/src/vitest-main.js +92 -9
  58. package/packages/datadog-instrumentations/src/vitest-worker.js +82 -14
  59. package/packages/datadog-instrumentations/src/webdriverio.js +986 -1
  60. package/packages/datadog-instrumentations/src/winston.js +6 -3
  61. package/packages/datadog-plugin-amqp10/src/consumer.js +3 -1
  62. package/packages/datadog-plugin-amqp10/src/producer.js +3 -1
  63. package/packages/datadog-plugin-amqp10/src/util.js +2 -1
  64. package/packages/datadog-plugin-avsc/src/schema_iterator.js +6 -1
  65. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +16 -5
  66. package/packages/datadog-plugin-cassandra-driver/src/index.js +8 -3
  67. package/packages/datadog-plugin-cucumber/src/index.js +0 -2
  68. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +262 -48
  69. package/packages/datadog-plugin-cypress/src/support.js +1 -0
  70. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -1
  71. package/packages/datadog-plugin-graphql/src/execute.js +998 -196
  72. package/packages/datadog-plugin-graphql/src/index.js +27 -7
  73. package/packages/datadog-plugin-graphql/src/jit.js +136 -0
  74. package/packages/datadog-plugin-graphql/src/request.js +18 -27
  75. package/packages/datadog-plugin-graphql/src/resolve-error.js +108 -0
  76. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -2
  77. package/packages/datadog-plugin-graphql/src/tools/transforms.js +45 -3
  78. package/packages/datadog-plugin-graphql/src/utils.js +208 -120
  79. package/packages/datadog-plugin-graphql/src/validate.js +10 -23
  80. package/packages/datadog-plugin-http/src/client.js +2 -15
  81. package/packages/datadog-plugin-http2/src/client.js +2 -15
  82. package/packages/datadog-plugin-jest/src/index.js +0 -6
  83. package/packages/datadog-plugin-langchain/src/tracing.js +7 -0
  84. package/packages/datadog-plugin-mocha/src/index.js +403 -75
  85. package/packages/datadog-plugin-mongodb-core/src/query.js +6 -0
  86. package/packages/datadog-plugin-mysql/src/index.js +41 -15
  87. package/packages/datadog-plugin-net/src/tcp.js +3 -1
  88. package/packages/datadog-plugin-next/src/index.js +63 -29
  89. package/packages/datadog-plugin-openai-agents/src/integration.js +15 -11
  90. package/packages/datadog-plugin-playwright/src/index.js +176 -28
  91. package/packages/datadog-plugin-undici/src/index.js +29 -56
  92. package/packages/datadog-plugin-vitest/src/index.js +6 -12
  93. package/packages/dd-trace/src/aiguard/evaluation.js +96 -21
  94. package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -3
  95. package/packages/dd-trace/src/aiguard/messages/anthropic.js +29 -10
  96. package/packages/dd-trace/src/aiguard/messages/openai.js +8 -1
  97. package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +20 -6
  98. package/packages/dd-trace/src/aiguard/noop.js +9 -1
  99. package/packages/dd-trace/src/aiguard/redaction.js +183 -0
  100. package/packages/dd-trace/src/aiguard/sdk.js +7 -2
  101. package/packages/dd-trace/src/aiguard/tags.js +2 -0
  102. package/packages/dd-trace/src/appsec/api_security/index.js +23 -6
  103. package/packages/dd-trace/src/appsec/api_security/sampler.js +99 -40
  104. package/packages/dd-trace/src/appsec/graphql.js +6 -2
  105. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +3 -3
  106. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -1
  107. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +8 -2
  108. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +11 -36
  109. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +1 -1
  110. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +10 -9
  111. package/packages/dd-trace/src/appsec/lambda.js +44 -26
  112. package/packages/dd-trace/src/appsec/rule_manager.js +2 -0
  113. package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +32 -2
  114. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +8 -8
  115. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +6 -4
  116. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +20 -4
  117. package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +7 -150
  118. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +7 -6
  119. package/packages/dd-trace/src/ci-visibility/exporters/agents.js +54 -0
  120. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +1 -2
  121. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +397 -234
  122. package/packages/dd-trace/src/ci-visibility/exporters/limits.js +9 -0
  123. package/packages/dd-trace/src/ci-visibility/exporters/request.js +323 -31
  124. package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +42 -0
  125. package/packages/dd-trace/src/ci-visibility/final-flush.js +21 -0
  126. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +57 -18
  127. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +0 -3
  128. package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +164 -71
  129. package/packages/dd-trace/src/ci-visibility/requests/video-request.js +176 -0
  130. package/packages/dd-trace/src/ci-visibility/telemetry.js +10 -7
  131. package/packages/dd-trace/src/ci-visibility/test-video.js +61 -0
  132. package/packages/dd-trace/src/config/generated-config-types.d.ts +10 -0
  133. package/packages/dd-trace/src/config/index.js +75 -14
  134. package/packages/dd-trace/src/config/parsers.js +11 -1
  135. package/packages/dd-trace/src/config/stable.js +3 -3
  136. package/packages/dd-trace/src/config/supported-configurations.json +47 -2
  137. package/packages/dd-trace/src/crashtracking/crashtracker.js +82 -18
  138. package/packages/dd-trace/src/debugger/config.js +12 -1
  139. package/packages/dd-trace/src/debugger/constants.js +1 -0
  140. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -1
  141. package/packages/dd-trace/src/debugger/devtools_client/request-options.js +33 -0
  142. package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -39
  143. package/packages/dd-trace/src/debugger/devtools_client/status.js +11 -6
  144. package/packages/dd-trace/src/debugger/devtools_client/tags.js +41 -0
  145. package/packages/dd-trace/src/debugger/index.js +23 -3
  146. package/packages/dd-trace/src/dogstatsd.js +532 -71
  147. package/packages/dd-trace/src/encode/0.4-cross-payload.js +170 -0
  148. package/packages/dd-trace/src/encode/0.4.js +5 -5
  149. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +9 -8
  150. package/packages/dd-trace/src/evp_proxy/direct.js +27 -23
  151. package/packages/dd-trace/src/exporters/agent/index.js +24 -3
  152. package/packages/dd-trace/src/exporters/agent/writer.js +28 -11
  153. package/packages/dd-trace/src/exporters/agentless/index.js +7 -9
  154. package/packages/dd-trace/src/exporters/agentless/writer.js +100 -118
  155. package/packages/dd-trace/src/exporters/common/agents.js +28 -6
  156. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -2
  157. package/packages/dd-trace/src/exporters/common/final-flush-request-tracker.js +191 -0
  158. package/packages/dd-trace/src/exporters/common/request.js +31 -11
  159. package/packages/dd-trace/src/exporters/common/url.js +40 -1
  160. package/packages/dd-trace/src/exporters/common/writer.js +31 -7
  161. package/packages/dd-trace/src/exporters/span-stats/index.js +23 -4
  162. package/packages/dd-trace/src/external-logger/src/index.js +4 -3
  163. package/packages/dd-trace/src/flush.js +105 -0
  164. package/packages/dd-trace/src/id.js +14 -0
  165. package/packages/dd-trace/src/index.js +5 -2
  166. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -0
  167. package/packages/dd-trace/src/llmobs/experiments/dataset.js +52 -2
  168. package/packages/dd-trace/src/llmobs/experiments/experiment.js +420 -105
  169. package/packages/dd-trace/src/llmobs/experiments/index.js +54 -42
  170. package/packages/dd-trace/src/llmobs/experiments/noop.js +39 -8
  171. package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
  172. package/packages/dd-trace/src/llmobs/experiments/util.js +21 -0
  173. package/packages/dd-trace/src/llmobs/index.js +111 -48
  174. package/packages/dd-trace/src/llmobs/noop.js +2 -1
  175. package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +22 -71
  176. package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +23 -13
  177. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +8 -4
  178. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +6 -3
  179. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +7 -0
  180. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +13 -6
  181. package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +5 -7
  182. package/packages/dd-trace/src/llmobs/util.js +0 -33
  183. package/packages/dd-trace/src/llmobs/writers/base.js +106 -53
  184. package/packages/dd-trace/src/log/index.js +7 -1
  185. package/packages/dd-trace/src/log-submission/log-submission-plugin.js +249 -0
  186. package/packages/dd-trace/src/noop/span.js +5 -0
  187. package/packages/dd-trace/src/openfeature/writers/base.js +14 -12
  188. package/packages/dd-trace/src/openfeature/writers/exposures.js +8 -1
  189. package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
  190. package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +45 -3
  191. package/packages/dd-trace/src/opentelemetry/logs/index.js +9 -25
  192. package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +7 -4
  193. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +14 -4
  194. package/packages/dd-trace/src/opentelemetry/metrics/index.js +18 -23
  195. package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +8 -0
  196. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +18 -6
  197. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +14 -2
  198. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +25 -5
  199. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +61 -25
  200. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +19 -4
  201. package/packages/dd-trace/src/opentelemetry/resource-attributes.js +55 -0
  202. package/packages/dd-trace/src/opentelemetry/trace/index.js +6 -1
  203. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +10 -0
  204. package/packages/dd-trace/src/opentelemetry/tracer.js +26 -2
  205. package/packages/dd-trace/src/opentracing/propagation/text_map.js +494 -351
  206. package/packages/dd-trace/src/opentracing/span.js +28 -0
  207. package/packages/dd-trace/src/otel-thread-ctx.js +23 -5
  208. package/packages/dd-trace/src/payload-tagging/index.js +2 -1
  209. package/packages/dd-trace/src/plugin_manager.js +2 -0
  210. package/packages/dd-trace/src/plugins/ci_plugin.js +1 -6
  211. package/packages/dd-trace/src/plugins/tracing.js +12 -10
  212. package/packages/dd-trace/src/plugins/util/ci.js +3 -1
  213. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +16 -15
  214. package/packages/dd-trace/src/plugins/util/status-validator.js +98 -0
  215. package/packages/dd-trace/src/plugins/util/test.js +157 -41
  216. package/packages/dd-trace/src/plugins/util/url.js +2 -2
  217. package/packages/dd-trace/src/plugins/util/web.js +6 -74
  218. package/packages/dd-trace/src/profiling/config.js +1 -0
  219. package/packages/dd-trace/src/profiling/oom.js +11 -5
  220. package/packages/dd-trace/src/profiling/profiler.js +30 -13
  221. package/packages/dd-trace/src/profiling/profilers/events.js +3 -3
  222. package/packages/dd-trace/src/profiling/profilers/space.js +38 -11
  223. package/packages/dd-trace/src/profiling/profilers/wall.js +14 -14
  224. package/packages/dd-trace/src/profiling/webspan-utils.js +7 -4
  225. package/packages/dd-trace/src/proxy.js +108 -10
  226. package/packages/dd-trace/src/remote_config/index.js +319 -101
  227. package/packages/dd-trace/src/remote_config/scheduler.js +37 -12
  228. package/packages/dd-trace/src/runtime_metrics/client.js +37 -8
  229. package/packages/dd-trace/src/runtime_metrics/index.js +5 -0
  230. package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +10 -1
  231. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +22 -7
  232. package/packages/dd-trace/src/sampling_rule.js +36 -9
  233. package/packages/dd-trace/src/serverless/telemetry-delivery-tracker.js +51 -0
  234. package/packages/dd-trace/src/serverless/vercel.js +155 -0
  235. package/packages/dd-trace/src/serverless.js +45 -21
  236. package/packages/dd-trace/src/service-naming/schemas/util.js +1 -1
  237. package/packages/dd-trace/src/span_stats.js +64 -31
  238. package/packages/dd-trace/src/startup-log.js +3 -2
  239. package/packages/dd-trace/src/telemetry/agentless-url.js +28 -0
  240. package/packages/dd-trace/src/telemetry/send-data.js +18 -16
  241. package/packages/dd-trace/src/telemetry/session-propagation.js +3 -2
  242. package/packages/dd-trace/src/tracer.js +26 -5
  243. package/packages/dd-trace/src/tracer_metadata.js +11 -3
  244. package/packages/dd-trace/src/web-tags-cache.js +67 -13
  245. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
  246. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  247. package/vendor/dist/protobufjs/index.js +1 -1
  248. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  249. package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +0 -27
  250. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +0 -53
  251. package/packages/dd-trace/src/encode/agentless-json.js +0 -209
@@ -18,9 +18,10 @@ const {
18
18
  getEfdRetryCountForDuration,
19
19
  hasEfdRetries,
20
20
  } = require('../../dd-trace/src/ci-visibility/efd-retry-policy')
21
+ const { FINAL_FLUSH_FALLBACK_DELAY, FINAL_FLUSH_TIMEOUT } =
22
+ require('../../dd-trace/src/ci-visibility/final-flush')
21
23
  const {
22
24
  getCoveredFilesFromCoverage,
23
- getExecutableFilesFromCoverage,
24
25
  JEST_WORKER_TRACE_PAYLOAD_CODE,
25
26
  JEST_WORKER_COVERAGE_PAYLOAD_CODE,
26
27
  JEST_WORKER_TELEMETRY_PAYLOAD_CODE,
@@ -39,7 +40,7 @@ const {
39
40
  logAttemptToFixTestExecution,
40
41
  logTestOptimizationSummary,
41
42
  TEST_IMPACT_ANALYSIS_ALL_TESTS_SKIPPED_MESSAGE,
42
- getTestCoverageLinesPercentage,
43
+ getTestCoverageLinesData,
43
44
  applySkippedCoverageToCoverage,
44
45
  getTestOptimizationRequestResults,
45
46
  } = require('../../dd-trace/src/plugins/util/test')
@@ -96,10 +97,10 @@ const itrSkippedSuitesCh = channel('ci:jest:itr:skipped-suites')
96
97
  // https://github.com/jestjs/jest/blob/1d682f21c7a35da4d3ab3a1436a357b980ebd0fa/packages/jest-worker/src/types.ts#L37
97
98
  const CHILD_MESSAGE_CALL = 1
98
99
 
99
- // Maximum time we'll wait for the tracer to flush
100
- // The exporter has a 10-second bounded final-flush deadline. Leave enough time
101
- // for its completion callback before Jest's --forceExit fallback takes over.
102
- const FLUSH_TIMEOUT = 12_000
100
+ // Maximum time we'll wait for the tracer to flush.
101
+ // Let the exporter enforce its hard deadline and invoke its completion callback
102
+ // before Jest's --forceExit fallback takes over.
103
+ const FLUSH_TIMEOUT = FINAL_FLUSH_TIMEOUT + FINAL_FLUSH_FALLBACK_DELAY + 5000
103
104
  const JEST_SESSION_STATE = Symbol.for('dd-trace:jest:session')
104
105
  const JEST_BAIL_REPORTER_PATH = require.resolve('./jest/bail-reporter')
105
106
  const DD_JEST_HANDLE_TEST_EVENT_WRAPPED = Symbol('dd-trace:jest:handle-test-event-wrapped')
@@ -174,9 +175,11 @@ const newTests = new Set()
174
175
  const testSuiteJestObjects = new Map()
175
176
  const testSuiteDatadogEnvironments = new Map()
176
177
  const wrappedJestGlobals = new WeakSet()
178
+ const wrappedJestEsmLoaders = new WeakSet()
177
179
  const wrappedJestObjects = new WeakSet()
178
180
  const wrappedWorkerInitializers = new WeakSet()
179
181
  const publishedRuntimeReferenceErrors = new WeakMap()
182
+ const jestEsmBypassModulePathsByRuntime = new WeakMap()
180
183
  const wrappedCoverageReporters = new WeakSet()
181
184
  const coverageReporterRequires = new WeakMap()
182
185
  const handledJestEvents = new WeakSet()
@@ -341,16 +344,17 @@ function getTestStats (testStatuses) {
341
344
  function formatIgnoredFailuresSummary (ignoredFailures) {
342
345
  if (!ignoredFailures?.efdFailureCount) return ''
343
346
 
344
- const items = ignoredFailures.efdNames.map(text => ({ text, suffix: 'Early Flake Detection' }))
345
-
346
- if (items.length === 0) return ''
347
-
348
- const shown = items.slice(0, MAX_IGNORED_TEST_NAMES)
349
- const more = items.length - shown.length
347
+ const shown = ignoredFailures.efdNames.slice(0, MAX_IGNORED_TEST_NAMES)
348
+ const more = ignoredFailures.efdNames.length - shown.length
350
349
  const moreSuffix = more > 0 ? `\n ... and ${more} more` : ''
351
- const formattedItems = shown
352
- .map(({ text, suffix }) => ` ${text}${suffix ? ` (${suffix})` : ''}`)
353
- .join('\n') + moreSuffix
350
+ let formattedItems = ''
351
+ let isFirstItem = true
352
+ for (const text of shown) {
353
+ if (!isFirstItem) formattedItems += '\n'
354
+ formattedItems += ` • ${text} (Early Flake Detection)`
355
+ isFirstItem = false
356
+ }
357
+ formattedItems += moreSuffix
354
358
 
355
359
  return `${ignoredFailures.efdFailureCount} test failure(s) were ignored. Exit code set to 0.\n\n${formattedItems}`
356
360
  }
@@ -763,7 +767,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
763
767
  }
764
768
  return test.call(this, testName, testFn, ...callArgs)
765
769
  }
766
- const eachBind = bind(eachTest).apply(this, eachArgs)
770
+ const boundTest = bind(eachTest)
771
+ const eachBind = boundTest.apply(this, eachArgs)
767
772
  return eachBind.apply(this, testArgs)
768
773
  }
769
774
  }
@@ -876,7 +881,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
876
881
  }
877
882
  return concurrentTest.call(this, testName, testFn, ...callArgs)
878
883
  }
879
- const eachBind = bind(concurrentEachTest, false, needsEachError).apply(this, eachArgs)
884
+ const boundTest = bind(concurrentEachTest, false, needsEachError)
885
+ const eachBind = boundTest.apply(this, eachArgs)
880
886
  return eachBind.apply(this, testArgs)
881
887
  }
882
888
  }
@@ -925,10 +931,12 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
925
931
 
926
932
  let jestEach
927
933
  try {
928
- jestEach = createRequire(path.join(this.rootDir, 'package.json'))('jest-each')
934
+ const requireFromPath = createRequire(path.join(this.rootDir, 'package.json'))
935
+ jestEach = requireFromPath('jest-each')
929
936
  } catch {
930
937
  try {
931
- jestEach = createRequire(path.join(process.cwd(), 'package.json'))('jest-each')
938
+ const requireFromPath = createRequire(path.join(process.cwd(), 'package.json'))
939
+ jestEach = requireFromPath('jest-each')
932
940
  } catch {
933
941
  jestEach = undefined
934
942
  }
@@ -2667,16 +2675,15 @@ function getTestSessionCoveragePayload (results, fallbackRootDir) {
2667
2675
  if (isSuitesSkipped) {
2668
2676
  applySkippedCoverageToJestCoverageMap(coverageMap, coverageRootDir)
2669
2677
  }
2670
- payload.testCodeCoverageLinesTotal = getTestCoverageLinesPercentage(
2678
+ const coverageLinesData = getTestCoverageLinesData(
2671
2679
  coverageMap,
2672
2680
  undefined,
2673
- coverageRootDir
2681
+ coverageRootDir,
2682
+ isTiaCoverageBackfillEnabled()
2674
2683
  )
2675
- if (isTiaCoverageBackfillEnabled()) {
2676
- payload.testSessionCoverageFiles = getExecutableFilesFromCoverage(coverageMap).map(({ filename, bitmap }) => ({
2677
- filename: getTestSuitePath(filename, coverageRootDir),
2678
- bitmap,
2679
- }))
2684
+ payload.testCodeCoverageLinesTotal = coverageLinesData.percentage
2685
+ if (coverageLinesData.executableFiles) {
2686
+ payload.testSessionCoverageFiles = coverageLinesData.executableFiles
2680
2687
  }
2681
2688
  } catch {
2682
2689
  // ignore errors
@@ -3067,9 +3074,7 @@ function getCliWrapper (isNewJestVersion) {
3067
3074
  result = await runCLI.apply(this, arguments)
3068
3075
  } catch (error) {
3069
3076
  try {
3070
- await waitForTestSessionFinish(getTestSessionFinishPayload('fail', error, {
3071
- isTestSessionFinalizationError: true,
3072
- }))
3077
+ await waitForTestSessionFinish(getTestSessionFinishPayload('fail', error))
3073
3078
  } catch (finalizationError) {
3074
3079
  log.error('Jest test session finalization error: %s', finalizationError)
3075
3080
  }
@@ -3728,7 +3733,13 @@ if (DD_MAJOR < 6) {
3728
3733
  }, jestConfigSyncWrapper)
3729
3734
  }
3730
3735
 
3736
+ const LOGGING_LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE = new Set([
3737
+ 'bunyan',
3738
+ 'pino',
3739
+ 'winston',
3740
+ ])
3731
3741
  const LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE = new Set([
3742
+ ...LOGGING_LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE,
3732
3743
  'selenium-webdriver',
3733
3744
  'selenium-webdriver/chrome',
3734
3745
  'selenium-webdriver/edge',
@@ -3736,7 +3747,6 @@ const LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE = new Set([
3736
3747
  'selenium-webdriver/firefox',
3737
3748
  'selenium-webdriver/ie',
3738
3749
  'selenium-webdriver/chromium',
3739
- 'winston',
3740
3750
  ])
3741
3751
 
3742
3752
  function recordMockedFile (suiteFilePath, moduleName) {
@@ -3786,8 +3796,6 @@ function wrapJestObject (jestObject, suiteFilePath) {
3786
3796
  wrappedJestObjects.add(jestObject)
3787
3797
 
3788
3798
  shimmer.wrap(jestObject, 'mock', mock => function (moduleName) {
3789
- // If the library is mocked with `jest.mock`, we don't want to bypass jest's own require engine
3790
- LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE.delete(moduleName)
3791
3799
  recordMockedFile(suiteFilePath, moduleName)
3792
3800
  return mock.apply(this, arguments)
3793
3801
  })
@@ -3870,6 +3878,111 @@ function requireOutsideJestRequireEngine (runtime, moduleName) {
3870
3878
  return require(moduleName)
3871
3879
  }
3872
3880
 
3881
+ /**
3882
+ * @param {object} runtime
3883
+ * @param {string} from
3884
+ * @param {string} moduleName
3885
+ * @returns {void}
3886
+ */
3887
+ function recordJestEsmBypassModulePath (runtime, from, moduleName) {
3888
+ if (typeof from !== 'string' || !LOGGING_LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE.has(moduleName)) return
3889
+
3890
+ let pathsByParent = jestEsmBypassModulePathsByRuntime.get(runtime)
3891
+ if (!pathsByParent) {
3892
+ pathsByParent = new Map()
3893
+ jestEsmBypassModulePathsByRuntime.set(runtime, pathsByParent)
3894
+ }
3895
+
3896
+ let modulePaths = pathsByParent.get(from)
3897
+ if (!modulePaths) {
3898
+ modulePaths = new Map()
3899
+ pathsByParent.set(from, modulePaths)
3900
+ }
3901
+ if (modulePaths.has(moduleName)) return
3902
+
3903
+ try {
3904
+ modulePaths.set(moduleName, createRequire(from).resolve(moduleName))
3905
+ } catch {
3906
+ modulePaths.set(moduleName, undefined)
3907
+ }
3908
+ }
3909
+
3910
+ /**
3911
+ * @param {object} runtime
3912
+ * @param {string} from
3913
+ * @param {string} modulePath
3914
+ * @returns {boolean}
3915
+ */
3916
+ function hasJestEsmBypassModulePath (runtime, from, modulePath) {
3917
+ const modulePaths = jestEsmBypassModulePathsByRuntime.get(runtime)?.get(from)
3918
+ if (!modulePaths) return false
3919
+
3920
+ for (const resolvedPath of modulePaths.values()) {
3921
+ if (resolvedPath === modulePath) return true
3922
+ }
3923
+ return false
3924
+ }
3925
+
3926
+ /**
3927
+ * @param {object} runtime
3928
+ * @returns {void}
3929
+ */
3930
+ function wrapJestEsmLoader (runtime) {
3931
+ const esmLoader = runtime?.esmLoader
3932
+ if (!esmLoader || wrappedJestEsmLoaders.has(esmLoader)) return
3933
+
3934
+ wrappedJestEsmLoaders.add(esmLoader)
3935
+ if (typeof esmLoader.resolveModule === 'function') {
3936
+ shimmer.wrap(esmLoader, 'resolveModule', resolveModule => function (moduleName, from) {
3937
+ recordJestEsmBypassModulePath(runtime, from, moduleName)
3938
+ return resolveModule.apply(this, arguments)
3939
+ })
3940
+ }
3941
+ if (typeof esmLoader.resolveSpecifierForSyncGraph === 'function') {
3942
+ shimmer.wrap(
3943
+ esmLoader,
3944
+ 'resolveSpecifierForSyncGraph',
3945
+ resolveSpecifier => function (from, moduleName) {
3946
+ recordJestEsmBypassModulePath(runtime, from, moduleName)
3947
+ return resolveSpecifier.apply(this, arguments)
3948
+ }
3949
+ )
3950
+ }
3951
+ }
3952
+
3953
+ /**
3954
+ * @param {object} runtime
3955
+ * @param {string} from
3956
+ * @param {string} moduleName
3957
+ * @returns {string | undefined}
3958
+ */
3959
+ function getJestBypassModulePath (runtime, from, moduleName) {
3960
+ if (typeof from !== 'string' || typeof moduleName !== 'string') return
3961
+
3962
+ if (!LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE.has(moduleName)) {
3963
+ // Jest passes the resolved path when a CommonJS package is imported from an ESM test.
3964
+ if (path.isAbsolute(moduleName) && hasJestEsmBypassModulePath(runtime, from, moduleName)) {
3965
+ return moduleName
3966
+ }
3967
+ return
3968
+ }
3969
+
3970
+ try {
3971
+ let jestModulePath
3972
+ if (typeof runtime._resolveCjsModule === 'function') {
3973
+ jestModulePath = runtime._resolveCjsModule(from, moduleName)
3974
+ } else if (typeof runtime.cjsLoader?.resolution?.resolveCjs === 'function') {
3975
+ jestModulePath = runtime.cjsLoader.resolution.resolveCjs(from, moduleName)
3976
+ } else {
3977
+ // Jest 24-27 uses this name for its synchronous CommonJS resolver.
3978
+ jestModulePath = runtime._resolveModule(from, moduleName)
3979
+ }
3980
+ if (jestModulePath === createRequire(from).resolve(moduleName)) return jestModulePath
3981
+ } catch {
3982
+ // Let Jest produce its own resolution error or load a resolver-only module.
3983
+ }
3984
+ }
3985
+
3873
3986
  function formatDefaultStackTrace (error, structuredStackTrace) {
3874
3987
  const errorString = Error.prototype.toString.call(error)
3875
3988
  if (structuredStackTrace.length === 0) return errorString
@@ -3893,10 +4006,29 @@ addHook({
3893
4006
  })
3894
4007
  }
3895
4008
 
4009
+ // Jest 28 through 30.3 keeps ESM dependency resolution on Runtime itself.
4010
+ if (typeof Runtime.prototype.resolveModule === 'function') {
4011
+ shimmer.wrap(Runtime.prototype, 'resolveModule', resolveModule => function (moduleName, from) {
4012
+ recordJestEsmBypassModulePath(this, from, moduleName)
4013
+ return resolveModule.apply(this, arguments)
4014
+ })
4015
+ }
4016
+
4017
+ if (typeof Runtime.prototype.unstable_importModule === 'function') {
4018
+ shimmer.wrap(Runtime.prototype, 'unstable_importModule', importModule => function () {
4019
+ wrapJestEsmLoader(this)
4020
+ return importModule.apply(this, arguments)
4021
+ })
4022
+ }
4023
+
3896
4024
  shimmer.wrap(Runtime.prototype, 'requireModule', requireModule => function (from, moduleName) {
3897
4025
  wrapJestGlobalsForRuntime(this)
3898
4026
  try {
3899
- const returnedValue = requireModule.apply(this, arguments)
4027
+ // Jest calls requireModule only after deciding that the module should not be mocked.
4028
+ const bypassModulePath = getJestBypassModulePath(this, from, moduleName)
4029
+ const returnedValue = bypassModulePath
4030
+ ? requireOutsideJestRequireEngine(this, bypassModulePath)
4031
+ : requireModule.apply(this, arguments)
3900
4032
  if (moduleName === '@jest/globals') {
3901
4033
  wrapConcurrentJestGlobalsForRuntime(this, returnedValue)
3902
4034
  }
@@ -3925,11 +4057,6 @@ addHook({
3925
4057
  return formatDefaultStackTrace(error, filteredStackTrace)
3926
4058
  }
3927
4059
  try {
3928
- // TODO: do this for every library that we instrument
3929
- if (LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE.has(moduleName)) {
3930
- // To bypass jest's own require engine
3931
- return requireOutsideJestRequireEngine(this, moduleName)
3932
- }
3933
4060
  let returnedValue
3934
4061
  try {
3935
4062
  returnedValue = requireModuleOrMock.apply(this, arguments)
@@ -3,6 +3,11 @@
3
3
  const shimmer = require('../../datadog-shimmer')
4
4
  const { addHook, channel } = require('./helpers/instrument')
5
5
  const { wrapThen } = require('./helpers/promise')
6
+ const {
7
+ wrapPoolRelease,
8
+ wrapPromisePoolAcquire,
9
+ wrapPromisePoolQueryMethod,
10
+ } = require('./helpers/pool-acquire')
6
11
 
7
12
  const startRawQueryCh = channel('datadog:knex:raw:start')
8
13
  const rawQuerySubscribes = channel('datadog:knex:raw:subscribes')
@@ -32,6 +37,14 @@ addHook({
32
37
  versions: ['>=2'],
33
38
  file: 'lib/knex-builder/Knex.js',
34
39
  }, Knex => {
40
+ shimmer.wrap(Knex.Client.prototype, 'acquireConnection', acquireConnection => wrapPromisePoolAcquire(
41
+ acquireConnection,
42
+ resolveKnexDriver,
43
+ resolveKnexConfig,
44
+ knexHasIdleConnection
45
+ ))
46
+ shimmer.wrap(Knex.Client.prototype, 'releaseConnection', wrapPoolRelease)
47
+
35
48
  shimmer.wrap(Knex.Client.prototype, 'raw', raw => function (...args) {
36
49
  if (!startRawQueryCh.hasSubscribers) {
37
50
  return raw.apply(this, args)
@@ -77,6 +90,34 @@ addHook({
77
90
  return Knex
78
91
  })
79
92
 
93
+ addHook({
94
+ name: 'knex',
95
+ versions: ['>=2'],
96
+ file: 'lib/execution/runner.js',
97
+ }, Runner => {
98
+ shimmer.wrap(Runner.prototype, 'ensureConnection', ensureConnection => wrapPromisePoolQueryMethod(
99
+ ensureConnection,
100
+ runner => runner.connection || runner.builder?._connection ? undefined : runner.client,
101
+ runner => resolveKnexDriver(runner.client)
102
+ ))
103
+
104
+ return Runner
105
+ })
106
+
107
+ addHook({
108
+ name: 'knex',
109
+ versions: ['>=2'],
110
+ file: 'lib/execution/transaction.js',
111
+ }, Transaction => {
112
+ shimmer.wrap(Transaction.prototype, 'acquireConnection', acquireConnection => wrapPromisePoolQueryMethod(
113
+ acquireConnection,
114
+ (transaction, args) => args[0]?.connection ? undefined : transaction.client,
115
+ transaction => resolveKnexDriver(transaction.client)
116
+ ))
117
+
118
+ return Transaction
119
+ })
120
+
80
121
  function wrapCallbackWithFinish (callback, finish, context) {
81
122
  if (typeof callback !== 'function') return callback
82
123
 
@@ -84,3 +125,38 @@ function wrapCallbackWithFinish (callback, finish, context) {
84
125
  finish(context, () => callback.apply(this, args))
85
126
  })
86
127
  }
128
+
129
+ /**
130
+ * @param {{ pool?: { numFree?: () => number, numPendingAcquires?: () => number } }} client
131
+ * @returns {boolean}
132
+ */
133
+ function knexHasIdleConnection (client) {
134
+ const pool = client.pool
135
+ if (typeof pool?.numFree !== 'function') return false
136
+ return pool.numFree() > pool.numPendingAcquires()
137
+ }
138
+
139
+ /**
140
+ * @param {{ driverName?: string }|undefined} client
141
+ * @returns {'mysql'|'mysql2'|'pg'|undefined}
142
+ */
143
+ function resolveKnexDriver (client) {
144
+ switch (client?.driverName) {
145
+ case 'mysql':
146
+ return 'mysql'
147
+ case 'mysql2':
148
+ return 'mysql2'
149
+ case 'pg':
150
+ case 'cockroachdb':
151
+ case 'pg-redshift':
152
+ return 'pg'
153
+ }
154
+ }
155
+
156
+ /**
157
+ * @param {{ connectionSettings?: Record<string, unknown> }} client
158
+ * @returns {Record<string, unknown>}
159
+ */
160
+ function resolveKnexConfig (client) {
161
+ return client.connectionSettings ?? {}
162
+ }