dd-trace 6.9.0 → 6.11.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 (175) hide show
  1. package/README.md +0 -17
  2. package/ci/vitest-no-worker-init-setup.mjs +112 -10
  3. package/index.d.ts +150 -3
  4. package/initialize.mjs +28 -17
  5. package/openfeature.js +2 -2
  6. package/package.json +14 -10
  7. package/packages/datadog-esbuild/index.js +0 -34
  8. package/packages/datadog-instrumentations/src/anthropic.js +210 -15
  9. package/packages/datadog-instrumentations/src/aws-sdk.js +9 -1
  10. package/packages/datadog-instrumentations/src/browser-bunyan.js +11 -0
  11. package/packages/datadog-instrumentations/src/bunyan.js +3 -16
  12. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +111 -6
  13. package/packages/datadog-instrumentations/src/cucumber.js +26 -11
  14. package/packages/datadog-instrumentations/src/cypress-config.js +182 -16
  15. package/packages/datadog-instrumentations/src/cypress-legacy-finalizers.js +30 -0
  16. package/packages/datadog-instrumentations/src/cypress.js +2 -0
  17. package/packages/datadog-instrumentations/src/fastify.js +2 -0
  18. package/packages/datadog-instrumentations/src/helpers/bunyan.js +22 -0
  19. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -1
  20. package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +634 -0
  21. package/packages/datadog-instrumentations/src/helpers/register.js +10 -8
  22. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -1
  23. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +81 -0
  24. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
  25. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +83 -1
  26. package/packages/datadog-instrumentations/src/jest.js +26 -18
  27. package/packages/datadog-instrumentations/src/mariadb.js +278 -21
  28. package/packages/datadog-instrumentations/src/mocha/main.js +540 -56
  29. package/packages/datadog-instrumentations/src/mocha/utils.js +132 -25
  30. package/packages/datadog-instrumentations/src/mysql.js +45 -15
  31. package/packages/datadog-instrumentations/src/mysql2.js +119 -18
  32. package/packages/datadog-instrumentations/src/path-to-regexp.js +67 -1
  33. package/packages/datadog-instrumentations/src/pg.js +116 -92
  34. package/packages/datadog-instrumentations/src/playwright-reporter.js +99 -0
  35. package/packages/datadog-instrumentations/src/playwright.js +149 -2
  36. package/packages/datadog-instrumentations/src/router.js +2 -0
  37. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +43 -4
  38. package/packages/datadog-instrumentations/src/vitest-main.js +180 -20
  39. package/packages/datadog-instrumentations/src/vitest-util.js +64 -5
  40. package/packages/datadog-instrumentations/src/vitest-worker.js +150 -25
  41. package/packages/datadog-instrumentations/src/webdriverio.js +31 -17
  42. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +12 -6
  43. package/packages/datadog-plugin-aws-sdk/src/base.js +1 -0
  44. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +163 -44
  45. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -13
  46. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -5
  47. package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
  48. package/packages/datadog-plugin-browser-bunyan/src/index.js +9 -0
  49. package/packages/datadog-plugin-bunyan/src/index.js +5 -8
  50. package/packages/datadog-plugin-cucumber/src/index.js +11 -0
  51. package/packages/datadog-plugin-cypress/src/after-run.js +5 -1
  52. package/packages/datadog-plugin-cypress/src/after-spec.js +5 -1
  53. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +82 -30
  54. package/packages/datadog-plugin-cypress/src/finalization.js +76 -0
  55. package/packages/datadog-plugin-cypress/src/index.js +12 -6
  56. package/packages/datadog-plugin-cypress/src/plugin.js +16 -3
  57. package/packages/datadog-plugin-dd-trace-api/src/index.js +4 -0
  58. package/packages/datadog-plugin-electron/src/index.js +2 -0
  59. package/packages/datadog-plugin-fs/src/index.js +1 -1
  60. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +31 -17
  61. package/packages/datadog-plugin-jest/src/index.js +11 -4
  62. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -3
  63. package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -3
  64. package/packages/datadog-plugin-kafkajs/src/producer.js +3 -2
  65. package/packages/datadog-plugin-kafkajs/src/utils.js +65 -7
  66. package/packages/datadog-plugin-mocha/src/index.js +606 -40
  67. package/packages/datadog-plugin-mysql/src/index.js +37 -0
  68. package/packages/datadog-plugin-nats/src/index.js +1 -1
  69. package/packages/datadog-plugin-next/src/index.js +1 -19
  70. package/packages/datadog-plugin-openai/src/tracing.js +41 -30
  71. package/packages/datadog-plugin-openai-agents/src/integration.js +279 -69
  72. package/packages/datadog-plugin-openai-agents/src/processor.js +16 -4
  73. package/packages/datadog-plugin-pg/src/index.js +1 -0
  74. package/packages/datadog-plugin-playwright/src/index.js +42 -13
  75. package/packages/datadog-plugin-vitest/src/index.js +14 -20
  76. package/packages/datadog-plugin-ws/src/util.js +2 -1
  77. package/packages/datadog-webpack/index.js +0 -11
  78. package/packages/dd-trace/index.js +0 -1
  79. package/packages/dd-trace/src/agent/info.js +6 -5
  80. package/packages/dd-trace/src/aiguard/client.js +100 -1
  81. package/packages/dd-trace/src/aiguard/errors.js +41 -0
  82. package/packages/dd-trace/src/aiguard/evaluation.js +357 -0
  83. package/packages/dd-trace/src/aiguard/integrations/anthropic.js +70 -0
  84. package/packages/dd-trace/src/aiguard/integrations/index.js +4 -0
  85. package/packages/dd-trace/src/aiguard/messages/anthropic.js +423 -0
  86. package/packages/dd-trace/src/aiguard/messages/openai.js +1 -24
  87. package/packages/dd-trace/src/aiguard/messages/utils.js +28 -0
  88. package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +1 -11
  89. package/packages/dd-trace/src/aiguard/sdk.js +22 -278
  90. package/packages/dd-trace/src/appsec/api_security/normalized-route.js +453 -0
  91. package/packages/dd-trace/src/appsec/handlers/http-request.js +13 -0
  92. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +9 -12
  93. package/packages/dd-trace/src/carrier.js +356 -0
  94. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +1 -0
  95. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +27 -3
  96. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +22 -6
  97. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +21 -5
  98. package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +164 -0
  99. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +22 -6
  100. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +365 -32
  101. package/packages/dd-trace/src/ci-visibility/exporters/request.js +201 -0
  102. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +5 -3
  103. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -5
  104. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
  105. package/packages/dd-trace/src/ci-visibility/requests/rate-limit.js +39 -0
  106. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -6
  107. package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +6 -2
  108. package/packages/dd-trace/src/config/generated-config-types.d.ts +7 -0
  109. package/packages/dd-trace/src/config/index.js +13 -2
  110. package/packages/dd-trace/src/config/major-overrides.js +7 -0
  111. package/packages/dd-trace/src/config/supported-configurations.json +24 -0
  112. package/packages/dd-trace/src/datastreams/context.js +6 -1
  113. package/packages/dd-trace/src/datastreams/index.js +2 -0
  114. package/packages/dd-trace/src/datastreams/manager.js +14 -3
  115. package/packages/dd-trace/src/datastreams/pathway.js +23 -22
  116. package/packages/dd-trace/src/datastreams/processor.js +16 -13
  117. package/packages/dd-trace/src/datastreams/size.js +5 -0
  118. package/packages/dd-trace/src/debugger/devtools_client/index.js +3 -2
  119. package/packages/dd-trace/src/exporters/agent/writer.js +49 -9
  120. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +6 -4
  121. package/packages/dd-trace/src/exporters/common/writer.js +11 -6
  122. package/packages/dd-trace/src/llmobs/constants/tags.js +5 -0
  123. package/packages/dd-trace/src/llmobs/experiments/client.js +163 -5
  124. package/packages/dd-trace/src/llmobs/experiments/dataset.js +241 -87
  125. package/packages/dd-trace/src/llmobs/experiments/experiment.js +280 -20
  126. package/packages/dd-trace/src/llmobs/experiments/index.js +58 -59
  127. package/packages/dd-trace/src/llmobs/experiments/noop.js +71 -3
  128. package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
  129. package/packages/dd-trace/src/llmobs/experiments/util.js +41 -5
  130. package/packages/dd-trace/src/llmobs/index.js +34 -2
  131. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +12 -3
  132. package/packages/dd-trace/src/llmobs/plugins/base.js +4 -2
  133. package/packages/dd-trace/src/llmobs/span_processor.js +16 -0
  134. package/packages/dd-trace/src/llmobs/tagger.js +96 -0
  135. package/packages/dd-trace/src/llmobs/util.js +78 -0
  136. package/packages/dd-trace/src/noop/proxy.js +3 -4
  137. package/packages/dd-trace/src/openfeature/flagging_provider.js +18 -2
  138. package/packages/dd-trace/src/openfeature/remote_config.js +1 -1
  139. package/packages/dd-trace/src/opentelemetry/context_manager.js +7 -7
  140. package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +2 -1
  141. package/packages/dd-trace/src/opentelemetry/logs/logger.js +67 -11
  142. package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +14 -3
  143. package/packages/dd-trace/src/opentelemetry/metrics/index.js +25 -12
  144. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +2 -5
  145. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +96 -43
  146. package/packages/dd-trace/src/opentracing/propagation/text_map.js +126 -120
  147. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +4 -8
  148. package/packages/dd-trace/src/opentracing/tracer.js +5 -2
  149. package/packages/dd-trace/src/otel-thread-ctx.js +387 -0
  150. package/packages/dd-trace/src/plugin_manager.js +5 -3
  151. package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
  152. package/packages/dd-trace/src/plugins/index.js +1 -0
  153. package/packages/{datadog-plugin-jest/src/util.js → dd-trace/src/plugins/util/jest.js} +5 -65
  154. package/packages/dd-trace/src/plugins/util/test.js +93 -14
  155. package/packages/dd-trace/src/plugins/util/web.js +56 -2
  156. package/packages/dd-trace/src/profiling/profiler.js +1 -1
  157. package/packages/dd-trace/src/profiling/profilers/space.js +1 -3
  158. package/packages/dd-trace/src/profiling/profilers/wall.js +37 -90
  159. package/packages/dd-trace/src/profiling/webspan-utils.js +45 -0
  160. package/packages/dd-trace/src/proxy.js +38 -29
  161. package/packages/dd-trace/src/ritm.js +9 -2
  162. package/packages/dd-trace/src/serverless.js +37 -0
  163. package/packages/dd-trace/src/span_format.js +1 -0
  164. package/packages/dd-trace/src/span_stats.js +30 -3
  165. package/packages/dd-trace/src/storage-channels.js +86 -0
  166. package/packages/dd-trace/src/tracer.js +9 -2
  167. package/packages/dd-trace/src/tracer_metadata.js +14 -1
  168. package/packages/dd-trace/src/web-tags-cache.js +132 -0
  169. package/vendor/dist/@datadog/openfeature-node-server/LICENSE +201 -0
  170. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -0
  171. package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +0 -65
  172. package/packages/datadog-webpack/src/optional-peer-loader.js +0 -17
  173. package/packages/dd-trace/src/feature-registry.js +0 -29
  174. package/packages/dd-trace/src/openfeature/register.js +0 -35
  175. package/packages/dd-trace/src/openfeature/require-provider.js +0 -18
