dd-trace 5.82.0 → 5.84.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 (150) hide show
  1. package/LICENSE-3rdparty.csv +77 -79
  2. package/ci/init.js +6 -6
  3. package/index.d.ts +213 -4
  4. package/loader-hook.mjs +1 -1
  5. package/package.json +59 -56
  6. package/packages/datadog-core/src/storage.js +7 -7
  7. package/packages/datadog-esbuild/index.js +6 -0
  8. package/packages/datadog-instrumentations/src/ai.js +7 -3
  9. package/packages/datadog-instrumentations/src/child_process.js +1 -1
  10. package/packages/datadog-instrumentations/src/cucumber.js +1 -1
  11. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  12. package/packages/datadog-instrumentations/src/helpers/instrumentations.js +4 -3
  13. package/packages/datadog-instrumentations/src/helpers/register.js +3 -7
  14. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +6 -0
  15. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -1
  16. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +73 -16
  17. package/packages/datadog-instrumentations/src/http/client.js +2 -2
  18. package/packages/datadog-instrumentations/src/jest.js +124 -64
  19. package/packages/datadog-instrumentations/src/koa.js +2 -1
  20. package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
  21. package/packages/datadog-instrumentations/src/mocha/main.js +2 -2
  22. package/packages/datadog-instrumentations/src/mocha/worker.js +1 -1
  23. package/packages/datadog-instrumentations/src/mocha.js +1 -1
  24. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  25. package/packages/datadog-instrumentations/src/mysql2.js +2 -2
  26. package/packages/datadog-instrumentations/src/net.js +13 -5
  27. package/packages/datadog-instrumentations/src/nyc.js +1 -1
  28. package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -4
  29. package/packages/datadog-instrumentations/src/pg.js +4 -2
  30. package/packages/datadog-instrumentations/src/playwright.js +15 -11
  31. package/packages/datadog-instrumentations/src/selenium.js +2 -2
  32. package/packages/datadog-instrumentations/src/undici.js +12 -1
  33. package/packages/datadog-plugin-aws-sdk/src/base.js +4 -4
  34. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +2 -2
  35. package/packages/datadog-plugin-azure-service-bus/src/producer.js +2 -2
  36. package/packages/datadog-plugin-cucumber/src/index.js +35 -34
  37. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -2
  38. package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -2
  39. package/packages/datadog-plugin-express/src/code_origin.js +21 -15
  40. package/packages/datadog-plugin-fastify/src/code_origin.js +17 -4
  41. package/packages/datadog-plugin-jest/src/index.js +2 -2
  42. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  43. package/packages/datadog-plugin-mongodb-core/src/index.js +2 -2
  44. package/packages/datadog-plugin-playwright/src/index.js +26 -26
  45. package/packages/datadog-plugin-undici/src/index.js +305 -2
  46. package/packages/datadog-plugin-vitest/src/index.js +5 -5
  47. package/packages/datadog-shimmer/src/shimmer.js +2 -5
  48. package/packages/dd-trace/index.js +19 -0
  49. package/packages/dd-trace/src/agent/info.js +57 -0
  50. package/packages/dd-trace/src/agent/url.js +28 -0
  51. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +1 -1
  52. package/packages/dd-trace/src/appsec/index.js +47 -7
  53. package/packages/dd-trace/src/appsec/rasp/index.js +2 -4
  54. package/packages/dd-trace/src/azure_metadata.js +8 -3
  55. package/packages/dd-trace/src/baggage.js +36 -11
  56. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +5 -1
  57. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -2
  58. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +3 -4
  59. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -2
  60. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +5 -5
  61. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  62. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +5 -11
  63. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -3
  64. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +4 -4
  65. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +1 -1
  66. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -2
  67. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -4
  68. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -4
  69. package/packages/dd-trace/src/ci-visibility/telemetry.js +6 -2
  70. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -2
  71. package/packages/dd-trace/src/{config_defaults.js → config/defaults.js} +3 -3
  72. package/packages/dd-trace/src/{config-helper.js → config/helper.js} +88 -15
  73. package/packages/dd-trace/src/{config.js → config/index.js} +107 -46
  74. package/packages/dd-trace/src/config/remote_config.js +188 -19
  75. package/packages/dd-trace/src/{config_stable.js → config/stable.js} +20 -32
  76. package/packages/dd-trace/src/{supported-configurations.json → config/supported-configurations.json} +3 -1
  77. package/packages/dd-trace/src/crashtracking/crashtracker.js +2 -5
  78. package/packages/dd-trace/src/datastreams/processor.js +1 -1
  79. package/packages/dd-trace/src/datastreams/writer.js +2 -8
  80. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
  81. package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -7
  82. package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +10 -11
  83. package/packages/dd-trace/src/debugger/devtools_client/send.js +3 -3
  84. package/packages/dd-trace/src/debugger/devtools_client/snapshot/constants.js +1 -1
  85. package/packages/dd-trace/src/debugger/index.js +83 -15
  86. package/packages/dd-trace/src/dogstatsd.js +5 -11
  87. package/packages/dd-trace/src/encode/0.4.js +2 -2
  88. package/packages/dd-trace/src/exporter.js +1 -1
  89. package/packages/dd-trace/src/exporters/agent/index.js +5 -11
  90. package/packages/dd-trace/src/exporters/agent/writer.js +12 -16
  91. package/packages/dd-trace/src/exporters/common/{agent-info-exporter.js → buffering-exporter.js} +10 -37
  92. package/packages/dd-trace/src/exporters/common/docker.js +2 -2
  93. package/packages/dd-trace/src/exporters/common/request.js +1 -1
  94. package/packages/dd-trace/src/exporters/common/util.js +2 -2
  95. package/packages/dd-trace/src/exporters/span-stats/index.js +3 -10
  96. package/packages/dd-trace/src/flare/index.js +1 -1
  97. package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
  98. package/packages/dd-trace/src/index.js +4 -4
  99. package/packages/dd-trace/src/lambda/handler.js +2 -2
  100. package/packages/dd-trace/src/lambda/index.js +2 -2
  101. package/packages/dd-trace/src/lambda/runtime/patch.js +2 -2
  102. package/packages/dd-trace/src/lambda/runtime/ritm.js +2 -2
  103. package/packages/dd-trace/src/llmobs/constants/tags.js +8 -1
  104. package/packages/dd-trace/src/llmobs/index.js +2 -2
  105. package/packages/dd-trace/src/llmobs/noop.js +2 -0
  106. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +3 -4
  107. package/packages/dd-trace/src/llmobs/sdk.js +33 -6
  108. package/packages/dd-trace/src/llmobs/span_processor.js +17 -7
  109. package/packages/dd-trace/src/llmobs/tagger.js +175 -1
  110. package/packages/dd-trace/src/llmobs/writers/base.js +118 -45
  111. package/packages/dd-trace/src/llmobs/writers/spans.js +4 -3
  112. package/packages/dd-trace/src/llmobs/writers/util.js +3 -9
  113. package/packages/dd-trace/src/log/index.js +50 -35
  114. package/packages/dd-trace/src/log/writer.js +13 -78
  115. package/packages/dd-trace/src/noop/proxy.js +3 -3
  116. package/packages/dd-trace/src/openfeature/writers/base.js +9 -16
  117. package/packages/dd-trace/src/openfeature/writers/util.js +3 -8
  118. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +2 -2
  119. package/packages/dd-trace/src/opentelemetry/tracer.js +48 -6
  120. package/packages/dd-trace/src/opentracing/propagation/text_map.js +45 -21
  121. package/packages/dd-trace/src/opentracing/span.js +4 -4
  122. package/packages/dd-trace/src/plugin_manager.js +8 -6
  123. package/packages/dd-trace/src/plugins/util/ci.js +5 -8
  124. package/packages/dd-trace/src/plugins/util/git-cache.js +3 -3
  125. package/packages/dd-trace/src/plugins/util/test.js +1 -1
  126. package/packages/dd-trace/src/plugins/util/user-provided-git.js +41 -43
  127. package/packages/dd-trace/src/profiler.js +4 -39
  128. package/packages/dd-trace/src/profiling/config.js +74 -34
  129. package/packages/dd-trace/src/profiling/exporter_cli.js +5 -5
  130. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  131. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +9 -2
  132. package/packages/dd-trace/src/profiling/index.js +1 -1
  133. package/packages/dd-trace/src/profiling/libuv-size.js +1 -1
  134. package/packages/dd-trace/src/profiling/profiler.js +57 -2
  135. package/packages/dd-trace/src/proxy.js +34 -5
  136. package/packages/dd-trace/src/remote_config/capabilities.js +4 -0
  137. package/packages/dd-trace/src/remote_config/index.js +2 -7
  138. package/packages/dd-trace/src/ritm.js +8 -4
  139. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +2 -2
  140. package/packages/dd-trace/src/serverless.js +2 -2
  141. package/packages/dd-trace/src/span_processor.js +2 -2
  142. package/packages/dd-trace/src/startup-log.js +7 -16
  143. package/packages/dd-trace/src/telemetry/endpoints.js +67 -5
  144. package/packages/dd-trace/src/telemetry/send-data.js +103 -4
  145. package/packages/dd-trace/src/telemetry/telemetry.js +229 -110
  146. package/vendor/dist/@isaacs/ttlcache/index.js +1 -1
  147. package/vendor/dist/esquery/index.js +1 -1
  148. package/vendor/dist/meriyah/index.js +1 -1
  149. package/vendor/dist/protobufjs/index.js +1 -1
  150. /package/packages/dd-trace/src/{git_properties.js → config/git_properties.js} +0 -0
