dd-trace 5.102.0 → 5.104.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 (201) hide show
  1. package/ext/exporters.js +1 -0
  2. package/index.d.ts +25 -3
  3. package/package.json +15 -13
  4. package/packages/datadog-esbuild/src/utils.js +2 -2
  5. package/packages/datadog-instrumentations/src/ai.js +1 -1
  6. package/packages/datadog-instrumentations/src/aws-sdk.js +2 -2
  7. package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -2
  8. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +32 -15
  9. package/packages/datadog-instrumentations/src/couchbase.js +69 -220
  10. package/packages/datadog-instrumentations/src/cucumber.js +104 -31
  11. package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
  12. package/packages/datadog-instrumentations/src/electron/preload.js +42 -0
  13. package/packages/datadog-instrumentations/src/electron.js +240 -0
  14. package/packages/datadog-instrumentations/src/fetch.js +5 -5
  15. package/packages/datadog-instrumentations/src/graphql.js +13 -17
  16. package/packages/datadog-instrumentations/src/grpc/client.js +48 -32
  17. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +2 -2
  18. package/packages/datadog-instrumentations/src/helpers/hook.js +4 -1
  19. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  20. package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
  21. package/packages/datadog-instrumentations/src/helpers/kafka.js +58 -0
  22. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +3 -2
  23. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +19 -5
  24. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +14 -13
  25. package/packages/datadog-instrumentations/src/http/client.js +2 -2
  26. package/packages/datadog-instrumentations/src/ioredis.js +18 -14
  27. package/packages/datadog-instrumentations/src/jest.js +382 -84
  28. package/packages/datadog-instrumentations/src/kafkajs.js +184 -174
  29. package/packages/datadog-instrumentations/src/mariadb.js +1 -1
  30. package/packages/datadog-instrumentations/src/memcached.js +2 -1
  31. package/packages/datadog-instrumentations/src/mocha/main.js +309 -56
  32. package/packages/datadog-instrumentations/src/mocha/utils.js +48 -8
  33. package/packages/datadog-instrumentations/src/mongodb-core.js +34 -9
  34. package/packages/datadog-instrumentations/src/mongoose.js +10 -12
  35. package/packages/datadog-instrumentations/src/mysql.js +2 -2
  36. package/packages/datadog-instrumentations/src/mysql2.js +1 -1
  37. package/packages/datadog-instrumentations/src/pg.js +25 -11
  38. package/packages/datadog-instrumentations/src/playwright.js +449 -60
  39. package/packages/datadog-instrumentations/src/redis.js +19 -10
  40. package/packages/datadog-instrumentations/src/router.js +4 -2
  41. package/packages/datadog-instrumentations/src/vitest.js +246 -149
  42. package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -21
  43. package/packages/datadog-plugin-aws-sdk/src/base.js +18 -24
  44. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  45. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -1
  46. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
  47. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
  48. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  49. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
  50. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -2
  51. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -1
  52. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
  53. package/packages/datadog-plugin-couchbase/src/index.js +58 -52
  54. package/packages/datadog-plugin-cucumber/src/index.js +1 -0
  55. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +239 -40
  56. package/packages/datadog-plugin-cypress/src/support.js +13 -1
  57. package/packages/datadog-plugin-elasticsearch/src/index.js +28 -8
  58. package/packages/datadog-plugin-electron/src/index.js +17 -0
  59. package/packages/datadog-plugin-electron/src/ipc.js +143 -0
  60. package/packages/datadog-plugin-electron/src/net.js +82 -0
  61. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +27 -18
  62. package/packages/datadog-plugin-graphql/src/execute.js +6 -28
  63. package/packages/datadog-plugin-graphql/src/resolve.js +30 -35
  64. package/packages/datadog-plugin-graphql/src/tools/signature.js +32 -7
  65. package/packages/datadog-plugin-graphql/src/tools/transforms.js +118 -100
  66. package/packages/datadog-plugin-graphql/src/utils.js +33 -1
  67. package/packages/datadog-plugin-grpc/src/client.js +6 -7
  68. package/packages/datadog-plugin-grpc/src/util.js +57 -22
  69. package/packages/datadog-plugin-http/src/client.js +2 -2
  70. package/packages/datadog-plugin-jest/src/index.js +92 -50
  71. package/packages/datadog-plugin-kafkajs/src/producer.js +32 -0
  72. package/packages/datadog-plugin-mocha/src/index.js +1 -0
  73. package/packages/datadog-plugin-mongodb-core/src/index.js +70 -69
  74. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  75. package/packages/datadog-plugin-openai/src/services.js +2 -1
  76. package/packages/datadog-plugin-pg/src/index.js +3 -3
  77. package/packages/datadog-plugin-playwright/src/index.js +4 -0
  78. package/packages/datadog-plugin-redis/src/index.js +54 -24
  79. package/packages/datadog-plugin-undici/src/index.js +19 -0
  80. package/packages/datadog-plugin-vitest/src/index.js +19 -7
  81. package/packages/datadog-shimmer/src/shimmer.js +35 -0
  82. package/packages/dd-trace/src/aiguard/index.js +3 -1
  83. package/packages/dd-trace/src/aiguard/sdk.js +36 -30
  84. package/packages/dd-trace/src/aiguard/tags.js +20 -11
  85. package/packages/dd-trace/src/appsec/blocking.js +2 -2
  86. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -2
  87. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
  88. package/packages/dd-trace/src/appsec/index.js +10 -3
  89. package/packages/dd-trace/src/appsec/reporter.js +19 -5
  90. package/packages/dd-trace/src/azure_metadata.js +17 -6
  91. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +4 -4
  92. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -2
  93. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +6 -4
  94. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +1 -1
  95. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -1
  96. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +5 -3
  97. package/packages/dd-trace/src/config/defaults.js +3 -14
  98. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
  99. package/packages/dd-trace/src/config/helper.js +4 -0
  100. package/packages/dd-trace/src/config/index.js +2 -2
  101. package/packages/dd-trace/src/config/major-overrides.js +98 -0
  102. package/packages/dd-trace/src/config/parsers.js +7 -1
  103. package/packages/dd-trace/src/config/supported-configurations.json +60 -38
  104. package/packages/dd-trace/src/crashtracking/crashtracker.js +15 -3
  105. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
  106. package/packages/dd-trace/src/datastreams/context.js +4 -2
  107. package/packages/dd-trace/src/datastreams/manager.js +1 -1
  108. package/packages/dd-trace/src/datastreams/processor.js +2 -2
  109. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +2 -2
  110. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
  111. package/packages/dd-trace/src/debugger/devtools_client/state.js +2 -1
  112. package/packages/dd-trace/src/debugger/index.js +7 -7
  113. package/packages/dd-trace/src/dogstatsd.js +2 -2
  114. package/packages/dd-trace/src/encode/0.4.js +45 -54
  115. package/packages/dd-trace/src/encode/0.5.js +34 -3
  116. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +26 -19
  117. package/packages/dd-trace/src/encode/agentless-json.js +1 -1
  118. package/packages/dd-trace/src/exporter.js +2 -0
  119. package/packages/dd-trace/src/exporters/agent/index.js +2 -1
  120. package/packages/dd-trace/src/exporters/agentless/index.js +3 -2
  121. package/packages/dd-trace/src/exporters/agentless/writer.js +2 -2
  122. package/packages/dd-trace/src/exporters/common/agents.js +3 -1
  123. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -1
  124. package/packages/dd-trace/src/exporters/common/request.js +4 -2
  125. package/packages/dd-trace/src/exporters/electron/index.js +49 -0
  126. package/packages/dd-trace/src/external-logger/src/index.js +2 -1
  127. package/packages/dd-trace/src/git_metadata.js +10 -8
  128. package/packages/dd-trace/src/id.js +17 -4
  129. package/packages/dd-trace/src/lambda/handler-paths.js +52 -0
  130. package/packages/dd-trace/src/lambda/handler.js +2 -4
  131. package/packages/dd-trace/src/lambda/index.js +62 -14
  132. package/packages/dd-trace/src/lambda/runtime/patch.js +21 -46
  133. package/packages/dd-trace/src/llmobs/index.js +13 -2
  134. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +45 -15
  135. package/packages/dd-trace/src/llmobs/sdk.js +10 -0
  136. package/packages/dd-trace/src/llmobs/writers/base.js +2 -1
  137. package/packages/dd-trace/src/log/writer.js +3 -1
  138. package/packages/dd-trace/src/noop/span.js +3 -1
  139. package/packages/dd-trace/src/openfeature/writers/base.js +2 -1
  140. package/packages/dd-trace/src/openfeature/writers/exposures.js +51 -20
  141. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
  142. package/packages/dd-trace/src/opentracing/propagation/text_map.js +20 -9
  143. package/packages/dd-trace/src/payload-tagging/config/index.js +2 -2
  144. package/packages/dd-trace/src/plugins/apollo.js +3 -1
  145. package/packages/dd-trace/src/plugins/ci_plugin.js +52 -17
  146. package/packages/dd-trace/src/plugins/database.js +54 -12
  147. package/packages/dd-trace/src/plugins/index.js +1 -0
  148. package/packages/dd-trace/src/plugins/log_plugin.js +3 -1
  149. package/packages/dd-trace/src/plugins/plugin.js +2 -4
  150. package/packages/dd-trace/src/plugins/tracing.js +5 -3
  151. package/packages/dd-trace/src/plugins/util/ci.js +8 -8
  152. package/packages/dd-trace/src/plugins/util/git-cache.js +20 -18
  153. package/packages/dd-trace/src/plugins/util/git.js +3 -1
  154. package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -2
  155. package/packages/dd-trace/src/plugins/util/test.js +119 -5
  156. package/packages/dd-trace/src/plugins/util/user-provided-git.js +17 -15
  157. package/packages/dd-trace/src/plugins/util/web.js +11 -0
  158. package/packages/dd-trace/src/priority_sampler.js +1 -1
  159. package/packages/dd-trace/src/profiling/profiler.js +1 -1
  160. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
  161. package/packages/dd-trace/src/profiling/ssi-heuristics.js +1 -1
  162. package/packages/dd-trace/src/rate_limiter.js +1 -1
  163. package/packages/dd-trace/src/remote_config/scheduler.js +1 -1
  164. package/packages/dd-trace/src/ritm.js +2 -1
  165. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -8
  166. package/packages/dd-trace/src/scope.js +7 -5
  167. package/packages/dd-trace/src/serverless.js +5 -2
  168. package/packages/dd-trace/src/service-naming/extra-services.js +14 -0
  169. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +20 -0
  170. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
  171. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +20 -0
  172. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
  173. package/packages/dd-trace/src/span_stats.js +1 -1
  174. package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
  175. package/packages/dd-trace/src/telemetry/endpoints.js +1 -1
  176. package/packages/dd-trace/src/telemetry/telemetry.js +2 -2
  177. package/packages/dd-trace/src/lambda/runtime/ritm.js +0 -133
  178. package/vendor/dist/opentracing/LICENSE +0 -201
  179. package/vendor/dist/opentracing/binary_carrier.d.ts +0 -11
  180. package/vendor/dist/opentracing/constants.d.ts +0 -61
  181. package/vendor/dist/opentracing/examples/demo/demo.d.ts +0 -2
  182. package/vendor/dist/opentracing/ext/tags.d.ts +0 -90
  183. package/vendor/dist/opentracing/functions.d.ts +0 -20
  184. package/vendor/dist/opentracing/global_tracer.d.ts +0 -14
  185. package/vendor/dist/opentracing/index.d.ts +0 -12
  186. package/vendor/dist/opentracing/index.js +0 -1
  187. package/vendor/dist/opentracing/mock_tracer/index.d.ts +0 -5
  188. package/vendor/dist/opentracing/mock_tracer/mock_context.d.ts +0 -13
  189. package/vendor/dist/opentracing/mock_tracer/mock_report.d.ts +0 -16
  190. package/vendor/dist/opentracing/mock_tracer/mock_span.d.ts +0 -50
  191. package/vendor/dist/opentracing/mock_tracer/mock_tracer.d.ts +0 -26
  192. package/vendor/dist/opentracing/noop.d.ts +0 -8
  193. package/vendor/dist/opentracing/reference.d.ts +0 -33
  194. package/vendor/dist/opentracing/span.d.ts +0 -147
  195. package/vendor/dist/opentracing/span_context.d.ts +0 -26
  196. package/vendor/dist/opentracing/test/api_compatibility.d.ts +0 -16
  197. package/vendor/dist/opentracing/test/mocktracer_implemenation.d.ts +0 -3
  198. package/vendor/dist/opentracing/test/noop_implementation.d.ts +0 -4
  199. package/vendor/dist/opentracing/test/opentracing_api.d.ts +0 -3
  200. package/vendor/dist/opentracing/test/unittest.d.ts +0 -2
  201. package/vendor/dist/opentracing/tracer.d.ts +0 -127
