dd-trace 5.54.0 → 5.55.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 (178) hide show
  1. package/ci/cypress/plugin.js +8 -0
  2. package/ci/cypress/polyfills.js +23 -0
  3. package/ci/init.js +8 -7
  4. package/initialize.mjs +2 -2
  5. package/package.json +6 -6
  6. package/packages/datadog-code-origin/index.js +22 -4
  7. package/packages/datadog-core/src/utils/src/kebabcase.js +3 -3
  8. package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -6
  9. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +2 -3
  10. package/packages/datadog-instrumentations/src/cookie-parser.js +1 -1
  11. package/packages/datadog-instrumentations/src/couchbase.js +3 -6
  12. package/packages/datadog-instrumentations/src/cucumber.js +21 -28
  13. package/packages/datadog-instrumentations/src/dns.js +4 -4
  14. package/packages/datadog-instrumentations/src/elasticsearch.js +9 -10
  15. package/packages/datadog-instrumentations/src/fastify.js +7 -9
  16. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +14 -16
  17. package/packages/datadog-instrumentations/src/hapi.js +10 -11
  18. package/packages/datadog-instrumentations/src/helpers/fetch.js +4 -5
  19. package/packages/datadog-instrumentations/src/helpers/hook.js +1 -2
  20. package/packages/datadog-instrumentations/src/helpers/register.js +6 -5
  21. package/packages/datadog-instrumentations/src/jest.js +67 -98
  22. package/packages/datadog-instrumentations/src/koa.js +2 -3
  23. package/packages/datadog-instrumentations/src/mariadb.js +11 -4
  24. package/packages/datadog-instrumentations/src/mocha/main.js +79 -75
  25. package/packages/datadog-instrumentations/src/mocha.js +3 -1
  26. package/packages/datadog-instrumentations/src/mysql.js +11 -2
  27. package/packages/datadog-instrumentations/src/nyc.js +2 -1
  28. package/packages/datadog-instrumentations/src/openai.js +2 -2
  29. package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -3
  30. package/packages/datadog-instrumentations/src/pg.js +2 -3
  31. package/packages/datadog-instrumentations/src/playwright.js +19 -22
  32. package/packages/datadog-instrumentations/src/protobufjs.js +3 -4
  33. package/packages/datadog-instrumentations/src/redis.js +1 -1
  34. package/packages/datadog-instrumentations/src/restify.js +9 -13
  35. package/packages/datadog-instrumentations/src/router.js +12 -11
  36. package/packages/datadog-instrumentations/src/tedious.js +1 -2
  37. package/packages/datadog-instrumentations/src/vitest.js +15 -29
  38. package/packages/datadog-plugin-avsc/src/schema_iterator.js +12 -12
  39. package/packages/datadog-plugin-aws-sdk/src/base.js +12 -8
  40. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +3 -5
  41. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +12 -20
  42. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -5
  43. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +3 -5
  44. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -5
  45. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -5
  46. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -2
  47. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +7 -10
  48. package/packages/datadog-plugin-cucumber/src/index.js +3 -2
  49. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -1
  50. package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -1
  51. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  52. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +1 -1
  53. package/packages/datadog-plugin-graphql/src/index.js +3 -2
  54. package/packages/datadog-plugin-graphql/src/resolve.js +17 -10
  55. package/packages/datadog-plugin-http/src/client.js +5 -6
  56. package/packages/datadog-plugin-http2/src/client.js +7 -8
  57. package/packages/datadog-plugin-jest/src/index.js +3 -2
  58. package/packages/datadog-plugin-mocha/src/index.js +6 -1
  59. package/packages/datadog-plugin-mongodb-core/src/index.js +2 -1
  60. package/packages/datadog-plugin-mysql/src/index.js +11 -0
  61. package/packages/datadog-plugin-next/src/index.js +1 -1
  62. package/packages/datadog-plugin-openai/src/tracing.js +2 -4
  63. package/packages/datadog-plugin-playwright/src/index.js +3 -2
  64. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +8 -9
  65. package/packages/datadog-plugin-redis/src/index.js +1 -3
  66. package/packages/datadog-plugin-vitest/src/index.js +5 -4
  67. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +0 -1
  68. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +0 -1
  69. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +0 -1
  70. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +0 -1
  71. package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +1 -2
  72. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +11 -12
  73. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
  74. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -1
  75. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +1 -1
  76. package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +1 -2
  77. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/range-utils.js +10 -11
  78. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +0 -4
  79. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +0 -1
  80. package/packages/dd-trace/src/appsec/index.js +4 -4
  81. package/packages/dd-trace/src/appsec/reporter.js +5 -7
  82. package/packages/dd-trace/src/appsec/sdk/set_user.js +2 -2
  83. package/packages/dd-trace/src/appsec/sdk/track_event.js +3 -3
  84. package/packages/dd-trace/src/appsec/telemetry/index.js +31 -1
  85. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -2
  86. package/packages/dd-trace/src/azure_metadata.js +8 -3
  87. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +8 -7
  88. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -1
  89. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -1
  90. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -1
  91. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -1
  92. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +4 -3
  93. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +7 -6
  94. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
  95. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -3
  96. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -3
  97. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -1
  98. package/packages/dd-trace/src/config-helper.js +89 -0
  99. package/packages/dd-trace/src/config.js +77 -78
  100. package/packages/dd-trace/src/config_stable.js +7 -4
  101. package/packages/dd-trace/src/datastreams/fnv.js +1 -1
  102. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +6 -6
  103. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +1 -2
  104. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -2
  105. package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -1
  106. package/packages/dd-trace/src/debugger/devtools_client/send.js +3 -2
  107. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +1 -2
  108. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +3 -4
  109. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +1 -1
  110. package/packages/dd-trace/src/debugger/index.js +1 -0
  111. package/packages/dd-trace/src/dogstatsd.js +2 -2
  112. package/packages/dd-trace/src/encode/0.4.js +5 -2
  113. package/packages/dd-trace/src/encode/0.5.js +3 -5
  114. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +5 -5
  115. package/packages/dd-trace/src/exporter.js +2 -1
  116. package/packages/dd-trace/src/exporters/common/docker.js +3 -2
  117. package/packages/dd-trace/src/exporters/common/request.js +4 -1
  118. package/packages/dd-trace/src/exporters/common/util.js +3 -1
  119. package/packages/dd-trace/src/id.js +3 -3
  120. package/packages/dd-trace/src/index.js +4 -3
  121. package/packages/dd-trace/src/lambda/handler.js +2 -1
  122. package/packages/dd-trace/src/lambda/index.js +2 -1
  123. package/packages/dd-trace/src/lambda/runtime/patch.js +3 -2
  124. package/packages/dd-trace/src/lambda/runtime/ritm.js +3 -2
  125. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
  126. package/packages/dd-trace/src/llmobs/index.js +21 -5
  127. package/packages/dd-trace/src/llmobs/noop.js +18 -20
  128. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +11 -13
  129. package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -2
  130. package/packages/dd-trace/src/llmobs/sdk.js +2 -1
  131. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  132. package/packages/dd-trace/src/llmobs/tagger.js +19 -6
  133. package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
  134. package/packages/dd-trace/src/log/index.js +5 -4
  135. package/packages/dd-trace/src/log/writer.js +1 -2
  136. package/packages/dd-trace/src/msgpack/encoder.js +3 -3
  137. package/packages/dd-trace/src/noop/span.js +1 -1
  138. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
  139. package/packages/dd-trace/src/opentracing/propagation/log.js +4 -5
  140. package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -18
  141. package/packages/dd-trace/src/opentracing/span.js +7 -6
  142. package/packages/dd-trace/src/payload-tagging/config/index.js +17 -21
  143. package/packages/dd-trace/src/plugin_manager.js +4 -3
  144. package/packages/dd-trace/src/plugins/ci_plugin.js +25 -1
  145. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  146. package/packages/dd-trace/src/plugins/util/ci.js +7 -7
  147. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  148. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  149. package/packages/dd-trace/src/plugins/util/stacktrace.js +8 -1
  150. package/packages/dd-trace/src/plugins/util/test.js +4 -3
  151. package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -1
  152. package/packages/dd-trace/src/plugins/util/web.js +3 -4
  153. package/packages/dd-trace/src/priority_sampler.js +46 -35
  154. package/packages/dd-trace/src/profiling/config.js +12 -32
  155. package/packages/dd-trace/src/profiling/exporter_cli.js +20 -20
  156. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  157. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -1
  158. package/packages/dd-trace/src/profiling/index.js +2 -1
  159. package/packages/dd-trace/src/profiling/profiler.js +7 -4
  160. package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +3 -1
  161. package/packages/dd-trace/src/profiling/tagger.js +22 -12
  162. package/packages/dd-trace/src/proxy.js +2 -1
  163. package/packages/dd-trace/src/ritm.js +4 -4
  164. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -2
  165. package/packages/dd-trace/src/sampler.js +10 -2
  166. package/packages/dd-trace/src/serverless.js +11 -4
  167. package/packages/dd-trace/src/span_processor.js +2 -1
  168. package/packages/dd-trace/src/standalone/tracesource.js +1 -2
  169. package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +1 -2
  170. package/packages/dd-trace/src/startup-log.js +5 -17
  171. package/packages/dd-trace/src/supported-configurations.json +439 -0
  172. package/packages/dd-trace/src/telemetry/dependencies.js +62 -57
  173. package/packages/dd-trace/src/telemetry/send-data.js +7 -6
  174. package/packages/dd-trace/src/telemetry/telemetry.js +12 -25
  175. package/packages/dd-trace/src/tracer.js +3 -7
  176. package/packages/dd-trace/src/util.js +0 -5
  177. package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +0 -120
  178. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +0 -20
