dd-trace 6.12.0 → 6.13.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 (97) hide show
  1. package/ci/test-optimization-validation/framework-adapters/cypress.js +9 -11
  2. package/ci/test-optimization-validation/scenarios/ci-wiring.js +5 -4
  3. package/index.d.ts +127 -26
  4. package/package.json +10 -10
  5. package/packages/datadog-instrumentations/src/bunyan.js +4 -2
  6. package/packages/datadog-instrumentations/src/helpers/bunyan.js +12 -3
  7. package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +1 -0
  8. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +28 -0
  9. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
  10. package/packages/datadog-instrumentations/src/jest.js +140 -18
  11. package/packages/datadog-instrumentations/src/mariadb-bundle.js +1597 -0
  12. package/packages/datadog-instrumentations/src/mariadb.js +7 -0
  13. package/packages/datadog-instrumentations/src/pino.js +15 -4
  14. package/packages/datadog-instrumentations/src/playwright.js +34 -20
  15. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +7 -4
  16. package/packages/datadog-instrumentations/src/vitest-worker.js +11 -0
  17. package/packages/datadog-instrumentations/src/webdriverio.js +26 -0
  18. package/packages/datadog-instrumentations/src/winston.js +6 -3
  19. package/packages/datadog-plugin-cypress/src/support.js +1 -0
  20. package/packages/datadog-plugin-http/src/client.js +2 -15
  21. package/packages/datadog-plugin-http2/src/client.js +2 -15
  22. package/packages/datadog-plugin-openai-agents/src/integration.js +15 -11
  23. package/packages/datadog-plugin-playwright/src/index.js +9 -1
  24. package/packages/datadog-plugin-undici/src/index.js +2 -15
  25. package/packages/dd-trace/src/aiguard/evaluation.js +94 -20
  26. package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -3
  27. package/packages/dd-trace/src/aiguard/messages/anthropic.js +21 -9
  28. package/packages/dd-trace/src/aiguard/noop.js +9 -1
  29. package/packages/dd-trace/src/aiguard/redaction.js +183 -0
  30. package/packages/dd-trace/src/aiguard/sdk.js +7 -2
  31. package/packages/dd-trace/src/aiguard/tags.js +2 -0
  32. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +10 -9
  33. package/packages/dd-trace/src/appsec/rule_manager.js +2 -0
  34. package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +51 -26
  35. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +5 -11
  36. package/packages/dd-trace/src/ci-visibility/final-flush.js +20 -0
  37. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +196 -29
  38. package/packages/dd-trace/src/config/generated-config-types.d.ts +6 -0
  39. package/packages/dd-trace/src/config/index.js +2 -1
  40. package/packages/dd-trace/src/config/supported-configurations.json +27 -0
  41. package/packages/dd-trace/src/debugger/devtools_client/send.js +4 -3
  42. package/packages/dd-trace/src/dogstatsd.js +45 -18
  43. package/packages/dd-trace/src/encode/agentless-json.js +5 -4
  44. package/packages/dd-trace/src/exporters/agent/index.js +22 -2
  45. package/packages/dd-trace/src/exporters/agent/writer.js +4 -4
  46. package/packages/dd-trace/src/exporters/common/writer.js +24 -2
  47. package/packages/dd-trace/src/exporters/span-stats/index.js +23 -4
  48. package/packages/dd-trace/src/external-logger/src/index.js +4 -3
  49. package/packages/dd-trace/src/flush.js +102 -0
  50. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -0
  51. package/packages/dd-trace/src/llmobs/experiments/dataset.js +51 -2
  52. package/packages/dd-trace/src/llmobs/experiments/experiment.js +420 -105
  53. package/packages/dd-trace/src/llmobs/experiments/index.js +54 -42
  54. package/packages/dd-trace/src/llmobs/experiments/noop.js +39 -8
  55. package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
  56. package/packages/dd-trace/src/llmobs/experiments/util.js +21 -0
  57. package/packages/dd-trace/src/llmobs/index.js +80 -17
  58. package/packages/dd-trace/src/llmobs/noop.js +2 -1
  59. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +8 -4
  60. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +6 -3
  61. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +13 -6
  62. package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +5 -7
  63. package/packages/dd-trace/src/llmobs/writers/base.js +60 -24
  64. package/packages/dd-trace/src/noop/span.js +5 -0
  65. package/packages/dd-trace/src/openfeature/writers/exposures.js +8 -1
  66. package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +45 -3
  67. package/packages/dd-trace/src/opentelemetry/logs/index.js +4 -1
  68. package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +7 -4
  69. package/packages/dd-trace/src/opentelemetry/metrics/index.js +3 -1
  70. package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +8 -0
  71. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +4 -2
  72. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +4 -2
  73. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +25 -5
  74. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +61 -25
  75. package/packages/dd-trace/src/opentelemetry/tracer.js +26 -2
  76. package/packages/dd-trace/src/opentracing/propagation/text_map.js +410 -342
  77. package/packages/dd-trace/src/opentracing/span.js +28 -0
  78. package/packages/dd-trace/src/otel-thread-ctx.js +23 -5
  79. package/packages/dd-trace/src/plugin_manager.js +2 -0
  80. package/packages/dd-trace/src/plugins/util/status-validator.js +98 -0
  81. package/packages/dd-trace/src/plugins/util/test.js +74 -21
  82. package/packages/dd-trace/src/plugins/util/web.js +2 -65
  83. package/packages/dd-trace/src/profiling/oom.js +4 -3
  84. package/packages/dd-trace/src/profiling/profiler.js +7 -0
  85. package/packages/dd-trace/src/profiling/profilers/events.js +3 -3
  86. package/packages/dd-trace/src/profiling/profilers/wall.js +14 -14
  87. package/packages/dd-trace/src/proxy.js +36 -8
  88. package/packages/dd-trace/src/runtime_metrics/index.js +5 -0
  89. package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +5 -0
  90. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +17 -6
  91. package/packages/dd-trace/src/serverless/telemetry-delivery-tracker.js +55 -0
  92. package/packages/dd-trace/src/serverless/vercel.js +122 -0
  93. package/packages/dd-trace/src/serverless.js +37 -20
  94. package/packages/dd-trace/src/span_stats.js +40 -3
  95. package/packages/dd-trace/src/tracer.js +22 -0
  96. package/packages/dd-trace/src/web-tags-cache.js +67 -13
  97. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