@@ -1,41 +1,66 @@
1
1
  'use strict'
2
2
 
3
3
  const { storage } = require('../../datadog-core')
4
- const baggageStorage = storage('baggage')
5
4
 
5
+ /**
6
+ * Spec (API semantics):
7
+ * - OpenTelemetry Baggage API: https://opentelemetry.io/docs/specs/otel/baggage/api/
8
+ *
9
+ * In-process baggage is a string->string map stored in async local storage.
10
+ * @typedef {import('../../datadog-core/src/storage').Store<string>} BaggageStore
11
+ */
12
+
13
+ /**
14
+ * @type {{ enterWith: (store?: BaggageStore) => void, getStore: () => (BaggageStore | undefined) }}
15
+ */
16
+ const baggageStorage =
17
+ /** @type {{ enterWith: (store?: BaggageStore) => void, getStore: () => (BaggageStore | undefined) }} */ (
18
+ /** @type {unknown} */ (storage('baggage'))
19
+ )
20
+
21
+ // TODO: Implement metadata https://opentelemetry.io/docs/specs/otel/baggage/api/#set-value
6
22
  /**
7
23
  * @param {string} key
8
24
  * @param {string} value
25
+ * @param {object} [metadata] Not used yet
9
26
  */
10
- function setBaggageItem (key, value) {
11
- storage('baggage').enterWith({ ...baggageStorage.getStore(), [key]: value })
12
- return storage('baggage').getStore()
27
+ function setBaggageItem (key, value, metadata) {
28
+ if (typeof key !== 'string' || typeof value !== 'string' || key === '') {
29
+ return baggageStorage.getStore() ?? {}
30
+ }
31
+
32
+ const store = baggageStorage.getStore()
33
+ const newStore = { ...store, [key]: value }
34
+ baggageStorage.enterWith(newStore)
35
+ return newStore
13
36
  }
14
37
 
15
38
  /**
16
39
  * @param {string} key
40
+ * @returns {string | undefined}
17
41
  */
18
42
  function getBaggageItem (key) {
19
- return storage('baggage').getStore()?.[key]
43
+ return baggageStorage.getStore()?.[key]
20
44
  }
21
45
 
22
46
  function getAllBaggageItems () {
23
- return storage('baggage').getStore() ?? {}
47
+ return baggageStorage.getStore() ?? {}
24
48
  }
25
49
 
26
50
  /**
27
51
  * @param {string} keyToRemove
28
- * @returns {Record<string, unknown>}
29
52
  */
30
53
  function removeBaggageItem (keyToRemove) {
31
- const { [keyToRemove]: _, ...newBaggage } = storage('baggage').getStore()
32
- storage('baggage').enterWith(newBaggage)
54
+ const store = baggageStorage.getStore() ?? {}
55
+ const { [keyToRemove]: _, ...newBaggage } = store
56
+ baggageStorage.enterWith(newBaggage)
33
57
  return newBaggage
34
58
  }
35
59
 
36
60
  function removeAllBaggageItems () {
37
- storage('baggage').enterWith()
38
- return storage('baggage').getStore()
61
+ const newContext = /** @type {BaggageStore} */ ({})
62
+ baggageStorage.enterWith(newContext)
63
+ return newContext
39
64
  }
40
65
 
41
66
  module.exports = {
@@ -4,7 +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
+ const { getEnvironmentVariables } = require('../../config/helper')
8
8
  const getDebuggerConfig = require('../../debugger/config')
9
9
 
10
10
  const probeIdToResolveBreakpointSet = new Map()
@@ -74,6 +74,10 @@ class TestVisDynamicInstrumentation {
74
74
  // for PnP support, hence why we deviate from the DI pattern here.
75
75
  // To avoid infinite initialization loops, we're disabling DI and tracing in the worker.
76
76
  env: {
77
+ // NOTE: We intentionally use `getEnvironmentVariables()` here (raw env)
78
+ // instead of stable-config resolution helpers. The DI worker is a forked
79
+ // process that should see exactly the parent process's environment, and
80
+ // we explicitly override a few DD_ vars below to disable tracing/DI there.
77
81
  ...getEnvironmentVariables(),
78
82
  DD_CIVISIBILITY_ENABLED: 'false',
79
83
  DD_TRACE_ENABLED: 'false',
@@ -3,7 +3,7 @@
3
3
  const request = require('../../exporters/common/request')
4
4
  const id = require('../../id')
5
5
  const log = require('../../log')
6
- const { getEnvironmentVariable } = require('../../config-helper')
6
+ const { getValueFromEnvSources } = require('../../config/helper')
7
7
 
8
8
  const {
9
9
  incrementCountMetric,
@@ -51,7 +51,7 @@ function getKnownTests ({
51
51
  options.path = `${evpProxyPrefix}/api/v2/ci/libraries/tests`
52
52
  options.headers['X-Datadog-EVP-Subdomain'] = 'api'
53
53
  } else {
54
- const apiKey = getEnvironmentVariable('DD_API_KEY')
54
+ const apiKey = getValueFromEnvSources('DD_API_KEY')
55
55
  if (!apiKey) {
56
56
  return done(new Error('Known tests were not fetched because Datadog API key is not defined.'))
57
57
  }
@@ -4,6 +4,7 @@ const AgentWriter = require('../../../exporters/agent/writer')
4
4
  const AgentlessWriter = require('../agentless/writer')
5
5
  const CoverageWriter = require('../agentless/coverage-writer')
6
6
  const CiVisibilityExporter = require('../ci-visibility-exporter')
7
+ const { fetchAgentInfo } = require('../../../agent/info')
7
8
 
8
9
  const AGENT_EVP_PROXY_PATH_PREFIX = '/evp_proxy/v'
9
10
  const AGENT_EVP_PROXY_PATH_REGEX = /\/evp_proxy\/v(\d+)\/?/
@@ -42,11 +43,11 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
42
43
  isTestDynamicInstrumentationEnabled
43
44
  } = config
44
45
 
45
- this.getAgentInfo((err, agentInfo) => {
46
+ fetchAgentInfo(this._url, (err, agentInfo) => {
46
47
  this._isInitialized = true
47
48
  let latestEvpProxyVersion = getLatestEvpProxyVersion(err, agentInfo)
48
49
  const isEvpCompatible = latestEvpProxyVersion >= 2
49
- const isGzipCompatible = latestEvpProxyVersion >= 4
50
+ this._isGzipCompatible = latestEvpProxyVersion >= 4
50
51
 
51
52
  // v3 does not work well citestcycle, so we downgrade to v2
52
53
  if (latestEvpProxyVersion === 3) {
@@ -72,7 +73,6 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
72
73
  const DynamicInstrumentationLogsWriter = require('../agentless/di-logs-writer')
73
74
  this._logsWriter = new DynamicInstrumentationLogsWriter({
74
75
  url: this._url,
75
- tags,
76
76
  isAgentProxy: true
77
77
  })
78
78
  this._canForwardLogs = true
@@ -92,7 +92,6 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
92
92
  this._resolveCanUseCiVisProtocol(isEvpCompatible)
93
93
  this.exportUncodedTraces()
94
94
  this.exportUncodedCoverages()
95
- this._isGzipCompatible = isGzipCompatible
96
95
  })
97
96
  }
98
97
 
@@ -2,7 +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
+ const { getValueFromEnvSources } = require('../../../config/helper')
6
6
 
7
7
  const { CoverageCIVisibilityEncoder } = require('../../../encode/coverage-ci-visibility')
8
8
  const BaseWriter = require('../../../exporters/common/writer')
@@ -29,7 +29,7 @@ class Writer extends BaseWriter {
29
29
  path: '/api/v2/citestcov',
30
30
  method: 'POST',
31
31
  headers: {
32
- 'dd-api-key': getEnvironmentVariable('DD_API_KEY'),
32
+ 'dd-api-key': getValueFromEnvSources('DD_API_KEY'),
33
33
  ...form.getHeaders()
34
34
  },
35
35
  timeout: 15_000,
@@ -3,7 +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
+ const { getValueFromEnvSources } = require('../../../config/helper')
7
7
 
8
8
  const BaseWriter = require('../../../exporters/common/writer')
9
9
 
@@ -11,7 +11,8 @@ const BaseWriter = require('../../../exporters/common/writer')
11
11
  // It is used to encode and send logs to both the logs intake directly and the
12
12
  // `/debugger/v1/input` endpoint in the agent, which is a proxy to the logs intake.
13
13
  class DynamicInstrumentationLogsWriter extends BaseWriter {
14
- constructor ({ url, timeout, isAgentProxy = false }) {
14
+ // TODO: what's a good value for timeout for the logs intake?
15
+ constructor ({ url, timeout = 15_000, isAgentProxy = false }) {
15
16
  super(...arguments)
16
17
  this._url = url
17
18
  this._encoder = new JSONEncoder()
@@ -24,11 +25,10 @@ class DynamicInstrumentationLogsWriter extends BaseWriter {
24
25
  path: '/api/v2/logs',
25
26
  method: 'POST',
26
27
  headers: {
27
- 'dd-api-key': getEnvironmentVariable('DD_API_KEY'),
28
+ 'dd-api-key': getValueFromEnvSources('DD_API_KEY'),
28
29
  'Content-Type': 'application/json'
29
30
  },
30
- // TODO: what's a good value for timeout for the logs intake?
31
- timeout: this.timeout || 15_000,
31
+ timeout: this.timeout,
32
32
  url: this._url
33
33
  }
34
34
 
@@ -2,7 +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
+ const { getValueFromEnvSources } = require('../../../config/helper')
6
6
 
7
7
  const { AgentlessCiVisibilityEncoder } = require('../../../encode/agentless-ci-visibility')
8
8
  const BaseWriter = require('../../../exporters/common/writer')
@@ -30,7 +30,7 @@ class Writer extends BaseWriter {
30
30
  path: '/api/v2/citestcycle',
31
31
  method: 'POST',
32
32
  headers: {
33
- 'dd-api-key': getEnvironmentVariable('DD_API_KEY'),
33
+ 'dd-api-key': getValueFromEnvSources('DD_API_KEY'),
34
34
  'Content-Type': 'application/msgpack'
35
35
  },
36
36
  timeout: 15_000,
@@ -8,7 +8,7 @@ const { getKnownTests: getKnownTestsRequest } = require('../early-flake-detectio
8
8
  const { getTestManagementTests: getTestManagementTestsRequest } =
9
9
  require('../test-management/get-test-management-tests')
10
10
  const log = require('../../log')
11
- const AgentInfoExporter = require('../../exporters/common/agent-info-exporter')
11
+ const BufferingExporter = require('../../exporters/common/buffering-exporter')
12
12
  const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../../plugins/util/tags')
13
13
  const { sendGitMetadata: sendGitMetadataRequest } = require('./git/git_metadata')
14
14
 
@@ -34,7 +34,7 @@ function getIsTestSessionTrace (trace) {
34
34
  const GIT_UPLOAD_TIMEOUT = 60_000 // 60 seconds
35
35
  const CAN_USE_CI_VIS_PROTOCOL_TIMEOUT = GIT_UPLOAD_TIMEOUT
36
36
 
37
- class CiVisibilityExporter extends AgentInfoExporter {
37
+ class CiVisibilityExporter extends BufferingExporter {
38
38
  constructor (config) {
39
39
  super(config)
40
40
  this._timer = undefined
@@ -68,7 +68,7 @@ class CiVisibilityExporter extends AgentInfoExporter {
68
68
  }
69
69
  })
70
70
 
71
- process.once('beforeExit', () => {
71
+ const flush = () => {
72
72
  if (this._writer) {
73
73
  this._writer.flush()
74
74
  }
@@ -78,7 +78,8 @@ class CiVisibilityExporter extends AgentInfoExporter {
78
78
  if (this._logsWriter) {
79
79
  this._logsWriter.flush()
80
80
  }
81
- })
81
+ }
82
+ globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(flush.bind(this))
82
83
  }
83
84
 
84
85
  shouldRequestSkippableSuites () {
@@ -102,10 +103,6 @@ class CiVisibilityExporter extends AgentInfoExporter {
102
103
  )
103
104
  }
104
105
 
105
- shouldRequestLibraryConfiguration () {
106
- return this._config.isIntelligentTestRunnerEnabled
107
- }
108
-
109
106
  canReportSessionTraces () {
110
107
  return this._canUseCiVisProtocol
111
108
  }
@@ -162,9 +159,6 @@ class CiVisibilityExporter extends AgentInfoExporter {
162
159
  getLibraryConfiguration (testConfiguration, callback) {
163
160
  const { repositoryUrl } = testConfiguration
164
161
  this.sendGitMetadata(repositoryUrl)
165
- if (!this.shouldRequestLibraryConfiguration()) {
166
- return callback(null, {})
167
- }
168
162
  this._canUseCiVisProtocolPromise.then((canUseCiVisProtocol) => {
169
163
  if (!canUseCiVisProtocol) {
170
164
  return callback(null, {})
@@ -5,7 +5,7 @@ const path = require('path')
5
5
 
6
6
  const FormData = require('../../../exporters/common/form-data')
7
7
  const request = require('../../../exporters/common/request')
8
- const { getEnvironmentVariable } = require('../../../config-helper')
8
+ const { getValueFromEnvSources } = require('../../../config/helper')
9
9
 
10
10
  const log = require('../../../log')
11
11
  const { isFalse } = require('../../../util')
@@ -51,7 +51,7 @@ function getCommonRequestOptions (url) {
51
51
  return {
52
52
  method: 'POST',
53
53
  headers: {
54
- 'dd-api-key': getEnvironmentVariable('DD_API_KEY')
54
+ 'dd-api-key': getValueFromEnvSources('DD_API_KEY')
55
55
  },
56
56
  timeout: 15_000,
57
57
  url
@@ -288,7 +288,7 @@ function sendGitMetadata (url, { isEvpProxy, evpProxyPrefix }, configRepositoryU
288
288
  }
289
289
  // Otherwise we unshallow and get commits to upload again
290
290
  log.debug('It is shallow clone, unshallowing...')
291
- if (!isFalse(getEnvironmentVariable('DD_CIVISIBILITY_GIT_UNSHALLOW_ENABLED'))) {
291
+ if (!isFalse(getValueFromEnvSources('DD_CIVISIBILITY_GIT_UNSHALLOW_ENABLED'))) {
292
292
  unshallowRepository(false)
293
293
  }
294
294
 
@@ -10,7 +10,7 @@ const {
10
10
  VITEST_WORKER_TRACE_PAYLOAD_CODE,
11
11
  VITEST_WORKER_LOGS_PAYLOAD_CODE
12
12
  } = require('../../../plugins/util/test')
13
- const { getEnvironmentVariable } = require('../../../config-helper')
13
+ const { getEnvironmentVariable, getValueFromEnvSources } = require('../../../config/helper')
14
14
  const Writer = require('./writer')
15
15
 
16
16
  function getInterprocessTraceCode () {
@@ -23,13 +23,13 @@ function getInterprocessTraceCode () {
23
23
  if (getEnvironmentVariable('MOCHA_WORKER_ID')) {
24
24
  return MOCHA_WORKER_TRACE_PAYLOAD_CODE
25
25
  }
26
- if (getEnvironmentVariable('DD_PLAYWRIGHT_WORKER')) {
26
+ if (getValueFromEnvSources('DD_PLAYWRIGHT_WORKER')) {
27
27
  return PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE
28
28
  }
29
29
  if (getEnvironmentVariable('TINYPOOL_WORKER_ID')) {
30
30
  return VITEST_WORKER_TRACE_PAYLOAD_CODE
31
31
  }
32
- if (getEnvironmentVariable('DD_VITEST_WORKER')) {
32
+ if (getValueFromEnvSources('DD_VITEST_WORKER')) {
33
33
  return VITEST_WORKER_TRACE_PAYLOAD_CODE
34
34
  }
35
35
  return null
@@ -50,7 +50,7 @@ function getInterprocessLogsCode () {
50
50
  if (getEnvironmentVariable('TINYPOOL_WORKER_ID')) {
51
51
  return VITEST_WORKER_LOGS_PAYLOAD_CODE
52
52
  }
53
- if (getEnvironmentVariable('DD_VITEST_WORKER')) {
53
+ if (getValueFromEnvSources('DD_VITEST_WORKER')) {
54
54
  return VITEST_WORKER_LOGS_PAYLOAD_CODE
55
55
  }
56
56
  return null
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
  const { JSONEncoder } = require('../../encode/json-encoder')
3
- const { getEnvironmentVariable } = require('../../../config-helper')
3
+ const { getEnvironmentVariable } = require('../../../config/helper')
4
4
  const log = require('../../../log')
5
5
  const {
6
6
  VITEST_WORKER_TRACE_PAYLOAD_CODE,
@@ -2,7 +2,7 @@
2
2
 
3
3
  const request = require('../../exporters/common/request')
4
4
  const log = require('../../log')
5
- const { getEnvironmentVariable } = require('../../config-helper')
5
+ const { getValueFromEnvSources } = require('../../config/helper')
6
6
  const {
7
7
  incrementCountMetric,
8
8
  distributionMetric,
@@ -49,7 +49,7 @@ function getSkippableSuites ({
49
49
  options.path = `${evpProxyPrefix}/api/v2/ci/tests/skippable`
50
50
  options.headers['X-Datadog-EVP-Subdomain'] = 'api'
51
51
  } else {
52
- const apiKey = getEnvironmentVariable('DD_API_KEY')
52
+ const apiKey = getValueFromEnvSources('DD_API_KEY')
53
53
  if (!apiKey) {
54
54
  return done(new Error('Skippable suites were not fetched because Datadog API key is not defined.'))
55
55
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  const Plugin = require('../../plugins/plugin')
4
4
  const log = require('../../log')
5
- const { getEnvironmentVariable } = require('../../config-helper')
5
+ const { getValueFromEnvSources } = require('../../config/helper')
6
6
 
7
7
  function getWinstonLogSubmissionParameters (config) {
8
8
  const { site, service } = config
@@ -12,16 +12,16 @@ function getWinstonLogSubmissionParameters (config) {
12
12
  path: `/api/v2/logs?ddsource=winston&service=${service}`,
13
13
  ssl: true,
14
14
  headers: {
15
- 'DD-API-KEY': getEnvironmentVariable('DD_API_KEY')
15
+ 'DD-API-KEY': getValueFromEnvSources('DD_API_KEY')
16
16
  }
17
17
  }
18
18
 
19
- if (!getEnvironmentVariable('DD_AGENTLESS_LOG_SUBMISSION_URL')) {
19
+ if (!getValueFromEnvSources('DD_AGENTLESS_LOG_SUBMISSION_URL')) {
20
20
  return defaultParameters
21
21
  }
22
22
 
23
23
  try {
24
- const url = new URL(getEnvironmentVariable('DD_AGENTLESS_LOG_SUBMISSION_URL'))
24
+ const url = new URL(getValueFromEnvSources('DD_AGENTLESS_LOG_SUBMISSION_URL'))
25
25
  return {
26
26
  host: url.hostname,
27
27
  port: url.port,
@@ -3,7 +3,7 @@
3
3
  const request = require('../../exporters/common/request')
4
4
  const id = require('../../id')
5
5
  const log = require('../../log')
6
- const { getEnvironmentVariable } = require('../../config-helper')
6
+ const { getValueFromEnvSources } = require('../../config/helper')
7
7
  const {
8
8
  incrementCountMetric,
9
9
  distributionMetric,
@@ -48,7 +48,7 @@ function getLibraryConfiguration ({
48
48
  options.path = `${evpProxyPrefix}/api/v2/libraries/tests/services/setting`
49
49
  options.headers['X-Datadog-EVP-Subdomain'] = 'api'
50
50
  } else {
51
- const apiKey = getEnvironmentVariable('DD_API_KEY')
51
+ const apiKey = getValueFromEnvSources('DD_API_KEY')
52
52
  if (!apiKey) {
53
53
  return done(new Error('Request to settings endpoint was not done because Datadog API key is not defined.'))
54
54
  }
@@ -126,11 +126,11 @@ function getLibraryConfiguration ({
126
126
 
127
127
  log.debug('Remote settings: %j', settings)
128
128
 
129
- if (getEnvironmentVariable('DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE')) {
129
+ if (getValueFromEnvSources('DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE')) {
130
130
  settings.isCodeCoverageEnabled = true
131
131
  log.debug('Dangerously set code coverage to true')
132
132
  }
133
- if (getEnvironmentVariable('DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING')) {
133
+ if (getValueFromEnvSources('DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING')) {
134
134
  settings.isSuitesSkippingEnabled = true
135
135
  log.debug('Dangerously set test skipping to true')
136
136
  }
@@ -21,8 +21,12 @@ const formattedTags = {
21
21
 
22
22
  // Transform tags dictionary to array of strings.
23
23
  // If tag value is true, then only tag key is added to the array.
24
+ /**
25
+ * @param {Record<string, unknown>} tagsDictionary
26
+ * @returns {string[]}
27
+ */
24
28
  function formatMetricTags (tagsDictionary) {
25
- return Object.keys(tagsDictionary).reduce((acc, tagKey) => {
29
+ return Object.keys(tagsDictionary).reduce((/** @type {string[]} */ acc, tagKey) => {
26
30
  if (tagKey === 'statusCode') {
27
31
  const statusCode = tagsDictionary[tagKey]
28
32
  if (isStatusCode400(statusCode)) {
@@ -31,7 +35,7 @@ function formatMetricTags (tagsDictionary) {
31
35
  acc.push(`error_type:${getErrorTypeFromStatusCode(statusCode)}`)
32
36
  return acc
33
37
  }
34
- const formattedTagKey = formattedTags[tagKey] || tagKey
38
+ const formattedTagKey = /** @type {string} */(formattedTags[tagKey] || tagKey)
35
39
  if (tagsDictionary[tagKey] === true) {
36
40
  acc.push(formattedTagKey)
37
41
  } else if (tagsDictionary[tagKey] !== undefined && tagsDictionary[tagKey] !== null) {
@@ -2,7 +2,7 @@
2
2
 
3
3
  const request = require('../../exporters/common/request')
4
4
  const id = require('../../id')
5
- const { getEnvironmentVariable } = require('../../config-helper')
5
+ const { getValueFromEnvSources } = require('../../config/helper')
6
6
  const log = require('../../log')
7
7
 
8
8
  function getTestManagementTests ({
@@ -35,7 +35,7 @@ function getTestManagementTests ({
35
35
  options.path = `${evpProxyPrefix}/api/v2/test/libraries/test-management/tests`
36
36
  options.headers['X-Datadog-EVP-Subdomain'] = 'api'
37
37
  } else {
38
- const apiKey = getEnvironmentVariable('DD_API_KEY')
38
+ const apiKey = getValueFromEnvSources('DD_API_KEY')
39
39
  if (!apiKey) {
40
40
  return done(new Error('Test management tests were not fetched because Datadog API key is not defined.'))
41
41
  }
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
- const pkg = require('./pkg')
4
- const { GRPC_CLIENT_ERROR_STATUSES, GRPC_SERVER_ERROR_STATUSES } = require('./constants')
5
- const { getEnvironmentVariable: getEnv } = require('./config-helper')
3
+ const pkg = require('../pkg')
4
+ const { GRPC_CLIENT_ERROR_STATUSES, GRPC_SERVER_ERROR_STATUSES } = require('../constants')
5
+ const { getEnvironmentVariable: getEnv } = require('./helper')
6
6
 
7
7
  // eslint-disable-next-line @stylistic/max-len
8
8
  const qsRegex = String.raw`(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\s|%20)*(?::|%3A)(?:\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|bearer(?:\s|%20)+[a-z0-9\._\-]+|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\w=-]|%3D)+\.ey[I-L](?:[\w=-]|%3D)+(?:\.(?:[\w.+\/=-]|%3D|%2F|%2B)+)?|[\-]{5}BEGIN(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY[\-]{5}[^\-]+[\-]{5}END(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY|ssh-rsa(?:\s|%20)*(?:[a-z0-9\/\.+]|%2F|%5C|%2B){100,}`
@@ -34,7 +34,66 @@ for (const deprecation of Object.keys(deprecations)) {
34
34
  )
35
35
  }
36
36
 
37
+ let localStableConfig
38
+ let fleetStableConfig
39
+ let stableConfigWarnings
40
+ let stableConfigLoaded = false
41
+
42
+ function loadStableConfig () {
43
+ stableConfigLoaded = true
44
+
45
+ // Lazy require to avoid circular dependency at module load time.
46
+ const { isInServerlessEnvironment } = require('../serverless')
47
+ if (isInServerlessEnvironment()) {
48
+ // Stable config is not supported in serverless environments.
49
+ return
50
+ }
51
+
52
+ const StableConfig = require('./stable')
53
+ const instance = new StableConfig()
54
+ localStableConfig = instance.localEntries
55
+ fleetStableConfig = instance.fleetEntries
56
+ stableConfigWarnings = instance.warnings
57
+ }
58
+
59
+ function getValueFromSource (name, source) {
60
+ const value = source[name]
61
+
62
+ if (value === undefined && aliases[name]) {
63
+ for (const alias of aliases[name]) {
64
+ if (source[alias] !== undefined) {
65
+ return source[alias]
66
+ }
67
+ }
68
+ }
69
+
70
+ return value
71
+ }
72
+
73
+ function validateAccess (name) {
74
+ if ((name.startsWith('DD_') || name.startsWith('OTEL_') || aliasToCanonical[name]) &&
75
+ !supportedConfigurations[name]) {
76
+ throw new Error(`Missing ${name} env/configuration in "supported-configurations.json" file.`)
77
+ }
78
+ }
79
+
37
80
  module.exports = {
81
+ /**
82
+ * Expose raw stable config maps and warnings for consumers that need
83
+ * per-source access (e.g. telemetry in Config).
84
+ *
85
+ * @returns {{ localStableConfig: object, fleetStableConfig: object, stableConfigWarnings: string[] }}
86
+ */
87
+ getStableConfigSources () {
88
+ if (!stableConfigLoaded) {
89
+ loadStableConfig()
90
+ }
91
+ return {
92
+ localStableConfig,
93
+ fleetStableConfig,
94
+ stableConfigWarnings,
95
+ }
96
+ },
38
97
  /**
39
98
  * Returns the environment variables that are supported by the tracer
40
99
  * (including all non-Datadog/OTEL specific environment variables).
@@ -46,6 +105,7 @@ module.exports = {
46
105
  getEnvironmentVariables () {
47
106
  const configs = {}
48
107
  for (const [key, value] of Object.entries(process.env)) {
108
+ // TODO(BridgeAR): Handle telemetry reporting for aliases.
49
109
  if (key.startsWith('DD_') || key.startsWith('OTEL_') || aliasToCanonical[key]) {
50
110
  if (supportedConfigurations[key]) {
51
111
  configs[key] = value
@@ -72,28 +132,41 @@ module.exports = {
72
132
  return configs
73
133
  },
74
134
 
135
+ getEnvironmentVariable (name) {
136
+ validateAccess(name)
137
+ return getValueFromSource(name, process.env)
138
+ },
139
+
75
140
  /**
76
- * Returns the environment variable, if it's supported or a non Datadog
77
- * configuration. Otherwise, it throws an error.
141
+ * Returns the value stored at the given name, assumed to be in environment variable format,
142
+ * from the supported env sources (process.env, local stable config, fleet stable config).
143
+ * Falls back to aliases if the canonical name is not set.
78
144
  *
79
145
  * @param {string} name Environment variable name
80
146
  * @returns {string|undefined}
81
147
  * @throws {Error} if the configuration is not supported
82
148
  */
83
- // This method, and callers of this method, need to be updated to check for declarative config sources as well.
84
- getEnvironmentVariable (name) {
85
- if ((name.startsWith('DD_') || name.startsWith('OTEL_') || aliasToCanonical[name]) &&
86
- !supportedConfigurations[name]) {
87
- throw new Error(`Missing ${name} env/configuration in "supported-configurations.json" file.`)
149
+ getValueFromEnvSources (name) {
150
+ validateAccess(name)
151
+
152
+ if (!stableConfigLoaded) {
153
+ loadStableConfig()
88
154
  }
89
- const config = process.env[name]
90
- if (config === undefined && aliases[name]) {
91
- for (const alias of aliases[name]) {
92
- if (process.env[alias] !== undefined) {
93
- return process.env[alias]
94
- }
155
+
156
+ if (fleetStableConfig !== undefined) {
157
+ const fromFleet = getValueFromSource(name, fleetStableConfig)
158
+ if (fromFleet !== undefined) {
159
+ return fromFleet
95
160
  }
96
161
  }
97
- return config
98
- }
162
+
163
+ const fromEnv = getValueFromSource(name, process.env)
164
+ if (fromEnv !== undefined) {
165
+ return fromEnv
166
+ }
167
+
168
+ if (localStableConfig !== undefined) {
169
+ return getValueFromSource(name, localStableConfig)
170
+ }
171
+ },
99
172
  }