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
@@ -11,23 +11,23 @@ const { keepTrace } = require('../priority_sampler')
11
11
  const { AI_GUARD } = require('../standalone/product')
12
12
  const NoopAIGuard = require('./noop')
13
13
  const executeRequest = require('./client')
14
- const {
15
- AI_GUARD_RESOURCE,
16
- AI_GUARD_TARGET_TAG_KEY,
17
- AI_GUARD_REASON_TAG_KEY,
18
- AI_GUARD_ACTION_TAG_KEY,
19
- AI_GUARD_EVENT_TAG_KEY,
20
- AI_GUARD_BLOCKED_TAG_KEY,
21
- AI_GUARD_META_STRUCT_KEY,
22
- AI_GUARD_TOOL_NAME_TAG_KEY,
23
- AI_GUARD_TELEMETRY_REQUESTS,
24
- AI_GUARD_TELEMETRY_TRUNCATED,
25
- } = require('./tags')
14
+ const TAGS = require('./tags')
26
15
 
27
- const appsecMetrics = telemetryMetrics.manager.namespace('appsec')
16
+ const aiguardMetrics = telemetryMetrics.manager.namespace('ai_guard')
28
17
 
29
18
  const ALLOW = 'ALLOW'
30
19
 
20
+ /**
21
+ * Reports a telemetry error
22
+ *
23
+ * @param {string} errorType - The error type constant (client_error, bad_status, bad_response)
24
+ * @param {{ source: string, integration: string }} telemetryTags - Source and integration tags
25
+ */
26
+ function reportTelemetryError (errorType, telemetryTags) {
27
+ aiguardMetrics.count(TAGS.TELEMETRY_REQUESTS, { error: true, ...telemetryTags }).inc(1)
28
+ aiguardMetrics.count(TAGS.TELEMETRY_ERROR, { type: errorType, ...telemetryTags }).inc(1)
29
+ }
30
+
31
31
  class AIGuardAbortError extends Error {
32
32
  constructor (reason, tags, tagProbs, sds) {
33
33
  super(reason)
@@ -99,10 +99,10 @@ class AIGuard extends NoopAIGuard {
99
99
  * - Clones each message so callers cannot mutate the data set in the meta struct.
100
100
  * - Truncates the list of messages and `content` fields emitting metrics accordingly.
101
101
  */
102
- #buildMessagesForMetaStruct (messages) {
102
+ #buildMessagesForMetaStruct (messages, telemetryTags) {
103
103
  const size = Math.min(messages.length, this.#maxMessagesLength)
104
104
  if (messages.length > size) {
105
- appsecMetrics.count(AI_GUARD_TELEMETRY_TRUNCATED, { type: 'messages' }).inc(1)
105
+ aiguardMetrics.count(TAGS.TELEMETRY_TRUNCATED, { type: 'messages', ...telemetryTags }).inc(1)
106
106
  }
107
107
  const result = []
108
108
  let contentTruncated = false
@@ -115,7 +115,7 @@ class AIGuard extends NoopAIGuard {
115
115
  result.push(message)
116
116
  }
117
117
  if (contentTruncated) {
118
- appsecMetrics.count(AI_GUARD_TELEMETRY_TRUNCATED, { type: 'content' }).inc(1)
118
+ aiguardMetrics.count(TAGS.TELEMETRY_TRUNCATED, { type: 'content', ...telemetryTags }).inc(1)
119
119
  }
120
120
  return result
121
121
  }
@@ -185,22 +185,23 @@ class AIGuard extends NoopAIGuard {
185
185
  if (!this.#initialized) {
186
186
  return super.evaluate(messages, opts)
187
187
  }
188
- const { block = true } = opts ?? {}
189
- return this.#tracer.trace(AI_GUARD_RESOURCE, {}, async (span) => {
188
+ const { block = true, source = TAGS.SOURCE_SDK, integration = TAGS.INTEGRATION_NONE } = opts ?? {}
189
+ const telemetryTags = { source, integration }
190
+ return this.#tracer.trace(TAGS.RESOURCE, {}, async (span) => {
190
191
  const last = messages[messages.length - 1]
191
192
  const target = this.#isToolCall(last) ? 'tool' : 'prompt'
192
- span.setTag(AI_GUARD_TARGET_TAG_KEY, target)
193
+ span.setTag(TAGS.TARGET_TAG_KEY, target)
193
194
  if (target === 'tool') {
194
195
  const name = this.#getToolName(last, messages)
195
196
  if (name) {
196
- span.setTag(AI_GUARD_TOOL_NAME_TAG_KEY, name)
197
+ span.setTag(TAGS.TOOL_NAME_TAG_KEY, name)
197
198
  }
198
199
  }
199
200
  const metaStruct = {
200
- messages: this.#buildMessagesForMetaStruct(messages),
201
+ messages: this.#buildMessagesForMetaStruct(messages, telemetryTags),
201
202
  }
202
203
  span.meta_struct = {
203
- [AI_GUARD_META_STRUCT_KEY]: metaStruct,
204
+ [TAGS.META_STRUCT_KEY]: metaStruct,
204
205
  }
205
206
  const rootSpan = span.context()?._trace?.started?.[0]
206
207
  if (rootSpan) {
@@ -208,7 +209,7 @@ class AIGuard extends NoopAIGuard {
208
209
  // keepTrace must be called before executeRequest so the sampling decision
209
210
  // is propagated correctly to outgoing HTTP client calls.
210
211
  keepTrace(rootSpan, AI_GUARD)
211
- rootSpan.setTag(AI_GUARD_EVENT_TAG_KEY, 'true')
212
+ rootSpan.setTag(TAGS.EVENT_TAG_KEY, 'true')
212
213
  }
213
214
  let response
214
215
  try {
@@ -224,18 +225,18 @@ class AIGuard extends NoopAIGuard {
224
225
  payload,
225
226
  { url: this.#evaluateUrl, headers: this.#headers, timeout: this.#timeout })
226
227
  } catch (e) {
227
- appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
228
+ reportTelemetryError(TAGS.ERROR_TYPE_CLIENT, telemetryTags)
228
229
  throw new AIGuardClientError(`Unexpected error calling AI Guard service: ${e.message}`, { cause: e })
229
230
  }
230
231
  if (response.status !== 200) {
231
- appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
232
+ reportTelemetryError(TAGS.ERROR_TYPE_STATUS, telemetryTags)
232
233
  throw new AIGuardClientError(
233
234
  `AI Guard service call failed, status ${response.status}`,
234
235
  { errors: response.body?.errors })
235
236
  }
236
237
  const attr = response.body?.data?.attributes
237
238
  if (!attr?.action) {
238
- appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
239
+ reportTelemetryError(TAGS.ERROR_TYPE_RESPONSE, telemetryTags)
239
240
  throw new AIGuardClientError(`AI Guard service returned unexpected response : ${response.body}`)
240
241
  }
241
242
  const action = attr.action
@@ -254,13 +255,18 @@ class AIGuard extends NoopAIGuard {
254
255
  }
255
256
  const blockingEnabled = attr.is_blocking_enabled ?? false
256
257
  const shouldBlock = block && blockingEnabled && action !== ALLOW
257
- appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { action, error: false, block: shouldBlock }).inc(1)
258
- span.setTag(AI_GUARD_ACTION_TAG_KEY, action)
258
+ aiguardMetrics.count(TAGS.TELEMETRY_REQUESTS, {
259
+ action,
260
+ error: false,
261
+ block: shouldBlock,
262
+ ...telemetryTags,
263
+ }).inc(1)
264
+ span.setTag(TAGS.ACTION_TAG_KEY, action)
259
265
  if (reason) {
260
- span.setTag(AI_GUARD_REASON_TAG_KEY, reason)
266
+ span.setTag(TAGS.REASON_TAG_KEY, reason)
261
267
  }
262
268
  if (shouldBlock) {
263
- span.setTag(AI_GUARD_BLOCKED_TAG_KEY, 'true')
269
+ span.setTag(TAGS.BLOCKED_TAG_KEY, 'true')
264
270
  throw new AIGuardAbortError(reason, tags, tagProbabilities, sdsFindings)
265
271
  }
266
272
  return { action, reason, tags, tagProbabilities, sds: sdsFindings }
@@ -1,15 +1,24 @@
1
1
  'use strict'
2
2
 
3
3
  module.exports = {
4
- AI_GUARD_RESOURCE: 'ai_guard',
5
- AI_GUARD_TARGET_TAG_KEY: 'ai_guard.target',
6
- AI_GUARD_TOOL_NAME_TAG_KEY: 'ai_guard.tool_name',
7
- AI_GUARD_ACTION_TAG_KEY: 'ai_guard.action',
8
- AI_GUARD_REASON_TAG_KEY: 'ai_guard.reason',
9
- AI_GUARD_BLOCKED_TAG_KEY: 'ai_guard.blocked',
10
- AI_GUARD_EVENT_TAG_KEY: 'ai_guard.event',
11
- AI_GUARD_META_STRUCT_KEY: 'ai_guard',
12
-
13
- AI_GUARD_TELEMETRY_REQUESTS: 'ai_guard.requests',
14
- AI_GUARD_TELEMETRY_TRUNCATED: 'ai_guard.truncated',
4
+ RESOURCE: 'ai_guard',
5
+ TARGET_TAG_KEY: 'ai_guard.target',
6
+ TOOL_NAME_TAG_KEY: 'ai_guard.tool_name',
7
+ ACTION_TAG_KEY: 'ai_guard.action',
8
+ REASON_TAG_KEY: 'ai_guard.reason',
9
+ BLOCKED_TAG_KEY: 'ai_guard.blocked',
10
+ EVENT_TAG_KEY: 'ai_guard.event',
11
+ META_STRUCT_KEY: 'ai_guard',
12
+
13
+ TELEMETRY_REQUESTS: 'requests',
14
+ TELEMETRY_TRUNCATED: 'truncated',
15
+ TELEMETRY_ERROR: 'error',
16
+
17
+ SOURCE_SDK: 'sdk',
18
+ SOURCE_AUTO: 'auto',
19
+ INTEGRATION_NONE: 'none',
20
+
21
+ ERROR_TYPE_CLIENT: 'client_error',
22
+ ERROR_TYPE_STATUS: 'bad_status',
23
+ ERROR_TYPE_RESPONSE: 'bad_response',
15
24
  }
@@ -104,8 +104,8 @@ function getBlockWithContentData (req, specificType, actionParameters) {
104
104
  const statusCode = actionParameters?.status_code || 403
105
105
 
106
106
  const headers = {
107
- 'Content-Type': type,
108
- 'Content-Length': Buffer.byteLength(body),
107
+ 'content-type': type,
108
+ 'content-length': Buffer.byteLength(body),
109
109
  }
110
110
 
111
111
  return { body, statusCode, headers }
@@ -208,8 +208,8 @@ let enableEsmRewriter = function (telemetryVerbosity) {
208
208
  }
209
209
  })
210
210
 
211
- port1.unref()
212
- port2.unref()
211
+ port1.unref?.()
212
+ port2.unref?.()
213
213
 
214
214
  try {
215
215
  Module.register('./rewriter-esm.mjs', {
@@ -100,7 +100,7 @@ function clearCache () { // only for test purposes
100
100
 
101
101
  function startClearCacheTimer () {
102
102
  resetVulnerabilityCacheTimer = setInterval(clearCache, RESET_VULNERABILITY_CACHE_INTERVAL)
103
- resetVulnerabilityCacheTimer.unref()
103
+ resetVulnerabilityCacheTimer.unref?.()
104
104
  }
105
105
 
106
106
  function stopClearCacheTimer () {
@@ -350,8 +350,15 @@ function onResponseBody ({ req, res, body }) {
350
350
  }
351
351
 
352
352
  function onResponseWriteHead ({ req, res, abortController, statusCode, responseHeaders }) {
353
- if (!isEmpty(responseHeaders)) {
354
- storedResponseHeaders.set(req, responseHeaders)
353
+ // Normalize header names to lowercase so downstream consumers see the same shape
354
+ // regardless of how the caller wrote them.
355
+ const normalizedResponseHeaders = {}
356
+ for (const [key, value] of Object.entries(responseHeaders)) {
357
+ normalizedResponseHeaders[key.toLowerCase()] = value
358
+ }
359
+
360
+ if (!isEmpty(normalizedResponseHeaders)) {
361
+ storedResponseHeaders.set(req, normalizedResponseHeaders)
355
362
  }
356
363
 
357
364
  // TODO: do not call waf if inside block()
@@ -376,7 +383,7 @@ function onResponseWriteHead ({ req, res, abortController, statusCode, responseH
376
383
  const results = waf.run({
377
384
  persistent: {
378
385
  [addresses.HTTP_INCOMING_RESPONSE_CODE]: String(statusCode),
379
- [addresses.HTTP_INCOMING_RESPONSE_HEADERS]: copyHeadersOmitting(responseHeaders, 'set-cookie'),
386
+ [addresses.HTTP_INCOMING_RESPONSE_HEADERS]: copyHeadersOmitting(normalizedResponseHeaders, 'set-cookie'),
380
387
  },
381
388
  }, req)
382
389
 
@@ -50,6 +50,11 @@ const contentHeaderList = [
50
50
  'content-language',
51
51
  ]
52
52
 
53
+ const mandatoryResponseHeaderList = [
54
+ 'content-type',
55
+ 'content-length',
56
+ ]
57
+
53
58
  const responseHeaderList = [
54
59
  ...contentHeaderList,
55
60
  'content-type',
@@ -102,6 +107,8 @@ const EVENT_HEADERS_MAP = mapHeaderAndTags(eventHeadersList, REQUEST_HEADER_TAG_
102
107
 
103
108
  const RESPONSE_HEADERS_MAP = mapHeaderAndTags(responseHeaderList, RESPONSE_HEADER_TAG_PREFIX)
104
109
 
110
+ const MANDATORY_RESPONSE_HEADERS_MAP = mapHeaderAndTags(mandatoryResponseHeaderList, RESPONSE_HEADER_TAG_PREFIX)
111
+
105
112
  const NON_EXTENDED_REQUEST_HEADERS = new Set([...requestHeadersList, ...eventHeadersList])
106
113
  const NON_EXTENDED_RESPONSE_HEADERS = new Set(responseHeaderList)
107
114
  const REDACTED_HEADERS = new Set(redactedHeadersList)
@@ -168,14 +175,21 @@ function getCollectedHeaders (req, res, shouldCollectEventHeaders, storedRespons
168
175
  // Mandatory
169
176
  const mandatoryCollectedHeaders = filterHeaders(req.headers, REQUEST_HEADERS_MAP)
170
177
 
171
- // Basic collection
172
- if (!shouldCollectEventHeaders) return mandatoryCollectedHeaders
173
-
174
178
  // Skip the spread when the stored side is empty -- common during the early
175
179
  // request lifecycle when no upstream response headers have been captured.
180
+ const liveResponseHeaders = res?.getHeaders?.()
176
181
  const responseHeaders = isEmpty(storedResponseHeaders)
177
- ? res.getHeaders()
178
- : { ...storedResponseHeaders, ...res.getHeaders() }
182
+ ? (liveResponseHeaders ?? {})
183
+ : (liveResponseHeaders ? { ...storedResponseHeaders, ...liveResponseHeaders } : storedResponseHeaders)
184
+
185
+ // content-type and content-length are always reported when appsec is enabled,
186
+ // even without a security event.
187
+ if (!shouldCollectEventHeaders) {
188
+ return Object.assign(
189
+ mandatoryCollectedHeaders,
190
+ filterHeaders(responseHeaders, MANDATORY_RESPONSE_HEADERS_MAP)
191
+ )
192
+ }
179
193
 
180
194
  const requestEventCollectedHeaders = filterHeaders(req.headers, EVENT_HEADERS_MAP)
181
195
  const responseEventCollectedHeaders = filterHeaders(responseHeaders, RESPONSE_HEADERS_MAP)
@@ -3,10 +3,8 @@
3
3
  // Modeled after https://github.com/DataDog/libdatadog/blob/f3994857a59bb5679a65967138c5a3aec418a65f/ddcommon/src/azure_app_services.rs
4
4
 
5
5
  const os = require('os')
6
- const {
7
- getEnvironmentVariable,
8
- getValueFromEnvSources,
9
- } = require('./config/helper')
6
+ const getConfig = require('./config')
7
+ const { getEnvironmentVariable } = require('./config/helper')
10
8
  const { getIsAzureFunction } = require('./serverless')
11
9
 
12
10
  function extractSubscriptionID (ownerName) {
@@ -19,7 +17,20 @@ function extractSubscriptionID (ownerName) {
19
17
  }
20
18
 
21
19
  function extractResourceGroup (ownerName) {
22
- return /.+\+(.+)-.+webspace(-Linux)?/.exec(ownerName)?.[1]
20
+ // WEBSITE_OWNER_NAME format: `<sub-id>+<rg>-<region>webspace[-Linux]`. Region
21
+ // names have no `-`; resource groups can. Plain string ops read more directly
22
+ // than `/.+\+(.+)-.+webspace(-Linux)?/` and avoid the engine backtracking
23
+ // through three `.+` quantifiers to land on the right `-`.
24
+ if (typeof ownerName !== 'string') return
25
+ const plusIdx = ownerName.indexOf('+')
26
+ if (plusIdx === -1) return
27
+ let rest = ownerName.slice(plusIdx + 1)
28
+ if (rest.endsWith('-Linux')) rest = rest.slice(0, -'-Linux'.length)
29
+ if (!rest.endsWith('webspace')) return
30
+ rest = rest.slice(0, -'webspace'.length)
31
+ const lastDash = rest.lastIndexOf('-')
32
+ if (lastDash === -1) return
33
+ return rest.slice(0, lastDash)
23
34
  }
24
35
 
25
36
  function buildResourceID (subscriptionID, siteName, resourceGroup) {
@@ -56,7 +67,7 @@ function buildMetadata () {
56
67
  const WEBSITE_SITE_NAME = getEnvironmentVariable('WEBSITE_SITE_NAME')
57
68
  const WEBSITE_SKU = getEnvironmentVariable('WEBSITE_SKU')
58
69
 
59
- const DD_AZURE_RESOURCE_GROUP = getValueFromEnvSources('DD_AZURE_RESOURCE_GROUP')
70
+ const { DD_AZURE_RESOURCE_GROUP } = getConfig()
60
71
  const isAzureFunction = FUNCTIONS_EXTENSION_VERSION !== undefined && FUNCTIONS_WORKER_RUNTIME !== undefined
61
72
  const isFlexConsumptionAzureFunction = isAzureFunction && WEBSITE_SKU === 'FlexConsumption'
62
73
 
@@ -120,7 +120,7 @@ class TestVisDynamicInstrumentation {
120
120
  })
121
121
 
122
122
  // Allow the parent to exit even if the worker is still running
123
- this.worker.unref()
123
+ this.worker.unref?.()
124
124
 
125
125
  this.breakpointSetChannel.port2.on('message', (probeId) => {
126
126
  const resolve = probeIdToResolveBreakpointSet.get(probeId)
@@ -128,7 +128,7 @@ class TestVisDynamicInstrumentation {
128
128
  resolve()
129
129
  probeIdToResolveBreakpointSet.delete(probeId)
130
130
  }
131
- }).unref()
131
+ }).unref?.()
132
132
 
133
133
  this.breakpointHitChannel.port2.on('message', ({ snapshot }) => {
134
134
  const { probe: { id: probeId } } = snapshot
@@ -138,7 +138,7 @@ class TestVisDynamicInstrumentation {
138
138
  } else {
139
139
  log.warn('Received a breakpoint hit for an unknown probe')
140
140
  }
141
- }).unref()
141
+ }).unref?.()
142
142
 
143
143
  this.breakpointRemoveChannel.port2.on('message', (probeId) => {
144
144
  const resolve = probeIdToResolveBreakpointRemove.get(probeId)
@@ -146,7 +146,7 @@ class TestVisDynamicInstrumentation {
146
146
  resolve()
147
147
  probeIdToResolveBreakpointRemove.delete(probeId)
148
148
  }
149
- }).unref()
149
+ }).unref?.()
150
150
  }
151
151
  }
152
152
 
@@ -48,11 +48,13 @@ class CiVisibilityExporter extends BufferingExporter {
48
48
 
49
49
  const gitUploadTimeoutId = setTimeout(() => {
50
50
  this._resolveGit(new Error('Timeout while uploading git metadata'))
51
- }, GIT_UPLOAD_TIMEOUT).unref()
51
+ }, GIT_UPLOAD_TIMEOUT)
52
+ gitUploadTimeoutId.unref?.()
52
53
 
53
54
  const canUseCiVisProtocolTimeoutId = setTimeout(() => {
54
55
  this._resolveCanUseCiVisProtocol(false)
55
- }, CAN_USE_CI_VIS_PROTOCOL_TIMEOUT).unref()
56
+ }, CAN_USE_CI_VIS_PROTOCOL_TIMEOUT)
57
+ canUseCiVisProtocolTimeoutId.unref?.()
56
58
 
57
59
  this._gitUploadPromise = new Promise(resolve => {
58
60
  this._resolveGit = (err) => {
@@ -11,10 +11,12 @@ const {
11
11
  VITEST_WORKER_TRACE_PAYLOAD_CODE,
12
12
  VITEST_WORKER_LOGS_PAYLOAD_CODE,
13
13
  } = require('../../../plugins/util/test')
14
- const { getEnvironmentVariable, getValueFromEnvSources } = require('../../../config/helper')
14
+ const getConfig = require('../../../config')
15
+ const { getEnvironmentVariable } = require('../../../config/helper')
15
16
  const Writer = require('./writer')
16
17
 
17
18
  function getInterprocessTraceCode () {
19
+ const { DD_PLAYWRIGHT_WORKER, DD_VITEST_WORKER } = getConfig()
18
20
  if (getEnvironmentVariable('JEST_WORKER_ID')) {
19
21
  return JEST_WORKER_TRACE_PAYLOAD_CODE
20
22
  }
@@ -24,13 +26,13 @@ function getInterprocessTraceCode () {
24
26
  if (getEnvironmentVariable('MOCHA_WORKER_ID')) {
25
27
  return MOCHA_WORKER_TRACE_PAYLOAD_CODE
26
28
  }
27
- if (getValueFromEnvSources('DD_PLAYWRIGHT_WORKER')) {
29
+ if (DD_PLAYWRIGHT_WORKER) {
28
30
  return PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE
29
31
  }
30
32
  if (getEnvironmentVariable('TINYPOOL_WORKER_ID')) {
31
33
  return VITEST_WORKER_TRACE_PAYLOAD_CODE
32
34
  }
33
- if (getValueFromEnvSources('DD_VITEST_WORKER')) {
35
+ if (DD_VITEST_WORKER) {
34
36
  return VITEST_WORKER_TRACE_PAYLOAD_CODE
35
37
  }
36
38
  return null
@@ -51,7 +53,7 @@ function getInterprocessLogsCode () {
51
53
  if (getEnvironmentVariable('TINYPOOL_WORKER_ID')) {
52
54
  return VITEST_WORKER_LOGS_PAYLOAD_CODE
53
55
  }
54
- if (getValueFromEnvSources('DD_VITEST_WORKER')) {
56
+ if (getConfig().DD_VITEST_WORKER) {
55
57
  return VITEST_WORKER_LOGS_PAYLOAD_CODE
56
58
  }
57
59
  return null
@@ -149,7 +149,7 @@ function touchLock (cacheKey) {
149
149
  */
150
150
  function startLockHeartbeat (cacheKey) {
151
151
  const interval = setInterval(() => touchLock(cacheKey), CACHE_LOCK_HEARTBEAT_MS)
152
- interval.unref()
152
+ interval.unref?.()
153
153
  return () => {
154
154
  clearInterval(interval)
155
155
  try { fs.unlinkSync(getLockPath(cacheKey)) } catch { /* ignore */ }
@@ -14,6 +14,8 @@ const {
14
14
  } = require('../../exporters/common/retry')
15
15
  const { urlToHttpOptions } = require('../../exporters/common/url-to-http-options-polyfill')
16
16
 
17
+ const legacyStorage = storage('legacy')
18
+
17
19
  function parseUrl (urlObjOrString) {
18
20
  if (urlObjOrString !== null && typeof urlObjOrString === 'object') {
19
21
  return urlToHttpOptions(urlObjOrString)
@@ -75,7 +77,7 @@ function request (data, options, callback) {
75
77
  let firstStatusCode = null
76
78
 
77
79
  const makeRequest = () => {
78
- storage('legacy').run({ noop: true }, () => {
80
+ legacyStorage.run({ noop: true }, () => {
79
81
  const req = client.request(opts, (res) => {
80
82
  // Capture non-2xx status code as soon as we see it so telemetry preserves it if the retry
81
83
  // fails with a network error (no HTTP response) before 'end' fires
@@ -8,6 +8,8 @@ const {
8
8
  } = require('../../plugins/util/test')
9
9
  const { storage } = require('../../../../datadog-core')
10
10
 
11
+ const legacyStorage = storage('legacy')
12
+
11
13
  class TestApiManualPlugin extends CiPlugin {
12
14
  static id = 'test-api-manual'
13
15
 
@@ -17,13 +19,13 @@ class TestApiManualPlugin extends CiPlugin {
17
19
  this.sourceRoot = process.cwd()
18
20
 
19
21
  this.unconfiguredAddSub('dd-trace:ci:manual:test:start', ({ testName, testSuite }) => {
20
- const store = storage('legacy').getStore()
22
+ const store = legacyStorage.getStore()
21
23
  const testSuiteRelative = getTestSuitePath(testSuite, this.sourceRoot)
22
24
  const testSpan = this.startTestSpan(testName, testSuiteRelative)
23
25
  this.enter(testSpan, store)
24
26
  })
25
27
  this.unconfiguredAddSub('dd-trace:ci:manual:test:finish', ({ status, error }) => {
26
- const store = storage('legacy').getStore()
28
+ const store = legacyStorage.getStore()
27
29
  const testSpan = store && store.span
28
30
  if (testSpan) {
29
31
  testSpan.setTag(TEST_STATUS, status)
@@ -35,7 +37,7 @@ class TestApiManualPlugin extends CiPlugin {
35
37
  }
36
38
  })
37
39
  this.unconfiguredAddSub('dd-trace:ci:manual:test:addTags', (tags) => {
38
- const store = storage('legacy').getStore()
40
+ const store = legacyStorage.getStore()
39
41
  const testSpan = store && store.span
40
42
  if (testSpan) {
41
43
  testSpan.addTags(tags)
@@ -5,29 +5,18 @@ const util = require('util')
5
5
 
6
6
  const { DD_MAJOR } = require('../../../../version')
7
7
  const { parsers, transformers, telemetryTransformers, setWarnInvalidValue } = require('./parsers')
8
+ const applyMajorOverrides = require('./major-overrides')
8
9
  const {
9
10
  supportedConfigurations,
10
11
  } = /** @type {import('./helper').SupportedConfigurationsJson} */ (require('./supported-configurations.json'))
11
12
 
13
+ applyMajorOverrides(supportedConfigurations, DD_MAJOR)
14
+
12
15
  let log
13
16
  let seqId = 0
14
17
  const configWithOrigin = new Map()
15
18
  const parseErrors = new Map()
16
19
 
17
- if (DD_MAJOR >= 6) {
18
- // Programmatic configuration of DD_IAST_SECURITY_CONTROLS_CONFIGURATION is not supported
19
- // in newer major versions. This is special handled here until a better solution is found.
20
- // TODO: Remove the programmatic configuration from supported-configurations.json once v5 is not supported anymore.
21
- supportedConfigurations.DD_IAST_SECURITY_CONTROLS_CONFIGURATION[0].internalPropertyName =
22
- supportedConfigurations.DD_IAST_SECURITY_CONTROLS_CONFIGURATION[0].configurationNames?.[0]
23
- delete supportedConfigurations.DD_IAST_SECURITY_CONTROLS_CONFIGURATION[0].configurationNames
24
- } else {
25
- // Default value for DD_TRACE_STARTUP_LOGS is 'false' in older major versions.
26
- // This is special handled here until a better solution is found.
27
- // TODO: Remove this here once v5 is not supported anymore.
28
- supportedConfigurations.DD_TRACE_STARTUP_LOGS[0].default = 'false'
29
- }
30
-
31
20
  /**
32
21
  * Warns about an invalid value for an option and adds the error to the last telemetry entry if it is not already set.
33
22
  * Logging happens only if the error is not already set or the option name is different from the last telemetry entry.
@@ -85,11 +85,12 @@ export interface GeneratedConfig {
85
85
  DD_CIVISIBILITY_TEST_MODULE_ID: string | undefined;
86
86
  DD_CIVISIBILITY_TEST_SESSION_ID: string | undefined;
87
87
  DD_CRASHTRACKING_ENABLED: boolean;
88
+ DD_CUSTOM_PARENT_ID: string | undefined;
88
89
  DD_CUSTOM_TRACE_ID: string | undefined;
89
90
  DD_ENABLE_LAGE_PACKAGE_NAME: boolean;
90
91
  DD_ENABLE_NX_SERVICE_NAME: boolean;
91
92
  DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED: boolean;
92
- DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR: string;
93
+ DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR: string | undefined;
93
94
  DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED: boolean;
94
95
  DD_EXPERIMENTAL_TEST_OPT_SETTINGS_CACHE: string;
95
96
  DD_EXPERIMENTAL_TEST_REQUESTS_FS_CACHE: boolean;
@@ -243,6 +244,7 @@ export interface GeneratedConfig {
243
244
  DD_TRACE_ELASTIC_ELASTICSEARCH_ENABLED: boolean;
244
245
  DD_TRACE_ELASTIC_TRANSPORT_ENABLED: boolean;
245
246
  DD_TRACE_ELASTICSEARCH_ENABLED: boolean;
247
+ DD_TRACE_ELECTRON_ENABLED: boolean;
246
248
  DD_TRACE_ENCODING_DEBUG: boolean;
247
249
  DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED: boolean;
248
250
  DD_TRACE_EXPERIMENTAL_SPAN_COUNTS: boolean;
@@ -322,6 +324,7 @@ export interface GeneratedConfig {
322
324
  DD_TRACE_MONGODB_CORE_ENABLED: boolean;
323
325
  DD_TRACE_MONGODB_ENABLED: boolean;
324
326
  DD_TRACE_MONGODB_HEARTBEAT_ENABLED: boolean;
327
+ DD_TRACE_MONGODB_OBFUSCATE_QUERY: "none" | "types" | "redact";
325
328
  DD_TRACE_MONGOOSE_ENABLED: boolean;
326
329
  DD_TRACE_MQUERY_ENABLED: boolean;
327
330
  DD_TRACE_MULTER_ENABLED: boolean;
@@ -21,10 +21,14 @@
21
21
  */
22
22
 
23
23
  const { deprecate } = require('util')
24
+ const { DD_MAJOR } = require('../../../../version')
25
+ const applyMajorOverrides = require('./major-overrides')
24
26
  const {
25
27
  supportedConfigurations,
26
28
  } = /** @type {SupportedConfigurationsJson} */ (require('./supported-configurations.json'))
27
29
 
30
+ applyMajorOverrides(supportedConfigurations, DD_MAJOR)
31
+
28
32
  /**
29
33
  * Types for environment variable handling.
30
34
  *
@@ -165,7 +165,7 @@ class Config extends ConfigBase {
165
165
  }
166
166
 
167
167
  /**
168
- * @param {TracerOptions} [options={}]
168
+ * @param {TracerOptions} [options]
169
169
  */
170
170
  constructor (options = {}) {
171
171
  super()
@@ -357,7 +357,7 @@ class Config extends ConfigBase {
357
357
  setAndTrack(this, 'DD_METRICS_OTEL_ENABLED', false)
358
358
  }
359
359
 
360
- if (this.OTEL_TRACES_EXPORTER === 'otlp' && this.protocolVersion && this.protocolVersion !== '0.4') {
360
+ if (this.OTEL_TRACES_EXPORTER === 'otlp' && trackedConfigOrigins.has('protocolVersion')) {
361
361
  log.warn('DD_TRACE_AGENT_PROTOCOL_VERSION is set, disabling OTLP traces export')
362
362
  setAndTrack(this, 'OTEL_TRACES_EXPORTER', 'none')
363
363
  }