dd-trace 5.106.0 → 5.108.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 (105) hide show
  1. package/index.d.ts +20 -1
  2. package/package.json +9 -11
  3. package/packages/datadog-core/src/storage.js +47 -48
  4. package/packages/datadog-esbuild/index.js +6 -1
  5. package/packages/datadog-instrumentations/src/ai.js +12 -3
  6. package/packages/datadog-instrumentations/src/body-parser.js +5 -2
  7. package/packages/datadog-instrumentations/src/connect.js +3 -2
  8. package/packages/datadog-instrumentations/src/cookie-parser.js +3 -2
  9. package/packages/datadog-instrumentations/src/cucumber.js +7 -0
  10. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +7 -5
  11. package/packages/datadog-instrumentations/src/express-session.js +12 -11
  12. package/packages/datadog-instrumentations/src/express.js +24 -20
  13. package/packages/datadog-instrumentations/src/fastify.js +18 -6
  14. package/packages/datadog-instrumentations/src/helpers/openai-ai-guard.js +27 -12
  15. package/packages/datadog-instrumentations/src/http/client.js +9 -12
  16. package/packages/datadog-instrumentations/src/http/server.js +30 -16
  17. package/packages/datadog-instrumentations/src/http2/client.js +15 -12
  18. package/packages/datadog-instrumentations/src/http2/server.js +15 -8
  19. package/packages/datadog-instrumentations/src/jest/bail-reporter.js +42 -0
  20. package/packages/datadog-instrumentations/src/jest.js +143 -73
  21. package/packages/datadog-instrumentations/src/mocha/main.js +43 -8
  22. package/packages/datadog-instrumentations/src/mocha/utils.js +128 -17
  23. package/packages/datadog-instrumentations/src/multer.js +3 -2
  24. package/packages/datadog-instrumentations/src/mysql2.js +34 -0
  25. package/packages/datadog-instrumentations/src/net.js +8 -6
  26. package/packages/datadog-instrumentations/src/openai.js +19 -7
  27. package/packages/datadog-instrumentations/src/pg.js +19 -0
  28. package/packages/datadog-instrumentations/src/router.js +12 -10
  29. package/packages/datadog-instrumentations/src/vitest.js +29 -4
  30. package/packages/datadog-plugin-aws-sdk/src/base.js +0 -3
  31. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +62 -11
  32. package/packages/datadog-plugin-cucumber/src/index.js +2 -0
  33. package/packages/datadog-plugin-cypress/src/support.js +31 -1
  34. package/packages/datadog-plugin-http/src/client.js +0 -3
  35. package/packages/datadog-plugin-http/src/server.js +11 -1
  36. package/packages/datadog-plugin-mocha/src/index.js +2 -0
  37. package/packages/datadog-plugin-pg/src/index.js +10 -0
  38. package/packages/dd-trace/src/aiguard/index.js +34 -15
  39. package/packages/dd-trace/src/aiguard/sdk.js +34 -3
  40. package/packages/dd-trace/src/aiguard/tags.js +6 -0
  41. package/packages/dd-trace/src/appsec/downstream_requests.js +3 -2
  42. package/packages/dd-trace/src/appsec/iast/index.js +3 -2
  43. package/packages/dd-trace/src/appsec/rasp/ssrf.js +2 -1
  44. package/packages/dd-trace/src/appsec/reporter.js +1 -1
  45. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -1
  46. package/packages/dd-trace/src/config/defaults.js +14 -0
  47. package/packages/dd-trace/src/config/generated-config-types.d.ts +2 -1
  48. package/packages/dd-trace/src/config/helper.js +1 -0
  49. package/packages/dd-trace/src/config/index.js +5 -9
  50. package/packages/dd-trace/src/config/parsers.js +8 -0
  51. package/packages/dd-trace/src/config/supported-configurations.json +20 -6
  52. package/packages/dd-trace/src/crashtracking/crashtracker.js +2 -2
  53. package/packages/dd-trace/src/datastreams/writer.js +1 -2
  54. package/packages/dd-trace/src/debugger/config.js +1 -1
  55. package/packages/dd-trace/src/debugger/devtools_client/config.js +3 -2
  56. package/packages/dd-trace/src/debugger/index.js +1 -2
  57. package/packages/dd-trace/src/dogstatsd.js +2 -3
  58. package/packages/dd-trace/src/encode/0.4.js +49 -41
  59. package/packages/dd-trace/src/encode/agentless-json.js +5 -1
  60. package/packages/dd-trace/src/encode/tags-processors.js +14 -0
  61. package/packages/dd-trace/src/exporters/agent/index.js +1 -2
  62. package/packages/dd-trace/src/exporters/agentless/index.js +6 -10
  63. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +1 -2
  64. package/packages/dd-trace/src/exporters/common/request.js +26 -0
  65. package/packages/dd-trace/src/exporters/span-stats/index.js +1 -2
  66. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +4 -0
  67. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +45 -0
  68. package/packages/dd-trace/src/llmobs/sdk.js +4 -1
  69. package/packages/dd-trace/src/llmobs/span_processor.js +17 -1
  70. package/packages/dd-trace/src/llmobs/tagger.js +5 -3
  71. package/packages/dd-trace/src/llmobs/util.js +54 -0
  72. package/packages/dd-trace/src/llmobs/writers/base.js +1 -2
  73. package/packages/dd-trace/src/llmobs/writers/util.js +1 -2
  74. package/packages/dd-trace/src/openfeature/writers/base.js +1 -10
  75. package/packages/dd-trace/src/openfeature/writers/util.js +1 -2
  76. package/packages/dd-trace/src/opentelemetry/metrics/instruments.js +26 -13
  77. package/packages/dd-trace/src/opentelemetry/metrics/meter.js +7 -10
  78. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +92 -0
  79. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +3 -2
  80. package/packages/dd-trace/src/opentracing/span.js +23 -18
  81. package/packages/dd-trace/src/opentracing/tracer.js +16 -12
  82. package/packages/dd-trace/src/plugins/ci_plugin.js +131 -46
  83. package/packages/dd-trace/src/priority_sampler.js +6 -5
  84. package/packages/dd-trace/src/profiling/config.js +3 -2
  85. package/packages/dd-trace/src/profiling/profilers/events.js +26 -4
  86. package/packages/dd-trace/src/profiling/profilers/space.js +3 -1
  87. package/packages/dd-trace/src/proxy.js +13 -10
  88. package/packages/dd-trace/src/remote_config/index.js +1 -2
  89. package/packages/dd-trace/src/runtime_metrics/client.js +30 -0
  90. package/packages/dd-trace/src/runtime_metrics/index.js +12 -2
  91. package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +284 -0
  92. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +2 -11
  93. package/packages/dd-trace/src/service-naming/source-resolver.js +5 -1
  94. package/packages/dd-trace/src/span_format.js +33 -25
  95. package/packages/dd-trace/src/span_stats.js +1 -1
  96. package/packages/dd-trace/src/startup-log.js +1 -2
  97. package/packages/dd-trace/src/telemetry/send-data.js +1 -1
  98. package/packages/dd-trace/src/tracer.js +1 -1
  99. package/vendor/dist/@apm-js-collab/code-transformer/index.js +2 -2
  100. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  101. package/vendor/dist/protobufjs/index.js +1 -1
  102. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  103. package/vendor/dist/shell-quote/index.js +1 -1
  104. package/packages/dd-trace/src/agent/url.js +0 -28
  105. package/scripts/preinstall.js +0 -34