@@ -7,9 +7,18 @@ const { pathToFileURL } = require('url')
7
7
 
8
8
  const log = require('../../dd-trace/src/log')
9
9
  const { getSegment } = require('../../dd-trace/src/util')
10
+ const {
11
+ finalizeAfterUserHandlers,
12
+ manualPluginOwner,
13
+ runUserHandler,
14
+ } = require('../../datadog-plugin-cypress/src/finalization')
10
15
  const { channel } = require('./helpers/instrument')
11
16
 
12
17
  const DD_CONFIG_WRAPPED = Symbol.for('dd-trace.cypress.config.wrapped')
18
+ const DD_CYPRESS_AFTER_SPEC_HANDLER = Symbol.for('dd-trace.cypress.after-spec.handler')
19
+ const DD_CYPRESS_AFTER_RUN_HANDLER = Symbol.for('dd-trace.cypress.after-run.handler')
20
+ const DD_CYPRESS_TASK_HANDLER = Symbol.for('dd-trace.cypress.task.handler')
21
+ const DD_CYPRESS_NOOP_TASK_HANDLER = Symbol.for('dd-trace.cypress.noop-task.handler')
13
22
  const BROWSER_INSTRUMENTATION_NOT_INSTALLED =
14
23
  'Browser-side Cypress Test Optimization instrumentation was not installed.'