@@ -20,7 +20,6 @@ const {
20
20
  } = require('../../dd-trace/src/ci-visibility/efd-retry-policy')
21
21
  const {
22
22
  getCoveredFilesFromCoverage,
23
- getExecutableFilesFromCoverage,
24
23
  JEST_WORKER_TRACE_PAYLOAD_CODE,
25
24
  JEST_WORKER_COVERAGE_PAYLOAD_CODE,
26
25
  JEST_WORKER_TELEMETRY_PAYLOAD_CODE,
@@ -39,7 +38,7 @@ const {
39
38
  logAttemptToFixTestExecution,
40
39
  logTestOptimizationSummary,
41
40
  TEST_IMPACT_ANALYSIS_ALL_TESTS_SKIPPED_MESSAGE,
42
- getTestCoverageLinesPercentage,
41
+ getTestCoverageLinesData,
43
42
  applySkippedCoverageToCoverage,
44
43
  getTestOptimizationRequestResults,
45
44
  } = require('../../dd-trace/src/plugins/util/test')
@@ -174,9 +173,11 @@ const newTests = new Set()
174
173
  const testSuiteJestObjects = new Map()
175
174
  const testSuiteDatadogEnvironments = new Map()
176
175
  const wrappedJestGlobals = new WeakSet()
176
+ const wrappedJestEsmLoaders = new WeakSet()
177
177
  const wrappedJestObjects = new WeakSet()
178
178
  const wrappedWorkerInitializers = new WeakSet()
179
179
  const publishedRuntimeReferenceErrors = new WeakMap()
180
+ const jestEsmBypassModulePathsByRuntime = new WeakMap()
180
181
  const wrappedCoverageReporters = new WeakSet()
181
182
  const coverageReporterRequires = new WeakMap()
182
183
  const handledJestEvents = new WeakSet()
@@ -2667,16 +2668,15 @@ function getTestSessionCoveragePayload (results, fallbackRootDir) {
2667
2668
  if (isSuitesSkipped) {
2668
2669
  applySkippedCoverageToJestCoverageMap(coverageMap, coverageRootDir)
2669
2670
  }
2670
- payload.testCodeCoverageLinesTotal = getTestCoverageLinesPercentage(
2671
+ const coverageLinesData = getTestCoverageLinesData(
2671
2672
  coverageMap,
2672
2673
  undefined,
2673
- coverageRootDir
2674
+ coverageRootDir,
2675
+ isTiaCoverageBackfillEnabled()
2674
2676
  )
2675
- if (isTiaCoverageBackfillEnabled()) {
2676
- payload.testSessionCoverageFiles = getExecutableFilesFromCoverage(coverageMap).map(({ filename, bitmap }) => ({
2677
- filename: getTestSuitePath(filename, coverageRootDir),
2678
- bitmap,
2679
- }))
2677
+ payload.testCodeCoverageLinesTotal = coverageLinesData.percentage
2678
+ if (coverageLinesData.executableFiles) {
2679
+ payload.testSessionCoverageFiles = coverageLinesData.executableFiles
2680
2680
  }
2681
2681
  } catch {
2682
2682
  // ignore errors
@@ -3728,7 +3728,13 @@ if (DD_MAJOR < 6) {
3728
3728
  }, jestConfigSyncWrapper)
3729
3729
  }
3730
3730
 
3731
+ const LOGGING_LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE = new Set([
3732
+ 'bunyan',
3733
+ 'pino',
3734
+ 'winston',
3735
+ ])
3731
3736
  const LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE = new Set([
3737
+ ...LOGGING_LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE,
3732
3738
  'selenium-webdriver',
3733
3739
  'selenium-webdriver/chrome',
3734
3740
  'selenium-webdriver/edge',
@@ -3736,7 +3742,6 @@ const LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE = new Set([
3736
3742
  'selenium-webdriver/firefox',
3737
3743
  'selenium-webdriver/ie',
3738
3744
  'selenium-webdriver/chromium',
3739
- 'winston',
3740
3745
  ])
3741
3746
 
3742
3747
  function recordMockedFile (suiteFilePath, moduleName) {
@@ -3786,8 +3791,6 @@ function wrapJestObject (jestObject, suiteFilePath) {
3786
3791
  wrappedJestObjects.add(jestObject)
3787
3792
 
3788
3793
  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
3794
  recordMockedFile(suiteFilePath, moduleName)
3792
3795
  return mock.apply(this, arguments)
3793
3796
  })
@@ -3870,6 +3873,111 @@ function requireOutsideJestRequireEngine (runtime, moduleName) {
3870
3873
  return require(moduleName)
3871
3874
  }
3872
3875
 
3876
+ /**
3877
+ * @param {object} runtime
3878
+ * @param {string} from
3879
+ * @param {string} moduleName
3880
+ * @returns {void}
3881
+ */
3882
+ function recordJestEsmBypassModulePath (runtime, from, moduleName) {
3883
+ if (typeof from !== 'string' || !LOGGING_LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE.has(moduleName)) return
3884
+
3885
+ let pathsByParent = jestEsmBypassModulePathsByRuntime.get(runtime)
3886
+ if (!pathsByParent) {
3887
+ pathsByParent = new Map()
3888
+ jestEsmBypassModulePathsByRuntime.set(runtime, pathsByParent)
3889
+ }
3890
+
3891
+ let modulePaths = pathsByParent.get(from)
3892
+ if (!modulePaths) {
3893
+ modulePaths = new Map()
3894
+ pathsByParent.set(from, modulePaths)
3895
+ }
3896
+ if (modulePaths.has(moduleName)) return
3897
+
3898
+ try {
3899
+ modulePaths.set(moduleName, createRequire(from).resolve(moduleName))
3900
+ } catch {
3901
+ modulePaths.set(moduleName, undefined)
3902
+ }
3903
+ }
3904
+
3905
+ /**
3906
+ * @param {object} runtime
3907
+ * @param {string} from
3908
+ * @param {string} modulePath
3909
+ * @returns {boolean}
3910
+ */
3911
+ function hasJestEsmBypassModulePath (runtime, from, modulePath) {
3912
+ const modulePaths = jestEsmBypassModulePathsByRuntime.get(runtime)?.get(from)
3913
+ if (!modulePaths) return false
3914
+
3915
+ for (const resolvedPath of modulePaths.values()) {
3916
+ if (resolvedPath === modulePath) return true
3917
+ }
3918
+ return false
3919
+ }
3920
+
3921
+ /**
3922
+ * @param {object} runtime
3923
+ * @returns {void}
3924
+ */
3925
+ function wrapJestEsmLoader (runtime) {
3926
+ const esmLoader = runtime?.esmLoader
3927
+ if (!esmLoader || wrappedJestEsmLoaders.has(esmLoader)) return
3928
+
3929
+ wrappedJestEsmLoaders.add(esmLoader)
3930
+ if (typeof esmLoader.resolveModule === 'function') {
3931
+ shimmer.wrap(esmLoader, 'resolveModule', resolveModule => function (moduleName, from) {
3932
+ recordJestEsmBypassModulePath(runtime, from, moduleName)
3933
+ return resolveModule.apply(this, arguments)
3934
+ })
3935
+ }
3936
+ if (typeof esmLoader.resolveSpecifierForSyncGraph === 'function') {
3937
+ shimmer.wrap(
3938
+ esmLoader,
3939
+ 'resolveSpecifierForSyncGraph',
3940
+ resolveSpecifier => function (from, moduleName) {
3941
+ recordJestEsmBypassModulePath(runtime, from, moduleName)
3942
+ return resolveSpecifier.apply(this, arguments)
3943
+ }
3944
+ )
3945
+ }
3946
+ }
3947
+
3948
+ /**
3949
+ * @param {object} runtime
3950
+ * @param {string} from
3951
+ * @param {string} moduleName
3952
+ * @returns {string | undefined}
3953
+ */
3954
+ function getJestBypassModulePath (runtime, from, moduleName) {
3955
+ if (typeof from !== 'string' || typeof moduleName !== 'string') return
3956
+
3957
+ if (!LIBRARIES_BYPASSING_JEST_REQUIRE_ENGINE.has(moduleName)) {
3958
+ // Jest passes the resolved path when a CommonJS package is imported from an ESM test.
3959
+ if (path.isAbsolute(moduleName) && hasJestEsmBypassModulePath(runtime, from, moduleName)) {
3960
+ return moduleName
3961
+ }
3962
+ return
3963
+ }
3964
+
3965
+ try {
3966
+ let jestModulePath
3967
+ if (typeof runtime._resolveCjsModule === 'function') {
3968
+ jestModulePath = runtime._resolveCjsModule(from, moduleName)
3969
+ } else if (typeof runtime.cjsLoader?.resolution?.resolveCjs === 'function') {
3970
+ jestModulePath = runtime.cjsLoader.resolution.resolveCjs(from, moduleName)
3971
+ } else {
3972
+ // Jest 24-27 uses this name for its synchronous CommonJS resolver.
3973
+ jestModulePath = runtime._resolveModule(from, moduleName)
3974
+ }
3975
+ if (jestModulePath === createRequire(from).resolve(moduleName)) return jestModulePath
3976
+ } catch {
3977
+ // Let Jest produce its own resolution error or load a resolver-only module.
3978
+ }
3979
+ }
3980
+
3873
3981
  function formatDefaultStackTrace (error, structuredStackTrace) {
3874
3982
  const errorString = Error.prototype.toString.call(error)
3875
3983
  if (structuredStackTrace.length === 0) return errorString
@@ -3893,10 +4001,29 @@ addHook({
3893
4001
  })
3894
4002
  }
3895
4003
 
4004
+ // Jest 28 through 30.3 keeps ESM dependency resolution on Runtime itself.
4005
+ if (typeof Runtime.prototype.resolveModule === 'function') {
4006
+ shimmer.wrap(Runtime.prototype, 'resolveModule', resolveModule => function (moduleName, from) {
4007
+ recordJestEsmBypassModulePath(this, from, moduleName)
4008
+ return resolveModule.apply(this, arguments)
4009
+ })
4010
+ }
4011
+
4012
+ if (typeof Runtime.prototype.unstable_importModule === 'function') {
4013
+ shimmer.wrap(Runtime.prototype, 'unstable_importModule', importModule => function () {
4014
+ wrapJestEsmLoader(this)
4015
+ return importModule.apply(this, arguments)
4016
+ })
4017
+ }
4018
+
3896
4019
  shimmer.wrap(Runtime.prototype, 'requireModule', requireModule => function (from, moduleName) {
3897
4020
  wrapJestGlobalsForRuntime(this)
3898
4021
  try {
3899
- const returnedValue = requireModule.apply(this, arguments)
4022
+ // Jest calls requireModule only after deciding that the module should not be mocked.
4023
+ const bypassModulePath = getJestBypassModulePath(this, from, moduleName)
4024
+ const returnedValue = bypassModulePath
4025
+ ? requireOutsideJestRequireEngine(this, bypassModulePath)
4026
+ : requireModule.apply(this, arguments)
3900
4027
  if (moduleName === '@jest/globals') {
3901
4028
  wrapConcurrentJestGlobalsForRuntime(this, returnedValue)
3902
4029
  }
@@ -3925,11 +4052,6 @@ addHook({
3925
4052
  return formatDefaultStackTrace(error, filteredStackTrace)
3926
4053
  }
3927
4054
  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
4055
  let returnedValue
3934
4056
  try {
3935
4057
  returnedValue = requireModuleOrMock.apply(this, arguments)