@@ -44,27 +44,46 @@ function disable () {
44
44
  /**
45
45
  * Handles channel messages with pre-converted messages.
46
46
  *
47
- * @param {{messages: Array<object>, integration?: string, resolve: Function, reject: Function}} ctx
47
+ * @param {object} ctx
48
+ * @param {Array<object>} ctx.messages
49
+ * @param {string} [ctx.integration]
50
+ * @param {object} [ctx.parentSpan] - LLM span to parent the `ai_guard` span under.
51
+ * @param {AbortController} ctx.abortController
52
+ * @param {Array<Promise<void>>} ctx.pending - Subscribers push only when they evaluate.
48
53
  */
49
54
  function onEvaluate (ctx) {
55
+ // Decline to evaluate empty payloads by not pushing to pending.
50
56
  if (!ctx.messages?.length) {
51
- ctx.resolve()
52
57
  return
53
58
  }
54
59
 
55
- const opts = { block, source: SOURCE_AUTO, integration: ctx.integration || INTEGRATION_NONE }
56
- aiguard.evaluate(ctx.messages, opts)
57
- .then(() => {
58
- ctx.resolve()
59
- })
60
- .catch(err => {
61
- if (err.name === 'AIGuardAbortError') {
62
- ctx.reject(err)
63
- } else {
64
- log.error('AIGuard: unexpected error during evaluation: %s', err.message)
65
- ctx.resolve()
66
- }
67
- })
60
+ const opts = {
61
+ block,
62
+ source: SOURCE_AUTO,
63
+ integration: ctx.integration || INTEGRATION_NONE,
64
+ childOf: ctx.parentSpan,
65
+ }
66
+
67
+ try {
68
+ ctx.pending.push(aiguard.evaluate(ctx.messages, opts).catch(handleEvaluationError.bind(null, ctx)))
69
+ } catch (err) {
70
+ ctx.pending.push(Promise.resolve().then(() => handleEvaluationError(ctx, err)))
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Handles an AI Guard evaluation failure.
76
+ *
77
+ * @param {object} ctx
78
+ * @param {AbortController} ctx.abortController
79
+ * @param {Error} err
80
+ */
81
+ function handleEvaluationError (ctx, err) {
82
+ if (err.name === 'AIGuardAbortError') {
83
+ ctx.abortController.abort(err)
84
+ } else {
85
+ log.error('AIGuard: unexpected error during evaluation: %s', err.message)
86
+ }
68
87
  }
69
88
 
70
89
  module.exports = { enable, disable }
@@ -1,7 +1,8 @@
1
1
  'use strict'
2
2
 
3
3
  const rfdc = require('../../../../vendor/dist/rfdc')({ proto: false, circles: false })
4
- const { HTTP_CLIENT_IP, NETWORK_CLIENT_IP } = require('../../../../ext/tags')
4
+ const { HTTP_CLIENT_IP, NETWORK_CLIENT_IP, HTTP_USERAGENT } = require('../../../../ext/tags')
5
+ const { USER_ID, USER_SESSION_ID } = require('../appsec/addresses')
5
6
  const { getActiveRequest } = require('../appsec/store')
6
7
  const log = require('../log')
7
8
  const { extractIp } = require('../plugins/util/ip_extractor')
@@ -17,6 +18,16 @@ const aiguardMetrics = telemetryMetrics.manager.namespace('ai_guard')
17
18
 
18
19
  const ALLOW = 'ALLOW'
19
20
 
21
+ // Tags from the service entry span that must be mirrored onto every AI Guard span
22
+ // so anomaly detection pipelines can process each span independently.
23
+ const SERVICE_ENTRY_TAG_MAPPINGS = [
24
+ [HTTP_USERAGENT, TAGS.HTTP_USERAGENT_TAG_KEY],
25
+ [HTTP_CLIENT_IP, TAGS.HTTP_CLIENT_IP_TAG_KEY],
26
+ [NETWORK_CLIENT_IP, TAGS.NETWORK_CLIENT_IP_TAG_KEY],
27
+ [USER_ID, TAGS.USR_ID_TAG_KEY],
28
+ [USER_SESSION_ID, TAGS.USR_SESSION_ID_TAG_KEY],
29
+ ]
30
+
20
31
  /**
21
32
  * Reports a telemetry error
22
33
  *
@@ -181,13 +192,32 @@ class AIGuard extends NoopAIGuard {
181
192
  }
182
193
  }
183
194
 
195
+ /**
196
+ * Copies service entry span tags needed by anomaly detection to the AI Guard span.
197
+ *
198
+ * @param {import('../opentracing/span')} guardSpan
199
+ * @param {import('../opentracing/span')} rootSpan
200
+ */
201
+ #copyServiceEntryTagsToGuardSpan (guardSpan, rootSpan) {
202
+ const rootTags = rootSpan.context().getTags()
203
+ for (const [sourceTag, destTag] of SERVICE_ENTRY_TAG_MAPPINGS) {
204
+ const value = rootTags[sourceTag]
205
+ if (value !== undefined && value !== null) {
206
+ guardSpan.setTag(destTag, value)
207
+ }
208
+ }
209
+ }
210
+
184
211
  evaluate (messages, opts) {
185
212
  if (!this.#initialized) {
186
213
  return super.evaluate(messages, opts)
187
214
  }
188
- const { block = true, source = TAGS.SOURCE_SDK, integration = TAGS.INTEGRATION_NONE } = opts ?? {}
215
+ const { block = true, source = TAGS.SOURCE_SDK, integration = TAGS.INTEGRATION_NONE, childOf } = opts ?? {}
189
216
  const telemetryTags = { source, integration }
190
- return this.#tracer.trace(TAGS.RESOURCE, {}, async (span) => {
217
+ // Only pass `childOf` when truthy so `tracer.trace`'s default (`scope().active()`)
218
+ // still applies for SDK callers that don't supply an explicit parent.
219
+ const traceOpts = childOf ? { childOf } : {}
220
+ return this.#tracer.trace(TAGS.RESOURCE, traceOpts, async (span) => {
191
221
  const last = messages[messages.length - 1]
192
222
  const target = this.#isToolCall(last) ? 'tool' : 'prompt'
193
223
  span.setTag(TAGS.TARGET_TAG_KEY, target)
@@ -206,6 +236,7 @@ class AIGuard extends NoopAIGuard {
206
236
  const rootSpan = span.context()?._trace?.started?.[0]
207
237
  if (rootSpan) {
208
238
  this.#setRootSpanClientIpTags(rootSpan)
239
+ this.#copyServiceEntryTagsToGuardSpan(span, rootSpan)
209
240
  // keepTrace must be called before executeRequest so the sampling decision
210
241
  // is propagated correctly to outgoing HTTP client calls.
211
242
  keepTrace(rootSpan, AI_GUARD)
@@ -10,6 +10,12 @@ module.exports = {
10
10
  EVENT_TAG_KEY: 'ai_guard.event',
11
11
  META_STRUCT_KEY: 'ai_guard',
12
12
 
13
+ HTTP_USERAGENT_TAG_KEY: 'ai_guard.http.useragent',
14
+ HTTP_CLIENT_IP_TAG_KEY: 'ai_guard.http.client_ip',
15
+ NETWORK_CLIENT_IP_TAG_KEY: 'ai_guard.network.client.ip',
16
+ USR_ID_TAG_KEY: 'ai_guard.usr.id',
17
+ USR_SESSION_ID_TAG_KEY: 'ai_guard.usr.session_id',
18
+
13
19
  TELEMETRY_REQUESTS: 'requests',
14
20
  TELEMETRY_TRUNCATED: 'truncated',
15
21
  TELEMETRY_ERROR: 'error',
@@ -2,6 +2,7 @@
2
2
 
3
3
  const web = require('../plugins/util/web')
4
4
  const log = require('../log')
5
+ const { isEmpty } = require('../util')
5
6
  const {
6
7
  HTTP_OUTGOING_METHOD,
7
8
  HTTP_OUTGOING_HEADERS,
@@ -137,7 +138,7 @@ function extractRequestData (ctx) {
137
138
  addresses[HTTP_OUTGOING_METHOD] = getMethod(options.method)
138
139
 
139
140
  const headers = options?.headers
140
- if (headers && Object.keys(headers).length > 0) {
141
+ if (headers && !isEmpty(headers)) {
141
142
  addresses[HTTP_OUTGOING_HEADERS] = lowercaseHeaderKeys(headers)
142
143
  }
143
144
 
@@ -177,7 +178,7 @@ function extractResponseData (res, responseBody) {
177
178
  }
178
179
 
179
180
  const headers = res.headers
180
- if (headers && Object.keys(headers).length > 0) {
181
+ if (headers && !isEmpty(headers)) {
181
182
  addresses[HTTP_OUTGOING_RESPONSE_HEADERS] = headers
182
183
  }
183
184
 
@@ -3,6 +3,7 @@
3
3
  const dc = require('dc-polyfill')
4
4
  const web = require('../../plugins/util/web')
5
5
  const { storage } = require('../../../../datadog-core')
6
+ const { isEmpty } = require('../../util')
6
7
  const { enable: enableFsPlugin, disable: disableFsPlugin, IAST_MODULE } = require('../rasp/fs-plugin')
7
8
  const { incomingHttpRequestStart, incomingHttpRequestEnd, responseWriteHead } = require('../channels')
8
9
  const vulnerabilityReporter = require('./vulnerability-reporter')
@@ -96,7 +97,7 @@ function onIncomingHttpRequestEnd (data) {
96
97
 
97
98
  iastResponseEnd.publish({ ...data, storedHeaders })
98
99
 
99
- if (Object.keys(storedHeaders).length) {
100
+ if (!isEmpty(storedHeaders)) {
100
101
  collectedResponseHeaders.delete(data.res)
101
102
  }
102
103
 
@@ -118,7 +119,7 @@ function onIncomingHttpRequestEnd (data) {
118
119
  function onResponseWriteHeadCollect ({ res, responseHeaders = {} }) {
119
120
  if (!res) return
120
121
 
121
- if (Object.keys(responseHeaders).length) {
122
+ if (!isEmpty(responseHeaders)) {
122
123
  collectedResponseHeaders.set(res, responseHeaders)
123
124
  }
124
125
  }
@@ -9,6 +9,7 @@ const addresses = require('../addresses')
9
9
  const web = require('../../plugins/util/web')
10
10
  const { getActiveRequest } = require('../store')
11
11
  const waf = require('../waf')
12
+ const { isEmpty } = require('../../util')
12
13
  const downstream = require('../downstream_requests')
13
14
  const { updateRaspRuleMatchMetricTags } = require('../telemetry')
14
15
  const { RULE_TYPES, handleResult } = require('./utils')
@@ -85,7 +86,7 @@ function handleResponseFinish ({ ctx, res, body }) {
85
86
  function runResponseEvaluation (res, req, responseBody) {
86
87
  const responseAddresses = downstream.extractResponseData(res, responseBody)
87
88
 
88
- if (!Object.keys(responseAddresses).length) return
89
+ if (isEmpty(responseAddresses)) return
89
90
 
90
91
  const raspRule = { type: RULE_TYPES.SSRF, variant: 'response' }
91
92
  const result = waf.run({ ephemeral: responseAddresses }, req, raspRule)
@@ -461,7 +461,7 @@ function truncateRequestBody (target, depth = 0) {
461
461
  }
462
462
 
463
463
  function reportRequestBody (rootSpan, requestBody, comesFromRaspAction = false) {
464
- if (!requestBody || Object.keys(requestBody).length === 0) return
464
+ if (!requestBody || isEmpty(requestBody)) return
465
465
 
466
466
  if (!rootSpan.meta_struct) {
467
467
  rootSpan.meta_struct = {}
@@ -9,7 +9,7 @@ const CoverageWriter = require('./coverage-writer')
9
9
  class AgentlessCiVisibilityExporter extends CiVisibilityExporter {
10
10
  constructor (config) {
11
11
  super(config)
12
- const { tags, site, url, isTestDynamicInstrumentationEnabled } = config
12
+ const { tags, site, DD_CIVISIBILITY_AGENTLESS_URL: url, isTestDynamicInstrumentationEnabled } = config
13
13
  // we don't need to request /info because we are using agentless by configuration
14
14
  this._isInitialized = true
15
15
  this._resolveCanUseCiVisProtocol(true)
@@ -72,6 +72,12 @@ for (const [name, value] of Object.entries(defaults)) {
72
72
  function generateTelemetry (value = null, origin, optionName) {
73
73
  const tableEntry = configurationsTable[optionName]
74
74
  const { type, canonicalName = optionName } = tableEntry ?? { type: typeof value }
75
+ // Sensitive configurations are excluded from configuration telemetry: their
76
+ // entry is never added to `configWithOrigin`, the single source for every
77
+ // telemetry path (app-started and app-client-configuration-change).
78
+ if (sensitiveConfigurations.has(canonicalName)) {
79
+ return
80
+ }
75
81
  // TODO: Should we not send defaults to telemetry to reduce size?
76
82
  // TODO: How to handle aliases/actual names in the future? Optional fields? Normalize the name at intake?
77
83
  // TODO: Validate that space separated tags are parsed by the backend. Optimizations would be possible with that.
@@ -196,6 +202,11 @@ const fallbackConfigurations = new Map()
196
202
 
197
203
  const regExps = {}
198
204
 
205
+ // Canonical names of configurations whose value is excluded from configuration
206
+ // telemetry. Driven by the `sensitive: true` attribute in
207
+ // `supported-configurations.json` so new entries opt in without code changes.
208
+ const sensitiveConfigurations = new Set()
209
+
199
210
  for (const [canonicalName, entries] of Object.entries(supportedConfigurations)) {
200
211
  if (entries.length !== 1) {
201
212
  // TODO: Determine if we really want to support multiple entries for a canonical name.
@@ -207,6 +218,9 @@ for (const [canonicalName, entries] of Object.entries(supportedConfigurations))
207
218
  )
208
219
  }
209
220
  for (const entry of entries) {
221
+ if (entry.sensitive) {
222
+ sensitiveConfigurations.add(canonicalName)
223
+ }
210
224
  const configurationNames = entry.internalPropertyName ? [entry.internalPropertyName] : entry.configurationNames
211
225
  const fullPropertyName = configurationNames?.[0] ?? canonicalName
212
226
  const type = entry.type.toUpperCase()
@@ -73,7 +73,7 @@ export interface GeneratedConfig {
73
73
  DD_APP_KEY: string | undefined;
74
74
  DD_AZURE_RESOURCE_GROUP: string | undefined;
75
75
  DD_CIVISIBILITY_AGENTLESS_ENABLED: boolean;
76
- DD_CIVISIBILITY_AGENTLESS_URL: string | undefined;
76
+ DD_CIVISIBILITY_AGENTLESS_URL: URL | undefined;
77
77
  DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER: string | undefined;
78
78
  DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE: boolean;
79
79
  DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING: boolean;
@@ -130,6 +130,7 @@ export interface GeneratedConfig {
130
130
  DD_MINI_AGENT_PATH: string | undefined;
131
131
  DD_PIPELINE_EXECUTION_ID: string | undefined;
132
132
  DD_PLAYWRIGHT_WORKER: string | undefined;
133
+ DD_PROFILING_ALLOCATION_ENABLED: boolean;
133
134
  DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED: boolean;
134
135
  DD_PROFILING_CODEHOTSPOTS_ENABLED: boolean;
135
136
  DD_PROFILING_CPU_ENABLED: boolean;
@@ -13,6 +13,7 @@
13
13
  * @property {string} [transform]
14
14
  * @property {string} [allowed]
15
15
  * @property {string|boolean} [deprecated]
16
+ * @property {boolean} [sensitive] Excludes the configuration value from configuration telemetry.
16
17
  */
17
18
 
18
19
  /**
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require('node:fs')
4
4
  const os = require('node:os')
5
- const { URL } = require('node:url')
5
+ const { URL, format } = require('node:url')
6
6
 
7
7
  const rfdc = require('../../../../vendor/dist/rfdc')({ proto: false, circles: false })
8
8
  const uuid = require('../../../../vendor/dist/crypto-randomuuid') // we need to keep the old uuid dep because of cypress
@@ -322,18 +322,14 @@ class Config extends ConfigBase {
322
322
  #applyCalculated () {
323
323
  undo(this, 'calculated')
324
324
 
325
- if (this.DD_CIVISIBILITY_AGENTLESS_URL ||
326
- this.url ||
325
+ if (this.url ||
327
326
  os.type() !== 'Windows_NT' &&
328
327
  !trackedConfigOrigins.has('hostname') &&
329
328
  !trackedConfigOrigins.has('port') &&
330
- !this.DD_CIVISIBILITY_AGENTLESS_ENABLED &&
331
329
  fs.existsSync('/var/run/datadog/apm.socket')) {
332
- setAndTrack(
333
- this,
334
- 'url',
335
- new URL(this.DD_CIVISIBILITY_AGENTLESS_URL || this.url || 'unix:///var/run/datadog/apm.socket')
336
- )
330
+ setAndTrack(this, 'url', new URL(this.url || 'unix:///var/run/datadog/apm.socket'))
331
+ } else {
332
+ setAndTrack(this, 'url', new URL(format({ protocol: 'http:', hostname: this.hostname, port: this.port })))
337
333
  }
338
334
 
339
335
  if (this.isCiVisibility) {
@@ -145,6 +145,14 @@ const transformers = {
145
145
  }
146
146
  return value.replaceAll(/\s*:\s*/g, ':')
147
147
  },
148
+ /**
149
+ * @param {string} value
150
+ */
151
+ toURL (value) {
152
+ try {
153
+ return new URL(value)
154
+ } catch {}
155
+ },
148
156
  validatePropagationStyles (value, optionName) {
149
157
  value = transformers.toLowerCase(value)
150
158
  for (let index = 0; index < value.length; index++) {
@@ -111,7 +111,8 @@
111
111
  "aliases": [
112
112
  "DATADOG_API_KEY"
113
113
  ],
114
- "internalPropertyName": "apiKey"
114
+ "internalPropertyName": "apiKey",
115
+ "sensitive": true
115
116
  }
116
117
  ],
117
118
  "DD_API_SECURITY_ENABLED": [
@@ -423,7 +424,8 @@
423
424
  {
424
425
  "implementation": "A",
425
426
  "type": "string",
426
- "default": null
427
+ "default": null,
428
+ "sensitive": true
427
429
  }
428
430
  ],
429
431
  "DD_AZURE_RESOURCE_GROUP": [
@@ -444,6 +446,7 @@
444
446
  {
445
447
  "implementation": "A",
446
448
  "type": "string",
449
+ "transform": "toURL",
447
450
  "default": null
448
451
  }
449
452
  ],
@@ -1305,6 +1308,13 @@
1305
1308
  "default": null
1306
1309
  }
1307
1310
  ],
1311
+ "DD_PROFILING_ALLOCATION_ENABLED": [
1312
+ {
1313
+ "implementation": "A",
1314
+ "type": "boolean",
1315
+ "default": "false"
1316
+ }
1317
+ ],
1308
1318
  "DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED": [
1309
1319
  {
1310
1320
  "implementation": "A",
@@ -3913,7 +3923,8 @@
3913
3923
  {
3914
3924
  "implementation": "B",
3915
3925
  "type": "map",
3916
- "default": null
3926
+ "default": null,
3927
+ "sensitive": true
3917
3928
  }
3918
3929
  ],
3919
3930
  "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": [
@@ -3930,7 +3941,8 @@
3930
3941
  "default": null,
3931
3942
  "aliases": [
3932
3943
  "OTEL_EXPORTER_OTLP_HEADERS"
3933
- ]
3944
+ ],
3945
+ "sensitive": true
3934
3946
  }
3935
3947
  ],
3936
3948
  "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL": [
@@ -3968,7 +3980,8 @@
3968
3980
  "default": null,
3969
3981
  "aliases": [
3970
3982
  "OTEL_EXPORTER_OTLP_HEADERS"
3971
- ]
3983
+ ],
3984
+ "sensitive": true
3972
3985
  }
3973
3986
  ],
3974
3987
  "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL": [
@@ -4006,7 +4019,8 @@
4006
4019
  "default": null,
4007
4020
  "aliases": [
4008
4021
  "OTEL_EXPORTER_OTLP_HEADERS"
4009
- ]
4022
+ ],
4023
+ "sensitive": true
4010
4024
  }
4011
4025
  ],
4012
4026
  "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": [
@@ -7,7 +7,6 @@ const libdatadog = require('@datadog/libdatadog')
7
7
  const binding = libdatadog.load('crashtracker')
8
8
 
9
9
  const log = require('../log')
10
- const { getAgentUrl } = require('../agent/url')
11
10
  const pkg = require('../../../../package.json')
12
11
  const processTags = require('../process-tags')
13
12
 
@@ -68,7 +67,7 @@ class Crashtracker {
68
67
  * @param {import('../config/config-base')} config - Tracer configuration
69
68
  */
70
69
  #getConfig (config) {
71
- const url = getAgentUrl(config)
70
+ const url = config.url
72
71
 
73
72
  // Out-of-process symbolication currently works on
74
73
  // Linux only, does not work on Mac.
@@ -78,6 +77,7 @@ class Crashtracker {
78
77
 
79
78
  return {
80
79
  additional_files: [],
80
+ collect_all_threads: true,
81
81
  create_alt_stack: true,
82
82
  use_alt_stack: true,
83
83
  endpoint: {
@@ -5,7 +5,6 @@ const pkg = require('../../../../package.json')
5
5
  const log = require('../log')
6
6
  const request = require('../exporters/common/request')
7
7
  const { encode: encodeMsgpack } = require('../msgpack')
8
- const { getAgentUrl } = require('../agent/url')
9
8
 
10
9
  function makeRequest (data, url, cb) {
11
10
  const options = {
@@ -29,7 +28,7 @@ function makeRequest (data, url, cb) {
29
28
 
30
29
  class DataStreamsWriter {
31
30
  constructor (config) {
32
- this._url = getAgentUrl(config)
31
+ this._url = config.url
33
32
  }
34
33
 
35
34
  flush (payload) {
@@ -16,7 +16,7 @@ module.exports = function getDebuggerConfig (config, inputPath) {
16
16
  repositoryUrl,
17
17
  runtimeId: config.tags['runtime-id'],
18
18
  service: config.service,
19
- url: config.url?.toString(),
19
+ url: config.url.toString(),
20
20
  version: config.version,
21
21
  inputPath,
22
22
  }
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
3
  const { workerData: { config: parentConfig, parentThreadId, configPort } } = require('node:worker_threads')
4
- const { getAgentUrl } = require('../../agent/url')
5
4
  const processTags = require('../../process-tags')
6
5
  const log = require('./log')
7
6
 
@@ -21,6 +20,8 @@ configPort.on('messageerror', (err) =>
21
20
  )
22
21
 
23
22
  function updateConfig (updates) {
24
- config.url = getAgentUrl(updates)
23
+ // The worker receives a serialized config (see ../config.js) where `url` is a string, so it is
24
+ // reconstructed into a URL here rather than read directly off a Config instance.
25
+ config.url = new URL(updates.url)
25
26
  config.dynamicInstrumentation.captureTimeoutNs = BigInt(updates.dynamicInstrumentation.captureTimeoutMs) * 1_000_000n
26
27
  }
@@ -6,7 +6,6 @@ const { join } = require('path')
6
6
  const { Worker, MessageChannel, threadId: parentThreadId } = require('worker_threads')
7
7
  const log = require('../log')
8
8
  const { fetchAgentInfo } = require('../agent/info')
9
- const { getAgentUrl } = require('../agent/url')
10
9
  const getDebuggerConfig = require('./config')
11
10
  const { DEBUGGER_DIAGNOSTICS_V1, DEBUGGER_INPUT_V2 } = require('./constants')
12
11
 
@@ -211,7 +210,7 @@ function cleanup (error) {
211
210
  function detectDebuggerEndpoint (config, cb) {
212
211
  log.debug('[debugger] Detecting available debugger endpoints...')
213
212
 
214
- fetchAgentInfo(getAgentUrl(config), (err, agentInfo) => {
213
+ fetchAgentInfo(config.url, (err, agentInfo) => {
215
214
  if (err) {
216
215
  log.warn('[debugger] Failed to query agent %s endpoint, falling back to %s',
217
216
  DEBUGGER_INPUT_V2,
@@ -6,7 +6,6 @@ const isIP = require('net').isIP
6
6
  const request = require('./exporters/common/request')
7
7
  const log = require('./log')
8
8
  const Histogram = require('./histogram')
9
- const { getAgentUrl } = require('./agent/url')
10
9
  const { entityId } = require('./exporters/common/docker')
11
10
 
12
11
  const MAX_BUFFER_SIZE = 1024 // limit from the agent
@@ -191,8 +190,8 @@ class DogStatsDClient {
191
190
  lookup: config.lookup,
192
191
  }
193
192
 
194
- if (config.url || config.port) {
195
- clientConfig.metricsProxyUrl = getAgentUrl(config)
193
+ if (config.url) {
194
+ clientConfig.metricsProxyUrl = config.url
196
195
  }
197
196
 
198
197
  return clientConfig