dd-trace 5.96.0 → 5.98.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 (173) hide show
  1. package/index.d.ts +60 -2
  2. package/package.json +9 -7
  3. package/packages/datadog-esbuild/index.js +20 -9
  4. package/packages/datadog-instrumentations/src/child_process.js +7 -17
  5. package/packages/datadog-instrumentations/src/crypto.js +1 -2
  6. package/packages/datadog-instrumentations/src/cucumber.js +69 -4
  7. package/packages/datadog-instrumentations/src/cypress-config.js +318 -0
  8. package/packages/datadog-instrumentations/src/cypress.js +86 -4
  9. package/packages/datadog-instrumentations/src/dns.js +1 -2
  10. package/packages/datadog-instrumentations/src/express.js +4 -4
  11. package/packages/datadog-instrumentations/src/fs.js +27 -29
  12. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  13. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +41 -13
  14. package/packages/datadog-instrumentations/src/helpers/hook.js +31 -6
  15. package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -19
  16. package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -13
  17. package/packages/datadog-instrumentations/src/helpers/register.js +103 -142
  18. package/packages/datadog-instrumentations/src/http/client.js +2 -3
  19. package/packages/datadog-instrumentations/src/http/server.js +2 -5
  20. package/packages/datadog-instrumentations/src/http2/client.js +1 -3
  21. package/packages/datadog-instrumentations/src/http2/server.js +1 -3
  22. package/packages/datadog-instrumentations/src/jest.js +117 -16
  23. package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
  24. package/packages/datadog-instrumentations/src/mocha/utils.js +12 -1
  25. package/packages/datadog-instrumentations/src/net.js +2 -8
  26. package/packages/datadog-instrumentations/src/pino.js +1 -1
  27. package/packages/datadog-instrumentations/src/playwright.js +4 -1
  28. package/packages/datadog-instrumentations/src/prisma.js +1 -2
  29. package/packages/datadog-instrumentations/src/redis.js +12 -6
  30. package/packages/datadog-instrumentations/src/selenium.js +4 -1
  31. package/packages/datadog-instrumentations/src/sequelize.js +1 -1
  32. package/packages/datadog-instrumentations/src/url.js +1 -3
  33. package/packages/datadog-instrumentations/src/vitest.js +5 -1
  34. package/packages/datadog-instrumentations/src/vm.js +1 -3
  35. package/packages/datadog-plugin-aws-sdk/src/base.js +5 -4
  36. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
  37. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
  38. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
  39. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -0
  40. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
  41. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
  42. package/packages/datadog-plugin-cucumber/src/index.js +13 -3
  43. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +166 -6
  44. package/packages/datadog-plugin-cypress/src/index.js +59 -2
  45. package/packages/datadog-plugin-fs/src/index.js +1 -1
  46. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
  47. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -7
  48. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  49. package/packages/datadog-plugin-http/src/client.js +1 -1
  50. package/packages/datadog-plugin-http/src/server.js +10 -2
  51. package/packages/datadog-plugin-http2/src/client.js +1 -1
  52. package/packages/datadog-plugin-http2/src/server.js +10 -2
  53. package/packages/datadog-plugin-jest/src/index.js +4 -2
  54. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +31 -4
  55. package/packages/datadog-plugin-mocha/src/index.js +5 -2
  56. package/packages/datadog-plugin-mongodb-core/src/index.js +3 -3
  57. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  58. package/packages/datadog-plugin-next/src/index.js +10 -16
  59. package/packages/datadog-plugin-openai/src/services.js +1 -0
  60. package/packages/datadog-plugin-pg/src/index.js +1 -1
  61. package/packages/datadog-plugin-tedious/src/index.js +1 -1
  62. package/packages/datadog-plugin-ws/src/close.js +1 -1
  63. package/packages/datadog-plugin-ws/src/receiver.js +1 -1
  64. package/packages/datadog-webpack/index.js +3 -3
  65. package/packages/dd-trace/index.js +12 -10
  66. package/packages/dd-trace/src/agent/url.js +2 -2
  67. package/packages/dd-trace/src/aiguard/sdk.js +26 -22
  68. package/packages/dd-trace/src/appsec/blocked_templates.js +4 -3
  69. package/packages/dd-trace/src/appsec/blocking.js +64 -33
  70. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
  71. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
  72. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
  73. package/packages/dd-trace/src/appsec/remote_config.js +1 -0
  74. package/packages/dd-trace/src/appsec/sdk/index.js +4 -0
  75. package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
  76. package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -5
  77. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
  78. package/packages/dd-trace/src/appsec/sdk/utils.js +4 -2
  79. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +6 -1
  80. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
  81. package/packages/dd-trace/src/config/defaults.js +315 -146
  82. package/packages/dd-trace/src/config/generated-config-types.d.ts +9 -1
  83. package/packages/dd-trace/src/config/helper.js +59 -10
  84. package/packages/dd-trace/src/config/index.js +587 -1496
  85. package/packages/dd-trace/src/config/parsers.js +256 -0
  86. package/packages/dd-trace/src/config/remote_config.js +59 -2
  87. package/packages/dd-trace/src/config/supported-configurations.json +406 -432
  88. package/packages/dd-trace/src/constants.js +1 -0
  89. package/packages/dd-trace/src/crashtracking/crashtracker.js +7 -1
  90. package/packages/dd-trace/src/crashtracking/index.js +1 -7
  91. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +5 -2
  92. package/packages/dd-trace/src/debugger/index.js +1 -1
  93. package/packages/dd-trace/src/dogstatsd.js +12 -9
  94. package/packages/dd-trace/src/encode/0.4.js +8 -7
  95. package/packages/dd-trace/src/encode/span-stats.js +4 -1
  96. package/packages/dd-trace/src/exporters/agent/writer.js +7 -1
  97. package/packages/dd-trace/src/exporters/common/request.js +9 -0
  98. package/packages/dd-trace/src/exporters/common/writer.js +12 -2
  99. package/packages/dd-trace/src/heap_snapshots.js +3 -0
  100. package/packages/dd-trace/src/index.js +5 -2
  101. package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -6
  102. package/packages/dd-trace/src/llmobs/index.js +4 -1
  103. package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -1
  104. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +60 -12
  105. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +4 -2
  106. package/packages/dd-trace/src/llmobs/sdk.js +12 -8
  107. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  108. package/packages/dd-trace/src/llmobs/tagger.js +9 -6
  109. package/packages/dd-trace/src/llmobs/writers/base.js +2 -0
  110. package/packages/dd-trace/src/llmobs/writers/util.js +3 -0
  111. package/packages/dd-trace/src/log/index.js +20 -59
  112. package/packages/dd-trace/src/log/writer.js +7 -19
  113. package/packages/dd-trace/src/noop/proxy.js +8 -0
  114. package/packages/dd-trace/src/openfeature/remote_config.js +6 -1
  115. package/packages/dd-trace/src/opentelemetry/context_manager.js +6 -4
  116. package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
  117. package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
  118. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +17 -2
  119. package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +14 -2
  120. package/packages/dd-trace/src/opentelemetry/otlp/trace.proto +358 -0
  121. package/packages/dd-trace/src/opentelemetry/otlp/trace_service.proto +78 -0
  122. package/packages/dd-trace/src/opentelemetry/trace/index.js +75 -0
  123. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +66 -0
  124. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +332 -0
  125. package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
  126. package/packages/dd-trace/src/opentracing/tracer.js +9 -4
  127. package/packages/dd-trace/src/payload-tagging/config/index.js +6 -5
  128. package/packages/dd-trace/src/plugin_manager.js +8 -6
  129. package/packages/dd-trace/src/plugins/ci_plugin.js +4 -0
  130. package/packages/dd-trace/src/plugins/log_plugin.js +3 -0
  131. package/packages/dd-trace/src/plugins/plugin.js +11 -13
  132. package/packages/dd-trace/src/plugins/storage.js +2 -2
  133. package/packages/dd-trace/src/plugins/tracing.js +22 -5
  134. package/packages/dd-trace/src/plugins/util/test.js +2 -0
  135. package/packages/dd-trace/src/plugins/util/web.js +6 -88
  136. package/packages/dd-trace/src/process-tags/index.js +3 -0
  137. package/packages/dd-trace/src/profiler.js +27 -2
  138. package/packages/dd-trace/src/profiling/config.js +73 -241
  139. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -4
  140. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +6 -2
  141. package/packages/dd-trace/src/profiling/profiler.js +78 -109
  142. package/packages/dd-trace/src/profiling/profilers/events.js +2 -3
  143. package/packages/dd-trace/src/profiling/profilers/wall.js +89 -6
  144. package/packages/dd-trace/src/profiling/ssi-heuristics.js +4 -1
  145. package/packages/dd-trace/src/propagation-hash/index.js +2 -1
  146. package/packages/dd-trace/src/proxy.js +40 -6
  147. package/packages/dd-trace/src/remote_config/index.js +3 -0
  148. package/packages/dd-trace/src/require-package-json.js +8 -4
  149. package/packages/dd-trace/src/ritm.js +58 -26
  150. package/packages/dd-trace/src/runtime_metrics/index.js +3 -0
  151. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +18 -11
  152. package/packages/dd-trace/src/sampler.js +1 -1
  153. package/packages/dd-trace/src/service-naming/index.js +1 -1
  154. package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -1
  155. package/packages/dd-trace/src/service-naming/schemas/util.js +15 -1
  156. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +24 -1
  157. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +60 -0
  158. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +17 -1
  159. package/packages/dd-trace/src/service-naming/schemas/v0/websocket.js +5 -0
  160. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +17 -0
  161. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +11 -1
  162. package/packages/dd-trace/src/service-naming/schemas/v1/websocket.js +6 -0
  163. package/packages/dd-trace/src/span_stats.js +5 -1
  164. package/packages/dd-trace/src/standalone/index.js +3 -0
  165. package/packages/dd-trace/src/telemetry/index.js +2 -3
  166. package/packages/dd-trace/src/telemetry/send-data.js +5 -19
  167. package/packages/dd-trace/src/telemetry/session-propagation.js +19 -44
  168. package/packages/dd-trace/src/telemetry/telemetry.js +28 -171
  169. package/packages/dd-trace/src/tracer.js +2 -2
  170. package/packages/dd-trace/src/util.js +0 -9
  171. package/vendor/dist/@apm-js-collab/code-transformer/index.js +28 -6
  172. package/vendor/dist/protobufjs/index.js +1 -1
  173. package/packages/dd-trace/src/log/utils.js +0 -16
