dd-trace 5.100.0 → 5.102.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 (189) hide show
  1. package/index.d.ts +14 -0
  2. package/package.json +11 -9
  3. package/packages/datadog-instrumentations/src/aerospike.js +2 -2
  4. package/packages/datadog-instrumentations/src/ai.js +8 -8
  5. package/packages/datadog-instrumentations/src/amqplib.js +6 -7
  6. package/packages/datadog-instrumentations/src/anthropic.js +10 -10
  7. package/packages/datadog-instrumentations/src/apollo-server-core.js +3 -3
  8. package/packages/datadog-instrumentations/src/apollo-server.js +5 -5
  9. package/packages/datadog-instrumentations/src/avsc.js +6 -6
  10. package/packages/datadog-instrumentations/src/aws-sdk.js +151 -67
  11. package/packages/datadog-instrumentations/src/azure-durable-functions.js +8 -8
  12. package/packages/datadog-instrumentations/src/bluebird.js +2 -2
  13. package/packages/datadog-instrumentations/src/body-parser.js +2 -2
  14. package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
  15. package/packages/datadog-instrumentations/src/child_process.js +12 -12
  16. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +9 -9
  17. package/packages/datadog-instrumentations/src/connect.js +7 -7
  18. package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
  19. package/packages/datadog-instrumentations/src/cookie.js +2 -2
  20. package/packages/datadog-instrumentations/src/couchbase.js +16 -30
  21. package/packages/datadog-instrumentations/src/crypto.js +4 -4
  22. package/packages/datadog-instrumentations/src/cucumber.js +77 -16
  23. package/packages/datadog-instrumentations/src/cypress.js +5 -3
  24. package/packages/datadog-instrumentations/src/dns.js +0 -3
  25. package/packages/datadog-instrumentations/src/elasticsearch.js +8 -11
  26. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +6 -6
  27. package/packages/datadog-instrumentations/src/express-session.js +4 -4
  28. package/packages/datadog-instrumentations/src/express.js +10 -11
  29. package/packages/datadog-instrumentations/src/fastify.js +2 -2
  30. package/packages/datadog-instrumentations/src/fs.js +14 -14
  31. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +5 -7
  32. package/packages/datadog-instrumentations/src/google-genai.js +4 -4
  33. package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
  34. package/packages/datadog-instrumentations/src/hapi.js +2 -2
  35. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +8 -8
  36. package/packages/datadog-instrumentations/src/helpers/promise.js +2 -2
  37. package/packages/datadog-instrumentations/src/hono.js +2 -2
  38. package/packages/datadog-instrumentations/src/http/client.js +26 -9
  39. package/packages/datadog-instrumentations/src/http/server.js +9 -9
  40. package/packages/datadog-instrumentations/src/jest.js +93 -63
  41. package/packages/datadog-instrumentations/src/kafkajs.js +9 -9
  42. package/packages/datadog-instrumentations/src/knex.js +17 -17
  43. package/packages/datadog-instrumentations/src/koa.js +12 -12
  44. package/packages/datadog-instrumentations/src/ldapjs.js +5 -5
  45. package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
  46. package/packages/datadog-instrumentations/src/limitd-client.js +4 -4
  47. package/packages/datadog-instrumentations/src/lodash.js +4 -4
  48. package/packages/datadog-instrumentations/src/mariadb.js +13 -13
  49. package/packages/datadog-instrumentations/src/memcached.js +2 -2
  50. package/packages/datadog-instrumentations/src/microgateway-core.js +2 -2
  51. package/packages/datadog-instrumentations/src/mocha/common.js +7 -4
  52. package/packages/datadog-instrumentations/src/mocha/main.js +37 -14
  53. package/packages/datadog-instrumentations/src/mocha/utils.js +133 -16
  54. package/packages/datadog-instrumentations/src/mocha/worker.js +12 -7
  55. package/packages/datadog-instrumentations/src/mongodb-core.js +9 -22
  56. package/packages/datadog-instrumentations/src/mongodb.js +5 -5
  57. package/packages/datadog-instrumentations/src/mongoose.js +21 -21
  58. package/packages/datadog-instrumentations/src/mquery.js +5 -5
  59. package/packages/datadog-instrumentations/src/multer.js +4 -4
  60. package/packages/datadog-instrumentations/src/mysql.js +16 -16
  61. package/packages/datadog-instrumentations/src/mysql2.js +4 -4
  62. package/packages/datadog-instrumentations/src/net.js +14 -8
  63. package/packages/datadog-instrumentations/src/nyc.js +5 -5
  64. package/packages/datadog-instrumentations/src/openai.js +19 -19
  65. package/packages/datadog-instrumentations/src/oracledb.js +6 -6
  66. package/packages/datadog-instrumentations/src/otel-sdk-trace.js +11 -6
  67. package/packages/datadog-instrumentations/src/passport-utils.js +5 -5
  68. package/packages/datadog-instrumentations/src/pg.js +15 -15
  69. package/packages/datadog-instrumentations/src/pino.js +6 -10
  70. package/packages/datadog-instrumentations/src/playwright.js +20 -15
  71. package/packages/datadog-instrumentations/src/protobufjs.js +16 -16
  72. package/packages/datadog-instrumentations/src/redis.js +1 -2
  73. package/packages/datadog-instrumentations/src/restify.js +2 -2
  74. package/packages/datadog-instrumentations/src/router.js +12 -12
  75. package/packages/datadog-instrumentations/src/stripe.js +12 -12
  76. package/packages/datadog-instrumentations/src/vitest.js +107 -26
  77. package/packages/datadog-instrumentations/src/winston.js +4 -4
  78. package/packages/datadog-instrumentations/src/ws.js +7 -7
  79. package/packages/datadog-plugin-aws-sdk/src/base.js +52 -4
  80. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +19 -12
  81. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +45 -35
  82. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +33 -22
  83. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +12 -13
  84. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +73 -54
  85. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +19 -17
  86. package/packages/datadog-plugin-aws-sdk/src/util.js +22 -0
  87. package/packages/datadog-plugin-bullmq/src/consumer.js +2 -2
  88. package/packages/datadog-plugin-bullmq/src/producer.js +14 -20
  89. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -6
  90. package/packages/datadog-plugin-cucumber/src/index.js +4 -0
  91. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +18 -4
  92. package/packages/datadog-plugin-cypress/src/plugin.js +5 -14
  93. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -5
  94. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +3 -1
  95. package/packages/datadog-plugin-http/src/client.js +1 -5
  96. package/packages/datadog-plugin-jest/src/util.js +1 -2
  97. package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -9
  98. package/packages/datadog-plugin-kafkajs/src/producer.js +2 -8
  99. package/packages/datadog-plugin-mocha/src/index.js +4 -0
  100. package/packages/datadog-plugin-mongodb-core/src/index.js +2 -1
  101. package/packages/datadog-plugin-openai/src/tracing.js +12 -23
  102. package/packages/datadog-plugin-playwright/src/index.js +1 -1
  103. package/packages/datadog-plugin-vitest/src/index.js +8 -1
  104. package/packages/datadog-shimmer/src/shimmer.js +7 -1
  105. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
  106. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +81 -81
  107. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
  108. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +2 -2
  109. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -2
  110. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -2
  111. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -0
  112. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -3
  113. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +83 -48
  114. package/packages/dd-trace/src/appsec/index.js +21 -24
  115. package/packages/dd-trace/src/appsec/reporter.js +7 -2
  116. package/packages/dd-trace/src/appsec/rule_manager.js +4 -2
  117. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +31 -16
  118. package/packages/dd-trace/src/ci-visibility/lage.js +2 -1
  119. package/packages/dd-trace/src/ci-visibility/requests/request.js +11 -33
  120. package/packages/dd-trace/src/config/config-types.d.ts +0 -2
  121. package/packages/dd-trace/src/config/git_properties.js +2 -2
  122. package/packages/dd-trace/src/config/index.js +1 -55
  123. package/packages/dd-trace/src/datastreams/checkpointer.js +4 -10
  124. package/packages/dd-trace/src/datastreams/encoding.js +39 -28
  125. package/packages/dd-trace/src/datastreams/index.js +2 -1
  126. package/packages/dd-trace/src/datastreams/pathway.js +29 -26
  127. package/packages/dd-trace/src/datastreams/processor.js +18 -17
  128. package/packages/dd-trace/src/datastreams/size.js +6 -2
  129. package/packages/dd-trace/src/debugger/config.js +5 -2
  130. package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -5
  131. package/packages/dd-trace/src/debugger/devtools_client/send.js +2 -1
  132. package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +1 -0
  133. package/packages/dd-trace/src/dogstatsd.js +10 -7
  134. package/packages/dd-trace/src/encode/0.4.js +759 -234
  135. package/packages/dd-trace/src/encode/0.5.js +15 -9
  136. package/packages/dd-trace/src/encode/agentless-json.js +2 -2
  137. package/packages/dd-trace/src/encode/tags-processors.js +2 -27
  138. package/packages/dd-trace/src/exporters/common/request.js +22 -11
  139. package/packages/dd-trace/src/exporters/common/retry.js +104 -0
  140. package/packages/dd-trace/src/git_metadata.js +66 -0
  141. package/packages/dd-trace/src/git_metadata_tagger.js +13 -5
  142. package/packages/dd-trace/src/id.js +15 -26
  143. package/packages/dd-trace/src/llmobs/constants/tags.js +2 -0
  144. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -2
  145. package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +27 -16
  146. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +3 -0
  147. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +33 -13
  148. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +20 -50
  149. package/packages/dd-trace/src/llmobs/sdk.js +29 -27
  150. package/packages/dd-trace/src/llmobs/span_processor.js +52 -6
  151. package/packages/dd-trace/src/llmobs/tagger.js +42 -0
  152. package/packages/dd-trace/src/llmobs/telemetry.js +29 -0
  153. package/packages/dd-trace/src/llmobs/util.js +81 -5
  154. package/packages/dd-trace/src/msgpack/chunk.js +6 -3
  155. package/packages/dd-trace/src/openfeature/noop.js +40 -36
  156. package/packages/dd-trace/src/openfeature/writers/exposures.js +33 -52
  157. package/packages/dd-trace/src/opentelemetry/active-span-proxy.js +42 -0
  158. package/packages/dd-trace/src/opentelemetry/bridge-span-base.js +106 -0
  159. package/packages/dd-trace/src/opentelemetry/context_manager.js +11 -2
  160. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +1 -2
  161. package/packages/dd-trace/src/opentelemetry/span-helpers.js +188 -50
  162. package/packages/dd-trace/src/opentelemetry/span.js +42 -80
  163. package/packages/dd-trace/src/opentelemetry/tracer.js +0 -22
  164. package/packages/dd-trace/src/opentracing/propagation/text_map.js +65 -27
  165. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -11
  166. package/packages/dd-trace/src/opentracing/propagation/tracestate.js +58 -22
  167. package/packages/dd-trace/src/opentracing/span.js +56 -48
  168. package/packages/dd-trace/src/opentracing/span_context.js +1 -0
  169. package/packages/dd-trace/src/plugins/util/ci.js +1 -1
  170. package/packages/dd-trace/src/plugins/util/git-cache.js +3 -5
  171. package/packages/dd-trace/src/plugins/util/test.js +19 -7
  172. package/packages/dd-trace/src/plugins/util/url.js +1 -3
  173. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
  174. package/packages/dd-trace/src/plugins/util/web.js +5 -7
  175. package/packages/dd-trace/src/priority_sampler.js +6 -4
  176. package/packages/dd-trace/src/profiling/config.js +5 -4
  177. package/packages/dd-trace/src/profiling/profilers/events.js +3 -23
  178. package/packages/dd-trace/src/profiling/profilers/wall.js +4 -5
  179. package/packages/dd-trace/src/remote_config/index.js +5 -3
  180. package/packages/dd-trace/src/runtime_metrics/index.js +2 -2
  181. package/packages/dd-trace/src/scope.js +3 -10
  182. package/packages/dd-trace/src/serverless.js +1 -4
  183. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +7 -1
  184. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +4 -0
  185. package/packages/dd-trace/src/span_format.js +52 -5
  186. package/packages/dd-trace/src/span_processor.js +0 -4
  187. package/packages/dd-trace/src/spanleak.js +0 -1
  188. package/packages/dd-trace/src/tracer.js +7 -7
  189. package/packages/dd-trace/src/util.js +17 -0