@@ -8,7 +8,6 @@ const { contains, intersects, remove } = require('./range-utils')
8
8
 
9
9
  const commandSensitiveAnalyzer = require('./sensitive-analyzers/command-sensitive-analyzer')
10
10
  const hardcodedPasswordAnalyzer = require('./sensitive-analyzers/hardcoded-password-analyzer')
11
- const headerSensitiveAnalyzer = require('./sensitive-analyzers/header-sensitive-analyzer')
12
11
  const jsonSensitiveAnalyzer = require('./sensitive-analyzers/json-sensitive-analyzer')
13
12
  const ldapSensitiveAnalyzer = require('./sensitive-analyzers/ldap-sensitive-analyzer')
14
13
  const sqlSensitiveAnalyzer = require('./sensitive-analyzers/sql-sensitive-analyzer')
@@ -30,9 +29,6 @@ class SensitiveHandler {
30
29
  this._sensitiveAnalyzers.set(vulnerabilities.HARDCODED_PASSWORD, (evidence) => {
31
30
  return hardcodedPasswordAnalyzer(evidence, this._valuePattern)
32
31
  })
33
- this._sensitiveAnalyzers.set(vulnerabilities.HEADER_INJECTION, (evidence) => {
34
- return headerSensitiveAnalyzer(evidence, this._namePattern, this._valuePattern)
35
- })
36
32
  this._sensitiveAnalyzers.set(vulnerabilities.LDAP_INJECTION, ldapSensitiveAnalyzer)
37
33
  this._sensitiveAnalyzers.set(vulnerabilities.NOSQL_MONGODB_INJECTION, jsonSensitiveAnalyzer)
38
34
  this._sensitiveAnalyzers.set(vulnerabilities.SQL_INJECTION, sqlSensitiveAnalyzer)
@@ -3,7 +3,6 @@ module.exports = {
3
3
  CODE_INJECTION: 'CODE_INJECTION',
4
4
  HARDCODED_PASSWORD: 'HARDCODED_PASSWORD',
5
5
  HARDCODED_SECRET: 'HARDCODED_SECRET',
6
- HEADER_INJECTION: 'HEADER_INJECTION',
7
6
  HSTS_HEADER_MISSING: 'HSTS_HEADER_MISSING',
8
7
  INSECURE_COOKIE: 'INSECURE_COOKIE',
9
8
  LDAP_INJECTION: 'LDAP_INJECTION',
@@ -45,7 +45,7 @@ function enable (_config) {
45
45
  if (isEnabled) return
46
46
 
47
47
  try {
48
- appsecTelemetry.enable(_config.telemetry)
48
+ appsecTelemetry.enable(_config)
49
49
  graphql.enable()
50
50
 
51
51
  if (_config.appsec.rasp.enabled) {
@@ -139,7 +139,7 @@ function incomingHttpStartTranslator ({ req, res, abortController }) {
139
139
  [HTTP_CLIENT_IP]: clientIp
140
140
  })
141
141
 
142
- const requestHeaders = Object.assign({}, req.headers)
142
+ const requestHeaders = { ...req.headers }
143
143
  delete requestHeaders.cookie
144
144
 
145
145
  const persistent = {
@@ -299,12 +299,12 @@ function onResponseWriteHead ({ req, res, abortController, statusCode, responseH
299
299
  const rootSpan = web.root(req)
300
300
  if (!rootSpan) return
301
301
 
302
- responseHeaders = Object.assign({}, responseHeaders)
302
+ responseHeaders = { ...responseHeaders }
303
303
  delete responseHeaders['set-cookie']
304
304
 
305
305
  const results = waf.run({
306
306
  persistent: {
307
- [addresses.HTTP_INCOMING_RESPONSE_CODE]: '' + statusCode,
307
+ [addresses.HTTP_INCOMING_RESPONSE_CODE]: String(statusCode),
308
308
  [addresses.HTTP_INCOMING_RESPONSE_HEADERS]: responseHeaders
309
309
  }
310
310
  }, req)
@@ -96,7 +96,7 @@ function formatHeaderName (name) {
96
96
  return name
97
97
  .trim()
98
98
  .slice(0, 200)
99
- .replace(/[^a-zA-Z0-9_\-:/]/g, '_')
99
+ .replaceAll(/[^a-zA-Z0-9_\-:/]/g, '_')
100
100
  .toLowerCase()
101
101
  }
102
102
 
@@ -116,7 +116,7 @@ function filterHeaders (headers, map) {
116
116
  for (const [headerName, tagName] of map) {
117
117
  const headerValue = headers[headerName]
118
118
  if (headerValue) {
119
- result[tagName] = '' + headerValue
119
+ result[tagName] = String(headerValue)
120
120
  }
121
121
  }
122
122
 
@@ -132,7 +132,7 @@ function filterExtendedHeaders (headers, excludedHeaderNames, tagPrefix, limit =
132
132
  for (const [headerName, headerValue] of Object.entries(headers)) {
133
133
  if (counter >= limit) break
134
134
  if (!excludedHeaderNames.has(headerName)) {
135
- result[getHeaderTag(tagPrefix, headerName)] = '' + headerValue
135
+ result[getHeaderTag(tagPrefix, headerName)] = String(headerValue)
136
136
  counter++
137
137
  }
138
138
  }
@@ -301,8 +301,6 @@ function reportAttack (attackData) {
301
301
  }
302
302
 
303
303
  function truncateRequestBody (target, depth = 0) {
304
- let wasTruncated = false
305
-
306
304
  switch (typeof target) {
307
305
  case 'string':
308
306
  if (target.length > COLLECTED_REQUEST_BODY_MAX_STRING_LENGTH) {
@@ -328,7 +326,7 @@ function truncateRequestBody (target, depth = 0) {
328
326
 
329
327
  if (Array.isArray(target)) {
330
328
  const maxArrayLength = Math.min(target.length, COLLECTED_REQUEST_BODY_MAX_ELEMENTS_PER_NODE)
331
- wasTruncated = target.length > COLLECTED_REQUEST_BODY_MAX_ELEMENTS_PER_NODE
329
+ let wasTruncated = target.length > COLLECTED_REQUEST_BODY_MAX_ELEMENTS_PER_NODE
332
330
  const truncatedArray = new Array(maxArrayLength)
333
331
  for (let i = 0; i < maxArrayLength; i++) {
334
332
  const { value, truncated } = truncateRequestBody(target[i], depth + 1)
@@ -341,7 +339,7 @@ function truncateRequestBody (target, depth = 0) {
341
339
 
342
340
  const keys = Object.keys(target)
343
341
  const maxKeysLength = Math.min(keys.length, COLLECTED_REQUEST_BODY_MAX_ELEMENTS_PER_NODE)
344
- wasTruncated = keys.length > COLLECTED_REQUEST_BODY_MAX_ELEMENTS_PER_NODE
342
+ let wasTruncated = keys.length > COLLECTED_REQUEST_BODY_MAX_ELEMENTS_PER_NODE
345
343
 
346
344
  const truncatedObject = {}
347
345
  for (let i = 0; i < maxKeysLength; i++) {
@@ -7,7 +7,7 @@ const addresses = require('../addresses')
7
7
 
8
8
  function setUserTags (user, rootSpan) {
9
9
  for (const k of Object.keys(user)) {
10
- rootSpan.setTag(`usr.${k}`, '' + user[k])
10
+ rootSpan.setTag(`usr.${k}`, String(user[k]))
11
11
  }
12
12
 
13
13
  rootSpan.setTag('_dd.appsec.user.collection_mode', 'sdk')
@@ -28,7 +28,7 @@ function setUser (tracer, user) {
28
28
  setUserTags(user, rootSpan)
29
29
 
30
30
  const persistent = {
31
- [addresses.USER_ID]: '' + user.id
31
+ [addresses.USER_ID]: String(user.id)
32
32
  }
33
33
 
34
34
  if (user.session_id && typeof user.session_id === 'string') {
@@ -196,7 +196,7 @@ function trackEvent (eventName, fields, sdkMethodName, rootSpan) {
196
196
  }
197
197
 
198
198
  for (const metadataKey of Object.keys(flatFields)) {
199
- tags[`appsec.events.${eventName}.${metadataKey}`] = '' + flatFields[metadataKey]
199
+ tags[`appsec.events.${eventName}.${metadataKey}`] = String(flatFields[metadataKey])
200
200
  }
201
201
  }
202
202
 
@@ -211,11 +211,11 @@ function runWaf (eventName, user) {
211
211
  }
212
212
 
213
213
  if (user?.id) {
214
- persistent[addresses.USER_ID] = '' + user.id
214
+ persistent[addresses.USER_ID] = String(user.id)
215
215
  }
216
216
 
217
217
  if (user?.login) {
218
- persistent[addresses.USER_LOGIN] = '' + user.login
218
+ persistent[addresses.USER_LOGIN] = String(user.login)
219
219
  }
220
220
 
221
221
  waf.run({ persistent })
@@ -15,17 +15,47 @@ const {
15
15
  incrementWafUpdates,
16
16
  incrementWafRequests
17
17
  } = require('./waf')
18
+ const telemetryMetrics = require('../../telemetry/metrics')
18
19
 
19
20
  const metricsStoreMap = new WeakMap()
20
21
 
22
+ const appsecMetrics = telemetryMetrics.manager.namespace('appsec')
23
+
21
24
  let enabled = false
25
+ let interval
26
+ const SUPPORTED_ORIGINS = new Set(['env_var', 'code', 'remote_config', 'unknown'])
22
27
 
23
- function enable (telemetryConfig) {
28
+ function enable (config) {
29
+ const telemetryConfig = config.telemetry
24
30
  enabled = telemetryConfig?.enabled && telemetryConfig.metrics
31
+
32
+ if (enabled) {
33
+ let origin = 'remote_config'
34
+
35
+ if (config.appsec.enabled) {
36
+ origin = config.getOrigin('appsec.enabled')
37
+
38
+ if (!SUPPORTED_ORIGINS.has(origin)) {
39
+ origin = 'unknown'
40
+ }
41
+ }
42
+
43
+ const gauge = appsecMetrics.gauge('enabled', { origin })
44
+ gauge.track()
45
+
46
+ interval = setInterval(() => {
47
+ gauge.track()
48
+ }, telemetryConfig.heartbeatInterval)
49
+ interval.unref?.()
50
+ }
25
51
  }
26
52
 
27
53
  function disable () {
28
54
  enabled = false
55
+ if (interval) {
56
+ clearInterval(interval)
57
+ interval = undefined
58
+ }
29
59
  }
30
60
 
31
61
  function newStore () {
@@ -49,8 +49,10 @@ class WAFContextWrapper {
49
49
  if (persistent !== null && typeof persistent === 'object') {
50
50
  const persistentInputs = {}
51
51
 
52
+ let hasPersistentInputs = false
52
53
  for (const key of Object.keys(persistent)) {
53
54
  if (!this.addressesToSkip.has(key) && this.knownAddresses.has(key)) {
55
+ hasPersistentInputs = true
54
56
  persistentInputs[key] = persistent[key]
55
57
  if (preventDuplicateAddresses.has(key)) {
56
58
  newAddressesToSkip.add(key)
@@ -58,7 +60,7 @@ class WAFContextWrapper {
58
60
  }
59
61
  }
60
62
 
61
- if (Object.keys(persistentInputs).length) {
63
+ if (hasPersistentInputs) {
62
64
  payload.persistent = persistentInputs
63
65
  payloadHasData = true
64
66
  }
@@ -67,13 +69,15 @@ class WAFContextWrapper {
67
69
  if (ephemeral !== null && typeof ephemeral === 'object') {
68
70
  const ephemeralInputs = {}
69
71
 
72
+ let hasEphemeral = false
70
73
  for (const key of Object.keys(ephemeral)) {
71
74
  if (this.knownAddresses.has(key)) {
75
+ hasEphemeral = true
72
76
  ephemeralInputs[key] = ephemeral[key]
73
77
  }
74
78
  }
75
79
 
76
- if (Object.keys(ephemeralInputs).length) {
80
+ if (hasEphemeral) {
77
81
  payload.ephemeral = ephemeralInputs
78
82
  payloadHasData = true
79
83
  }
@@ -4,6 +4,7 @@
4
4
 
5
5
  const os = require('os')
6
6
  const { getIsAzureFunction } = require('./serverless')
7
+ const { getEnvironmentVariable, getEnvironmentVariables } = require('../../dd-trace/src/config-helper')
7
8
 
8
9
  function extractSubscriptionID (ownerName) {
9
10
  if (ownerName !== undefined) {
@@ -45,7 +46,7 @@ function buildMetadata () {
45
46
  WEBSITE_OS,
46
47
  WEBSITE_RESOURCE_GROUP,
47
48
  WEBSITE_SITE_NAME
48
- } = process.env
49
+ } = getEnvironmentVariables()
49
50
 
50
51
  const subscriptionID = extractSubscriptionID(WEBSITE_OWNER_NAME)
51
52
 
@@ -78,11 +79,15 @@ function getAzureAppMetadata () {
78
79
  // DD_AZURE_APP_SERVICES is an environment variable introduced by the .NET APM team and is set automatically for
79
80
  // anyone using the Datadog APM Extensions (.NET, Java, or Node) for Windows Azure App Services
80
81
  // See: https://github.com/DataDog/datadog-aas-extension/blob/01f94b5c28b7fa7a9ab264ca28bd4e03be603900/node/src/applicationHost.xdt#L20-L21
81
- return process.env.DD_AZURE_APP_SERVICES === undefined ? undefined : buildMetadata()
82
+ if (getEnvironmentVariable('DD_AZURE_APP_SERVICES') !== undefined) {
83
+ return buildMetadata()
84
+ }
82
85
  }
83
86
 
84
87
  function getAzureFunctionMetadata () {
85
- return getIsAzureFunction() ? buildMetadata() : undefined
88
+ if (getIsAzureFunction()) {
89
+ return buildMetadata()
90
+ }
86
91
  }
87
92
 
88
93
  // Modeled after https://github.com/DataDog/libdatadog/blob/92272e90a7919f07178f3246ef8f82295513cfed/profiling/src/exporter/mod.rs#L187
@@ -4,6 +4,7 @@ const { join } = require('path')
4
4
  const { Worker, threadId: parentThreadId } = require('worker_threads')
5
5
  const { randomUUID } = require('crypto')
6
6
  const log = require('../../log')
7
+ const { getEnvironmentVariables } = require('../../config-helper')
7
8
 
8
9
  const probeIdToResolveBreakpointSet = new Map()
9
10
  const probeIdToResolveBreakpointRemove = new Map()
@@ -72,13 +73,13 @@ class TestVisDynamicInstrumentation {
72
73
  // for PnP support, hence why we deviate from the DI pattern here.
73
74
  // To avoid infinite initialization loops, we're disabling DI and tracing in the worker.
74
75
  env: {
75
- ...process.env,
76
- DD_CIVISIBILITY_ENABLED: 0,
77
- DD_TRACE_ENABLED: 0,
78
- DD_TEST_FAILED_TEST_REPLAY_ENABLED: 0,
79
- DD_CIVISIBILITY_MANUAL_API_ENABLED: 0,
80
- DD_TRACING_ENABLED: 0,
81
- DD_TRACE_TELEMETRY_ENABLED: 0
76
+ ...getEnvironmentVariables(),
77
+ DD_CIVISIBILITY_ENABLED: 'false',
78
+ DD_TRACE_ENABLED: 'false',
79
+ DD_TEST_FAILED_TEST_REPLAY_ENABLED: 'false',
80
+ DD_CIVISIBILITY_MANUAL_API_ENABLED: 'false',
81
+ DD_TRACING_ENABLED: 'false',
82
+ DD_INSTRUMENTATION_TELEMETRY_ENABLED: 'false'
82
83
  },
83
84
  workerData: {
84
85
  config: this._config.serialize(),
@@ -1,6 +1,7 @@
1
1
  const request = require('../../exporters/common/request')
2
2
  const id = require('../../id')
3
3
  const log = require('../../log')
4
+ const { getEnvironmentVariable } = require('../../config-helper')
4
5
 
5
6
  const {
6
7
  incrementCountMetric,
@@ -48,7 +49,7 @@ function getKnownTests ({
48
49
  options.path = `${evpProxyPrefix}/api/v2/ci/libraries/tests`
49
50
  options.headers['X-Datadog-EVP-Subdomain'] = 'api'
50
51
  } else {
51
- const apiKey = process.env.DATADOG_API_KEY || process.env.DD_API_KEY
52
+ const apiKey = getEnvironmentVariable('DD_API_KEY')
52
53
  if (!apiKey) {
53
54
  return done(new Error('Known tests were not fetched because Datadog API key is not defined.'))
54
55
  }
@@ -2,6 +2,7 @@
2
2
  const request = require('../../../exporters/common/request')
3
3
  const log = require('../../../log')
4
4
  const { safeJSONStringify } = require('../../../exporters/common/util')
5
+ const { getEnvironmentVariable } = require('../../../config-helper')
5
6
 
6
7
  const { CoverageCIVisibilityEncoder } = require('../../../encode/coverage-ci-visibility')
7
8
  const BaseWriter = require('../../../exporters/common/writer')
@@ -28,7 +29,7 @@ class Writer extends BaseWriter {
28
29
  path: '/api/v2/citestcov',
29
30
  method: 'POST',
30
31
  headers: {
31
- 'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY,
32
+ 'dd-api-key': getEnvironmentVariable('DD_API_KEY'),
32
33
  ...form.getHeaders()
33
34
  },
34
35
  timeout: 15_000,
@@ -3,6 +3,7 @@ const request = require('../../../exporters/common/request')
3
3
  const log = require('../../../log')
4
4
  const { safeJSONStringify } = require('../../../exporters/common/util')
5
5
  const { JSONEncoder } = require('../../encode/json-encoder')
6
+ const { getEnvironmentVariable } = require('../../../config-helper')
6
7
 
7
8
  const BaseWriter = require('../../../exporters/common/writer')
8
9
 
@@ -23,7 +24,7 @@ class DynamicInstrumentationLogsWriter extends BaseWriter {
23
24
  path: '/api/v2/logs',
24
25
  method: 'POST',
25
26
  headers: {
26
- 'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY,
27
+ 'dd-api-key': getEnvironmentVariable('DD_API_KEY'),
27
28
  'Content-Type': 'application/json'
28
29
  },
29
30
  // TODO: what's a good value for timeout for the logs intake?
@@ -2,6 +2,7 @@
2
2
  const request = require('../../../exporters/common/request')
3
3
  const { safeJSONStringify } = require('../../../exporters/common/util')
4
4
  const log = require('../../../log')
5
+ const { getEnvironmentVariable } = require('../../../config-helper')
5
6
 
6
7
  const { AgentlessCiVisibilityEncoder } = require('../../../encode/agentless-ci-visibility')
7
8
  const BaseWriter = require('../../../exporters/common/writer')
@@ -29,7 +30,7 @@ class Writer extends BaseWriter {
29
30
  path: '/api/v2/citestcycle',
30
31
  method: 'POST',
31
32
  headers: {
32
- 'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY,
33
+ 'dd-api-key': getEnvironmentVariable('DD_API_KEY'),
33
34
  'Content-Type': 'application/msgpack'
34
35
  },
35
36
  timeout: 15_000,
@@ -3,6 +3,7 @@ const path = require('path')
3
3
 
4
4
  const FormData = require('../../../exporters/common/form-data')
5
5
  const request = require('../../../exporters/common/request')
6
+ const { getEnvironmentVariable } = require('../../../config-helper')
6
7
 
7
8
  const log = require('../../../log')
8
9
  const { isFalse } = require('../../../util')
@@ -38,7 +39,7 @@ function validateCommits (commits) {
38
39
  throw new Error('Invalid commit type response')
39
40
  }
40
41
  if (isValidSha1(commitSha) || isValidSha256(commitSha)) {
41
- return commitSha.replace(/[^0-9a-f]+/g, '')
42
+ return commitSha.replaceAll(/[^0-9a-f]+/g, '')
42
43
  }
43
44
  throw new Error('Invalid commit format')
44
45
  })
@@ -48,7 +49,7 @@ function getCommonRequestOptions (url) {
48
49
  return {
49
50
  method: 'POST',
50
51
  headers: {
51
- 'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY
52
+ 'dd-api-key': getEnvironmentVariable('DD_API_KEY')
52
53
  },
53
54
  timeout: 15_000,
54
55
  url
@@ -285,7 +286,7 @@ function sendGitMetadata (url, { isEvpProxy, evpProxyPrefix }, configRepositoryU
285
286
  }
286
287
  // Otherwise we unshallow and get commits to upload again
287
288
  log.debug('It is shallow clone, unshallowing...')
288
- if (!isFalse(process.env.DD_CIVISIBILITY_GIT_UNSHALLOW_ENABLED)) {
289
+ if (!isFalse(getEnvironmentVariable('DD_CIVISIBILITY_GIT_UNSHALLOW_ENABLED'))) {
289
290
  unshallowRepository()
290
291
  }
291
292
 
@@ -9,18 +9,19 @@ const {
9
9
  JEST_WORKER_LOGS_PAYLOAD_CODE,
10
10
  PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE
11
11
  } = require('../../../plugins/util/test')
12
+ const { getEnvironmentVariable } = require('../../../config-helper')
12
13
 
13
14
  function getInterprocessTraceCode () {
14
- if (process.env.JEST_WORKER_ID) {
15
+ if (getEnvironmentVariable('JEST_WORKER_ID')) {
15
16
  return JEST_WORKER_TRACE_PAYLOAD_CODE
16
17
  }
17
- if (process.env.CUCUMBER_WORKER_ID) {
18
+ if (getEnvironmentVariable('CUCUMBER_WORKER_ID')) {
18
19
  return CUCUMBER_WORKER_TRACE_PAYLOAD_CODE
19
20
  }
20
- if (process.env.MOCHA_WORKER_ID) {
21
+ if (getEnvironmentVariable('MOCHA_WORKER_ID')) {
21
22
  return MOCHA_WORKER_TRACE_PAYLOAD_CODE
22
23
  }
23
- if (process.env.DD_PLAYWRIGHT_WORKER) {
24
+ if (getEnvironmentVariable('DD_PLAYWRIGHT_WORKER')) {
24
25
  return PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE
25
26
  }
26
27
  return null
@@ -28,14 +29,14 @@ function getInterprocessTraceCode () {
28
29
 
29
30
  // TODO: make it available with cucumber
30
31
  function getInterprocessCoverageCode () {
31
- if (process.env.JEST_WORKER_ID) {
32
+ if (getEnvironmentVariable('JEST_WORKER_ID')) {
32
33
  return JEST_WORKER_COVERAGE_PAYLOAD_CODE
33
34
  }
34
35
  return null
35
36
  }
36
37
 
37
38
  function getInterprocessLogsCode () {
38
- if (process.env.JEST_WORKER_ID) {
39
+ if (getEnvironmentVariable('JEST_WORKER_ID')) {
39
40
  return JEST_WORKER_LOGS_PAYLOAD_CODE
40
41
  }
41
42
  return null
@@ -1,5 +1,6 @@
1
1
  const request = require('../../exporters/common/request')
2
2
  const log = require('../../log')
3
+ const { getEnvironmentVariable } = require('../../config-helper')
3
4
  const {
4
5
  incrementCountMetric,
5
6
  distributionMetric,
@@ -46,7 +47,7 @@ function getSkippableSuites ({
46
47
  options.path = `${evpProxyPrefix}/api/v2/ci/tests/skippable`
47
48
  options.headers['X-Datadog-EVP-Subdomain'] = 'api'
48
49
  } else {
49
- const apiKey = process.env.DATADOG_API_KEY || process.env.DD_API_KEY
50
+ const apiKey = getEnvironmentVariable('DD_API_KEY')
50
51
  if (!apiKey) {
51
52
  return done(new Error('Skippable suites were not fetched because Datadog API key is not defined.'))
52
53
  }
@@ -1,5 +1,6 @@
1
1
  const Plugin = require('../../plugins/plugin')
2
2
  const log = require('../../log')
3
+ const { getEnvironmentVariable } = require('../../config-helper')
3
4
 
4
5
  function getWinstonLogSubmissionParameters (config) {
5
6
  const { site, service } = config
@@ -9,16 +10,16 @@ function getWinstonLogSubmissionParameters (config) {
9
10
  path: `/api/v2/logs?ddsource=winston&service=${service}`,
10
11
  ssl: true,
11
12
  headers: {
12
- 'DD-API-KEY': process.env.DD_API_KEY
13
+ 'DD-API-KEY': getEnvironmentVariable('DD_API_KEY')
13
14
  }
14
15
  }
15
16
 
16
- if (!process.env.DD_AGENTLESS_LOG_SUBMISSION_URL) {
17
+ if (!getEnvironmentVariable('DD_AGENTLESS_LOG_SUBMISSION_URL')) {
17
18
  return defaultParameters
18
19
  }
19
20
 
20
21
  try {
21
- const url = new URL(process.env.DD_AGENTLESS_LOG_SUBMISSION_URL)
22
+ const url = new URL(getEnvironmentVariable('DD_AGENTLESS_LOG_SUBMISSION_URL'))
22
23
  return {
23
24
  host: url.hostname,
24
25
  port: url.port,
@@ -1,6 +1,7 @@
1
1
  const request = require('../../exporters/common/request')
2
2
  const id = require('../../id')
3
3
  const log = require('../../log')
4
+ const { getEnvironmentVariable } = require('../../config-helper')
4
5
  const {
5
6
  incrementCountMetric,
6
7
  distributionMetric,
@@ -45,7 +46,7 @@ function getLibraryConfiguration ({
45
46
  options.path = `${evpProxyPrefix}/api/v2/libraries/tests/services/setting`
46
47
  options.headers['X-Datadog-EVP-Subdomain'] = 'api'
47
48
  } else {
48
- const apiKey = process.env.DATADOG_API_KEY || process.env.DD_API_KEY
49
+ const apiKey = getEnvironmentVariable('DD_API_KEY')
49
50
  if (!apiKey) {
50
51
  return done(new Error('Request to settings endpoint was not done because Datadog API key is not defined.'))
51
52
  }
@@ -123,11 +124,11 @@ function getLibraryConfiguration ({
123
124
 
124
125
  log.debug(() => `Remote settings: ${JSON.stringify(settings)}`)
125
126
 
126
- if (process.env.DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE) {
127
+ if (getEnvironmentVariable('DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE')) {
127
128
  settings.isCodeCoverageEnabled = true
128
129
  log.debug(() => 'Dangerously set code coverage to true')
129
130
  }
130
- if (process.env.DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING) {
131
+ if (getEnvironmentVariable('DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING')) {
131
132
  settings.isSuitesSkippingEnabled = true
132
133
  log.debug(() => 'Dangerously set test skipping to true')
133
134
  }
@@ -1,5 +1,6 @@
1
1
  const request = require('../../exporters/common/request')
2
2
  const id = require('../../id')
3
+ const { getEnvironmentVariable } = require('../../config-helper')
3
4
 
4
5
  function getTestManagementTests ({
5
6
  url,
@@ -28,7 +29,7 @@ function getTestManagementTests ({
28
29
  options.path = `${evpProxyPrefix}/api/v2/test/libraries/test-management/tests`
29
30
  options.headers['X-Datadog-EVP-Subdomain'] = 'api'
30
31
  } else {
31
- const apiKey = process.env.DATADOG_API_KEY || process.env.DD_API_KEY
32
+ const apiKey = getEnvironmentVariable('DD_API_KEY')
32
33
  if (!apiKey) {
33
34
  return done(new Error('Test management tests were not fetched because Datadog API key is not defined.'))
34
35
  }
@@ -0,0 +1,89 @@
1
+ 'use strict'
2
+
3
+ /* eslint-disable eslint-rules/eslint-process-env */
4
+
5
+ const { deprecate } = require('util')
6
+ const { supportedConfigurations, aliases, deprecations } = require('./supported-configurations.json')
7
+
8
+ const aliasToCanonical = {}
9
+ for (const canonical of Object.keys(aliases)) {
10
+ for (const alias of aliases[canonical]) {
11
+ if (aliasToCanonical[alias]) {
12
+ throw new Error(`The alias ${alias} is already used for ${aliasToCanonical[alias]}.`)
13
+ }
14
+ aliasToCanonical[alias] = canonical
15
+ }
16
+ }
17
+
18
+ const deprecationMethods = {}
19
+ for (const deprecation of Object.keys(deprecations)) {
20
+ deprecationMethods[deprecation] = deprecate(
21
+ () => {},
22
+ `The environment variable ${deprecation} is deprecated.` +
23
+ (aliasToCanonical[deprecation]
24
+ ? ` Please use ${aliasToCanonical[deprecation]} instead.`
25
+ : ` ${deprecations[deprecation]}`),
26
+ `DATADOG_${deprecation}`
27
+ )
28
+ }
29
+
30
+ module.exports = {
31
+ /**
32
+ * Returns the environment variables that are supported by the tracer
33
+ * (including all non-Datadog/OTEL specific environment variables)
34
+ *
35
+ * @returns {Partial<process.env>} The environment variables
36
+ */
37
+ getEnvironmentVariables () {
38
+ const configs = {}
39
+ for (const [key, value] of Object.entries(process.env)) {
40
+ if (key.startsWith('DD_') || key.startsWith('OTEL_') || aliasToCanonical[key]) {
41
+ if (supportedConfigurations[key]) {
42
+ configs[key] = value
43
+ } else if (aliasToCanonical[key] && configs[aliasToCanonical[key]] === undefined) {
44
+ // The alias should only be used if the actual configuration is not set
45
+ // In case that more than a single alias exist, use the one defined first in our own order
46
+ for (const alias of aliases[aliasToCanonical[key]]) {
47
+ if (process.env[alias] !== undefined) {
48
+ configs[aliasToCanonical[key]] = value
49
+ break
50
+ }
51
+ }
52
+ // TODO(BridgeAR) Implement logging. It would have to use a timeout to
53
+ // lazily log the message after all loading being done otherwise.
54
+ // debug(
55
+ // `Missing configuration ${env} in supported-configurations file. The environment variable is ignored.`
56
+ // )
57
+ }
58
+ deprecationMethods[key]?.()
59
+ } else {
60
+ configs[key] = value
61
+ }
62
+ }
63
+ return configs
64
+ },
65
+
66
+ /**
67
+ * Returns the environment variable, if it's supported or a non Datadog
68
+ * configuration. Otherwise, it throws an error.
69
+ *
70
+ * @param {string} name Environment variable name
71
+ * @returns {string|undefined}
72
+ * @throws {Error} if the configuration is not supported
73
+ */
74
+ getEnvironmentVariable (name) {
75
+ if ((name.startsWith('DD_') || name.startsWith('OTEL_') || aliasToCanonical[name]) &&
76
+ !supportedConfigurations[name]) {
77
+ throw new Error(`Missing ${name} env/configuration in "supported-configurations.json" file.`)
78
+ }
79
+ const config = process.env[name]
80
+ if (config === undefined && aliases[name]) {
81
+ for (const alias of aliases[name]) {
82
+ if (process.env[alias] !== undefined) {
83
+ return process.env[alias]
84
+ }
85
+ }
86
+ }
87
+ return config
88
+ }
89
+ }