@@ -7,8 +7,9 @@ const log = require('../../log')
7
7
  const tags = require('../../../../../ext/tags')
8
8
  const types = require('../../../../../ext/types')
9
9
  const kinds = require('../../../../../ext/kinds')
10
- const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../constants')
10
+ const { ERROR_MESSAGE } = require('../../constants')
11
11
  const TracingPlugin = require('../tracing')
12
+ const { storage } = require('../../../../datadog-core')
12
13
  const urlFilter = require('./urlfilter')
13
14
  const { createInferredProxySpan, finishInferredProxySpan } = require('./inferred_proxy')
14
15
  const { extractURL, obfuscateQs, calculateHttpEndpoint } = require('./url')
@@ -125,33 +126,13 @@ const web = {
125
126
  context.tracer = tracer
126
127
  context.span = span
127
128
  context.res = res
129
+ context.store = storage('legacy').getStore()
128
130
 
129
131
  this.setConfig(req, config)
130
132
  addRequestTags(context, this.TYPE)
131
133
 
132
134
  return span
133
135
  },
134
- wrap (req) {
135
- const context = contexts.get(req)
136
- if (!context.instrumented) {
137
- this.wrapEnd(context)
138
- context.instrumented = true
139
- }
140
- },
141
- // Start a span and activate a scope for a request.
142
- instrument (tracer, config, req, res, name, callback) {
143
- const span = this.startSpan(tracer, config, req, res, name)
144
-
145
- this.wrap(req)
146
-
147
- return callback && tracer.scope().activate(span, () => callback(span))
148
- },
149
-
150
- // Reactivate the request scope in case it was changed by a middleware.
151
- reactivate (req, fn) {
152
- return reactivate(req, fn)
153
- },
154
-
155
136
  // Add a route segment that will be used for the resource name.
