dd-trace 5.82.0 → 5.83.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 (134) hide show
  1. package/LICENSE-3rdparty.csv +78 -79
  2. package/ci/init.js +6 -6
  3. package/index.d.ts +152 -3
  4. package/loader-hook.mjs +1 -1
  5. package/package.json +58 -55
  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/index.js +1 -1
  15. package/packages/datadog-instrumentations/src/http/client.js +2 -2
  16. package/packages/datadog-instrumentations/src/jest.js +35 -14
  17. package/packages/datadog-instrumentations/src/koa.js +2 -1
  18. package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
  19. package/packages/datadog-instrumentations/src/mocha/main.js +2 -2
  20. package/packages/datadog-instrumentations/src/mocha/worker.js +1 -1
  21. package/packages/datadog-instrumentations/src/mocha.js +1 -1
  22. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  23. package/packages/datadog-instrumentations/src/mysql2.js +2 -2
  24. package/packages/datadog-instrumentations/src/net.js +13 -5
  25. package/packages/datadog-instrumentations/src/nyc.js +1 -1
  26. package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -4
  27. package/packages/datadog-instrumentations/src/pg.js +4 -2
  28. package/packages/datadog-instrumentations/src/playwright.js +3 -3
  29. package/packages/datadog-instrumentations/src/selenium.js +2 -2
  30. package/packages/datadog-instrumentations/src/undici.js +12 -1
  31. package/packages/datadog-plugin-aws-sdk/src/base.js +4 -4
  32. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +2 -2
  33. package/packages/datadog-plugin-azure-service-bus/src/producer.js +2 -2
  34. package/packages/datadog-plugin-cucumber/src/index.js +2 -2
  35. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -2
  36. package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -2
  37. package/packages/datadog-plugin-express/src/code_origin.js +21 -15
  38. package/packages/datadog-plugin-fastify/src/code_origin.js +17 -4
  39. package/packages/datadog-plugin-jest/src/index.js +2 -2
  40. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  41. package/packages/datadog-plugin-mongodb-core/src/index.js +2 -2
  42. package/packages/datadog-plugin-playwright/src/index.js +3 -3
  43. package/packages/datadog-plugin-undici/src/index.js +305 -2
  44. package/packages/datadog-plugin-vitest/src/index.js +5 -5
  45. package/packages/dd-trace/index.js +19 -0
  46. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +1 -1
  47. package/packages/dd-trace/src/appsec/rasp/index.js +2 -4
  48. package/packages/dd-trace/src/azure_metadata.js +8 -3
  49. package/packages/dd-trace/src/baggage.js +36 -11
  50. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +5 -1
  51. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -2
  52. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -2
  53. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -2
  54. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  55. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +3 -2
  56. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -3
  57. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +4 -4
  58. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +1 -1
  59. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -2
  60. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -4
  61. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -4
  62. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -2
  63. package/packages/dd-trace/src/{config_defaults.js → config/defaults.js} +3 -3
  64. package/packages/dd-trace/src/{config-helper.js → config/helper.js} +88 -15
  65. package/packages/dd-trace/src/{config.js → config/index.js} +92 -45
  66. package/packages/dd-trace/src/config/remote_config.js +187 -19
  67. package/packages/dd-trace/src/{config_stable.js → config/stable.js} +20 -32
  68. package/packages/dd-trace/src/{supported-configurations.json → config/supported-configurations.json} +2 -0
  69. package/packages/dd-trace/src/crashtracking/crashtracker.js +1 -1
  70. package/packages/dd-trace/src/datastreams/processor.js +1 -1
  71. package/packages/dd-trace/src/datastreams/writer.js +1 -1
  72. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
  73. package/packages/dd-trace/src/debugger/devtools_client/config.js +1 -1
  74. package/packages/dd-trace/src/debugger/devtools_client/send.js +3 -3
  75. package/packages/dd-trace/src/debugger/devtools_client/snapshot/constants.js +1 -1
  76. package/packages/dd-trace/src/debugger/index.js +83 -15
  77. package/packages/dd-trace/src/dogstatsd.js +2 -2
  78. package/packages/dd-trace/src/encode/0.4.js +2 -2
  79. package/packages/dd-trace/src/exporter.js +1 -1
  80. package/packages/dd-trace/src/exporters/agent/index.js +2 -4
  81. package/packages/dd-trace/src/exporters/agent/writer.js +9 -14
  82. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +1 -1
  83. package/packages/dd-trace/src/exporters/common/docker.js +2 -2
  84. package/packages/dd-trace/src/exporters/common/request.js +1 -1
  85. package/packages/dd-trace/src/exporters/common/util.js +2 -2
  86. package/packages/dd-trace/src/exporters/span-stats/index.js +1 -1
  87. package/packages/dd-trace/src/flare/index.js +1 -1
  88. package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
  89. package/packages/dd-trace/src/index.js +4 -4
  90. package/packages/dd-trace/src/lambda/handler.js +2 -2
  91. package/packages/dd-trace/src/lambda/index.js +2 -2
  92. package/packages/dd-trace/src/lambda/runtime/patch.js +2 -2
  93. package/packages/dd-trace/src/lambda/runtime/ritm.js +2 -2
  94. package/packages/dd-trace/src/llmobs/constants/tags.js +8 -1
  95. package/packages/dd-trace/src/llmobs/index.js +2 -2
  96. package/packages/dd-trace/src/llmobs/noop.js +2 -0
  97. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +3 -4
  98. package/packages/dd-trace/src/llmobs/sdk.js +33 -6
  99. package/packages/dd-trace/src/llmobs/span_processor.js +17 -7
  100. package/packages/dd-trace/src/llmobs/tagger.js +175 -1
  101. package/packages/dd-trace/src/llmobs/writers/base.js +116 -37
  102. package/packages/dd-trace/src/llmobs/writers/spans.js +4 -3
  103. package/packages/dd-trace/src/log/index.js +5 -5
  104. package/packages/dd-trace/src/noop/proxy.js +3 -3
  105. package/packages/dd-trace/src/openfeature/writers/base.js +7 -8
  106. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +2 -2
  107. package/packages/dd-trace/src/opentelemetry/tracer.js +48 -6
  108. package/packages/dd-trace/src/opentracing/propagation/text_map.js +45 -21
  109. package/packages/dd-trace/src/opentracing/span.js +4 -4
  110. package/packages/dd-trace/src/plugin_manager.js +8 -6
  111. package/packages/dd-trace/src/plugins/util/ci.js +5 -8
  112. package/packages/dd-trace/src/plugins/util/git-cache.js +3 -3
  113. package/packages/dd-trace/src/plugins/util/test.js +1 -1
  114. package/packages/dd-trace/src/plugins/util/user-provided-git.js +41 -43
  115. package/packages/dd-trace/src/profiler.js +4 -39
  116. package/packages/dd-trace/src/profiling/config.js +74 -31
  117. package/packages/dd-trace/src/profiling/exporter_cli.js +5 -5
  118. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  119. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +9 -2
  120. package/packages/dd-trace/src/profiling/index.js +1 -1
  121. package/packages/dd-trace/src/profiling/libuv-size.js +1 -1
  122. package/packages/dd-trace/src/profiling/profiler.js +57 -2
  123. package/packages/dd-trace/src/proxy.js +34 -5
  124. package/packages/dd-trace/src/remote_config/capabilities.js +3 -0
  125. package/packages/dd-trace/src/remote_config/index.js +1 -1
  126. package/packages/dd-trace/src/ritm.js +8 -4
  127. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +2 -2
  128. package/packages/dd-trace/src/serverless.js +2 -2
  129. package/packages/dd-trace/src/span_processor.js +2 -2
  130. package/packages/dd-trace/src/startup-log.js +6 -15
  131. package/packages/dd-trace/src/telemetry/endpoints.js +67 -5
  132. package/packages/dd-trace/src/telemetry/send-data.js +103 -4
  133. package/packages/dd-trace/src/telemetry/telemetry.js +229 -110
  134. /package/packages/dd-trace/src/{git_properties.js → config/git_properties.js} +0 -0
