dd-trace 5.19.0 → 5.21.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 (67) hide show
  1. package/ext/formats.d.ts +1 -0
  2. package/ext/formats.js +2 -1
  3. package/index.d.ts +2 -1
  4. package/init.js +3 -15
  5. package/package.json +5 -4
  6. package/packages/datadog-instrumentations/src/body-parser.js +14 -2
  7. package/packages/datadog-instrumentations/src/cucumber.js +10 -0
  8. package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -2
  9. package/packages/datadog-instrumentations/src/helpers/register.js +21 -12
  10. package/packages/datadog-instrumentations/src/http/client.js +7 -1
  11. package/packages/datadog-instrumentations/src/http/server.js +50 -13
  12. package/packages/datadog-instrumentations/src/mocha/main.js +111 -78
  13. package/packages/datadog-instrumentations/src/nyc.js +23 -0
  14. package/packages/datadog-instrumentations/src/process.js +29 -0
  15. package/packages/datadog-instrumentations/src/vitest.js +65 -25
  16. package/packages/datadog-plugin-aws-sdk/src/base.js +15 -1
  17. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
  18. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -1
  19. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +3 -3
  20. package/packages/datadog-plugin-cucumber/src/index.js +12 -2
  21. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +53 -12
  22. package/packages/datadog-plugin-jest/src/index.js +17 -4
  23. package/packages/datadog-plugin-mocha/src/index.js +25 -6
  24. package/packages/datadog-plugin-nyc/src/index.js +35 -0
  25. package/packages/datadog-plugin-playwright/src/index.js +9 -4
  26. package/packages/datadog-plugin-vitest/src/index.js +32 -5
  27. package/packages/dd-trace/src/appsec/blocking.js +10 -1
  28. package/packages/dd-trace/src/appsec/channels.js +4 -1
  29. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
  30. package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +16 -0
  31. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +2 -0
  32. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +2 -1
  33. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +11 -0
  34. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/code-injection-sensitive-analyzer.js +25 -0
  35. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -0
  36. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +2 -2
  37. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
  38. package/packages/dd-trace/src/appsec/index.js +12 -7
  39. package/packages/dd-trace/src/appsec/rasp.js +121 -7
  40. package/packages/dd-trace/src/appsec/recommended.json +220 -2
  41. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +40 -1
  42. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -4
  43. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -4
  44. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +8 -7
  45. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -4
  46. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -4
  47. package/packages/dd-trace/src/ci-visibility/telemetry.js +29 -2
  48. package/packages/dd-trace/src/config.js +158 -153
  49. package/packages/dd-trace/src/data_streams.js +44 -0
  50. package/packages/dd-trace/src/datastreams/pathway.js +4 -2
  51. package/packages/dd-trace/src/log/index.js +32 -0
  52. package/packages/dd-trace/src/opentelemetry/context_manager.js +22 -39
  53. package/packages/dd-trace/src/opentelemetry/span_context.js +2 -2
  54. package/packages/dd-trace/src/opentelemetry/tracer.js +23 -14
  55. package/packages/dd-trace/src/opentelemetry/tracer_provider.js +9 -1
  56. package/packages/dd-trace/src/opentracing/propagation/log.js +1 -1
  57. package/packages/dd-trace/src/opentracing/propagation/text_map.js +60 -0
  58. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +43 -0
  59. package/packages/dd-trace/src/opentracing/span_context.js +1 -0
  60. package/packages/dd-trace/src/opentracing/tracer.js +10 -6
  61. package/packages/dd-trace/src/plugins/ci_plugin.js +11 -4
  62. package/packages/dd-trace/src/plugins/index.js +1 -0
  63. package/packages/dd-trace/src/plugins/plugin.js +12 -1
  64. package/packages/dd-trace/src/plugins/util/git.js +14 -1
  65. package/packages/dd-trace/src/proxy.js +1 -0
  66. package/packages/dd-trace/src/telemetry/index.js +1 -1
  67. package/packages/dd-trace/src/tracer.js +2 -0