15
24
  const CONFIG_INSTRUMENTATION_NOT_INSTALLED =
@@ -184,6 +193,47 @@ function isDatadogTaskRegistration (handler) {
184
193
  typeof handler['dd:addTags'] === 'function'
185
194
  }
186
195
 
196
+ /**
197
+ * @param {unknown} handler Cypress after:run handler
198
+ * @returns {boolean} whether this is the handler registered by the manual Datadog plugin
199
+ */
200
+ function isDatadogAfterRunHandler (handler) {
201
+ return typeof handler === 'function' && handler[DD_CYPRESS_AFTER_RUN_HANDLER] === true
202
+ }
203
+
204
+ /**
205
+ * @param {unknown} handler Cypress after:spec handler
206
+ * @returns {boolean} whether this is the handler registered by the manual Datadog plugin
207
+ */
208
+ function isDatadogAfterSpecHandler (handler) {
209
+ return typeof handler === 'function' && handler[DD_CYPRESS_AFTER_SPEC_HANDLER] === true
210
+ }
211
+
212
+ /**
213
+ * @param {object} manualPlugin manual plugin registration state
214
+ * @returns {boolean} whether the manual plugin supports error-aware finalization
215
+ */
216
+ function supportsErrorAwareFinalization (manualPlugin) {
217
+ return isDatadogAfterSpecHandler(manualPlugin.afterSpecHandler) &&
218
+ isDatadogAfterRunHandler(manualPlugin.afterRunHandler)
219
+ }
220
+
221
+ /**
222
+ * @param {unknown} handler Cypress task handler map
223
+ * @returns {boolean} whether the current manual Datadog plugin owns the task map
224
+ */
225
+ function isCurrentDatadogTaskRegistration (handler) {
226
+ return !!handler && handler[DD_CYPRESS_TASK_HANDLER] === manualPluginOwner
227
+ }
228
+
229
+ /**
230
+ * @param {unknown} handler Cypress task handler map
231
+ * @returns {boolean} whether the manual plugin registered only fallback tasks
232
+ */
233
+ function isDatadogNoopTaskRegistration (handler) {
234
+ return !!handler && handler[DD_CYPRESS_NOOP_TASK_HANDLER] === true
235
+ }
236
+
187
237
  /**
188
238
  * @param {unknown} value
189
239
  * @returns {boolean}
@@ -393,15 +443,61 @@ function registerManualAfterScreenshotHandlers (on, handlers, datadogHandler) {
393
443
  *
394
444
  * @param {Function} on Cypress event registration function
395
445
  * @param {Function[]} handlers collected after:spec handlers
446
+ * @param {Function} [datadogHandler] manual Datadog after:spec handler
447
+ * @param {Function} [cleanup] removes generated support files after an error
396
448
  * @returns {void}
397
449
  */