@@ -143,9 +143,31 @@ const extractQueueMetadata = queueURL => {
143
143
  return { queueName, arn }
144
144
  }
145
145
 
146
+ /**
147
+ * Returns true when `obj` has no own enumerable properties. The
148
+ * `for-in` loop with an early return is the only allocation-free shape
149
+ * for this check; benchmarks pin it as 1.3-1.4x faster than
150
+ * `Object.keys(obj).length === 0` across small / medium / large
151
+ * objects, and this is the hot path on every AWS messaging send.
152
+ *
153
+ * Callers in this package only pass plain objects they construct
154
+ * locally, so prototype-enumerable keys are not a concern here. Do not
155
+ * reuse this helper on caller-supplied objects without revisiting that
156
+ * assumption.
157
+ *
158
+ * @param {object} obj
159
+ * @returns {boolean}
160
+ */
161
+ const isEmpty = obj => {
162
+ // eslint-disable-next-line no-unreachable-loop
163
+ for (const _ in obj) return false
164
+ return true
165
+ }
166
+
146
167
  module.exports = {
147
168
  generatePointerHash,
148
169
  encodeValue,
149
170
  extractPrimaryKeys,
150
171
  extractQueueMetadata,
172
+ isEmpty,
151
173
  }
@@ -69,8 +69,8 @@ class BullmqConsumerPlugin extends ConsumerPlugin {
69
69
  const ddCarrier = metadata._datadog
70
70
  if (!ddCarrier) return
71
71
 
72
- // Clean up only our _datadog key, preserve other metadata
73
- delete metadata._datadog
72
+ // Avoid `delete`'s hidden-class transition; JSON.stringify also omits undefined values.
73
+ metadata._datadog = undefined
74
74
  job.opts.telemetry.metadata = JSON.stringify(metadata)
75
75
 
76
76
  return ddCarrier
@@ -56,12 +56,14 @@ class BaseBullmqProducerPlugin extends ProducerPlugin {
56
56
  throw new Error('injectTraceContext must be implemented by subclass')
57
57
  }
58
58
 
59
+ // Returned so setProducerCheckpoint can mutate it without a second parse.
59
60
  _injectIntoOpts (span, opts) {
60
61
  const carrier = {}
61
62
  this.tracer.inject(span, 'text_map', carrier)
62
63
  const metadata = parseTelemetryMetadata(opts.telemetry?.metadata)
63
64
  metadata._datadog = carrier
64
65
  opts.telemetry = { metadata: JSON.stringify(metadata), omitContext: true }
66
+ return metadata
65
67
  }
66
68
 
67
69
  setProducerCheckpoint (span, ctx) {
@@ -70,7 +72,7 @@ class BaseBullmqProducerPlugin extends ProducerPlugin {
70
72
  const dataStreamsContext = this.tracer.setCheckpoint(edgeTags, span, payloadSize)
71
73
 
72
74
  if (optsTarget && typeof optsTarget === 'object') {
73
- const metadata = parseTelemetryMetadata(optsTarget.telemetry?.metadata)
75
+ const metadata = ctx._ddMetadata ?? parseTelemetryMetadata(optsTarget.telemetry?.metadata)
74
76
  DsmPathwayCodec.encode(dataStreamsContext, metadata._datadog || metadata)
75
77
  if (!metadata._datadog) metadata._datadog = {}
76
78
  optsTarget.telemetry = { metadata: JSON.stringify(metadata), omitContext: true }
@@ -110,7 +112,7 @@ class QueueAddPlugin extends BaseBullmqProducerPlugin {
110
112
 
111
113
  injectTraceContext (span, ctx) {
112
114
  const opts = this.#ensureOpts(ctx)
113
- this._injectIntoOpts(span, opts)
115
+ ctx._ddMetadata = this._injectIntoOpts(span, opts)
114
116
  }
115
117
 
116
118
  getDsmData (ctx) {
@@ -146,36 +148,28 @@ class QueueAddBulkPlugin extends BaseBullmqProducerPlugin {
146
148
  const jobs = ctx.arguments?.[0]
147
149
  if (!Array.isArray(jobs)) return
148
150
 
149
- for (const job of jobs) {
151
+ const cache = []
152
+ for (let i = 0; i < jobs.length; i++) {
153
+ const job = jobs[i]
150
154
  if (!job) continue
151
155
  job.opts = job.opts || {}
152
- this._injectIntoOpts(span, job.opts)
153
- }
154
- }
155
-
156
- getDsmData (ctx) {
157
- const jobs = ctx.arguments?.[0] || []
158
- const payloadSize = jobs.reduce((total, job) => {
159
- return total + (job?.data ? getMessageSize(job.data) : 0)
160
- }, 0)
161
- return {
162
- queueName: ctx.self?.name || 'bullmq',
163
- payloadSize,
164
- optsTarget: jobs[0]?.opts,
156
+ cache[i] = this._injectIntoOpts(span, job.opts)
165
157
  }
158
+ ctx._ddMetadata = cache
166
159
  }
167
160
 
168
161
  setProducerCheckpoint (span, ctx) {
169
162
  const jobs = ctx.arguments?.[0] || []
170
163
  const queueName = ctx.self?.name || 'bullmq'
171
164
  const edgeTags = ['direction:out', `topic:${queueName}`, 'type:bullmq']
165
+ const cache = ctx._ddMetadata
172
166
 
173
- for (const job of jobs) {
167
+ for (let i = 0; i < jobs.length; i++) {
168
+ const job = jobs[i]
174
169
  if (!job?.data) continue
175
170
  const payloadSize = getMessageSize(job.data)
176
171
  const dataStreamsContext = this.tracer.setCheckpoint(edgeTags, span, payloadSize)
177
- job.opts = job.opts || {}
178
- const metadata = parseTelemetryMetadata(job.opts.telemetry?.metadata)
172
+ const metadata = cache?.[i] ?? parseTelemetryMetadata(job.opts.telemetry?.metadata)
179
173
  DsmPathwayCodec.encode(dataStreamsContext, metadata._datadog || metadata)
180
174
  if (!metadata._datadog) metadata._datadog = {}
181
175
  job.opts.telemetry = { metadata: JSON.stringify(metadata), omitContext: true }
@@ -201,7 +195,7 @@ class FlowProducerAddPlugin extends BaseBullmqProducerPlugin {
201
195
  const flow = ctx.arguments?.[0]
202
196
  if (!flow) return
203
197
  flow.opts = flow.opts || {}
204
- this._injectIntoOpts(span, flow.opts)
198
+ ctx._ddMetadata = this._injectIntoOpts(span, flow.opts)
205
199
  }
206
200
 
207
201
  getDsmData (ctx) {
@@ -5,7 +5,7 @@ const shellParser = require('../../../vendor/dist/shell-quote').parse
5
5
  const ALLOWED_ENV_VARIABLES = new Set(['LD_PRELOAD', 'LD_LIBRARY_PATH', 'PATH'])
6
6
  const PROCESS_DENYLIST = new Set(['md5'])
7
7
 
8
- const VARNAMES_REGEX = /\$([\w\d_]*)(?:[^\w\d_]|$)/gmi
8
+ const VARNAMES_REGEX = /\$(\w*)(?:[^\w]|$)/gmi
9
9
  // eslint-disable-next-line @stylistic/max-len
10
10
  const PARAM_PATTERN = '^-{0,2}(?:p(?:ass(?:w(?:or)?d)?)?|address|api[-_]?key|e?mail|secret(?:[-_]?key)?|a(?:ccess|uth)[-_]?token|mysql_pwd|credentials|(?:stripe)?token)$'
11
11
  const regexParam = new RegExp(PARAM_PATTERN, 'i')
@@ -104,13 +104,13 @@ function scrubChildProcessCmd (expression) {
104
104
  result.push(token)
105
105
 
106
106
  if (PROCESS_DENYLIST.has(token)) {
107
- for (index++; index < expressionTokens.length; index++) {
108
- const token = expressionTokens[index]
107
+ for (let i = index + 1; i < expressionTokens.length; i++) {
108
+ const innerToken = expressionTokens[i]
109
109
 
110
- if (token.op) {
111
- result.push(token.op)
110
+ if (innerToken.op) {
111
+ result.push(innerToken.op)
112
112
  } else {
113
- expressionTokens[index] = REDACTED
113
+ expressionTokens[i] = REDACTED
114
114
  result.push(REDACTED)
115
115
  }
116
116
  }
@@ -308,6 +308,7 @@ class CucumberPlugin extends CiPlugin {
308
308
  isDisabled,
309
309
  isQuarantined,
310
310
  isModified,
311
+ earlyFlakeAbortReason,
311
312
  finalStatus,
312
313
  }) => {
313
314
  const statusTag = isStep ? 'step.status' : TEST_STATUS
@@ -317,6 +318,9 @@ class CucumberPlugin extends CiPlugin {
317
318
  if (finalStatus) {
318
319
  span.setTag(TEST_FINAL_STATUS, finalStatus)
319
320
  }
321
+ if (earlyFlakeAbortReason) {
322
+ span.setTag(TEST_EARLY_FLAKE_ABORT_REASON, earlyFlakeAbortReason)
323
+ }
320
324
 
321
325
  if (isNew) {
322
326
  span.setTag(TEST_IS_NEW, 'true')
@@ -4,6 +4,7 @@
4
4
  const { performance } = require('perf_hooks')
5
5
  const dateNow = Date.now
6
6
 
7
+ const satisfies = require('../../../vendor/dist/semifies')
7
8
  const {
8
9
  TEST_STATUS,
9
10
  TEST_IS_RUM_ACTIVE,
@@ -108,6 +109,7 @@ const {
108
109
  } = require('./source-map-utils')
109
110
 
110
111
  const TEST_FRAMEWORK_NAME = 'cypress'
112
+ let hasWarnedDeprecatedCypressVersion = false
111
113
 
112
114
  const CYPRESS_STATUS_TO_TEST_STATUS = {
113
115
  passed: 'pass',
@@ -136,6 +138,20 @@ function getCypressVersion (details) {
136
138
  return ''
137
139
  }
138
140
 
141
+ function warnDeprecatedCypressVersion (version) {
142
+ if (DD_MAJOR >= 6 || hasWarnedDeprecatedCypressVersion || !version || !satisfies(version, '<12.0.0')) {
143
+ return
144
+ }
145
+
146
+ hasWarnedDeprecatedCypressVersion = true
147
+ // console.warn does not seem to work reliably in Cypress, so use console.log instead.
148
+ // eslint-disable-next-line no-console
149
+ console.log(
150
+ 'WARNING: dd-trace support for Cypress<12.0.0 is deprecated' +
151
+ ' and will not be supported in dd-trace v6. Please upgrade Cypress to >=12.0.0.'
152
+ )
153
+ }
154
+
139
155
  function getRootDir (details) {
140
156
  if (details?.config) {
141
157
  return details.config.projectRoot || details.config.repoRoot || process.cwd()
@@ -434,6 +450,7 @@ class CypressPlugin {
434
450
  this._isInit = true
435
451
  this.tracer = tracer
436
452
  this.cypressConfig = cypressConfig
453
+ warnDeprecatedCypressVersion(cypressConfig.version)
437
454
 
438
455
  this.isTestIsolationEnabled = getIsTestIsolationEnabled(cypressConfig)
439
456
 
@@ -1037,10 +1054,7 @@ class CypressPlugin {
1037
1054
  rumFlushWaitMillis: this.rumFlushWaitMillis,
1038
1055
  }
1039
1056
 
1040
- if (this.testSuiteSpan) {
1041
- return suitePayload
1042
- }
1043
- this.testSuiteSpan = this.getTestSuiteSpan({ testSuite, testSuiteAbsolutePath })
1057
+ this.testSuiteSpan ||= this.getTestSuiteSpan({ testSuite, testSuiteAbsolutePath })
1044
1058
  return suitePayload
1045
1059
  },
1046
1060
  'dd:beforeEach': (test) => {
@@ -23,22 +23,13 @@ const noopTask = {
23
23
  module.exports = function CypressPlugin (on, config) {
24
24
  const tracer = require('../../dd-trace')
25
25
 
26
- if (satisfies(config.version, '<10.2.0')) {
27
- if (DD_MAJOR >= 6) {
28
- // eslint-disable-next-line no-console
29
- console.error(
30
- 'ERROR: dd-trace v6 has deleted support for Cypress<10.2.0.'
31
- )
32
- on('task', noopTask)
33
- return config
34
- }
35
-
36
- // console.warn does not seem to work in cypress, so using console.log instead
26
+ if (DD_MAJOR >= 6 && satisfies(config.version, '<12.0.0')) {
37
27
  // eslint-disable-next-line no-console
38
- console.log(
39
- 'WARNING: dd-trace support for Cypress<10.2.0 is deprecated' +
40
- ' and will not be supported in future versions of dd-trace.'
28
+ console.error(
29
+ 'ERROR: dd-trace v6 has deleted support for Cypress<12.0.0.'
41
30
  )
31
+ on('task', noopTask)
32
+ return config
42
33
  }
43
34
 
44
35
  // The tracer was not init correctly for whatever reason (such as invalid DD_SITE)
@@ -122,8 +122,6 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
122
122
 
123
123
  const topicName = topic?.slice(topic.lastIndexOf('/') + 1) ??
124
124
  subscription.name.slice(subscription.name.lastIndexOf('/') + 1)
125
- const baseService = this.tracer._service || 'unknown'
126
- const serviceName = this.config.service || { name: `${baseService}-pubsub`, source: baseService }
127
125
 
128
126
  const meta = {
129
127
  'gcloud.project_id': subscription.pubsub.projectId,
@@ -133,8 +131,6 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
133
131
  'pubsub.subscription': subscription.name,
134
132
  'pubsub.subscription_type': 'pull',
135
133
  'messaging.operation': 'receive',
136
- base_service: baseService,
137
- service_override_type: 'custom',
138
134
  }
139
135
 
140
136
  if (batchRequestTraceId && batchRequestSpanId) {
@@ -168,7 +164,7 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
168
164
  childOf,
169
165
  resource: `Message from ${topicName}`,
170
166
  type: 'worker',
171
- service: serviceName,
167
+ service: this.config.service || this.serviceName(),
172
168
  meta,
173
169
  metrics,
174
170
  }, ctx)
@@ -10,6 +10,8 @@ const pushReceiveSpans = new WeakMap()
10
10
 
11
11
  class GoogleCloudPubsubPushSubscriptionPlugin extends TracingPlugin {
12
12
  static get id () { return 'google-cloud-pubsub-push-subscription' }
13
+ static type = 'messaging'
14
+ static kind = 'consumer'
13
15
 
14
16
  constructor (...args) {
15
17
  super(...args)
@@ -150,7 +152,7 @@ class GoogleCloudPubsubPushSubscriptionPlugin extends TracingPlugin {
150
152
  childOf: parentContext,
151
153
  startTime,
152
154
  kind: 'consumer',
153
- service: this.config.service || { name: `${this.tracer._service}-pubsub`, source: this.tracer._service },
155
+ service: this.config.service || this.serviceName(),
154
156
  meta: {
155
157
  component: 'google-cloud-pubsub',
156
158
  'pubsub.method': 'receive',
@@ -79,11 +79,7 @@ class HttpClientPlugin extends ClientPlugin {
79
79
  }
80
80
 
81
81
  shouldInjectTraceHeaders (options, uri) {
82
- if (!this.config.propagationFilter(uri)) {
83
- return false
84
- }
85
-
86
- return true
82
+ return Boolean(this.config.propagationFilter(uri))
87
83
  }
88
84
 
89
85
  bindAsyncStart ({ parentStore }) {
@@ -3,7 +3,7 @@
3
3
  const { readFileSync } = require('fs')
4
4
  const { parse } = require('../../../vendor/dist/jest-docblock')
5
5
 
6
- const { getTestSuitePath, getEfdRetryCount } = require('../../dd-trace/src/plugins/util/test')
6
+ const { getTestSuitePath } = require('../../dd-trace/src/plugins/util/test')
7
7
  const log = require('../../dd-trace/src/log')
8
8
 
9
9
  /**
@@ -172,5 +172,4 @@ module.exports = {
172
172
  getJestTestName,
173
173
  getJestSuitesToRun,
174
174
  isMarkedAsUnskippable,
175
- getEfdRetryCount,
176
175
  }
@@ -56,15 +56,8 @@ class KafkajsConsumerPlugin extends ConsumerPlugin {
56
56
 
57
57
  commit (commitList) {
58
58
  if (!this.config.dsmEnabled) return
59
- const keys = [
60
- 'consumer_group',
61
- 'type',
62
- 'partition',
63
- 'offset',
64
- 'topic',
65
- ]
66
- for (const commit of commitList.map(this.transformCommit)) {
67
- if (keys.some(key => !commit.hasOwnProperty(key))) continue
59
+ for (const rawCommit of commitList) {
60
+ const commit = this.transformCommit(rawCommit)
68
61
  this.tracer.setOffset(commit)
69
62
  }
70
63
  }
@@ -64,14 +64,8 @@ class KafkajsProducerPlugin extends ProducerPlugin {
64
64
 
65
65
  if (!this.config.dsmEnabled) return
66
66
  if (!commitList || !Array.isArray(commitList)) return
67
- const keys = [
68
- 'type',
69
- 'partition',
70
- 'offset',
71
- 'topic',
72
- ]
73
- for (const commit of commitList.map(r => this.transformProduceResponse(r, clusterId))) {
74
- if (keys.some(key => !commit.hasOwnProperty(key))) continue
67
+ for (const rawCommit of commitList) {
68
+ const commit = this.transformProduceResponse(rawCommit, clusterId)
75
69
  this.tracer.setOffset(commit)
76
70
  }
77
71
  }
@@ -218,12 +218,16 @@ class MochaPlugin extends CiPlugin {
218
218
  isAttemptToFixRetry,
219
219
  isAtrRetry,
220
220
  finalStatus,
221
+ earlyFlakeAbortReason,
221
222
  }) => {
222
223
  if (span) {
223
224
  span.setTag(TEST_STATUS, status)
224
225
  if (finalStatus) {
225
226
  span.setTag(TEST_FINAL_STATUS, finalStatus)
226
227
  }
228
+ if (earlyFlakeAbortReason) {
229
+ span.setTag(TEST_EARLY_FLAKE_ABORT_REASON, earlyFlakeAbortReason)
230
+ }
227
231
  if (hasBeenRetried) {
228
232
  span.setTag(TEST_IS_RETRY, 'true')
229
233
  if (isAtrRetry) {
@@ -173,9 +173,10 @@ function limitDepth (input) {
173
173
  } else if (shouldSimplify(child)) {
174
174
  output[key] = child
175
175
  } else {
176
+ output[key] = {}
176
177
  queue.push({
177
178
  input: child,
178
- output: output[key] = {},
179
+ output: output[key],
179
180
  depth: nextDepth,
180
181
  })
181
182
  }
@@ -560,9 +560,8 @@ function createResponseResponseExtraction (tags, body, openaiStore) {
560
560
 
561
561
  // The server almost always responds with JSON
562
562
  function coerceResponseBody (body, methodName) {
563
- switch (methodName) {
564
- case 'downloadFile':
565
- return { file: body }
563
+ if (methodName === 'downloadFile') {
564
+ return { file: body }
566
565
  }
567
566
 
568
567
  const type = typeof body
@@ -574,9 +573,8 @@ function coerceResponseBody (body, methodName) {
574
573
  }
575
574
  } else if (type === 'object') {
576
575
  return body
577
- } else {
578
- return {}
579
576
  }
577
+ return {}
580
578
  }
581
579
 
582
580
  // This method is used to replace a dynamic URL segment with an asterisk
@@ -594,28 +592,19 @@ function lookupOperationEndpoint (operationId, methodName, url) {
594
592
  return '/v1/files/*/content'
595
593
 
596
594
  case 'retrieveFineTune':
597
- switch (methodName) {
598
- case 'fine_tuning.jobs.retrieve':
599
- return '/v1/fine_tuning/jobs/*'
600
- default:
601
- return '/v1/fine-tunes/*'
602
- }
595
+ return methodName === 'fine_tuning.jobs.retrieve'
596
+ ? '/v1/fine_tuning/jobs/*'
597
+ : '/v1/fine-tunes/*'
603
598
 
604
599
  case 'listFineTuneEvents':
605
- switch (methodName) {
606
- case 'fine_tuning.jobs.listEvents':
607
- return '/v1/fine_tuning/jobs/*/events'
608
- default:
609
- return '/v1/fine-tunes/*/events'
610
- }
600
+ return methodName === 'fine_tuning.jobs.listEvents'
601
+ ? '/v1/fine_tuning/jobs/*/events'
602
+ : '/v1/fine-tunes/*/events'
611
603
 
612
604
  case 'cancelFineTune':
613
- switch (methodName) {
614
- case 'fine_tuning.jobs.cancel':
615
- return '/v1/fine_tuning/jobs/*/cancel'
616
- default:
617
- return '/v1/fine-tunes/*/cancel'
618
- }
605
+ return methodName === 'fine_tuning.jobs.cancel'
606
+ ? '/v1/fine_tuning/jobs/*/cancel'
607
+ : '/v1/fine-tunes/*/cancel'
619
608
  }
620
609
 
621
610
  return url
@@ -491,7 +491,7 @@ class PlaywrightPlugin extends CiPlugin {
491
491
  [TEST_SOURCE_START]: testSourceLine,
492
492
  }
493
493
  if (testSourceFile) {
494
- extraTags[TEST_SOURCE_FILE] = testSourceFile || testSuite
494
+ extraTags[TEST_SOURCE_FILE] = testSourceFile
495
495
  }
496
496
  if (browserName) {
497
497
  // Added as parameter too because it should affect the test fingerprint
@@ -213,13 +213,16 @@ class VitestPlugin extends CiPlugin {
213
213
  return ctx.currentStore
214
214
  })
215
215
 
216
- this.addSub('ci:vitest:test:pass', ({ span, task, finalStatus }) => {
216
+ this.addSub('ci:vitest:test:pass', ({ span, task, finalStatus, earlyFlakeAbortReason }) => {
217
217
  if (span) {
218
218
  this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'test', this.getTestTelemetryTags(span))
219
219
  span.setTag(TEST_STATUS, 'pass')
220
220
  if (finalStatus) {
221
221
  span.setTag(TEST_FINAL_STATUS, finalStatus)
222
222
  }
223
+ if (earlyFlakeAbortReason) {
224
+ span.setTag(TEST_EARLY_FLAKE_ABORT_REASON, earlyFlakeAbortReason)
225
+ }
223
226
  span.finish(this.taskToFinishTime.get(task))
224
227
  finishAllTraceSpans(span)
225
228
  }
@@ -234,6 +237,7 @@ class VitestPlugin extends CiPlugin {
234
237
  hasFailedAllRetries,
235
238
  attemptToFixFailed,
236
239
  finalStatus,
240
+ earlyFlakeAbortReason,
237
241
  }) => {
238
242
  if (!span) {
239
243
  return
@@ -262,6 +266,9 @@ class VitestPlugin extends CiPlugin {
262
266
  if (finalStatus) {
263
267
  span.setTag(TEST_FINAL_STATUS, finalStatus)
264
268
  }
269
+ if (earlyFlakeAbortReason) {
270
+ span.setTag(TEST_EARLY_FLAKE_ABORT_REASON, earlyFlakeAbortReason)
271
+ }
265
272
  if (duration) {
266
273
  span.finish(span._startTime + duration - MILLISECONDS_TO_SUBTRACT_FROM_FAILED_TEST_DURATION) // milliseconds
267
274
  } else {
@@ -267,7 +267,13 @@ function assertMethod (target, name, method) {
267
267
  * @throws {Error} If the target is a class constructor.
268
268
  */
269
269
  function assertNotClass (target) {
270
- if (Function.prototype.toString.call(target).startsWith('class')) {
270
+ // Class constructors have a non-writable `prototype` property; functions have a
271
+ // writable one and arrows / async / method-shorthand have none at all. The
272
+ // `'prototype' in target` gate skips the descriptor lookup for the no-prototype
273
+ // shapes; the `in` operator is cheaper than reading `target.prototype` since
274
+ // it returns a boolean instead of materialising the prototype reference.
275
+ if ('prototype' in target &&
276
+ Object.getOwnPropertyDescriptor(target, 'prototype').writable === false) {
271
277
  throw new TypeError('Target is a native class constructor and cannot be wrapped.')
272
278
  }
273
279
  }
@@ -5,7 +5,7 @@ const { NameAndValue } = require('./hardcoded-rule-type')
5
5
  module.exports = [
6
6
  {
7
7
  id: 'hardcoded-password',
8
- regex: /(?:pwd|pswd|pass|secret)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|""]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9a-z\-_.=]{10,150})(?:['"\s\x60;]|$)/i,
8
+ regex: /(?:pwd|pswd|pass|secret)(?:[0-9a-z\-_\t.]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:{1,3}=|\|\|:|<=|=>|:|\?=)(?:'|""|\s|=|\x60){0,5}([0-9a-z\-_.=]{10,150})(?:['"\s\x60;]|$)/i,
9
9
  type: NameAndValue,
10
10
  },
11
11
  ]