@@ -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
  }
@@ -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
  }
@@ -4,28 +4,28 @@ const fs = require('fs')
4
4
  const os = require('os')
5
5
  const { URL } = require('url')
6
6
  const path = require('path')
7
- const uuid = require('../../../vendor/dist/crypto-randomuuid') // we need to keep the old uuid dep because of cypress
8
-
9
- const set = require('../../datadog-core/src/utils/src/set')
10
- const { DD_MAJOR } = require('../../../version')
11
- const log = require('./log')
12
- const tagger = require('./tagger')
13
- const { isTrue, isFalse, normalizeProfilingEnabledValue } = require('./util')
14
- const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('./plugins/util/tags')
15
- const { getGitMetadataFromGitProperties, removeUserSensitiveInfo, getRemoteOriginURL, resolveGitHeadSHA } =
16
- require('./git_properties')
17
- const { updateConfig } = require('./telemetry')
18
- const telemetryMetrics = require('./telemetry/metrics')
7
+ const uuid = require('../../../../vendor/dist/crypto-randomuuid') // we need to keep the old uuid dep because of cypress
8
+
9
+ const set = require('../../../datadog-core/src/utils/src/set')
10
+ const { DD_MAJOR } = require('../../../../version')
11
+ const log = require('../log')
12
+ const tagger = require('../tagger')
13
+ const { isTrue, isFalse, normalizeProfilingEnabledValue } = require('../util')
14
+ const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../plugins/util/tags')
15
+ const { updateConfig } = require('../telemetry')
16
+ const telemetryMetrics = require('../telemetry/metrics')
19
17
  const {
20
18
  isInServerlessEnvironment,
21
19
  getIsGCPFunction,
22
20
  getIsAzureFunction,
23
21
  enableGCPPubSubPushSubscription
24
- } = require('./serverless')
25
- const { ORIGIN_KEY } = require('./constants')
26
- const { appendRules } = require('./payload-tagging/config')
27
- const { getEnvironmentVariable: getEnv, getEnvironmentVariables } = require('./config-helper')
28
- const defaults = require('./config_defaults')
22
+ } = require('../serverless')
23
+ const { ORIGIN_KEY } = require('../constants')
24
+ const { appendRules } = require('../payload-tagging/config')
25
+ const { getGitMetadataFromGitProperties, removeUserSensitiveInfo, getRemoteOriginURL, resolveGitHeadSHA } =
26
+ require('./git_properties')
27
+ const { getEnvironmentVariable: getEnv, getEnvironmentVariables, getStableConfigSources } = require('./helper')
28
+ const defaults = require('./defaults')
29
29
 