@@ -29,14 +29,14 @@ const telemetryCounters = {
29
29
  function getCounter (event, ddVar, otelVar) {
30
30
  const counters = telemetryCounters[event]
31
31
  const tags = []
32
- const ddVarPrefix = 'config.datadog:'
33
- const otelVarPrefix = 'config.opentelemetry:'
32
+ const ddVarPrefix = 'config_datadog:'
33
+ const otelVarPrefix = 'config_opentelemetry:'
34
34
  if (ddVar) {
35
- ddVar = ddVarPrefix + ddVar
35
+ ddVar = ddVarPrefix + ddVar.toLowerCase()
36
36
  tags.push(ddVar)
37
37
  }
38
38
  if (otelVar) {
39
- otelVar = otelVarPrefix + otelVar
39
+ otelVar = otelVarPrefix + otelVar.toLowerCase()
40
40
  tags.push(otelVar)
41
41
  }
42
42
 
@@ -183,7 +183,7 @@ function remapify (input, mappings) {
183
183
  return output
184
184
  }
185
185
 
186
- function propagationStyle (key, option, defaultValue) {
186
+ function propagationStyle (key, option) {
187
187
  // Extract by key if in object-form value
188
188
  if (option !== null && typeof option === 'object' && !Array.isArray(option)) {
189
189
  option = option[key]
@@ -206,69 +206,42 @@ function propagationStyle (key, option, defaultValue) {
206
206
  .filter(v => v !== '')
207
207
  .map(v => v.trim().toLowerCase())
208
208
  }
209
+ }
209
210
 
210
- return defaultValue
211
+ function reformatSpanSamplingRules (rules) {
212
+ if (!rules) return rules
213
+ return rules.map(rule => {
214
+ return remapify(rule, {
215
+ sample_rate: 'sampleRate',
216
+ max_per_second: 'maxPerSecond'
217
+ })
218
+ })
211
219
  }
212
220
 
213
221
  class Config {
214
- constructor (options) {
215
- options = options || {}
216
- options = this.options = {
222
+ constructor (options = {}) {
223
+ options = {
217
224
  ...options,
218
225
  appsec: options.appsec != null ? options.appsec : options.experimental?.appsec,
219
226
  iast: options.iast != null ? options.iast : options.experimental?.iast
220
227
  }
221
228
 
222
- checkIfBothOtelAndDdEnvVarSet()
223
-
224
229
  // Configure the logger first so it can be used to warn about other configs
225
- this.debug = isTrue(coalesce(
226
- process.env.DD_TRACE_DEBUG,
227
- process.env.OTEL_LOG_LEVEL && process.env.OTEL_LOG_LEVEL === 'debug',
228
- false
229
- ))
230
- this.logger = options.logger
231
-
232
- this.logLevel = coalesce(
233
- options.logLevel,
234
- process.env.DD_TRACE_LOG_LEVEL,
235
- process.env.OTEL_LOG_LEVEL,
236
- 'debug'
237
- )
230
+ const logConfig = log.getConfig()
231
+ this.debug = logConfig.enabled
232
+ this.logger = coalesce(options.logger, logConfig.logger)
233
+ this.logLevel = coalesce(options.logLevel, logConfig.logLevel)
238
234
 
239
235
  log.use(this.logger)
240
- log.toggle(this.debug, this.logLevel, this)
241
-
242
- const DD_TRACE_MEMCACHED_COMMAND_ENABLED = coalesce(
243
- process.env.DD_TRACE_MEMCACHED_COMMAND_ENABLED,
244
- false
245
- )
236
+ log.toggle(this.debug, this.logLevel)
246
237
 
247
- const DD_SERVICE_MAPPING = coalesce(
248
- options.serviceMapping,
249
- process.env.DD_SERVICE_MAPPING
250
- ? fromEntries(
251
- process.env.DD_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
252
- )
253
- : {}
254
- )
238
+ checkIfBothOtelAndDdEnvVarSet()
255
239
 
256
240
  const DD_API_KEY = coalesce(
257
241
  process.env.DATADOG_API_KEY,
258
242
  process.env.DD_API_KEY
259
243
  )
260
244
 
261
- // TODO: Remove the experimental env vars as a major?
262
- const DD_TRACE_B3_ENABLED = coalesce(
263
- options.experimental && options.experimental.b3,
264
- process.env.DD_TRACE_EXPERIMENTAL_B3_ENABLED,
265
- false
266
- )
267
- const defaultPropagationStyle = ['datadog', 'tracecontext']
268
- if (isTrue(DD_TRACE_B3_ENABLED)) {
269
- defaultPropagationStyle.push('b3')
270
- defaultPropagationStyle.push('b3 single header')
271
- }
272
245
  if (process.env.DD_TRACE_PROPAGATION_STYLE && (
273
246
  process.env.DD_TRACE_PROPAGATION_STYLE_INJECT ||
274
247
  process.env.DD_TRACE_PROPAGATION_STYLE_EXTRACT
@@ -282,21 +255,11 @@ class Config {
282
255
  const PROPAGATION_STYLE_INJECT = propagationStyle(
283
256
  'inject',
284
257
  options.tracePropagationStyle,
285
- defaultPropagationStyle
286
- )
287
- const PROPAGATION_STYLE_EXTRACT = propagationStyle(
288
- 'extract',
289
- options.tracePropagationStyle,
290
- defaultPropagationStyle
258
+ this._getDefaultPropagationStyle(options)
291
259
  )
292
260
 
293
261
  validateOtelPropagators(PROPAGATION_STYLE_INJECT)
294
262
 
295
- const DD_TRACE_PROPAGATION_EXTRACT_FIRST = coalesce(
296
- process.env.DD_TRACE_PROPAGATION_EXTRACT_FIRST,
297
- false
298
- )
299
-
300
263
  if (typeof options.appsec === 'boolean') {
301
264
  options.appsec = {
302
265
  enabled: options.appsec
@@ -305,33 +268,6 @@ class Config {
305
268
  options.appsec = {}
306
269
  }
307
270
 
308
- const DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON = coalesce(
309
- maybeFile(options.appsec.blockedTemplateGraphql),
310
- maybeFile(process.env.DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON)
311
- )
312
- const DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING = coalesce(
313
- options.appsec.eventTracking && options.appsec.eventTracking.mode,
314
- process.env.DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING,
315
- 'safe'
316
- ).toLowerCase()
317
- const DD_API_SECURITY_ENABLED = coalesce(
318
- options.appsec?.apiSecurity?.enabled,
319
- process.env.DD_API_SECURITY_ENABLED && isTrue(process.env.DD_API_SECURITY_ENABLED),
320
- process.env.DD_EXPERIMENTAL_API_SECURITY_ENABLED && isTrue(process.env.DD_EXPERIMENTAL_API_SECURITY_ENABLED),
321
- true
322
- )
323
- const DD_API_SECURITY_REQUEST_SAMPLE_RATE = coalesce(
324
- options.appsec?.apiSecurity?.requestSampling,
325
- parseFloat(process.env.DD_API_SECURITY_REQUEST_SAMPLE_RATE),
326
- 0.1
327
- )
328
-
329
- // 0: disabled, 1: logging, 2: garbage collection + logging
330
- const DD_TRACE_SPAN_LEAK_DEBUG = coalesce(
331
- process.env.DD_TRACE_SPAN_LEAK_DEBUG,
332
- 0
333
- )
334
-
335
271
  const DD_INSTRUMENTATION_INSTALL_ID = coalesce(
336
272
  process.env.DD_INSTRUMENTATION_INSTALL_ID,
337
273
  null
@@ -345,51 +281,10 @@ class Config {
345
281
  null
346
282
  )
347
283
 
348
- const sampler = {
349
- spanSamplingRules: coalesce(
350
- options.spanSamplingRules,
351
- safeJsonParse(maybeFile(process.env.DD_SPAN_SAMPLING_RULES_FILE)),
352
- safeJsonParse(process.env.DD_SPAN_SAMPLING_RULES),
353
- []
354
- ).map(rule => {
355
- return remapify(rule, {
356
- sample_rate: 'sampleRate',
357
- max_per_second: 'maxPerSecond'
358
- })
359
- })
360
- }
361
-
362
284
  // TODO: refactor
363
285
  this.apiKey = DD_API_KEY
364
- this.serviceMapping = DD_SERVICE_MAPPING
365
- this.tracePropagationStyle = {
366
- inject: PROPAGATION_STYLE_INJECT,
367
- extract: PROPAGATION_STYLE_EXTRACT,
368
- otelPropagators: process.env.DD_TRACE_PROPAGATION_STYLE ||
369
- process.env.DD_TRACE_PROPAGATION_STYLE_INJECT ||
370
- process.env.DD_TRACE_PROPAGATION_STYLE_EXTRACT
371
- ? false
372
- : !!process.env.OTEL_PROPAGATORS
373
- }
374
- this.tracePropagationExtractFirst = isTrue(DD_TRACE_PROPAGATION_EXTRACT_FIRST)
375
- this.sampler = sampler
376
- this.appsec = {
377
- blockedTemplateGraphql: DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON,
378
- eventTracking: {
379
- enabled: ['extended', 'safe'].includes(DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING),
380
- mode: DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING
381
- },
382
- apiSecurity: {
383
- enabled: DD_API_SECURITY_ENABLED,
384
- // Coerce value between 0 and 1
385
- requestSampling: Math.min(1, Math.max(0, DD_API_SECURITY_REQUEST_SAMPLE_RATE))
386
- }
387
- }
388
286
 
389
- // Requires an accompanying DD_APM_OBFUSCATION_MEMCACHED_KEEP_COMMAND=true in the agent
390
- this.memcachedCommandEnabled = isTrue(DD_TRACE_MEMCACHED_COMMAND_ENABLED)
391
- this.isAzureFunction = getIsAzureFunction()
392
- this.spanLeakDebug = Number(DD_TRACE_SPAN_LEAK_DEBUG)
287
+ // sent in telemetry event app-started
393
288
  this.installSignature = {
394
289
  id: DD_INSTRUMENTATION_INSTALL_ID,
395
290
  time: DD_INSTRUMENTATION_INSTALL_TIME,
@@ -463,6 +358,21 @@ class Config {
463
358
  this._merge()
464
359
  }
465
360
 
361
+ _getDefaultPropagationStyle (options) {
362
+ // TODO: Remove the experimental env vars as a major?
363
+ const DD_TRACE_B3_ENABLED = coalesce(
364
+ options.experimental && options.experimental.b3,
365
+ process.env.DD_TRACE_EXPERIMENTAL_B3_ENABLED,
366
+ false
367
+ )
368
+ const defaultPropagationStyle = ['datadog', 'tracecontext']
369
+ if (isTrue(DD_TRACE_B3_ENABLED)) {
370
+ defaultPropagationStyle.push('b3')
371
+ defaultPropagationStyle.push('b3 single header')
372
+ }
373
+ return defaultPropagationStyle
374
+ }
375
+
466
376
  _isInServerlessEnvironment () {
467
377
  const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
468
378
  const isGCPFunction = getIsGCPFunction()
@@ -486,14 +396,19 @@ class Config {
486
396
  pkg.name ||
487
397
  'node'
488
398
 
489
- const defaults = this._defaults = {}
399
+ const defaults = setHiddenProperty(this, '_defaults', {})
490
400
 
401
+ this._setValue(defaults, 'appsec.apiSecurity.enabled', true)
402
+ this._setValue(defaults, 'appsec.apiSecurity.requestSampling', 0.1)
403
+ this._setValue(defaults, 'appsec.blockedTemplateGraphql', undefined)
491
404
  this._setValue(defaults, 'appsec.blockedTemplateHtml', undefined)
492
405
  this._setValue(defaults, 'appsec.blockedTemplateJson', undefined)
493
406
  this._setValue(defaults, 'appsec.enabled', undefined)
407
+ this._setValue(defaults, 'appsec.eventTracking.enabled', true)
408
+ this._setValue(defaults, 'appsec.eventTracking.mode', 'safe')
494
409
  this._setValue(defaults, 'appsec.obfuscatorKeyRegex', defaultWafObfuscatorKeyRegex)
495
410
  this._setValue(defaults, 'appsec.obfuscatorValueRegex', defaultWafObfuscatorValueRegex)
496
- this._setValue(defaults, 'appsec.rasp.enabled', false)
411
+ this._setValue(defaults, 'appsec.rasp.enabled', true)
497
412
  this._setValue(defaults, 'appsec.rateLimit', 100)
498
413
  this._setValue(defaults, 'appsec.rules', undefined)
499
414
  this._setValue(defaults, 'appsec.sca.enabled', null)
@@ -526,6 +441,7 @@ class Config {
526
441
  this._setValue(defaults, 'iast.redactionValuePattern', null)
527
442
  this._setValue(defaults, 'iast.requestSampling', 30)
528
443
  this._setValue(defaults, 'iast.telemetryVerbosity', 'INFORMATION')
444
+ this._setValue(defaults, 'isAzureFunction', false)
529
445
  this._setValue(defaults, 'isCiVisibility', false)
530
446
  this._setValue(defaults, 'isEarlyFlakeDetectionEnabled', false)
531
447
  this._setValue(defaults, 'isGCPFunction', false)
@@ -534,6 +450,7 @@ class Config {
534
450
  this._setValue(defaults, 'isManualApiEnabled', false)
535
451
  this._setValue(defaults, 'logInjection', false)
536
452
  this._setValue(defaults, 'lookup', undefined)
453
+ this._setValue(defaults, 'memcachedCommandEnabled', false)
537
454
  this._setValue(defaults, 'openAiLogsEnabled', false)
538
455
  this._setValue(defaults, 'openaiSpanCharLimit', 128)
539
456
  this._setValue(defaults, 'peerServiceMapping', {})
@@ -554,11 +471,14 @@ class Config {
554
471
  this._setValue(defaults, 'sampleRate', undefined)
555
472
  this._setValue(defaults, 'sampler.rateLimit', undefined)
556
473
  this._setValue(defaults, 'sampler.rules', [])
474
+ this._setValue(defaults, 'sampler.spanSamplingRules', [])
557
475
  this._setValue(defaults, 'scope', undefined)
558
476
  this._setValue(defaults, 'service', service)
477
+ this._setValue(defaults, 'serviceMapping', {})
559
478
  this._setValue(defaults, 'site', 'datadoghq.com')
560
479
  this._setValue(defaults, 'spanAttributeSchema', 'v0')
561
480
  this._setValue(defaults, 'spanComputePeerService', false)
481
+ this._setValue(defaults, 'spanLeakDebug', 0)
562
482
  this._setValue(defaults, 'spanRemoveIntegrationFromService', false)
563
483
  this._setValue(defaults, 'startupLogs', false)
564
484
  this._setValue(defaults, 'stats.enabled', false)
@@ -572,6 +492,10 @@ class Config {
572
492
  this._setValue(defaults, 'telemetry.metrics', true)
573
493
  this._setValue(defaults, 'traceId128BitGenerationEnabled', true)
574
494
  this._setValue(defaults, 'traceId128BitLoggingEnabled', false)
495
+ this._setValue(defaults, 'tracePropagationExtractFirst', false)
496
+ this._setValue(defaults, 'tracePropagationStyle.inject', ['datadog', 'tracecontext'])
497
+ this._setValue(defaults, 'tracePropagationStyle.extract', ['datadog', 'tracecontext'])
498
+ this._setValue(defaults, 'tracePropagationStyle.otelPropagators', false)
575
499
  this._setValue(defaults, 'tracing', true)
576
500
  this._setValue(defaults, 'url', undefined)
577
501
  this._setValue(defaults, 'version', pkg.version)
@@ -582,7 +506,11 @@ class Config {
582
506
  const {
583
507
  AWS_LAMBDA_FUNCTION_NAME,
584
508
  DD_AGENT_HOST,
509
+ DD_API_SECURITY_ENABLED,
510
+ DD_API_SECURITY_REQUEST_SAMPLE_RATE,
511
+ DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING,
585
512
  DD_APPSEC_ENABLED,
513
+ DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON,
586
514
  DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML,
587
515
  DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON,
588
516
  DD_APPSEC_MAX_STACK_TRACES,
@@ -600,6 +528,7 @@ class Config {
600
528
  DD_DOGSTATSD_HOSTNAME,
601
529
  DD_DOGSTATSD_PORT,
602
530
  DD_ENV,
531
+ DD_EXPERIMENTAL_API_SECURITY_ENABLED,
603
532
  DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED,
604
533
  DD_EXPERIMENTAL_PROFILING_ENABLED,
605
534
  JEST_WORKER_ID,
@@ -626,8 +555,11 @@ class Config {
626
555
  DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS,
627
556
  DD_RUNTIME_METRICS_ENABLED,
628
557
  DD_SERVICE,
558
+ DD_SERVICE_MAPPING,
629
559
  DD_SERVICE_NAME,
630
560
  DD_SITE,
561
+ DD_SPAN_SAMPLING_RULES,
562
+ DD_SPAN_SAMPLING_RULES_FILE,
631
563
  DD_TAGS,
632
564
  DD_TELEMETRY_DEBUG,
633
565
  DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED,
@@ -647,9 +579,14 @@ class Config {
647
579
  DD_TRACE_GIT_METADATA_ENABLED,
648
580
  DD_TRACE_GLOBAL_TAGS,
649
581
  DD_TRACE_HEADER_TAGS,
582
+ DD_TRACE_MEMCACHED_COMMAND_ENABLED,
650
583
  DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP,
651
584
  DD_TRACE_PARTIAL_FLUSH_MIN_SPANS,
652
585
  DD_TRACE_PEER_SERVICE_MAPPING,
586
+ DD_TRACE_PROPAGATION_EXTRACT_FIRST,
587
+ DD_TRACE_PROPAGATION_STYLE,
588
+ DD_TRACE_PROPAGATION_STYLE_INJECT,
589
+ DD_TRACE_PROPAGATION_STYLE_EXTRACT,
653
590
  DD_TRACE_RATE_LIMIT,
654
591
  DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED,
655
592
  DD_TRACE_REPORT_HOSTNAME,
@@ -657,33 +594,46 @@ class Config {
657
594
  DD_TRACE_SAMPLING_RULES,
658
595
  DD_TRACE_SCOPE,
659
596
  DD_TRACE_SPAN_ATTRIBUTE_SCHEMA,
597
+ DD_TRACE_SPAN_LEAK_DEBUG,
660
598
  DD_TRACE_STARTUP_LOGS,
661
599
  DD_TRACE_TAGS,
662
600
  DD_TRACE_TELEMETRY_ENABLED,
663
601
  DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
664
602
  DD_TRACING_ENABLED,
665
603
  DD_VERSION,
666
- OTEL_SERVICE_NAME,
604
+ OTEL_METRICS_EXPORTER,
605
+ OTEL_PROPAGATORS,
667
606
  OTEL_RESOURCE_ATTRIBUTES,
607
+ OTEL_SERVICE_NAME,
668
608
  OTEL_TRACES_SAMPLER,
669
- OTEL_TRACES_SAMPLER_ARG,
670
- OTEL_METRICS_EXPORTER
609
+ OTEL_TRACES_SAMPLER_ARG
671
610
  } = process.env
672
611
 
673
612
  const tags = {}
674
- const env = this._env = {}
675
- this._envUnprocessed = {}
613
+ const env = setHiddenProperty(this, '_env', {})
614
+ setHiddenProperty(this, '_envUnprocessed', {})
676
615
 
677
616
  tagger.add(tags, OTEL_RESOURCE_ATTRIBUTES, true)
678
617
  tagger.add(tags, DD_TAGS)
679
618
  tagger.add(tags, DD_TRACE_TAGS)
680
619
  tagger.add(tags, DD_TRACE_GLOBAL_TAGS)
681
620
 
621
+ this._setBoolean(env, 'appsec.apiSecurity.enabled', coalesce(
622
+ DD_API_SECURITY_ENABLED && isTrue(DD_API_SECURITY_ENABLED),
623
+ DD_EXPERIMENTAL_API_SECURITY_ENABLED && isTrue(DD_EXPERIMENTAL_API_SECURITY_ENABLED)
624
+ ))
625
+ this._setUnit(env, 'appsec.apiSecurity.requestSampling', DD_API_SECURITY_REQUEST_SAMPLE_RATE)
626
+ this._setValue(env, 'appsec.blockedTemplateGraphql', maybeFile(DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON))
682
627
  this._setValue(env, 'appsec.blockedTemplateHtml', maybeFile(DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML))
683
628
  this._envUnprocessed['appsec.blockedTemplateHtml'] = DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML
684
629
  this._setValue(env, 'appsec.blockedTemplateJson', maybeFile(DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON))
685
630
  this._envUnprocessed['appsec.blockedTemplateJson'] = DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON
686
631
  this._setBoolean(env, 'appsec.enabled', DD_APPSEC_ENABLED)
632
+ if (DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING) {
633
+ this._setValue(env, 'appsec.eventTracking.enabled',
634
+ ['extended', 'safe'].includes(DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING.toLowerCase()))
635
+ this._setValue(env, 'appsec.eventTracking.mode', DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING.toLowerCase())
636
+ }
687
637
  this._setString(env, 'appsec.obfuscatorKeyRegex', DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP)
688
638
  this._setString(env, 'appsec.obfuscatorValueRegex', DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP)
689
639
  this._setBoolean(env, 'appsec.rasp.enabled', DD_APPSEC_RASP_ENABLED)
@@ -731,8 +681,11 @@ class Config {
731
681
  }
732
682
  this._envUnprocessed['iast.requestSampling'] = DD_IAST_REQUEST_SAMPLING
733
683
  this._setString(env, 'iast.telemetryVerbosity', DD_IAST_TELEMETRY_VERBOSITY)
684
+ this._setBoolean(env, 'isAzureFunction', getIsAzureFunction())
734
685
  this._setBoolean(env, 'isGCPFunction', getIsGCPFunction())
735
686
  this._setBoolean(env, 'logInjection', DD_LOGS_INJECTION)
687
+ // Requires an accompanying DD_APM_OBFUSCATION_MEMCACHED_KEEP_COMMAND=true in the agent
688
+ this._setBoolean(env, 'memcachedCommandEnabled', DD_TRACE_MEMCACHED_COMMAND_ENABLED)
736
689
  this._setBoolean(env, 'openAiLogsEnabled', DD_OPENAI_LOGS_ENABLED)
737
690
  this._setValue(env, 'openaiSpanCharLimit', maybeInt(DD_OPENAI_SPAN_CHAR_LIMIT))
738
691
  this._envUnprocessed.openaiSpanCharLimit = DD_OPENAI_SPAN_CHAR_LIMIT
@@ -772,6 +725,10 @@ class Config {
772
725
  : undefined
773
726
  this._setBoolean(env, 'runtimeMetrics', DD_RUNTIME_METRICS_ENABLED ||
774
727
  otelSetRuntimeMetrics)
728
+ this._setArray(env, 'sampler.spanSamplingRules', reformatSpanSamplingRules(coalesce(
729
+ safeJsonParse(maybeFile(DD_SPAN_SAMPLING_RULES_FILE)),
730
+ safeJsonParse(DD_SPAN_SAMPLING_RULES)
731
+ )))
775
732
  this._setUnit(env, 'sampleRate', DD_TRACE_SAMPLE_RATE ||
776
733
  getFromOtelSamplerMap(OTEL_TRACES_SAMPLER, OTEL_TRACES_SAMPLER_ARG))
777
734
  this._setValue(env, 'sampler.rateLimit', DD_TRACE_RATE_LIMIT)
@@ -779,11 +736,18 @@ class Config {
779
736
  this._envUnprocessed['sampler.rules'] = DD_TRACE_SAMPLING_RULES
780
737
  this._setString(env, 'scope', DD_TRACE_SCOPE)
781
738
  this._setString(env, 'service', DD_SERVICE || DD_SERVICE_NAME || tags.service || OTEL_SERVICE_NAME)
739
+ if (DD_SERVICE_MAPPING) {
740
+ this._setValue(env, 'serviceMapping', fromEntries(
741
+ process.env.DD_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
742
+ ))
743
+ }
782
744
  this._setString(env, 'site', DD_SITE)
783
745
  if (DD_TRACE_SPAN_ATTRIBUTE_SCHEMA) {
784
746
  this._setString(env, 'spanAttributeSchema', validateNamingVersion(DD_TRACE_SPAN_ATTRIBUTE_SCHEMA))
785
747
  this._envUnprocessed.spanAttributeSchema = DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
786
748
  }
749
+ // 0: disabled, 1: logging, 2: garbage collection + logging
750
+ this._setValue(env, 'spanLeakDebug', maybeInt(DD_TRACE_SPAN_LEAK_DEBUG))
787
751
  this._setBoolean(env, 'spanRemoveIntegrationFromService', DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED)
788
752
  this._setBoolean(env, 'startupLogs', DD_TRACE_STARTUP_LOGS)
789
753
  this._setTags(env, 'tags', tags)
@@ -807,24 +771,40 @@ class Config {
807
771
  this._setBoolean(env, 'telemetry.metrics', DD_TELEMETRY_METRICS_ENABLED)
808
772
  this._setBoolean(env, 'traceId128BitGenerationEnabled', DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
809
773
  this._setBoolean(env, 'traceId128BitLoggingEnabled', DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
774
+ this._setBoolean(env, 'tracePropagationExtractFirst', DD_TRACE_PROPAGATION_EXTRACT_FIRST)
775
+ this._setBoolean(env, 'tracePropagationStyle.otelPropagators',
776
+ DD_TRACE_PROPAGATION_STYLE ||
777
+ DD_TRACE_PROPAGATION_STYLE_INJECT ||
778
+ DD_TRACE_PROPAGATION_STYLE_EXTRACT
779
+ ? false
780
+ : !!OTEL_PROPAGATORS)
810
781
  this._setBoolean(env, 'tracing', DD_TRACING_ENABLED)
811
782
  this._setString(env, 'version', DD_VERSION || tags.version)
812
783
  }
813
784
 
814
785
  _applyOptions (options) {
815
- const opts = this._options = this._options || {}
786
+ const opts = setHiddenProperty(this, '_options', this._options || {})
816
787
  const tags = {}
817
- this._optsUnprocessed = {}
788
+ setHiddenProperty(this, '_optsUnprocessed', {})
818
789
 
819
- options = this.options = Object.assign({ ingestion: {} }, options, opts)
790
+ options = setHiddenProperty(this, '_optionsArg', Object.assign({ ingestion: {} }, options, opts))
820
791
 
821
792
  tagger.add(tags, options.tags)
822
793
 
794
+ this._setBoolean(opts, 'appsec.apiSecurity.enabled', options.appsec.apiSecurity?.enabled)
795
+ this._setUnit(opts, 'appsec.apiSecurity.requestSampling', options.appsec.apiSecurity?.requestSampling)
796
+ this._setValue(opts, 'appsec.blockedTemplateGraphql', maybeFile(options.appsec.blockedTemplateGraphql))
823
797
  this._setValue(opts, 'appsec.blockedTemplateHtml', maybeFile(options.appsec.blockedTemplateHtml))
824
798
  this._optsUnprocessed['appsec.blockedTemplateHtml'] = options.appsec.blockedTemplateHtml
825
799
  this._setValue(opts, 'appsec.blockedTemplateJson', maybeFile(options.appsec.blockedTemplateJson))
826
800
  this._optsUnprocessed['appsec.blockedTemplateJson'] = options.appsec.blockedTemplateJson
827
801
  this._setBoolean(opts, 'appsec.enabled', options.appsec.enabled)
802
+ let eventTracking = options.appsec.eventTracking?.mode
803
+ if (eventTracking) {
804
+ eventTracking = eventTracking.toLowerCase()
805
+ this._setValue(opts, 'appsec.eventTracking.enabled', ['extended', 'safe'].includes(eventTracking))
806
+ this._setValue(opts, 'appsec.eventTracking.mode', eventTracking)
807
+ }
828
808
  this._setString(opts, 'appsec.obfuscatorKeyRegex', options.appsec.obfuscatorKeyRegex)
829
809
  this._setString(opts, 'appsec.obfuscatorValueRegex', options.appsec.obfuscatorValueRegex)
830
810
  this._setBoolean(opts, 'appsec.rasp.enabled', options.appsec.rasp?.enabled)
@@ -890,11 +870,13 @@ class Config {
890
870
  }
891
871
  this._setBoolean(opts, 'reportHostname', options.reportHostname)
892
872
  this._setBoolean(opts, 'runtimeMetrics', options.runtimeMetrics)
873
+ this._setArray(opts, 'sampler.spanSamplingRules', reformatSpanSamplingRules(options.spanSamplingRules))
893
874
  this._setUnit(opts, 'sampleRate', coalesce(options.sampleRate, options.ingestion.sampleRate))
894
875
  const ingestion = options.ingestion || {}
895
876
  this._setValue(opts, 'sampler.rateLimit', coalesce(options.rateLimit, ingestion.rateLimit))
896
877
  this._setSamplingRule(opts, 'sampler.rules', options.samplingRules)
897
878
  this._setString(opts, 'service', options.service || tags.service)
879
+ this._setValue(opts, 'serviceMapping', options.serviceMapping)
898
880
  this._setString(opts, 'site', options.site)
899
881
  if (options.spanAttributeSchema) {
900
882
  this._setString(opts, 'spanAttributeSchema', validateNamingVersion(options.spanAttributeSchema))
@@ -914,7 +896,7 @@ class Config {
914
896
 
915
897
  _isCiVisibility () {
916
898
  return coalesce(
917
- this.options.isCiVisibility,
899
+ this._optionsArg.isCiVisibility,
918
900
  this._defaults.isCiVisibility
919
901
  )
920
902
  }
@@ -930,9 +912,9 @@ class Config {
930
912
  const DD_CIVISIBILITY_AGENTLESS_URL = process.env.DD_CIVISIBILITY_AGENTLESS_URL
931
913
  const url = DD_CIVISIBILITY_AGENTLESS_URL
932
914
  ? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
933
- : getAgentUrl(this._getTraceAgentUrl(), this.options)
915
+ : getAgentUrl(this._getTraceAgentUrl(), this._optionsArg)
934
916
  const DD_AGENT_HOST = coalesce(
935
- this.options.hostname,
917
+ this._optionsArg.hostname,
936
918
  process.env.DD_AGENT_HOST,
937
919
  process.env.DD_TRACE_AGENT_HOSTNAME,
938
920
  '127.0.0.1'
@@ -943,17 +925,17 @@ class Config {
943
925
  _getSpanComputePeerService () {
944
926
  const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
945
927
  coalesce(
946
- this.options.spanAttributeSchema,
928
+ this._optionsArg.spanAttributeSchema,
947
929
  process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
948
930
  )
949
931
  )
950
932
 
951
933
  const peerServiceSet = (
952
- this.options.hasOwnProperty('spanComputePeerService') ||
934
+ this._optionsArg.hasOwnProperty('spanComputePeerService') ||
953
935
  process.env.hasOwnProperty('DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED')
954
936
  )
955
937
  const peerServiceValue = coalesce(
956
- this.options.spanComputePeerService,
938
+ this._optionsArg.spanComputePeerService,
957
939
  process.env.DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
958
940
  )
959
941
 
@@ -984,7 +966,7 @@ class Config {
984
966
 
985
967
  _isTraceStatsComputationEnabled () {
986
968
  return coalesce(
987
- this.options.stats,
969
+ this._optionsArg.stats,
988
970
  process.env.DD_TRACE_STATS_COMPUTATION_ENABLED,
989
971
  getIsGCPFunction() || getIsAzureFunction()
990
972
  )
@@ -992,7 +974,7 @@ class Config {
992
974
 
993
975
  _getTraceAgentUrl () {
994
976
  return coalesce(
995
- this.options.url,
977
+ this._optionsArg.url,
996
978
  process.env.DD_TRACE_AGENT_URL,
997
979
  process.env.DD_TRACE_URL,
998
980
  null
@@ -1001,20 +983,21 @@ class Config {
1001
983
 
1002
984
  // handles values calculated from a mixture of options and env vars
1003
985
  _applyCalculated () {
1004
- const calc = this._calculated = {}
986
+ const calc = setHiddenProperty(this, '_calculated', {})
1005
987
 
1006
988
  const {
1007
- DD_CIVISIBILITY_AGENTLESS_URL
989
+ DD_CIVISIBILITY_AGENTLESS_URL,
990
+ DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED
1008
991
  } = process.env
1009
992
 
1010
993
  if (DD_CIVISIBILITY_AGENTLESS_URL) {
1011
994
  this._setValue(calc, 'url', new URL(DD_CIVISIBILITY_AGENTLESS_URL))
1012
995
  } else {
1013
- this._setValue(calc, 'url', getAgentUrl(this._getTraceAgentUrl(), this.options))
996
+ this._setValue(calc, 'url', getAgentUrl(this._getTraceAgentUrl(), this._optionsArg))
1014
997
  }
1015
998
  if (this._isCiVisibility()) {
1016
999
  this._setBoolean(calc, 'isEarlyFlakeDetectionEnabled',
1017
- coalesce(process.env.DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED, true))
1000
+ coalesce(DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED, true))
1018
1001
  this._setBoolean(calc, 'isIntelligentTestRunnerEnabled', isTrue(this._isCiVisibilityItrEnabled()))
1019
1002
  this._setBoolean(calc, 'isManualApiEnabled', this._isCiVisibilityManualApiEnabled())
1020
1003
  }
@@ -1023,11 +1006,24 @@ class Config {
1023
1006
  calc.isIntelligentTestRunnerEnabled && !isFalse(this._isCiVisibilityGitUploadEnabled()))
1024
1007
  this._setBoolean(calc, 'spanComputePeerService', this._getSpanComputePeerService())
1025
1008
  this._setBoolean(calc, 'stats.enabled', this._isTraceStatsComputationEnabled())
1009
+ const defaultPropagationStyle = this._getDefaultPropagationStyle(this._optionsArg)
1010
+ this._setValue(calc, 'tracePropagationStyle.inject', propagationStyle(
1011
+ 'inject',
1012
+ this._optionsArg.tracePropagationStyle
1013
+ ))
1014
+ this._setValue(calc, 'tracePropagationStyle.extract', propagationStyle(
1015
+ 'extract',
1016
+ this._optionsArg.tracePropagationStyle
1017
+ ))
1018
+ if (defaultPropagationStyle.length > 2) {
1019
+ calc['tracePropagationStyle.inject'] = calc['tracePropagationStyle.inject'] || defaultPropagationStyle
1020
+ calc['tracePropagationStyle.extract'] = calc['tracePropagationStyle.extract'] || defaultPropagationStyle
1021
+ }
1026
1022
  }
1027
1023
 
1028
1024
  _applyRemote (options) {
1029
- const opts = this._remote = this._remote || {}
1030
- this._remoteUnprocessed = {}
1025
+ const opts = setHiddenProperty(this, '_remote', this._remote || {})
1026
+ setHiddenProperty(this, '_remoteUnprocessed', {})
1031
1027
  const tags = {}
1032
1028
  const headerTags = options.tracing_header_tags
1033
1029
  ? options.tracing_header_tags.map(tag => {
@@ -1196,4 +1192,13 @@ function getAgentUrl (url, options) {
1196
1192
  }
1197
1193
  }
1198
1194
 
1195
+ function setHiddenProperty (obj, name, value) {
1196
+ Object.defineProperty(obj, name, {
1197
+ value,
1198
+ enumerable: false,
1199
+ writable: true
1200
+ })
1201
+ return obj[name]
1202
+ }
1203
+
1199
1204
  module.exports = Config
@@ -0,0 +1,44 @@
1
+ const DataStreamsContext = require('./data_streams_context')
2
+
3
+ class DataStreamsCheckpointer {
4
+ constructor (tracer) {
5
+ this.tracer = tracer
6
+ this.config = tracer._config
7
+ this.dsmProcessor = tracer._dataStreamsProcessor
8
+ }
9
+
10
+ setProduceCheckpoint (type, target, carrier) {
11
+ if (!this.config.dsmEnabled) return
12
+
13
+ const ctx = this.dsmProcessor.setCheckpoint(
14
+ ['type:' + type, 'topic:' + target, 'direction:out', 'manual_checkpoint:true'],
15
+ null,
16
+ DataStreamsContext.getDataStreamsContext(),
17
+ null
18
+ )
19
+ DataStreamsContext.setDataStreamsContext(ctx)
20
+
21
+ this.tracer.inject(ctx, 'text_map_dsm', carrier)
22
+ }
23
+
24
+ setConsumeCheckpoint (type, source, carrier) {
25
+ if (!this.config.dsmEnabled) return
26
+
27
+ const parentCtx = this.tracer.extract('text_map_dsm', carrier)
28
+ DataStreamsContext.setDataStreamsContext(parentCtx)
29
+
30
+ const ctx = this.dsmProcessor.setCheckpoint(
31
+ ['type:' + type, 'topic:' + source, 'direction:in', 'manual_checkpoint:true'],
32
+ null,
33
+ parentCtx,
34
+ null
35
+ )
36
+ DataStreamsContext.setDataStreamsContext(ctx)
37
+
38
+ return ctx
39
+ }
40
+ }
41
+
42
+ module.exports = {
43
+ DataStreamsCheckpointer
44
+ }