@@ -49,6 +49,7 @@ const {
49
49
  getTestSuiteCommonTags,
50
50
  TEST_STATUS,
51
51
  TEST_SKIPPED_BY_ITR,
52
+ TEST_ITR_SKIPPING_ENABLED,
52
53
  ITR_CORRELATION_ID,
53
54
  TEST_SOURCE_FILE,
54
55
  TEST_LEVEL_EVENT_TYPES,
@@ -64,7 +65,11 @@ const {
64
65
  getModifiedFilesFromDiff,
65
66
  getPullRequestBaseBranch,
66
67
  getSessionRequestErrorTags,
67
- DD_CI_LIBRARY_CONFIGURATION_ERROR,
68
+ DD_CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS,
69
+ DD_CI_LIBRARY_CONFIGURATION_ERROR_SKIPPABLE_TESTS,
70
+ DD_CI_LIBRARY_CONFIGURATION_ERROR_KNOWN_TESTS,
71
+ DD_CI_LIBRARY_CONFIGURATION_ERROR_TEST_MANAGEMENT_TESTS,
72
+ getSessionItrSkippingEnabledTags,
68
73
  TEST_IS_TEST_FRAMEWORK_WORKER,
69
74
  TEST_IS_NEW,
70
75
  TEST_IS_RUM_ACTIVE,
@@ -74,8 +79,11 @@ const {
74
79
  TEST_IS_MODIFIED,
75
80
  TEST_IS_RETRY,
76
81
  TEST_RETRY_REASON,
82
+ DD_CAPABILITIES_TEST_IMPACT_ANALYSIS,
77
83
  } = require('./util/test')
78
84
 
85
+ const legacyStorage = storage('legacy')
86
+
79
87
  const FRAMEWORK_TO_TRIMMED_COMMAND = {
80
88
  vitest: 'vitest run',
81
89
  mocha: 'mocha',
@@ -99,6 +107,21 @@ const TEST_FRAMEWORKS_TO_SKIP_GIT_METADATA_EXTRACTION = new Set([
99
107
  'cucumber',
100
108
  ])
101
109
 
110
+ function setItrSkippingEnabledTagFromLibraryConfig (plugin, frameworkVersion) {
111
+ const libraryCapabilitiesTags = getLibraryCapabilitiesTags(plugin.constructor.id, frameworkVersion)
112
+
113
+ if (!libraryCapabilitiesTags[DD_CAPABILITIES_TEST_IMPACT_ANALYSIS] ||
114
+ !plugin.libraryConfig ||
115
+ !plugin.testSessionSpan ||
116
+ !plugin.testModuleSpan) {
117
+ return
118
+ }
119
+
120
+ const skippingEnabled = plugin.libraryConfig.isSuitesSkippingEnabled ? 'true' : 'false'
121
+ plugin.testSessionSpan.setTag(TEST_ITR_SKIPPING_ENABLED, skippingEnabled)
122
+ plugin.testModuleSpan.setTag(TEST_ITR_SKIPPING_ENABLED, skippingEnabled)
123
+ }
124
+
102
125
  function getTestSuiteLevelVisibilityTags (testSuiteSpan, testFramework) {
103
126
  const testSuiteSpanContext = testSuiteSpan.context()
104
127
 
@@ -126,7 +149,7 @@ module.exports = class CiPlugin extends Plugin {
126
149
 
127
150
  this.addSub(`ci:${this.constructor.id}:library-configuration`, (ctx) => {
128
151
  const { onDone, frameworkVersion } = ctx
129
- ctx.currentStore = storage('legacy').getStore()
152
+ ctx.currentStore = legacyStorage.getStore()
130
153
 
131
154
  if (!this.tracer._exporter || !this.tracer._exporter.getLibraryConfiguration) {
132
155
  return onDone({ err: new Error('Test optimization was not initialized correctly') })
@@ -134,9 +157,10 @@ module.exports = class CiPlugin extends Plugin {
134
157
  this.tracer._exporter.getLibraryConfiguration(this.testConfiguration, (err, libraryConfig) => {
135
158
  if (err) {
136
159
  log.error('Library configuration could not be fetched. %s', err.message)
137
- this._addRequestErrorTag(DD_CI_LIBRARY_CONFIGURATION_ERROR, err)
160
+ this._addRequestErrorTag(DD_CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS, err)
138
161
  } else {
139
162
  this.libraryConfig = libraryConfig
163
+ setItrSkippingEnabledTagFromLibraryConfig(this, frameworkVersion)
140
164
  }
141
165
 
142
166
  const requestErrorTags = this.testSessionSpan
@@ -165,6 +189,7 @@ module.exports = class CiPlugin extends Plugin {
165
189
  this.tracer._exporter.getSkippableSuites(this.testConfiguration, (err, skippableSuites, itrCorrelationId) => {
166
190
  if (err) {
167
191
  log.error('Skippable suites could not be fetched. %s', err.message)
192
+ this._addRequestErrorTag(DD_CI_LIBRARY_CONFIGURATION_ERROR_SKIPPABLE_TESTS, err)
168
193
  } else {
169
194
  this.itrCorrelationId = itrCorrelationId
170
195
  }
@@ -225,18 +250,7 @@ module.exports = class CiPlugin extends Plugin {
225
250
  },
226
251
  integrationName: this.constructor.id,
227
252
  })
228
- // only for vitest
229
- // These are added for the worker threads to use
230
- if (this.constructor.id === 'vitest') {
231
- // TODO: Figure out alternative ways to pass this information to the worker threads
232
- // eslint-disable-next-line eslint-rules/eslint-process-env
233
- process.env.DD_CIVISIBILITY_TEST_SESSION_ID = this.testSessionSpan.context().toTraceId()
234
- // eslint-disable-next-line eslint-rules/eslint-process-env
235
- process.env.DD_CIVISIBILITY_TEST_MODULE_ID = this.testModuleSpan.context().toSpanId()
236
- // eslint-disable-next-line eslint-rules/eslint-process-env
237
- process.env.DD_CIVISIBILITY_TEST_COMMAND = this.command
238
- }
239
-
253
+ setItrSkippingEnabledTagFromLibraryConfig(this, frameworkVersion)
240
254
  this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'module')
241
255
  })
242
256
 
@@ -246,6 +260,7 @@ module.exports = class CiPlugin extends Plugin {
246
260
  const testSuiteMetadata = {
247
261
  ...getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, this.constructor.id),
248
262
  ...getSessionRequestErrorTags(this.testSessionSpan),
263
+ ...getSessionItrSkippingEnabledTags(this.testSessionSpan),
249
264
  }
250
265
  if (this.itrCorrelationId) {
251
266
  testSuiteMetadata[ITR_CORRELATION_ID] = this.itrCorrelationId
@@ -277,6 +292,7 @@ module.exports = class CiPlugin extends Plugin {
277
292
  this.tracer._exporter.getKnownTests(this.testConfiguration, (err, knownTests) => {
278
293
  if (err) {
279
294
  log.error('Known tests could not be fetched. %s', err.message)
295
+ this._addRequestErrorTag(DD_CI_LIBRARY_CONFIGURATION_ERROR_KNOWN_TESTS, err)
280
296
  if (this.libraryConfig) {
281
297
  this.libraryConfig.isEarlyFlakeDetectionEnabled = false
282
298
  this.libraryConfig.isKnownTestsEnabled = false
@@ -297,6 +313,7 @@ module.exports = class CiPlugin extends Plugin {
297
313
  this.tracer._exporter.getTestManagementTests(this.testConfiguration, (err, testManagementTests) => {
298
314
  if (err) {
299
315
  log.error('Test management tests could not be fetched. %s', err.message)
316
+ this._addRequestErrorTag(DD_CI_LIBRARY_CONFIGURATION_ERROR_TEST_MANAGEMENT_TESTS, err)
300
317
  if (this.libraryConfig) {
301
318
  this.libraryConfig.isTestManagementEnabled = false
302
319
  }
@@ -342,6 +359,9 @@ module.exports = class CiPlugin extends Plugin {
342
359
 
343
360
  if (span.name?.startsWith(`${this.constructor.id}.`)) {
344
361
  span.meta[TEST_IS_TEST_FRAMEWORK_WORKER] = 'true'
362
+ if (span.name === `${this.constructor.id}.test` || span.name === `${this.constructor.id}.test_suite`) {
363
+ Object.assign(span.meta, getSessionItrSkippingEnabledTags(this.testSessionSpan))
364
+ }
345
365
  // augment with git information (since it will not be available in the worker)
346
366
  for (const key in this.testEnvironmentMetadata) {
347
367
  // CAREFUL: this bypasses the metadata/metrics distinction
@@ -372,7 +392,8 @@ module.exports = class CiPlugin extends Plugin {
372
392
 
373
393
  // Jest and Vitest worker test spans are serialized in the worker and may not include
374
394
  // request error tags; add them from the session span in the main process.
375
- if ((span.name === 'jest.test' || span.name === 'vitest.test') && this.testSessionSpan) {
395
+ if ((span.name === 'jest.test' || span.name === 'vitest.test' || span.name === 'vitest.test_suite') &&
396
+ this.testSessionSpan) {
376
397
  Object.assign(span.meta, getSessionRequestErrorTags(this.testSessionSpan))
377
398
  }
378
399
  }
@@ -449,13 +470,16 @@ module.exports = class CiPlugin extends Plugin {
449
470
  * Adds a hidden _dd tag to the test session span when a test-optimization request fails.
450
471
  * If the session span does not exist yet (e.g. library-configuration failed before session:start),
451
472
  * the tag is queued and applied when the span is created.
452
- * @param {string} tag - Tag name (e.g. DD_CI_LIBRARY_CONFIGURATION_ERROR)
473
+ * @param {string} tag - Tag name (e.g. DD_CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS)
453
474
  * @param {Error} err - Request error
454
475
  */
455
476
  _addRequestErrorTag (tag, err) {
456
477
  const value = 'true'
457
478
  if (this.testSessionSpan) {
458
479
  this.testSessionSpan.setTag(tag, value)
480
+ if (this.testModuleSpan) {
481
+ this.testModuleSpan.setTag(tag, value)
482
+ }
459
483
  } else {
460
484
  this._pendingRequestErrorTags.push({ tag, value })
461
485
  }
@@ -469,6 +493,15 @@ module.exports = class CiPlugin extends Plugin {
469
493
  return getSessionRequestErrorTags(this.testSessionSpan)
470
494
  }
471
495
 
496
+ /**
497
+ * Returns ITR skipping-enabled tags from the test session span for propagation to child events.
498
+ *
499
+ * @returns {Record<string, string>}
500
+ */
501
+ getSessionItrSkippingEnabledTags () {
502
+ return getSessionItrSkippingEnabledTags(this.testSessionSpan)
503
+ }
504
+
472
505
  /**
473
506
  * @param {import('../config/config-base')} config - Tracer configuration
474
507
  * @param {boolean} shouldGetEnvironmentData - Whether to get environment data
@@ -596,6 +629,8 @@ module.exports = class CiPlugin extends Plugin {
596
629
  }
597
630
  }
598
631
 
632
+ Object.assign(testTags, getSessionItrSkippingEnabledTags(this.testSessionSpan))
633
+
599
634
  this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'test', { hasCodeOwners: !!codeOwners })
600
635
 
601
636
  const testSpan = this.tracer
@@ -1,13 +1,47 @@
1
1
  'use strict'
2
2
 
3
+ const { LRUCache } = require('../../../../vendor/dist/lru-cache')
3
4
  const { PEER_SERVICE_KEY, PEER_SERVICE_SOURCE_KEY } = require('../constants')
4
5
  const propagationHash = require('../propagation-hash')
5
6
  const StoragePlugin = require('./storage')
6
7
 
8
+ // Unreserved RFC 3986 set that `encodeURIComponent` leaves untouched (a conservative subset:
9
+ // `! * ' ( )` are also untouched but rarely appear in db / host / service names so we skip them).
10
+ const SAFE_ENCODE_RE = /^[\w\-.~]*$/
11
+
12
+ // Cap `#dbmPrefixCache` so a high-cardinality `db.name` (MongoDB sets it to
13
+ // `${database}.${collection}`) cannot grow the map without bound. Steady-state working sets
14
+ // fit well below the cap; cache misses cost a few hundred nanoseconds, so an evicted entry
15
+ // rebuilds cheaply on the next query.
16
+ const DBM_PREFIX_CACHE_MAX = 256
17
+
7
18
  class DatabasePlugin extends StoragePlugin {
8
19
  static operation = 'query'
9
20
  static peerServicePrecursors = ['db.name']
10
21
 
22
+ // dde / ddps / ddpv are tracer-process constants. They are baked in at `configure()` time as
23
+ // two pre-templated fragments — `dbmEnvFragment` splices between dddbs and ddh; `dbmEndFragment`
24
+ // trails ddh — so per-query work shrinks to encoding dddb / dddbs / ddh and concatenating.
25
+ #dbmEnvFragment
26
+ #dbmEndFragment
27
+ // Cache the rendered prefix per `${db.name}\0${out.host}\0${dbmService}`. The triple is
28
+ // connection-stable for a real workload, so the steady state is one `LRUCache.get` plus the
29
+ // optional per-call `,ddprs='...'` suffix.
30
+ #dbmPrefixCache = new LRUCache({ max: DBM_PREFIX_CACHE_MAX })
31
+
32
+ /**
33
+ * @override
34
+ * @param {boolean | import('../config/config-base') & {enabled: boolean}} config
35
+ */
36
+ configure (config) {
37
+ super.configure(config)
38
+ // Match the previous shape exactly: `dde` is `encode`d; `ddps` / `ddpv` are template-literal
39
+ // coerced so `undefined` renders as the literal `'undefined'` the way the original did.
40
+ this.#dbmEnvFragment = `,dde='${encode(this.tracer._env)}',`
41
+ this.#dbmEndFragment = `,ddps='${this.tracer._service ?? ''}',ddpv='${this.tracer._version}'`
42
+ this.#dbmPrefixCache.clear()
43
+ }
44
+
11
45
  /**
12
46
  * @param {string} serviceName
13
47
  * @param {import('../../../..').Span} span
@@ -16,20 +50,21 @@ class DatabasePlugin extends StoragePlugin {
16
50
  */
17
51
  #createDBMPropagationCommentService (serviceName, span, peerData) {
18
52
  const spanTags = span.context()._tags
19
- const encodedDddb = encode(spanTags['db.name'])
20
- const encodedDddbs = encode(serviceName)
21
- const encodedDde = encode(this.tracer._env)
22
- const encodedDdh = encode(spanTags['out.host'])
23
- const encodedDdps = this.tracer._service ?? ''
24
- const encodedDdpv = this.tracer._version
25
-
26
- let dbmComment = `dddb='${encodedDddb}',dddbs='${encodedDddbs}',dde='${encodedDde}',ddh='${encodedDdh}',` +
27
- `ddps='${encodedDdps}',ddpv='${encodedDdpv}'`
53
+ const dddb = spanTags['db.name']
54
+ const ddh = spanTags['out.host']
55
+ const cacheKey = `${dddb ?? ''}\0${ddh ?? ''}\0${serviceName ?? ''}`
56
+
57
+ let prefix = this.#dbmPrefixCache.get(cacheKey)
58
+ if (prefix === undefined) {
59
+ prefix = `dddb='${encode(dddb)}',dddbs='${encode(serviceName)}'${this.#dbmEnvFragment}` +
60
+ `ddh='${encode(ddh)}'${this.#dbmEndFragment}`
61
+ this.#dbmPrefixCache.set(cacheKey, prefix)
62
+ }
28
63
 
29
64
  if (peerData !== undefined && peerData[PEER_SERVICE_SOURCE_KEY] === PEER_SERVICE_KEY) {
30
- dbmComment += `,ddprs='${encode(peerData[PEER_SERVICE_KEY])}'`
65
+ return `${prefix},ddprs='${encode(peerData[PEER_SERVICE_KEY])}'`
31
66
  }
32
- return dbmComment
67
+ return prefix
33
68
  }
34
69
 
35
70
  /**
@@ -118,6 +153,13 @@ class DatabasePlugin extends StoragePlugin {
118
153
  }
119
154
  }
120
155
 
121
- const encode = value => value ? encodeURIComponent(value) : ''
156
+ /**
157
+ * @param {string | number | undefined | null} value
158
+ * @returns {string}
159
+ */
160
+ function encode (value) {
161
+ if (!value) return ''
162
+ return SAFE_ENCODE_RE.test(value) ? value : encodeURIComponent(value)
163
+ }
122
164
 
123
165
  module.exports = DatabasePlugin
@@ -49,6 +49,7 @@ const plugins = {
49
49
  get dns () { return require('../../../datadog-plugin-dns/src') },
50
50
  get 'dd-trace-api' () { return require('../../../datadog-plugin-dd-trace-api/src') },
51
51
  get elasticsearch () { return require('../../../datadog-plugin-elasticsearch/src') },
52
+ get electron () { return require('../../../datadog-plugin-electron/src') },
52
53
  get express () { return require('../../../datadog-plugin-express/src') },
53
54
  get fastify () { return require('../../../datadog-plugin-fastify/src') },
54
55
  get 'find-my-way' () { return require('../../../datadog-plugin-find-my-way/src') },
@@ -4,6 +4,8 @@ const { LOG } = require('../../../../ext/formats')
4
4
  const { storage } = require('../../../datadog-core')
5
5
  const Plugin = require('./plugin')
6
6
 
7
+ const legacyStorage = storage('legacy')
8
+
7
9
  function messageProxy (message, holder) {
8
10
  return new Proxy(message, {
9
11
  get (target, key) {
@@ -38,7 +40,7 @@ module.exports = class LogPlugin extends Plugin {
38
40
  super(...args)
39
41
 
40
42
  this.addSub(`apm:${this.constructor.id}:log`, (arg) => {
41
- const span = storage('legacy').getStore()?.span
43
+ const span = legacyStorage.getStore()?.span
42
44
 
43
45
  // NOTE: This needs to run whether or not there is a span
44
46
  // so service, version, and env will always get injected.
@@ -160,14 +160,12 @@ module.exports = class Plugin {
160
160
  /**
161
161
  * Enable or disable the plugin and (re)apply its configuration.
162
162
  *
163
- * TODO: Remove the overloading with `enabled` and use the config object directly.
164
- *
165
- * @param {boolean | import('../config/config-base') & {enabled: boolean}} config Either a boolean to
163
+ * @param {boolean | Record<string, unknown> & {enabled: boolean}} config Either a boolean to
166
164
  * enable/disable or a configuration object containing at least `{ enabled: boolean }`.
167
165
  */
168
166
  configure (config) {
169
167
  if (typeof config === 'boolean') {
170
- config = /** @type {import('../config/config-base') & {enabled: boolean}} */ ({ enabled: config })
168
+ config = { enabled: config }
171
169
  }
172
170
  this.config = config
173
171
  if (config.enabled) {
@@ -5,6 +5,8 @@ const analyticsSampler = require('../analytics_sampler')
5
5
  const { COMPONENT, SVC_SRC_KEY } = require('../constants')
6
6
  const Plugin = require('./plugin')
7
7
 
8
+ const legacyStorage = storage('legacy')
9
+
8
10
  class TracingPlugin extends Plugin {
9
11
  constructor (...args) {
10
12
  super(...args)
@@ -16,7 +18,7 @@ class TracingPlugin extends Plugin {
16
18
  }
17
19
 
18
20
  get activeSpan () {
19
- const store = /** @type {{ span?: import('../../../..').Span }} */ (storage('legacy').getStore())
21
+ const store = /** @type {{ span?: import('../../../..').Span }} */ (legacyStorage.getStore())
20
22
 
21
23
  return store?.span
22
24
  }
@@ -193,7 +195,7 @@ class TracingPlugin extends Plugin {
193
195
  serviceSource = service ? 'opt.plugin' : undefined
194
196
  }
195
197
 
196
- const store = storage('legacy').getStore()
198
+ const store = legacyStorage.getStore()
197
199
  if (store && childOf === undefined) {
198
200
  childOf = /** @type {import('../opentracing/span') | undefined} */ (store.span)
199
201
  }
@@ -226,7 +228,7 @@ class TracingPlugin extends Plugin {
226
228
 
227
229
  // TODO: Remove this after migration to TracingChannel is done.
228
230
  if (enterOrCtx === true) {
229
- storage('legacy').enterWith({ ...store, span })
231
+ legacyStorage.enterWith({ ...store, span })
230
232
  } else if (enterOrCtx) {
231
233
  enterOrCtx.parentStore = store
232
234
  enterOrCtx.currentStore = { ...store, span }
@@ -2,7 +2,8 @@
2
2
 
3
3
  const { readFileSync, readdirSync, existsSync } = require('fs')
4
4
  const path = require('path')
5
- const { getEnvironmentVariable, getEnvironmentVariables, getValueFromEnvSources } = require('../../config/helper')
5
+ const getConfig = require('../../config')
6
+ const { getEnvironmentVariable, getEnvironmentVariables } = require('../../config/helper')
6
7
  const {
7
8
  GIT_BRANCH,
8
9
  GIT_COMMIT_SHA,
@@ -217,7 +218,7 @@ const githubWellKnownDiagnosticDirPatternsWin = ['C:/actions-runner/*/_diag', 'C
217
218
  const githubJobIDRegex = /"job":\s*{[\s\S]*?"v"\s*:\s*(\d+)(?:\.0)?/
218
219
 
219
220
  function getJobIDFromDiagFile () {
220
- const runnerTemp = getValueFromEnvSources('RUNNER_TEMP')
221
+ const runnerTemp = getEnvironmentVariable('RUNNER_TEMP')
221
222
  if (!runnerTemp || !existsSync(runnerTemp)) { return null }
222
223
 
223
224
  const isWin = process.platform === 'win32'
@@ -298,7 +299,7 @@ module.exports = {
298
299
  CHANGE_ID,
299
300
  CHANGE_TARGET,
300
301
  } = env
301
- const DD_CUSTOM_TRACE_ID = getValueFromEnvSources('DD_CUSTOM_TRACE_ID')
302
+ const { DD_CUSTOM_TRACE_ID, DD_CUSTOM_PARENT_ID } = getConfig()
302
303
 
303
304
  tags = {
304
305
  [CI_PIPELINE_ID]: BUILD_TAG,
@@ -308,7 +309,7 @@ module.exports = {
308
309
  [GIT_COMMIT_SHA]: JENKINS_GIT_COMMIT,
309
310
  [GIT_REPOSITORY_URL]: JENKINS_GIT_REPOSITORY_URL || JENKINS_GIT_REPOSITORY_URL_1,
310
311
  [CI_WORKSPACE_PATH]: WORKSPACE,
311
- [CI_ENV_VARS]: JSON.stringify({ DD_CUSTOM_TRACE_ID }),
312
+ [CI_ENV_VARS]: JSON.stringify({ DD_CUSTOM_TRACE_ID, DD_CUSTOM_PARENT_ID }),
312
313
  [CI_NODE_NAME]: NODE_NAME,
313
314
  [PR_NUMBER]: CHANGE_ID,
314
315
  [GIT_PULL_REQUEST_BASE_BRANCH]: CHANGE_TARGET,
@@ -738,11 +739,11 @@ module.exports = {
738
739
  }),
739
740
  [CI_NODE_NAME]: BUILDKITE_AGENT_ID,
740
741
  [CI_NODE_LABELS]: JSON.stringify(extraTags),
741
- [PR_NUMBER]: BUILDKITE_PULL_REQUEST,
742
742
  [CI_JOB_ID]: BUILDKITE_JOB_ID,
743
743
  }
744
744
 
745
- if (BUILDKITE_PULL_REQUEST) {
745
+ if (BUILDKITE_PULL_REQUEST && BUILDKITE_PULL_REQUEST !== 'false') {
746
+ tags[PR_NUMBER] = BUILDKITE_PULL_REQUEST
746
747
  tags[GIT_PULL_REQUEST_BASE_BRANCH] = BUILDKITE_PULL_REQUEST_BASE_BRANCH
747
748
  }
748
749
  }
@@ -868,8 +869,7 @@ module.exports = {
868
869
  }
869
870
 
870
871
  if (env.CODEBUILD_INITIATOR?.startsWith('codepipeline/')) {
871
- const DD_ACTION_EXECUTION_ID = getValueFromEnvSources('DD_ACTION_EXECUTION_ID')
872
- const DD_PIPELINE_EXECUTION_ID = getValueFromEnvSources('DD_PIPELINE_EXECUTION_ID')
872
+ const { DD_ACTION_EXECUTION_ID, DD_PIPELINE_EXECUTION_ID } = getConfig()
873
873
  tags = {
874
874
  [CI_PROVIDER_NAME]: 'awscodepipeline',
875
875
  [CI_PIPELINE_ID]: DD_PIPELINE_EXECUTION_ID,
@@ -7,24 +7,31 @@ const crypto = require('crypto')
7
7
  const cp = require('child_process')
8
8
 
9
9
  const log = require('../../log')
10
- const { getValueFromEnvSources } = require('../../config/helper')
11
- const { isTrue } = require('../../util')
10
+ const getConfig = require('../../config')
12
11
 
13
- let isGitEnabled = isTrue(getValueFromEnvSources('DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED'))
14
- const GIT_CACHE_DIR = getValueFromEnvSources('DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR') ||
15
- path.join(os.tmpdir(), 'dd-trace-git-cache')
12
+ let isGitEnabled
13
+ let gitCacheDir
16
14
 
17
15
  function ensureCacheDir () {
16
+ if (isGitEnabled === undefined) {
17
+ const config = getConfig()
18
+ isGitEnabled = config.DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED
19
+ // TODO: Move the default to config/index.js applyCalculated
20
+ // when using the config singleton.
21
+ gitCacheDir = config.DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR ||
22
+ path.join(os.tmpdir(), 'dd-trace-git-cache')
23
+ }
24
+
18
25
  if (!isGitEnabled) return false
19
26
 
20
27
  try {
21
- if (fs.existsSync(GIT_CACHE_DIR)) {
22
- const stats = fs.statSync(GIT_CACHE_DIR)
28
+ if (fs.existsSync(gitCacheDir)) {
29
+ const stats = fs.statSync(gitCacheDir)
23
30
  if (!stats.isDirectory()) {
24
- throw new Error(`Cache directory path exists but is not a directory: ${GIT_CACHE_DIR}`)
31
+ throw new Error(`Cache directory path exists but is not a directory: ${gitCacheDir}`)
25
32
  }
26
33
  } else {
27
- fs.mkdirSync(GIT_CACHE_DIR, { recursive: true })
34
+ fs.mkdirSync(gitCacheDir, { recursive: true })
28
35
  }
29
36
  return true
30
37
  } catch (err) {
@@ -34,9 +41,6 @@ function ensureCacheDir () {
34
41
  }
35
42
  }
36
43
 
37
- // Initialize cache directory at module load time
38
- ensureCacheDir()
39
-
40
44
  function getCacheKey (cmd, flags) {
41
45
  // Create a hash of the command and flags to use as cache key
42
46
  const commandString = `${cmd} ${flags.join(' ')}`
@@ -44,11 +48,12 @@ function getCacheKey (cmd, flags) {
44
48
  }
45
49
 
46
50
  function getCacheFilePath (cacheKey) {
47
- return path.join(GIT_CACHE_DIR, `${cacheKey}.cache`)
51
+ ensureCacheDir()
52
+ return path.join(gitCacheDir, `${cacheKey}.cache`)
48
53
  }
49
54
 
50
55
  function getCache (cacheKey) {
51
- if (!isGitEnabled) return null
56
+ if (!ensureCacheDir()) return null
52
57
 
53
58
  try {
54
59
  const cacheFilePath = getCacheFilePath(cacheKey)
@@ -63,9 +68,6 @@ function getCache (cacheKey) {
63
68
  }
64
69
 
65
70
  function setCache (cacheKey, result) {
66
- if (!isGitEnabled) return
67
-
68
- // Ensure cache directory exists
69
71
  if (!ensureCacheDir()) return
70
72
 
71
73
  try {
@@ -80,7 +82,7 @@ function cachedExec (cmd, flags, options) {
80
82
  if (options === undefined) {
81
83
  options = { stdio: 'pipe' }
82
84
  }
83
- if (!isGitEnabled) {
85
+ if (!ensureCacheDir()) {
84
86
  return cp.execFileSync(cmd, flags, options)
85
87
  }
86
88
  const cacheKey = getCacheKey(cmd, flags)
@@ -37,6 +37,8 @@ const {
37
37
  const { filterSensitiveInfoFromRepository } = require('./url')
38
38
  const { cachedExec } = require('./git-cache')
39
39
 
40
+ const legacyStorage = storage('legacy')
41
+
40
42
  const GIT_REV_LIST_MAX_BUFFER = 12 * 1024 * 1024 // 12MB
41
43
 
42
44
  function sanitizedExec (
@@ -47,7 +49,7 @@ function sanitizedExec (
47
49
  errorMetric,
48
50
  shouldTrim = true
49
51
  ) {
50
- return storage('legacy').run({ noop: true }, () => {
52
+ return legacyStorage.run({ noop: true }, () => {
51
53
  let startTime
52
54
  if (operationMetric) {
53
55
  incrementCountMetric(operationMetric.name, operationMetric.tags)
@@ -14,7 +14,7 @@ const NODE_MODULES_PATTERN_START = `node_modules${sep}`
14
14
  * In production, these frames are already filtered by isNodeModulesFrame.
15
15
  */
16
16
  const SHOULD_FILTER_DD_TRACE_INSTRUMENTAION = __filename.endsWith(
17
- join(sep, 'dd-trace-js', 'packages', 'dd-trace', 'src', 'plugins', 'util', 'stacktrace.js')
17
+ join('packages', 'dd-trace', 'src', 'plugins', 'util', 'stacktrace.js')
18
18
  )
19
19
 
20
20
  module.exports = {
@@ -46,7 +46,7 @@ function getCallSites (constructorOpt) {
46
46
  * Get stack trace of user-land frames.
47
47
  *
48
48
  * @param {string} stack - The stack trace to parse
49
- * @param {number} [limit=Infinity] - The maximum number of frames to return
49
+ * @param {number} [limit] - The maximum number of frames to return
50
50
  * @returns {StackFrame[]} - A list of stack frames from user-land code
51
51
  */
52
52
  function parseUserLandFrames (stack, limit = Infinity) {