30
30
  const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
31
31
 
@@ -276,9 +276,12 @@ class Config {
276
276
 
277
277
  constructor (options = {}) {
278
278
  if (!isInServerlessEnvironment()) {
279
- // Bail out early if we're in a serverless environment, stable config isn't supported
280
- const StableConfig = require('./config_stable')
281
- this.stableConfig = new StableConfig()
279
+ const configEnvSources = getStableConfigSources()
280
+ this.stableConfig = {
281
+ fleetEntries: configEnvSources.fleetStableConfig,
282
+ localEntries: configEnvSources.localStableConfig,
283
+ warnings: configEnvSources.stableConfigWarnings
284
+ }
282
285
  }
283
286
 
284
287
  options = {
@@ -328,7 +331,6 @@ class Config {
328
331
  this.#applyStableConfig(this.stableConfig?.fleetEntries ?? {}, this.#fleetStableConfig)
329
332
  this.#applyOptions(options)
330
333
  this.#applyCalculated()
331
- this.#applyRemote({})
332
334
  this.#merge()
333
335
 
334
336
  tagger.add(this.tags, {
@@ -353,15 +355,38 @@ class Config {
353
355
  return this.#parsedDdTags
354
356
  }
355
357
 
356
- // Supports only a subset of options for now.
357
- configure (options, remote) {
358
- if (remote) {
359
- this.#applyRemote(options)
360
- } else {
361
- this.#applyOptions(options)
358
+ /**
359
+ * Set the configuration with remote config settings.
360
+ * Applies remote configuration, recalculates derived values, and merges all configuration sources.
361
+ *
362
+ * @param {import('./config/remote_config').RemoteConfigOptions|null} options - Configurations received via Remote
363
+ * Config or null to reset all remote configuration
364
+ */
365
+ setRemoteConfig (options) {
366
+ // Clear all RC-managed fields to ensure previous values don't persist.
367
+ // State is instead managed by the `RCClientLibConfigManager` class
368
+ this.#remote = {}
369
+ this.#remoteUnprocessed = {}
370
+
371
+ // Special case: if options is null, nothing to apply
372
+ // This happens when all remote configs are removed
373
+ if (options !== null) {
374
+ this.#applyRemoteConfig(options)
362
375
  }
363
376
 
364
- // TODO: test
377
+ this.#applyCalculated()
378
+ this.#merge()
379
+ }
380
+
381
+ // TODO: Remove the `updateOptions` method. We don't want to support updating the config this way
382
+ /**
383
+ * Updates the configuration with new programmatic options.
384
+ *
385
+ * @deprecated This method should not be used and will be removed in a future version.
386
+ * @param {object} options - Configuration options to apply (same format as tracer init options)
387
+ */
388
+ updateOptions (options) {
389
+ this.#applyOptions(options)
365
390
  this.#applyCalculated()
366
391
  this.#merge()
367
392
  }
@@ -478,6 +503,7 @@ class Config {
478
503
  DD_IAST_STACK_TRACE_ENABLED,
479
504
  DD_INJECTION_ENABLED,
480
505
  DD_INJECT_FORCE,
506
+ DD_ENABLE_NX_SERVICE_NAME,
481
507
  DD_INSTRUMENTATION_TELEMETRY_ENABLED,
482
508
  DD_INSTRUMENTATION_CONFIG_ID,
483
509
  DD_LOGS_INJECTION,
@@ -591,7 +617,8 @@ class Config {
591
617
  OTEL_BSP_SCHEDULE_DELAY,
592
618
  OTEL_BSP_MAX_EXPORT_BATCH_SIZE,
593
619
  OTEL_BSP_MAX_QUEUE_SIZE,
594
- OTEL_METRIC_EXPORT_INTERVAL
620
+ OTEL_METRIC_EXPORT_INTERVAL,
621
+ NX_TASK_TARGET_PROJECT
595
622
  } = source
596
623
 
597
624
  const tags = {}
@@ -862,7 +889,22 @@ class Config {
862
889
  this.#setSamplingRule(target, 'sampler.rules', safeJsonParse(DD_TRACE_SAMPLING_RULES))
863
890
  unprocessedTarget['sampler.rules'] = DD_TRACE_SAMPLING_RULES
864
891
  this.#setString(target, 'scope', DD_TRACE_SCOPE)
865
- this.#setString(target, 'service', DD_SERVICE || tags.service || OTEL_SERVICE_NAME)
892
+ // Priority:
893
+ // DD_SERVICE > tags.service > OTEL_SERVICE_NAME > NX_TASK_TARGET_PROJECT (if DD_ENABLE_NX_SERVICE_NAME) > default
894
+ let serviceName = DD_SERVICE || tags.service || OTEL_SERVICE_NAME
895
+ if (!serviceName && NX_TASK_TARGET_PROJECT) {
896
+ if (isTrue(DD_ENABLE_NX_SERVICE_NAME)) {
897
+ serviceName = NX_TASK_TARGET_PROJECT
898
+ } else if (DD_MAJOR < 6) {
899
+ // Warn about v6 behavior change for Nx projects
900
+ log.warn(
901
+ 'NX_TASK_TARGET_PROJECT is set but no service name was configured. ' +
902
+ 'In v6, NX_TASK_TARGET_PROJECT will be used as the default service name. ' +
903
+ 'Set DD_ENABLE_NX_SERVICE_NAME=true to opt-in to this behavior now, or set a service name explicitly.'
904
+ )
905
+ }
906
+ }
907
+ this.#setString(target, 'service', serviceName)
866
908
  if (DD_SERVICE_MAPPING) {
867
909
  target.serviceMapping = Object.fromEntries(
868
910
  DD_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
@@ -1287,31 +1329,36 @@ class Config {
1287
1329
  }
1288
1330
  }
1289
1331
 
1290
- #applyRemote (options) {
1332
+ /**
1333
+ * Applies remote configuration options from APM_TRACING configs.
1334
+ *
1335
+ * @param {import('./config/remote_config').RemoteConfigOptions} options - Configurations received via Remote Config
1336
+ */
1337
+ #applyRemoteConfig (options) {
1291
1338
  const opts = this.#remote
1292
- const tags = {}
1293
- const headerTags = options.tracing_header_tags
1294
- ? options.tracing_header_tags.map(tag => {
1295
- return tag.tag_name ? `${tag.header}:${tag.tag_name}` : tag.header
1296
- })
1297
- : undefined
1298
-
1299
- tagger.add(tags, options.tracing_tags)
1300
- if (Object.keys(tags).length) tags['runtime-id'] = runtimeId
1301
1339
 
1340
+ this.#setBoolean(opts, 'dynamicInstrumentation.enabled', options.dynamic_instrumentation_enabled)
1341
+ this.#setBoolean(opts, 'codeOriginForSpans.enabled', options.code_origin_enabled)
1302
1342
  this.#setUnit(opts, 'sampleRate', options.tracing_sampling_rate)
1303
1343
  this.#setBoolean(opts, 'logInjection', options.log_injection_enabled)
1304
- opts.headerTags = headerTags
1305
- this.#setTags(opts, 'tags', tags)
1306
1344
  this.#setBoolean(opts, 'tracing', options.tracing_enabled)
1307
1345
  this.#remoteUnprocessed['sampler.rules'] = options.tracing_sampling_rules
1308
- this.#setSamplingRule(opts, 'sampler.rules', this.#reformatTags(options.tracing_sampling_rules))
1346
+ this.#setSamplingRule(opts, 'sampler.rules', this.#reformatTagsFromRC(options.tracing_sampling_rules))
1347
+
1348
+ opts.headerTags = options.tracing_header_tags?.map(tag => {
1349
+ return tag.tag_name ? `${tag.header}:${tag.tag_name}` : tag.header
1350
+ })
1351
+
1352
+ const tags = {}
1353
+ tagger.add(tags, options.tracing_tags)
1354
+ if (Object.keys(tags).length) tags['runtime-id'] = runtimeId
1355
+ this.#setTags(opts, 'tags', tags)
1309
1356
  }
1310
1357
 
1311
- #reformatTags (samplingRules) {
1358
+ #reformatTagsFromRC (samplingRules) {
1312
1359
  for (const rule of (samplingRules || [])) {
1313
- const reformattedTags = {}
1314
1360
  if (rule.tags) {
1361
+ const reformattedTags = {}
1315
1362
  for (const tag of rule.tags) {
1316
1363
  reformattedTags[tag.key] = tag.value_glob
1317
1364
  }