398
- function registerAfterSpecHandlers (on, handlers) {
399
- if (handlers.length === 0) return
450
+ function registerAfterSpecHandlers (on, handlers, datadogHandler, cleanup) {
451
+ const userHandlers = datadogHandler
452
+ ? handlers.filter(handler => handler !== datadogHandler)
453
+ : handlers
400
454
 
401
- on('after:spec', (spec, results) => handlers.reduce(
402
- (chain, handler) => chain.then(() => handler(spec, results)),
403
- Promise.resolve()
404
- ))
455
+ if (userHandlers.length === 0) {
456
+ if (datadogHandler) {
457
+ if (cleanup) {
458
+ on('after:spec', (...args) => Promise.resolve().then(() => datadogHandler(...args)).catch((error) => {
459
+ cleanup()
460
+ throw error
461
+ }))
462
+ } else {
463
+ on('after:spec', datadogHandler)
464
+ }
465
+ }
466
+ return
467
+ }
468
+
469
+ on('after:spec', (spec, results) => {
470
+ const callHandler = datadogHandler
471
+ ? handler => runUserHandler(() => handler(spec, results))
472
+ : handler => handler(spec, results)
473
+ const chain = userHandlers.reduce(
474
+ (promise, handler) => promise.then(() => callHandler(handler)),
475
+ Promise.resolve()
476
+ )
477
+ if (!datadogHandler) return chain
478
+ const finalization = finalizeAfterUserHandlers(chain, (...args) => datadogHandler(spec, results, ...args))
479
+ if (!cleanup) return finalization
480
+ return finalization.catch((error) => {
481
+ cleanup()
482
+ throw error
483
+ })
484
+ })
485
+ }
486
+
487
+ /**
488
+ * Enables the Cypress lifecycle events needed to finish Test Optimization
489
+ * sessions in interactive mode.
490
+ *
491
+ * @param {object} config Cypress resolved config object
492
+ * @returns {void}
493
+ */
494
+ function enableInteractiveRunEvents (config) {
495
+ if (config.isInteractive && config.experimentalInteractiveRunEvents !== true) {
496
+ config.experimentalInteractiveRunEvents = true
497
+ log.warn(
498
+ 'Datadog enabled Cypress experimentalInteractiveRunEvents so Test Optimization can finish the test session.'
499
+ )
500
+ }
405
501
  }
406
502
 
407
503
  /**
@@ -412,6 +508,7 @@ function registerAfterSpecHandlers (on, handlers) {
412
508
  *
413
509
  * @param {Function} on Cypress event registration function
414
510
  * @param {object} config Cypress resolved config object
511
+ * @param {Function[]} userBeforeRunHandlers user's before:run handlers collected from wrappedOn
415
512
  * @param {Function[]} userAfterSpecHandlers user's after:spec handlers collected from wrappedOn
416
513
  * @param {Function[]} userAfterRunHandlers user's after:run handlers collected from wrappedOn
417
514
  * @param {Function[]} userAfterScreenshotHandlers user's after:screenshot handlers collected from wrappedOn
@@ -421,6 +518,7 @@ function registerAfterSpecHandlers (on, handlers) {
421
518
  function registerDdTraceHooks (
422
519
  on,
423
520
  config,
521
+ userBeforeRunHandlers,
424
522
  userAfterSpecHandlers,
425
523
  userAfterRunHandlers,
426
524
  userAfterScreenshotHandlers,
@@ -433,13 +531,23 @@ function registerDdTraceHooks (
433
531
  if (generatedSupportFiles) cleanupGeneratedFiles(generatedSupportFiles)
434
532
  }
435
533
 
436
- const registerAfterRunWithCleanup = () => {
534
+ const registerAfterRunWithCleanup = (datadogHandler) => {
535
+ const handlers = datadogHandler
536
+ ? userAfterRunHandlers.filter(handler => handler !== datadogHandler)
537
+ : userAfterRunHandlers
538
+
437
539
  on('after:run', (results) => {
438
- const chain = userAfterRunHandlers.reduce(
439
- (p, h) => p.then(() => h(results)),
540
+ const callHandler = datadogHandler
541
+ ? handler => runUserHandler(() => handler(results))
542
+ : handler => handler(results)
543
+ const chain = handlers.reduce(
544
+ (promise, handler) => promise.then(() => callHandler(handler)),
440
545
  Promise.resolve()
441
546
  )
442
- return chain.finally(cleanupWrapper)
547
+ if (!datadogHandler) return chain.finally(cleanupWrapper)
548
+
549
+ return finalizeAfterUserHandlers(chain, (...args) => datadogHandler(results, ...args))
550
+ .finally(cleanupWrapper)
443
551
  })
444
552
  }
445
553
 
@@ -450,13 +558,36 @@ function registerDdTraceHooks (
450
558
  on('task', noopTask)
451
559
  }
452
560
 
453
- if (manualPlugin.detected) {
454
- registerAfterSpecHandlers(on, userAfterSpecHandlers)
561
+ if (manualPlugin.detected &&
562
+ (manualPlugin.isNoop ||
563
+ manualPlugin.ownsCurrentPlugin ||
564
+ supportsErrorAwareFinalization(manualPlugin) ||
565
+ !setupNodeEventsCh.hasSubscribers)) {
566
+ if (manualPlugin.afterRunHandler) {
567
+ enableInteractiveRunEvents(config)
568
+ if (manualPlugin.initialConfig !== config) {
569
+ manualPlugin.initialConfig.experimentalInteractiveRunEvents = config.experimentalInteractiveRunEvents
570
+ }
571
+ }
572
+ for (const handler of userBeforeRunHandlers) on('before:run', handler)
573
+ registerAfterSpecHandlers(on, userAfterSpecHandlers, manualPlugin.afterSpecHandler, cleanupWrapper)
455
574
  registerManualAfterScreenshotHandlers(on, userAfterScreenshotHandlers, manualPlugin.afterScreenshotHandler)
456
- registerAfterRunWithCleanup()
575
+ registerAfterRunWithCleanup(manualPlugin.afterRunHandler)
576
+ on('task', manualPlugin.taskHandler)
457
577
  return config
458
578
  }
459
579
 
580
+ if (manualPlugin.detected) {
581
+ userBeforeRunHandlers = userBeforeRunHandlers.filter(handler => handler !== manualPlugin.beforeRunHandler)
582
+ userAfterSpecHandlers = userAfterSpecHandlers.filter(handler => handler !== manualPlugin.afterSpecHandler)
583
+ userAfterRunHandlers = userAfterRunHandlers.filter(handler => handler !== manualPlugin.afterRunHandler)
584
+ userAfterScreenshotHandlers = userAfterScreenshotHandlers.filter(
585
+ handler => handler !== manualPlugin.afterScreenshotHandler
586
+ )
587
+ }
588
+
589
+ for (const handler of userBeforeRunHandlers) on('before:run', handler)
590
+
460
591
  if (!setupNodeEventsCh.hasSubscribers) {
461
592
  registerNoopHandlers()
462
593
  return config
@@ -483,6 +614,7 @@ function registerDdTraceHooks (
483
614
  return config
484
615
  }
485
616
 
617
+ enableInteractiveRunEvents(config)
486
618
  return payload.configPromise || config
487
619
  }
488
620
 
@@ -492,28 +624,60 @@ function registerDdTraceHooks (
492
624
  */
493
625
  function wrapSetupNodeEvents (originalSetupNodeEvents) {
494
626
  return function ddSetupNodeEvents (on, config) {
627
+ const userBeforeRunHandlers = []
495
628
  const userAfterSpecHandlers = []
496
629
  const userAfterRunHandlers = []
497
630
  const userAfterScreenshotHandlers = []
498
631
  const manualPlugin = {
499
632
  detected: false,
633
+ initialConfig: config,
634
+ beforeRunHandler: undefined,
635
+ afterSpecHandler: undefined,
636
+ afterRunHandler: undefined,
500
637
  afterScreenshotHandler: undefined,
638
+ taskHandler: undefined,
639
+ ownsCurrentPlugin: false,
640
+ isNoop: false,
501
641
  }
642
+ const recentRegistrations = []
502
643
 
503
644
  const wrappedOn = (event, handler) => {
504
- if (event === 'after:spec') {
645
+ if (event === 'before:run') {
646
+ userBeforeRunHandlers.push(handler)
647
+ } else if (event === 'after:spec') {
505
648
  userAfterSpecHandlers.push(handler)
649
+ if (isDatadogAfterSpecHandler(handler)) manualPlugin.afterSpecHandler = handler
506
650
  } else if (event === 'after:run') {
507
651
  userAfterRunHandlers.push(handler)
652
+ if (isDatadogAfterRunHandler(handler)) manualPlugin.afterRunHandler = handler
508
653
  } else if (event === 'after:screenshot') {
509
654
  userAfterScreenshotHandlers.push(handler)
510
655
  } else {
511
656
  if (event === 'task' && isDatadogTaskRegistration(handler)) {
512
657
  manualPlugin.detected = true
513
- manualPlugin.afterScreenshotHandler = userAfterScreenshotHandlers.at(-1)
658
+ manualPlugin.ownsCurrentPlugin = isCurrentDatadogTaskRegistration(handler)
659
+ manualPlugin.isNoop = isDatadogNoopTaskRegistration(handler)
660
+ const afterRun = recentRegistrations.at(-1)
661
+ const afterSpec = recentRegistrations.at(-2)
662
+ const possibleAfterScreenshot = recentRegistrations.at(-3)
663
+ const hasAfterScreenshot = possibleAfterScreenshot?.event === 'after:screenshot'
664
+ const beforeRun = hasAfterScreenshot ? recentRegistrations.at(-4) : possibleAfterScreenshot
665
+ if (!manualPlugin.isNoop &&
666
+ beforeRun?.event === 'before:run' &&
667
+ afterSpec?.event === 'after:spec' &&
668
+ afterRun?.event === 'after:run') {
669
+ manualPlugin.beforeRunHandler ||= beforeRun.handler
670
+ manualPlugin.afterSpecHandler ||= afterSpec.handler
671
+ manualPlugin.afterRunHandler ||= afterRun.handler
672
+ if (hasAfterScreenshot) manualPlugin.afterScreenshotHandler ||= possibleAfterScreenshot.handler
673
+ }
674
+ manualPlugin.taskHandler = handler
675
+ } else {
676
+ on(event, handler)
514
677
  }
515
- on(event, handler)
516
678
  }
679
+ recentRegistrations.push({ event, handler })
680
+ if (recentRegistrations.length > 4) recentRegistrations.shift()
517
681
  }
518
682
 
519
683
  const maybePromise = originalSetupNodeEvents
@@ -525,6 +689,7 @@ function wrapSetupNodeEvents (originalSetupNodeEvents) {
525
689
  return registerDdTraceHooks(
526
690
  on,
527
691
  mergeReturnedConfig(config, result),
692
+ userBeforeRunHandlers,
528
693
  userAfterSpecHandlers,
529
694
  userAfterRunHandlers,
530
695
  userAfterScreenshotHandlers,
@@ -536,6 +701,7 @@ function wrapSetupNodeEvents (originalSetupNodeEvents) {
536
701
  return registerDdTraceHooks(
537
702
  on,
538
703
  mergeReturnedConfig(config, maybePromise),
704
+ userBeforeRunHandlers,
539
705
  userAfterSpecHandlers,
540
706
  userAfterRunHandlers,
541
707
  userAfterScreenshotHandlers,
@@ -0,0 +1,30 @@
1
+ 'use strict'
2
+
3
+ const { shouldDeferLegacyFinalization } = require('../../datadog-plugin-cypress/src/finalization')
4
+ const Hook = require('./helpers/hook')
5
+
6
+ const DD_CYPRESS_LEGACY_FINALIZER_WRAPPED = Symbol.for('dd-trace.cypress.legacy-finalizer.wrapped')
7
+ const LEGACY_FINALIZER_MODULES = new Set([
8
+ 'dd-trace/packages/datadog-plugin-cypress/src/after-run.js',
9
+ 'dd-trace/packages/datadog-plugin-cypress/src/after-spec.js',
10
+ ])
11
+
12
+ /**
13
+ * @param {Function} finalizer standalone Datadog Cypress finalizer
14
+ * @returns {Function} context-aware finalizer
15
+ */
16
+ function wrapLegacyFinalizer (finalizer) {
17
+ if (finalizer[DD_CYPRESS_LEGACY_FINALIZER_WRAPPED]) return finalizer
18
+
19
+ function wrappedLegacyFinalizer () {
20
+ if (shouldDeferLegacyFinalization()) return
21
+ return finalizer.apply(this, arguments)
22
+ }
23
+ wrappedLegacyFinalizer[DD_CYPRESS_LEGACY_FINALIZER_WRAPPED] = true
24
+ return wrappedLegacyFinalizer
25
+ }
26
+
27
+ Hook(['dd-trace'], { internals: true }, (moduleExports, moduleName) => {
28
+ if (!LEGACY_FINALIZER_MODULES.has(moduleName.replaceAll('\\', '/'))) return moduleExports
29
+ return wrapLegacyFinalizer(moduleExports)
30
+ })
@@ -8,6 +8,8 @@ const {
8
8
  wrapConfig,
9
9
  } = require('./cypress-config')
10
10
 
11
+ require('./cypress-legacy-finalizers')
12
+
11
13
  const MINIMUM_CYPRESS_VERSION = DD_MAJOR >= 6 ? '>=12.0.0' : '>=10.2.0'
12
14
 
13
15
  // Wrap defineConfig() so configs are instrumented when loaded in Cypress's
@@ -146,6 +146,7 @@ function wrapHookDone (ctx, request, reply, req, name, doneCallback) {
146
146
  ctx.error = error
147
147
  publishError(ctx)
148
148
 
149
+ // eslint-disable-next-line no-restricted-syntax -- arbitrary cookie names; publishing {} sets a WAF address
149
150
  const hasCookies = request.cookies && Object.keys(request.cookies).length > 0
150
151
 
151
152
  if (cookieParserReadCh.hasSubscribers && hasCookies && !cookiesPublished.has(req)) {
@@ -193,6 +194,7 @@ function preHandler (request, reply, done) {
193
194
  const res = getRes(reply)
194
195
  const ctx = { req, res }
195
196
 
197
+ // eslint-disable-next-line no-restricted-syntax -- arbitrary body keys; publishing {} sets a WAF address
196
198
  const hasBody = request.body && Object.keys(request.body).length > 0
197
199
 
198
200
  // For multipart/form-data, the body is not available until after preValidation hook
@@ -0,0 +1,22 @@
1
+ 'use strict'
2
+
3
+ const shimmer = require('../../../datadog-shimmer')
4
+ const { channel } = require('./instrument')
5
+
6
+ /**
7
+ * @param {{ prototype: object }} Logger
8
+ * @param {string} id
9
+ */
10
+ module.exports = function wrapLogger (Logger, id) {
11
+ const logCh = channel(`apm:${id}:log`)
12
+ shimmer.wrap(Logger.prototype, '_emit', emit => {
13
+ return function wrappedEmit (rec) {
14
+ if (logCh.hasSubscribers) {
15
+ const payload = { message: rec }
16
+ logCh.publish(payload)
17
+ arguments[0] = payload.message
18
+ }
19
+ return emit.apply(this, arguments)
20
+ }
21
+ })
22
+ }
@@ -70,6 +70,7 @@ module.exports = {
70
70
  'aws-sdk': () => require('../aws-sdk'),
71
71
  bluebird: () => require('../bluebird'),
72
72
  'body-parser': () => require('../body-parser'),
73
+ 'browser-bunyan': () => require('../browser-bunyan'),
73
74
  bullmq: () => require('../bullmq'),
74
75
  bunyan: () => require('../bunyan'),
75
76
  'cassandra-driver': () => require('../cassandra-driver'),
@@ -110,7 +111,7 @@ module.exports = {
110
111
  'light-my-request': () => require('../light-my-request'),
111
112
  'limitd-client': () => require('../limitd-client'),
112
113
  lodash: () => require('../lodash'),
113
- mariadb: () => require('../mariadb'),
114
+ mariadb: { esmFirst: true, fn: () => require('../mariadb') },
114
115
  memcached: () => require('../memcached'),
115
116
  mercurius: () => require('../mercurius'),
116
117
  'microgateway-core': () => require('../microgateway-core'),