156
137
  enterRoute (req, path) {
157
138
  if (typeof path === 'string') {
@@ -172,61 +153,6 @@ const web = {
172
153
  contexts.get(req).paths.pop()
173
154
  },
174
155
 
175
- // Start a new middleware span and activate a new scope with the span.
176
- wrapMiddleware (req, middleware, name, fn) {
177
- if (!this.active(req)) return fn()
178
-
179
- const context = contexts.get(req)
180
- const tracer = context.tracer
181
- const childOf = this.active(req)
182
- const config = context.config
183
- const traceCtx = context.traceCtx
184
-
185
- if (config.middleware === false) return this.bindAndWrapMiddlewareErrors(fn, req, tracer, childOf)
186
-
187
- const span = startSpanHelper(tracer, name, { childOf }, traceCtx, config)
188
-
189
- analyticsSampler.sample(span, config.measured)
190
-
191
- span.addTags({
192
- [RESOURCE_NAME]: middleware._name || middleware.name || '<anonymous>',
193
- })
194
-
195
- context.middleware.push(span)
196
-
197
- return tracer.scope().activate(span, fn)
198
- },
199
-
200
- // catch errors and apply to active span
201
- bindAndWrapMiddlewareErrors (fn, req, tracer, activeSpan) {
202
- try {
203
- return tracer.scope().bind(fn, activeSpan).apply(this, arguments)
204
- } catch (e) {
205
- web.addError(req, e) // TODO: remove when error formatting is moved to Span
206
- throw e
207
- }
208
- },
209
-
210
- // Finish the active middleware span.
211
- finish (req, error) {
212
- if (!this.active(req)) return
213
-
214
- const context = contexts.get(req)
215
- const span = context.middleware.pop()
216
-
217
- if (span) {
218
- if (error) {
219
- span.addTags({
220
- [ERROR_TYPE]: error.name,
221
- [ERROR_MESSAGE]: error.message,
222
- [ERROR_STACK]: error.stack,
223
- })
224
- }
225
-
226
- span.finish()
227
- }
228
- },
229
-
230
156
  // Register a callback to run before res.end() is called.
231
157
  beforeEnd (req, callback) {
232
158
  contexts.get(req).beforeEnd.push(callback)
@@ -278,7 +204,6 @@ const web = {
278
204
  startServerlessSpanWithInferredProxy (tracer, config, name, req, traceCtx) {
279
205
  const headers = req.headers
280
206
  const reqCtx = contexts.get(req)
281
- const { storage } = require('../../../../datadog-core')
282
207
  const store = storage('legacy').getStore()
283
208
  const pubsubSpan = store?.span?._name === 'pubsub.push.receive' ? store.span : null
284
209
 
@@ -391,7 +316,6 @@ const web = {
391
316
  }
392
317
  },
393
318
  wrapEnd (context) {
394
- const scope = context.tracer.scope()
395
319
  const req = context.req
396
320
  const res = context.res
397
321
  const end = res.end
@@ -406,7 +330,9 @@ const web = {
406
330
  return ends.get(this)
407
331
  },
408
332
  set (value) {
409
- ends.set(this, scope.bind(value, context.span))
333
+ ends.set(this, function () {
334
+ return storage('legacy').run(context.store, value, ...arguments)
335
+ })
410
336
  },
411
337
  })
412
338
  },
@@ -453,14 +379,6 @@ function splitHeader (str) {
453
379
  return typeof str === 'string' ? str.split(/\s*,\s*/) : []
454
380
  }
455
381
 
456
- function reactivate (req, fn) {
457
- const context = contexts.get(req)
458
-
459
- return context
460
- ? context.tracer.scope().activate(context.span, fn)
461
- : fn()
462
- }
463
-
464
382
  function addRequestTags (context, spanType) {
465
383
  const { req, span, inferredProxySpan, config } = context
466
384
  const url = extractURL(req)
@@ -72,6 +72,9 @@ function buildProcessTags (config) {
72
72
 
73
73
  // Singleton with constant defaults so pre-init reads don't blow up
74
74
  const processTags = module.exports = {
75
+ /**
76
+ * @param {import('../config/config-base')} config
77
+ */
75
78
  initialize (config) {
76
79
  // check if one of the properties added during build exist and if so return
77
80
  if (processTags.tags) return
@@ -5,13 +5,38 @@ const { profiler } = require('./profiling')
5
5
  globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(() => { profiler.stop() })
6
6
 
7
7
  module.exports = {
8
- start: config => {
8
+ /**
9
+ * @param {import('./config/config-base')} config - Tracer configuration
10
+ */
11
+ start (config) {
9
12
  // Forward the full tracer config to the profiling layer.
10
13
  // Profiling code is responsible for deriving the specific options it needs.
11
14
  return profiler.start(config)
12
15
  },
13
16
 
14
- stop: () => {
17
+ stop () {
15
18
  profiler.stop()
16
19
  },
20
+
21
+ /**
22
+ * Declares the set of custom label keys that will be used with
23
+ * {@link runWithLabels}.
24
+ *
25
+ * @param {Iterable<string>} keys - Custom label key names
26
+ */
27
+ setCustomLabelKeys: (keys) => {
28
+ profiler.setCustomLabelKeys(keys)
29
+ },
30
+
31
+ /**
32
+ * Runs a function with custom profiling labels attached to wall profiler samples.
33
+ *
34
+ * @param {Record<string, string | number>} labels - Custom labels to attach
35
+ * @param {function(): T} fn - Function to execute with the labels
36
+ * @returns {T} The return value of fn
37
+ * @template T
38
+ */
39
+ runWithLabels: (labels, fn) => {
40
+ return profiler.runWithLabels(labels, fn)
41
+ },
17
42
  }
@@ -6,9 +6,8 @@ const { pathToFileURL } = require('url')
6
6
  const satisfies = require('../../../../vendor/dist/semifies')
7
7
  const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../plugins/util/tags')
8
8
  const { getIsAzureFunction } = require('../serverless')
9
- const { isFalse, isTrue } = require('../util')
10
9
  const { getAzureTagsFromMetadata, getAzureAppMetadata, getAzureFunctionMetadata } = require('../azure_metadata')
11
- const { getEnvironmentVariable, getValueFromEnvSources } = require('../config/helper')
10
+ const { getEnvironmentVariable } = require('../config/helper')
12
11
  const { getAgentUrl } = require('../agent/url')
13
12
  const { isACFActive } = require('../../../datadog-core/src/storage')
14
13
 
@@ -22,59 +21,22 @@ const { oomExportStrategies, snapshotKinds } = require('./constants')
22
21
  const { tagger } = require('./tagger')
23
22
 
24
23
  class Config {
25
- constructor (options = {}) {
26
- // TODO: Remove entries that were already resolved in config.
27
- // For the others, move them over to config.
24
+ constructor (options) {
28
25
  const AWS_LAMBDA_FUNCTION_NAME = getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME')
29
26
 
30
- // TODO: Move initialization of these values to packages/dd-trace/src/config/index.js, and just read from config
31
- const {
32
- DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED,
33
- DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED,
34
- DD_PROFILING_CODEHOTSPOTS_ENABLED,
35
- DD_PROFILING_CPU_ENABLED,
36
- DD_PROFILING_DEBUG_SOURCE_MAPS,
37
- DD_PROFILING_DEBUG_UPLOAD_COMPRESSION,
38
- DD_PROFILING_ENDPOINT_COLLECTION_ENABLED,
39
- DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES,
40
- DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE,
41
- DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT,
42
- DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED,
43
- DD_PROFILING_HEAP_ENABLED,
44
- DD_PROFILING_HEAP_SAMPLING_INTERVAL,
45
- DD_PROFILING_PPROF_PREFIX,
46
- DD_PROFILING_PROFILERS,
47
- DD_PROFILING_TIMELINE_ENABLED,
48
- DD_PROFILING_UPLOAD_PERIOD,
49
- DD_PROFILING_UPLOAD_TIMEOUT,
50
- DD_PROFILING_V8_PROFILER_BUG_WORKAROUND,
51
- DD_PROFILING_WALLTIME_ENABLED,
52
- DD_TAGS,
53
- } = getProfilingEnvValues()
54
-
55
- // Must be longer than one minute so pad with five seconds
56
- const flushInterval = options.interval ?? (Number(DD_PROFILING_UPLOAD_PERIOD) * 1000 || 65 * 1000)
57
- const uploadTimeout = options.uploadTimeout ?? (Number(DD_PROFILING_UPLOAD_TIMEOUT) || 60 * 1000)
58
- const pprofPrefix = options.pprofPrefix ?? DD_PROFILING_PPROF_PREFIX ?? ''
59
-
60
- // TODO: Remove the fallback. Just use the value from the config.
61
- this.service = options.service || 'node'
27
+ this.version = options.version
28
+ this.service = options.service
62
29
  this.env = options.env
63
30
  this.functionname = AWS_LAMBDA_FUNCTION_NAME
64
31
 
65
- this.version = options.version
66
- this.tags = Object.assign(
67
- tagger.parse(DD_TAGS),
68
- tagger.parse(options.tags),
69
- tagger.parse({
70
- env: options.env,
32
+ this.tags = {
33
+ ...options.tags,
34
+ ...tagger.parse({
71
35
  host: options.reportHostname ? require('os').hostname() : undefined,
72
- service: this.service,
73
- version: this.version,
74
36
  functionname: AWS_LAMBDA_FUNCTION_NAME,
75
37
  }),
76
- getAzureTagsFromMetadata(getIsAzureFunction() ? getAzureFunctionMetadata() : getAzureAppMetadata())
77
- )
38
+ ...getAzureTagsFromMetadata(getIsAzureFunction() ? getAzureFunctionMetadata() : getAzureAppMetadata()),
39
+ }
78
40
 
79
41
  // Add source code integration tags if available
80
42
  if (options.repositoryUrl && options.commitSHA) {
@@ -82,58 +44,35 @@ class Config {
82
44
  this.tags[GIT_COMMIT_SHA] = options.commitSHA
83
45
  }
84
46
 
85
- this.logger = ensureLogger(options.logger)
86
- // Profiler sampling contexts are not available on Windows, so features
87
- // depending on those (code hotspots and endpoint collection) need to default
88
- // to false on Windows.
89
- const samplingContextsAvailable = process.platform !== 'win32'
90
- function checkOptionAllowed (option, description, condition) {
91
- if (option && !condition) {
92
- // injection hardening: all of these can only happen if user explicitly
93
- // sets an environment variable to its non-default value on the platform.
94
- // In practical terms, it'd require someone explicitly turning on OOM
95
- // monitoring, code hotspots, endpoint profiling, or CPU profiling on
96
- // Windows, where it is not supported.
97
- throw new Error(`${description} not supported on ${process.platform}.`)
98
- }
99
- }
100
- function checkOptionWithSamplingContextAllowed (option, description) {
101
- checkOptionAllowed(option, description, samplingContextsAvailable)
102
- }
47
+ // Normalize from seconds to milliseconds. Default must be longer than a minute.
48
+ this.flushInterval = options.DD_PROFILING_UPLOAD_PERIOD * 1000
49
+ this.uploadTimeout = options.DD_PROFILING_UPLOAD_TIMEOUT
50
+ this.sourceMap = options.DD_PROFILING_SOURCE_MAP
51
+ this.debugSourceMaps = options.DD_PROFILING_DEBUG_SOURCE_MAPS
52
+ this.endpointCollectionEnabled = options.DD_PROFILING_ENDPOINT_COLLECTION_ENABLED
53
+ this.pprofPrefix = options.DD_PROFILING_PPROF_PREFIX
54
+ this.v8ProfilerBugWorkaroundEnabled = options.DD_PROFILING_V8_PROFILER_BUG_WORKAROUND
103
55
 
104
- this.flushInterval = flushInterval
105
- this.uploadTimeout = uploadTimeout
106
- this.sourceMap = options.sourceMap
107
- this.debugSourceMaps = isTrue(options.debugSourceMaps ?? DD_PROFILING_DEBUG_SOURCE_MAPS)
108
- this.endpointCollectionEnabled = isTrue(options.endpointCollection ??
109
- DD_PROFILING_ENDPOINT_COLLECTION_ENABLED ?? samplingContextsAvailable)
110
- checkOptionWithSamplingContextAllowed(this.endpointCollectionEnabled, 'Endpoint collection')
111
-
112
- this.pprofPrefix = pprofPrefix
113
- this.v8ProfilerBugWorkaroundEnabled = isTrue(options.v8ProfilerBugWorkaround ??
114
- DD_PROFILING_V8_PROFILER_BUG_WORKAROUND ?? true)
56
+ this.logger = ensureLogger(options.logger)
115
57
  this.url = getAgentUrl(options)
116
58
 
117
- this.libraryInjected = options.libraryInjected
118
- this.activation = options.activation
119
- this.exporters = ensureExporters(options.exporters || [
120
- new AgentExporter(this),
121
- ], this)
59
+ this.libraryInjected = !!options.DD_INJECTION_ENABLED
122
60
 
123
- // OOM monitoring does not work well on Windows, so it is disabled by default.
124
- const oomMonitoringSupported = process.platform !== 'win32'
61
+ let activation
62
+ if (options.profiling.enabled === 'auto') {
63
+ activation = 'auto'
64
+ } else if (options.profiling.enabled === 'true') {
65
+ activation = 'manual'
66
+ } // else activation = undefined
125
67
 
126
- const oomMonitoringEnabled = isTrue(options.oomMonitoring ??
127
- DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED ?? oomMonitoringSupported)
128
- checkOptionAllowed(oomMonitoringEnabled, 'OOM monitoring', oomMonitoringSupported)
68
+ this.activation = activation
69
+ this.exporters = ensureExporters(options.DD_PROFILING_EXPORTERS, this)
129
70
 
130
- const heapLimitExtensionSize = options.oomHeapLimitExtensionSize ??
131
- (Number(DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE) || 0)
132
- const maxHeapExtensionCount = options.oomMaxHeapExtensionCount ??
133
- (Number(DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT) || 0)
71
+ const oomMonitoringEnabled = options.DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED
72
+ const heapLimitExtensionSize = options.DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE
73
+ const maxHeapExtensionCount = options.DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT
134
74
  const exportStrategies = oomMonitoringEnabled
135
- ? ensureOOMExportStrategies(options.oomExportStrategies ?? DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES ??
136
- [oomExportStrategies.PROCESS], this)
75
+ ? ensureOOMExportStrategies(options.DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES, this)
137
76
  : []
138
77
  const exportCommand = oomMonitoringEnabled ? buildExportCommand(this) : undefined
139
78
  this.oomMonitoring = {
@@ -144,61 +83,26 @@ class Config {
144
83
  exportCommand,
145
84
  }
146
85
 
147
- const profilers = options.profilers || getProfilers({
148
- DD_PROFILING_HEAP_ENABLED,
149
- DD_PROFILING_WALLTIME_ENABLED,
150
- DD_PROFILING_PROFILERS,
151
- })
86
+ const profilers = getProfilers(options)
152
87
 
153
- this.timelineEnabled = isTrue(
154
- options.timelineEnabled ?? DD_PROFILING_TIMELINE_ENABLED ?? samplingContextsAvailable
155
- )
156
- checkOptionWithSamplingContextAllowed(this.timelineEnabled, 'Timeline view')
157
- this.timelineSamplingEnabled = isTrue(
158
- options.timelineSamplingEnabled ?? DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED ?? true
159
- )
88
+ this.timelineEnabled = options.DD_PROFILING_TIMELINE_ENABLED
89
+ this.timelineSamplingEnabled = options.DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED
90
+ this.codeHotspotsEnabled = options.DD_PROFILING_CODEHOTSPOTS_ENABLED
91
+ this.cpuProfilingEnabled = options.DD_PROFILING_CPU_ENABLED
92
+ this.heapSamplingInterval = options.DD_PROFILING_HEAP_SAMPLING_INTERVAL
160
93
 
161
- this.codeHotspotsEnabled = isTrue(
162
- options.codeHotspotsEnabled ?? DD_PROFILING_CODEHOTSPOTS_ENABLED ?? samplingContextsAvailable
163
- )
164
- checkOptionWithSamplingContextAllowed(this.codeHotspotsEnabled, 'Code hotspots')
165
-
166
- this.cpuProfilingEnabled = isTrue(
167
- options.cpuProfilingEnabled ?? DD_PROFILING_CPU_ENABLED ?? samplingContextsAvailable
168
- )
169
- checkOptionWithSamplingContextAllowed(this.cpuProfilingEnabled, 'CPU profiling')
170
-
171
- this.samplingInterval = options.samplingInterval || 1e3 / 99 // 99hz in millis
172
-
173
- this.heapSamplingInterval = options.heapSamplingInterval ??
174
- (Number(DD_PROFILING_HEAP_SAMPLING_INTERVAL) || 512 * 1024)
94
+ this.samplingInterval = 1e3 / 99 // 99hz in milliseconds
175
95
 
176
96
  const isAtLeast24 = satisfies(process.versions.node, '>=24.0.0')
177
97
 
178
- const uploadCompression0 = options.uploadCompression ?? DD_PROFILING_DEBUG_UPLOAD_COMPRESSION ?? 'on'
98
+ const uploadCompression0 = options.DD_PROFILING_DEBUG_UPLOAD_COMPRESSION
179
99
  let [uploadCompression, level0] = uploadCompression0.split('-')
180
- if (!['on', 'off', 'gzip', 'zstd'].includes(uploadCompression)) {
181
- this.logger.warn(`Invalid profile upload compression method "${uploadCompression0}". Will use "on".`)
182
- uploadCompression = 'on'
183
- }
184
100
  let level = level0 ? Number.parseInt(level0, 10) : undefined
185
101
  if (level !== undefined) {
186
- if (['on', 'off'].includes(uploadCompression)) {
187
- this.logger.warn(`Compression levels are not supported for "${uploadCompression}".`)
188
- level = undefined
189
- } else if (Number.isNaN(level)) {
190
- this.logger.warn(
191
- `Invalid compression level "${level0}". Will use default level.`)
192
- level = undefined
193
- } else if (level < 1) {
194
- this.logger.warn(`Invalid compression level ${level}. Will use 1.`)
195
- level = 1
196
- } else {
197
- const maxLevel = { gzip: 9, zstd: 22 }[uploadCompression]
198
- if (level > maxLevel) {
199
- this.logger.warn(`Invalid compression level ${level}. Will use ${maxLevel}.`)
200
- level = maxLevel
201
- }
102
+ const maxLevel = { gzip: 9, zstd: 22 }[uploadCompression]
103
+ if (level > maxLevel) {
104
+ this.logger.warn(`Invalid compression level ${level}. Will use ${maxLevel}.`)
105
+ level = maxLevel
202
106
  }
203
107
  }
204
108
 
@@ -219,13 +123,9 @@ class Config {
219
123
  that.asyncContextFrameEnabled = false
220
124
  }
221
125
 
222
- const canUseAsyncContextFrame = samplingContextsAvailable && isACFActive
223
-
224
- this.asyncContextFrameEnabled = isTrue(DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED ?? canUseAsyncContextFrame)
225
- if (this.asyncContextFrameEnabled && !canUseAsyncContextFrame) {
226
- if (!samplingContextsAvailable) {
227
- turnOffAsyncContextFrame(`on ${process.platform}`)
228
- } else if (isAtLeast24) {
126
+ this.asyncContextFrameEnabled = options.DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED ?? isACFActive
127
+ if (this.asyncContextFrameEnabled && !isACFActive) {
128
+ if (isAtLeast24) {
229
129
  turnOffAsyncContextFrame('with --no-async-context-frame')
230
130
  } else if (satisfies(process.versions.node, '>=22.9.0')) {
231
131
  turnOffAsyncContextFrame('without --experimental-async-context-frame')
@@ -234,7 +134,7 @@ class Config {
234
134
  }
235
135
  }
236
136
 
237
- this.heartbeatInterval = options.heartbeatInterval || 60 * 1000 // 1 minute
137
+ this.heartbeatInterval = options.telemetry.heartbeatInterval
238
138
 
239
139
  this.profilers = ensureProfilers(profilers, this)
240
140
  }
@@ -248,7 +148,7 @@ class Config {
248
148
  endpointCollectionEnabled: this.endpointCollectionEnabled,
249
149
  heapSamplingInterval: this.heapSamplingInterval,
250
150
  oomMonitoring: { ...this.oomMonitoring },
251
- profilerTypes: this.profilers.map(p => p.type),
151
+ profilerTypes: this.profilers.map(profiler => profiler.type),
252
152
  sourceMap: this.sourceMap,
253
153
  timelineEnabled: this.timelineEnabled,
254
154
  timelineSamplingEnabled: this.timelineSamplingEnabled,
@@ -263,7 +163,9 @@ class Config {
263
163
  module.exports = { Config }
264
164
 
265
165
  function getProfilers ({
266
- DD_PROFILING_HEAP_ENABLED, DD_PROFILING_WALLTIME_ENABLED, DD_PROFILING_PROFILERS,
166
+ DD_PROFILING_HEAP_ENABLED,
167
+ DD_PROFILING_WALLTIME_ENABLED,
168
+ DD_PROFILING_PROFILERS,
267
169
  }) {
268
170
  // First consider "legacy" DD_PROFILING_PROFILERS env variable, defaulting to space + wall
269
171
  // Use a Set to avoid duplicates
@@ -272,26 +174,26 @@ function getProfilers ({
272
174
  // snapshots the space profile won't include memory taken by profiles created
273
175
  // before it in the sequence. That memory is ultimately transient and will be
274
176
  // released when all profiles are subsequently encoded.
275
- const profilers = new Set((DD_PROFILING_PROFILERS ?? 'space,wall').split(','))
177
+ const profilers = new Set(DD_PROFILING_PROFILERS)
276
178
 
277
179
  let spaceExplicitlyEnabled = false
278
180
  // Add/remove space depending on the value of DD_PROFILING_HEAP_ENABLED
279
- if (DD_PROFILING_HEAP_ENABLED != null) {
280
- if (isTrue(DD_PROFILING_HEAP_ENABLED)) {
181
+ if (DD_PROFILING_HEAP_ENABLED !== undefined) {
182
+ if (DD_PROFILING_HEAP_ENABLED) {
281
183
  if (!profilers.has('space')) {
282
184
  profilers.add('space')
283
185
  spaceExplicitlyEnabled = true
284
186
  }
285
- } else if (isFalse(DD_PROFILING_HEAP_ENABLED)) {
187
+ } else {
286
188
  profilers.delete('space')
287
189
  }
288
190
  }
289
191
 
290
192
  // Add/remove wall depending on the value of DD_PROFILING_WALLTIME_ENABLED
291
- if (DD_PROFILING_WALLTIME_ENABLED != null) {
292
- if (isTrue(DD_PROFILING_WALLTIME_ENABLED)) {
193
+ if (DD_PROFILING_WALLTIME_ENABLED !== undefined) {
194
+ if (DD_PROFILING_WALLTIME_ENABLED) {
293
195
  profilers.add('wall')
294
- } else if (isFalse(DD_PROFILING_WALLTIME_ENABLED)) {
196
+ } else {
295
197
  profilers.delete('wall')
296
198
  profilers.delete('cpu') // remove alias too
297
199
  }
@@ -321,22 +223,12 @@ function getExportStrategy (name, options) {
321
223
  }
322
224
 
323
225
  function ensureOOMExportStrategies (strategies, options) {
324
- if (!strategies) {
325
- return []
226
+ const set = new Set()
227
+ for (const strategy of strategies) {
228
+ set.add(getExportStrategy(strategy, options))
326
229
  }
327
230
 
328
- if (typeof strategies === 'string') {
329
- strategies = strategies.split(',')
330
- }
331
-
332
- for (let i = 0; i < strategies.length; i++) {
333
- const strategy = strategies[i]
334
- if (typeof strategy === 'string') {
335
- strategies[i] = getExportStrategy(strategy, options)
336
- }
337
- }
338
-
339
- return [...new Set(strategies)]
231
+ return [...set]
340
232
  }
341
233
 
342
234
  function getExporter (name, options) {
@@ -345,22 +237,13 @@ function getExporter (name, options) {
345
237
  return new AgentExporter(options)
346
238
  case 'file':
347
239
  return new FileExporter(options)
240
+ default:
241
+ options.logger.error(`Unknown exporter "${name}"`)
348
242
  }
349
243
  }
350
244
 
351
245
  function ensureExporters (exporters, options) {
352
- if (typeof exporters === 'string') {
353
- exporters = exporters.split(',')
354
- }
355
-
356
- for (let i = 0; i < exporters.length; i++) {
357
- const exporter = exporters[i]
358
- if (typeof exporter === 'string') {
359
- exporters[i] = getExporter(exporter, options)
360
- }
361
- }
362
-
363
- return exporters
246
+ return exporters.map((exporter) => getExporter(exporter, options))
364
247
  }
365
248
 
366
249
  function getProfiler (name, options) {
@@ -376,30 +259,26 @@ function getProfiler (name, options) {
376
259
  }
377
260
 
378
261
  function ensureProfilers (profilers, options) {
379
- if (typeof profilers === 'string') {
380
- profilers = profilers.split(',')
381
- }
262
+ const filteredProfilers = []
382
263
 
383
264
  for (let i = 0; i < profilers.length; i++) {
384
- const profiler = profilers[i]
385
- if (typeof profiler === 'string') {
386
- profilers[i] = getProfiler(profiler, options)
265
+ const profiler = getProfiler(profilers[i], options)
266
+ if (profiler !== undefined) {
267
+ filteredProfilers.push(profiler)
387
268
  }
388
269
  }
389
270
 
390
271
  // Events profiler is a profiler that produces timeline events. It is only
391
272
  // added if timeline is enabled and there's a wall profiler.
392
- if (options.timelineEnabled && profilers.some(p => p instanceof WallProfiler)) {
393
- profilers.push(new EventsProfiler(options))
273
+ if (options.timelineEnabled && filteredProfilers.some(profiler => profiler instanceof WallProfiler)) {
274
+ filteredProfilers.push(new EventsProfiler(options))
394
275
  }
395
276
 
396
- // Filter out any invalid profilers
397
- return profilers.filter(Boolean)
277
+ return filteredProfilers
398
278
  }
399
279
 
400
280
  function ensureLogger (logger) {
401
- if (typeof logger !== 'object' ||
402
- typeof logger.debug !== 'function' ||
281
+ if (typeof logger?.debug !== 'function' ||
403
282
  typeof logger.info !== 'function' ||
404
283
  typeof logger.warn !== 'function' ||
405
284
  typeof logger.error !== 'function') {
@@ -424,50 +303,3 @@ function buildExportCommand (options) {
424
303
  path.join(__dirname, 'exporter_cli.js'),
425
304
  urls.join(','), tags, 'space']
426
305
  }
427
-
428
- function getProfilingEnvValues () {
429
- return {
430
- DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED:
431
- getValueFromEnvSources('DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED'),
432
- DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED:
433
- getValueFromEnvSources('DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED'),
434
- DD_PROFILING_CODEHOTSPOTS_ENABLED:
435
- getValueFromEnvSources('DD_PROFILING_CODEHOTSPOTS_ENABLED'),
436
- DD_PROFILING_CPU_ENABLED:
437
- getValueFromEnvSources('DD_PROFILING_CPU_ENABLED'),
438
- DD_PROFILING_DEBUG_SOURCE_MAPS:
439
- getValueFromEnvSources('DD_PROFILING_DEBUG_SOURCE_MAPS'),
440
- DD_PROFILING_DEBUG_UPLOAD_COMPRESSION:
441
- getValueFromEnvSources('DD_PROFILING_DEBUG_UPLOAD_COMPRESSION'),
442
- DD_PROFILING_ENDPOINT_COLLECTION_ENABLED:
443
- getValueFromEnvSources('DD_PROFILING_ENDPOINT_COLLECTION_ENABLED'),
444
- DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES:
445
- getValueFromEnvSources('DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES'),
446
- DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE:
447
- getValueFromEnvSources('DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE'),
448
- DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT:
449
- getValueFromEnvSources('DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT'),
450
- DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED:
451
- getValueFromEnvSources('DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED'),
452
- DD_PROFILING_HEAP_ENABLED:
453
- getValueFromEnvSources('DD_PROFILING_HEAP_ENABLED'),
454
- DD_PROFILING_HEAP_SAMPLING_INTERVAL:
455
- getValueFromEnvSources('DD_PROFILING_HEAP_SAMPLING_INTERVAL'),
456
- DD_PROFILING_PPROF_PREFIX:
457
- getValueFromEnvSources('DD_PROFILING_PPROF_PREFIX'),
458
- DD_PROFILING_PROFILERS:
459
- getValueFromEnvSources('DD_PROFILING_PROFILERS'),
460
- DD_PROFILING_TIMELINE_ENABLED:
461
- getValueFromEnvSources('DD_PROFILING_TIMELINE_ENABLED'),
462
- DD_PROFILING_UPLOAD_PERIOD:
463
- getValueFromEnvSources('DD_PROFILING_UPLOAD_PERIOD'),
464
- DD_PROFILING_UPLOAD_TIMEOUT:
465
- getValueFromEnvSources('DD_PROFILING_UPLOAD_TIMEOUT'),
466
- DD_PROFILING_V8_PROFILER_BUG_WORKAROUND:
467
- getValueFromEnvSources('DD_PROFILING_V8_PROFILER_BUG_WORKAROUND'),
468
- DD_PROFILING_WALLTIME_ENABLED:
469
- getValueFromEnvSources('DD_PROFILING_WALLTIME_ENABLED'),
470
- DD_TAGS:
471
- getValueFromEnvSources('DD_TAGS'),
472
- }
473
- }
@@ -17,9 +17,6 @@ function exporterFromURL (url) {
17
17
  if (url.protocol === 'file:') {
18
18
  return new FileExporter({ pprofPrefix: fileURLToPath(url) })
19
19
  }
20
- // TODO: Why is DD_INJECTION_ENABLED a comma separated list?
21
- const injectionEnabled = (getValueFromEnvSources('DD_INJECTION_ENABLED') ?? '').split(',')
22
- const libraryInjected = injectionEnabled.length > 0
23
20
  const profilingEnabled = (getValueFromEnvSources('DD_PROFILING_ENABLED') ?? '').toLowerCase()
24
21
  const activation = ['true', '1'].includes(profilingEnabled)
25
22
  ? 'manual'
@@ -30,7 +27,7 @@ function exporterFromURL (url) {
30
27
  url,
31
28
  logger,
32
29
  uploadTimeout: timeoutMs,
33
- libraryInjected,
30
+ libraryInjected: !!getValueFromEnvSources('DD_INJECTION_ENABLED'),
34
31
  activation,
35
32
  })
36
33
  }