dd-trace 4.45.0 → 4.47.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 (153) hide show
  1. package/LICENSE-3rdparty.csv +2 -0
  2. package/index.d.ts +20 -8
  3. package/package.json +11 -5
  4. package/packages/datadog-instrumentations/src/aerospike.js +1 -1
  5. package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
  6. package/packages/datadog-instrumentations/src/aws-sdk.js +4 -4
  7. package/packages/datadog-instrumentations/src/body-parser.js +4 -4
  8. package/packages/datadog-instrumentations/src/cassandra-driver.js +2 -2
  9. package/packages/datadog-instrumentations/src/child_process.js +2 -2
  10. package/packages/datadog-instrumentations/src/connect.js +4 -4
  11. package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
  12. package/packages/datadog-instrumentations/src/couchbase.js +12 -12
  13. package/packages/datadog-instrumentations/src/cucumber.js +294 -56
  14. package/packages/datadog-instrumentations/src/dns.js +10 -10
  15. package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
  16. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +3 -3
  17. package/packages/datadog-instrumentations/src/express.js +4 -4
  18. package/packages/datadog-instrumentations/src/fastify.js +6 -6
  19. package/packages/datadog-instrumentations/src/fetch.js +1 -1
  20. package/packages/datadog-instrumentations/src/find-my-way.js +2 -2
  21. package/packages/datadog-instrumentations/src/fs.js +2 -2
  22. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +2 -2
  23. package/packages/datadog-instrumentations/src/grpc/client.js +4 -6
  24. package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
  25. package/packages/datadog-instrumentations/src/hapi.js +10 -13
  26. package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
  27. package/packages/datadog-instrumentations/src/http/client.js +3 -3
  28. package/packages/datadog-instrumentations/src/jest.js +8 -5
  29. package/packages/datadog-instrumentations/src/kafkajs.js +67 -31
  30. package/packages/datadog-instrumentations/src/knex.js +2 -2
  31. package/packages/datadog-instrumentations/src/koa.js +5 -5
  32. package/packages/datadog-instrumentations/src/ldapjs.js +1 -1
  33. package/packages/datadog-instrumentations/src/mariadb.js +8 -8
  34. package/packages/datadog-instrumentations/src/memcached.js +2 -2
  35. package/packages/datadog-instrumentations/src/microgateway-core.js +7 -5
  36. package/packages/datadog-instrumentations/src/mocha/common.js +1 -1
  37. package/packages/datadog-instrumentations/src/mocha/main.js +139 -53
  38. package/packages/datadog-instrumentations/src/mocha/utils.js +37 -18
  39. package/packages/datadog-instrumentations/src/mocha/worker.js +29 -1
  40. package/packages/datadog-instrumentations/src/mocha.js +4 -0
  41. package/packages/datadog-instrumentations/src/moleculer/server.js +2 -2
  42. package/packages/datadog-instrumentations/src/mongodb-core.js +7 -7
  43. package/packages/datadog-instrumentations/src/mongoose.js +5 -6
  44. package/packages/datadog-instrumentations/src/mysql.js +3 -3
  45. package/packages/datadog-instrumentations/src/mysql2.js +6 -6
  46. package/packages/datadog-instrumentations/src/net.js +2 -2
  47. package/packages/datadog-instrumentations/src/next.js +5 -5
  48. package/packages/datadog-instrumentations/src/openai.js +62 -71
  49. package/packages/datadog-instrumentations/src/oracledb.js +8 -8
  50. package/packages/datadog-instrumentations/src/passport-http.js +1 -1
  51. package/packages/datadog-instrumentations/src/passport-local.js +1 -1
  52. package/packages/datadog-instrumentations/src/passport-utils.js +1 -1
  53. package/packages/datadog-instrumentations/src/pg.js +60 -5
  54. package/packages/datadog-instrumentations/src/pino.js +4 -4
  55. package/packages/datadog-instrumentations/src/playwright.js +6 -4
  56. package/packages/datadog-instrumentations/src/redis.js +2 -2
  57. package/packages/datadog-instrumentations/src/restify.js +4 -4
  58. package/packages/datadog-instrumentations/src/rhea.js +4 -4
  59. package/packages/datadog-instrumentations/src/router.js +5 -5
  60. package/packages/datadog-instrumentations/src/sharedb.js +2 -2
  61. package/packages/datadog-instrumentations/src/vitest.js +188 -12
  62. package/packages/datadog-instrumentations/src/winston.js +2 -3
  63. package/packages/datadog-plugin-amqplib/src/consumer.js +1 -3
  64. package/packages/datadog-plugin-aws-sdk/src/base.js +33 -0
  65. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
  66. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -0
  67. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -1
  68. package/packages/datadog-plugin-cucumber/src/index.js +24 -1
  69. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +39 -10
  70. package/packages/datadog-plugin-cypress/src/support.js +4 -1
  71. package/packages/datadog-plugin-hapi/src/index.js +2 -2
  72. package/packages/datadog-plugin-http/src/client.js +1 -42
  73. package/packages/datadog-plugin-http2/src/client.js +1 -26
  74. package/packages/datadog-plugin-jest/src/index.js +18 -1
  75. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +20 -0
  76. package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -2
  77. package/packages/datadog-plugin-kafkajs/src/index.js +3 -1
  78. package/packages/datadog-plugin-mocha/src/index.js +18 -0
  79. package/packages/datadog-plugin-openai/src/index.js +85 -65
  80. package/packages/datadog-plugin-playwright/src/index.js +9 -0
  81. package/packages/datadog-plugin-rhea/src/consumer.js +1 -3
  82. package/packages/datadog-plugin-vitest/src/index.js +68 -3
  83. package/packages/datadog-shimmer/src/shimmer.js +144 -10
  84. package/packages/dd-trace/src/appsec/addresses.js +3 -1
  85. package/packages/dd-trace/src/appsec/blocking.js +23 -17
  86. package/packages/dd-trace/src/appsec/channels.js +4 -2
  87. package/packages/dd-trace/src/appsec/graphql.js +3 -1
  88. package/packages/dd-trace/src/appsec/iast/iast-log.js +2 -1
  89. package/packages/dd-trace/src/appsec/rasp/index.js +103 -0
  90. package/packages/dd-trace/src/appsec/rasp/sql_injection.js +86 -0
  91. package/packages/dd-trace/src/appsec/rasp/ssrf.js +37 -0
  92. package/packages/dd-trace/src/appsec/rasp/utils.js +63 -0
  93. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -0
  94. package/packages/dd-trace/src/appsec/remote_config/index.js +16 -7
  95. package/packages/dd-trace/src/appsec/remote_config/manager.js +93 -52
  96. package/packages/dd-trace/src/appsec/rule_manager.js +8 -0
  97. package/packages/dd-trace/src/appsec/telemetry.js +3 -3
  98. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +33 -14
  99. package/packages/dd-trace/src/appsec/waf/waf_manager.js +2 -1
  100. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +4 -0
  101. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +15 -1
  102. package/packages/dd-trace/src/config.js +100 -40
  103. package/packages/dd-trace/src/constants.js +11 -1
  104. package/packages/dd-trace/src/data_streams_context.js +3 -0
  105. package/packages/dd-trace/src/datastreams/fnv.js +23 -0
  106. package/packages/dd-trace/src/datastreams/pathway.js +12 -5
  107. package/packages/dd-trace/src/datastreams/processor.js +35 -0
  108. package/packages/dd-trace/src/datastreams/schemas/schema.js +8 -0
  109. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +125 -0
  110. package/packages/dd-trace/src/datastreams/schemas/schema_sampler.js +29 -0
  111. package/packages/dd-trace/src/debugger/devtools_client/config.js +24 -0
  112. package/packages/dd-trace/src/debugger/devtools_client/index.js +57 -0
  113. package/packages/dd-trace/src/debugger/devtools_client/inspector_promises_polyfill.js +23 -0
  114. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +164 -0
  115. package/packages/dd-trace/src/debugger/devtools_client/send.js +28 -0
  116. package/packages/dd-trace/src/debugger/devtools_client/session.js +7 -0
  117. package/packages/dd-trace/src/debugger/devtools_client/state.js +47 -0
  118. package/packages/dd-trace/src/debugger/devtools_client/status.js +109 -0
  119. package/packages/dd-trace/src/debugger/index.js +92 -0
  120. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +29 -2
  121. package/packages/dd-trace/src/exporters/common/request.js +1 -1
  122. package/packages/dd-trace/src/lambda/handler.js +1 -0
  123. package/packages/dd-trace/src/lambda/index.js +12 -1
  124. package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -6
  125. package/packages/dd-trace/src/payload-tagging/config/aws.json +30 -0
  126. package/packages/dd-trace/src/payload-tagging/config/index.js +30 -0
  127. package/packages/dd-trace/src/payload-tagging/index.js +93 -0
  128. package/packages/dd-trace/src/payload-tagging/tagging.js +83 -0
  129. package/packages/dd-trace/src/plugin_manager.js +11 -10
  130. package/packages/dd-trace/src/plugins/ci_plugin.js +33 -8
  131. package/packages/dd-trace/src/plugins/util/env.js +5 -2
  132. package/packages/dd-trace/src/plugins/util/test.js +24 -4
  133. package/packages/dd-trace/src/profiler.js +15 -5
  134. package/packages/dd-trace/src/profiling/config.js +7 -4
  135. package/packages/dd-trace/src/profiling/exporter_cli.js +13 -1
  136. package/packages/dd-trace/src/profiling/exporters/agent.js +8 -2
  137. package/packages/dd-trace/src/profiling/profiler.js +0 -9
  138. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +13 -0
  139. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +16 -0
  140. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +16 -0
  141. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +24 -0
  142. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +16 -0
  143. package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +48 -0
  144. package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +24 -0
  145. package/packages/dd-trace/src/profiling/profilers/events.js +108 -32
  146. package/packages/dd-trace/src/profiling/profilers/shared.js +5 -0
  147. package/packages/dd-trace/src/profiling/profilers/wall.js +9 -3
  148. package/packages/dd-trace/src/profiling/ssi-heuristics.js +59 -60
  149. package/packages/dd-trace/src/proxy.js +31 -24
  150. package/packages/dd-trace/src/span_stats.js +4 -2
  151. package/packages/dd-trace/src/telemetry/index.js +23 -6
  152. package/packages/dd-trace/src/telemetry/logs/index.js +20 -0
  153. package/packages/dd-trace/src/appsec/rasp.js +0 -176
@@ -3,7 +3,7 @@
3
3
  const fs = require('fs')
4
4
  const os = require('os')
5
5
  const uuid = require('crypto-randomuuid') // we need to keep the old uuid dep because of cypress
6
- const URL = require('url').URL
6
+ const { URL } = require('url')
7
7
  const log = require('./log')
8
8
  const pkg = require('./pkg')
9
9
  const coalesce = require('koalas')
@@ -18,6 +18,7 @@ const { updateConfig } = require('./telemetry')
18
18
  const telemetryMetrics = require('./telemetry/metrics')
19
19
  const { getIsGCPFunction, getIsAzureFunction } = require('./serverless')
20
20
  const { ORIGIN_KEY } = require('./constants')
21
+ const { appendRules } = require('./payload-tagging/config')
21
22
 
22
23
  const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
23
24
 
@@ -173,6 +174,21 @@ function validateNamingVersion (versionString) {
173
174
  return versionString
174
175
  }
175
176
 
177
+ /**
178
+ * Given a string of comma-separated paths, return the array of paths.
179
+ * If a blank path is provided a null is returned to signal that the feature is disabled.
180
+ * An empty array means the feature is enabled but that no rules need to be applied.
181
+ *
182
+ * @param {string} input
183
+ * @returns {[string]|null}
184
+ */
185
+ function splitJSONPathRules (input) {
186
+ if (!input) return null
187
+ if (Array.isArray(input)) return input
188
+ if (input === 'all') return []
189
+ return input.split(',')
190
+ }
191
+
176
192
  // Shallow clone with property name remapping
177
193
  function remapify (input, mappings) {
178
194
  if (!input) return
@@ -281,6 +297,26 @@ class Config {
281
297
  null
282
298
  )
283
299
 
300
+ const DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING = splitJSONPathRules(
301
+ coalesce(
302
+ process.env.DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING,
303
+ options.cloudPayloadTagging?.request,
304
+ ''
305
+ ))
306
+
307
+ const DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING = splitJSONPathRules(
308
+ coalesce(
309
+ process.env.DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING,
310
+ options.cloudPayloadTagging?.response,
311
+ ''
312
+ ))
313
+
314
+ const DD_TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH = coalesce(
315
+ process.env.DD_TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH,
316
+ options.cloudPayloadTagging?.maxDepth,
317
+ 10
318
+ )
319
+
284
320
  // TODO: refactor
285
321
  this.apiKey = DD_API_KEY
286
322
 
@@ -291,6 +327,15 @@ class Config {
291
327
  type: DD_INSTRUMENTATION_INSTALL_TYPE
292
328
  }
293
329
 
330
+ this.cloudPayloadTagging = {
331
+ requestsEnabled: !!DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING,
332
+ responsesEnabled: !!DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING,
333
+ maxDepth: DD_TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH,
334
+ rules: appendRules(
335
+ DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING, DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING
336
+ )
337
+ }
338
+
294
339
  this._applyDefaults()
295
340
  this._applyEnvironment()
296
341
  this._applyOptions(options)
@@ -423,6 +468,7 @@ class Config {
423
468
  this._setValue(defaults, 'dogstatsd.hostname', '127.0.0.1')
424
469
  this._setValue(defaults, 'dogstatsd.port', '8125')
425
470
  this._setValue(defaults, 'dsmEnabled', false)
471
+ this._setValue(defaults, 'dynamicInstrumentationEnabled', false)
426
472
  this._setValue(defaults, 'env', undefined)
427
473
  this._setValue(defaults, 'experimental.enableGetRumData', false)
428
474
  this._setValue(defaults, 'experimental.exporter', undefined)
@@ -441,13 +487,17 @@ class Config {
441
487
  this._setValue(defaults, 'iast.redactionValuePattern', null)
442
488
  this._setValue(defaults, 'iast.requestSampling', 30)
443
489
  this._setValue(defaults, 'iast.telemetryVerbosity', 'INFORMATION')
490
+ this._setValue(defaults, 'injectionEnabled', [])
444
491
  this._setValue(defaults, 'isAzureFunction', false)
445
492
  this._setValue(defaults, 'isCiVisibility', false)
446
493
  this._setValue(defaults, 'isEarlyFlakeDetectionEnabled', false)
494
+ this._setValue(defaults, 'isFlakyTestRetriesEnabled', false)
495
+ this._setValue(defaults, 'flakyTestRetriesCount', 5)
447
496
  this._setValue(defaults, 'isGCPFunction', false)
448
497
  this._setValue(defaults, 'isGitUploadEnabled', false)
449
498
  this._setValue(defaults, 'isIntelligentTestRunnerEnabled', false)
450
499
  this._setValue(defaults, 'isManualApiEnabled', false)
500
+ this._setValue(defaults, 'ciVisibilityTestSessionName', '')
451
501
  this._setValue(defaults, 'logInjection', false)
452
502
  this._setValue(defaults, 'lookup', undefined)
453
503
  this._setValue(defaults, 'memcachedCommandEnabled', false)
@@ -459,8 +509,6 @@ class Config {
459
509
  this._setValue(defaults, 'profiling.enabled', undefined)
460
510
  this._setValue(defaults, 'profiling.exporters', 'agent')
461
511
  this._setValue(defaults, 'profiling.sourceMap', true)
462
- this._setValue(defaults, 'profiling.ssi', false)
463
- this._setValue(defaults, 'profiling.heuristicsEnabled', false)
464
512
  this._setValue(defaults, 'profiling.longLivedThreshold', undefined)
465
513
  this._setValue(defaults, 'protocolVersion', '0.4')
466
514
  this._setValue(defaults, 'queryStringObfuscation', qsRegex)
@@ -527,6 +575,7 @@ class Config {
527
575
  DD_DBM_PROPAGATION_MODE,
528
576
  DD_DOGSTATSD_HOSTNAME,
529
577
  DD_DOGSTATSD_PORT,
578
+ DD_DYNAMIC_INSTRUMENTATION_ENABLED,
530
579
  DD_ENV,
531
580
  DD_EXPERIMENTAL_API_SECURITY_ENABLED,
532
581
  DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED,
@@ -656,6 +705,7 @@ class Config {
656
705
  this._setString(env, 'dogstatsd.hostname', DD_DOGSTATSD_HOSTNAME)
657
706
  this._setString(env, 'dogstatsd.port', DD_DOGSTATSD_PORT)
658
707
  this._setBoolean(env, 'dsmEnabled', DD_DATA_STREAMS_ENABLED)
708
+ this._setBoolean(env, 'dynamicInstrumentationEnabled', DD_DYNAMIC_INSTRUMENTATION_ENABLED)
659
709
  this._setString(env, 'env', DD_ENV || tags.env)
660
710
  this._setBoolean(env, 'experimental.enableGetRumData', DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED)
661
711
  this._setString(env, 'experimental.exporter', DD_TRACE_EXPERIMENTAL_EXPORTER)
@@ -681,6 +731,7 @@ class Config {
681
731
  }
682
732
  this._envUnprocessed['iast.requestSampling'] = DD_IAST_REQUEST_SAMPLING
683
733
  this._setString(env, 'iast.telemetryVerbosity', DD_IAST_TELEMETRY_VERBOSITY)
734
+ this._setArray(env, 'injectionEnabled', DD_INJECTION_ENABLED)
684
735
  this._setBoolean(env, 'isAzureFunction', getIsAzureFunction())
685
736
  this._setBoolean(env, 'isGCPFunction', getIsGCPFunction())
686
737
  this._setBoolean(env, 'logInjection', DD_LOGS_INJECTION)
@@ -696,18 +747,18 @@ class Config {
696
747
  this._envUnprocessed.peerServiceMapping = DD_TRACE_PEER_SERVICE_MAPPING
697
748
  }
698
749
  this._setString(env, 'port', DD_TRACE_AGENT_PORT)
699
- this._setBoolean(env, 'profiling.enabled', coalesce(DD_EXPERIMENTAL_PROFILING_ENABLED, DD_PROFILING_ENABLED))
750
+ const profilingEnabledEnv = coalesce(DD_EXPERIMENTAL_PROFILING_ENABLED, DD_PROFILING_ENABLED)
751
+ const profilingEnabled = isTrue(profilingEnabledEnv)
752
+ ? 'true'
753
+ : isFalse(profilingEnabledEnv)
754
+ ? 'false'
755
+ : profilingEnabledEnv === 'auto' ? 'auto' : undefined
756
+ this._setString(env, 'profiling.enabled', profilingEnabled)
700
757
  this._setString(env, 'profiling.exporters', DD_PROFILING_EXPORTERS)
701
758
  this._setBoolean(env, 'profiling.sourceMap', DD_PROFILING_SOURCE_MAP && !isFalse(DD_PROFILING_SOURCE_MAP))
702
- if (DD_PROFILING_ENABLED === 'auto' || DD_INJECTION_ENABLED) {
703
- this._setBoolean(env, 'profiling.ssi', true)
704
- if (DD_PROFILING_ENABLED === 'auto' || DD_INJECTION_ENABLED.split(',').includes('profiler')) {
705
- this._setBoolean(env, 'profiling.heuristicsEnabled', true)
706
- }
707
- if (DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD) {
708
- // This is only used in testing to not have to wait 30s
709
- this._setValue(env, 'profiling.longLivedThreshold', Number(DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD))
710
- }
759
+ if (DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD) {
760
+ // This is only used in testing to not have to wait 30s
761
+ this._setValue(env, 'profiling.longLivedThreshold', Number(DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD))
711
762
  }
712
763
 
713
764
  this._setString(env, 'protocolVersion', DD_TRACE_AGENT_PROTOCOL_VERSION)
@@ -762,12 +813,7 @@ class Config {
762
813
  this._setBoolean(env, 'telemetry.dependencyCollection', DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED)
763
814
  this._setValue(env, 'telemetry.heartbeatInterval', maybeInt(Math.floor(DD_TELEMETRY_HEARTBEAT_INTERVAL * 1000)))
764
815
  this._envUnprocessed['telemetry.heartbeatInterval'] = DD_TELEMETRY_HEARTBEAT_INTERVAL * 1000
765
- const hasTelemetryLogsUsingFeatures =
766
- env['iast.enabled'] || env['profiling.enabled'] || env['profiling.heuristicsEnabled']
767
- ? true
768
- : undefined
769
- this._setBoolean(env, 'telemetry.logCollection', coalesce(DD_TELEMETRY_LOG_COLLECTION_ENABLED,
770
- hasTelemetryLogsUsingFeatures))
816
+ this._setBoolean(env, 'telemetry.logCollection', DD_TELEMETRY_LOG_COLLECTION_ENABLED)
771
817
  this._setBoolean(env, 'telemetry.metrics', DD_TELEMETRY_METRICS_ENABLED)
772
818
  this._setBoolean(env, 'traceId128BitGenerationEnabled', DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
773
819
  this._setBoolean(env, 'traceId128BitLoggingEnabled', DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
@@ -827,11 +873,11 @@ class Config {
827
873
  this._setString(opts, 'dogstatsd.port', options.dogstatsd.port)
828
874
  }
829
875
  this._setBoolean(opts, 'dsmEnabled', options.dsmEnabled)
876
+ this._setBoolean(opts, 'dynamicInstrumentationEnabled', options.experimental?.dynamicInstrumentationEnabled)
830
877
  this._setString(opts, 'env', options.env || tags.env)
831
- this._setBoolean(opts, 'experimental.enableGetRumData',
832
- options.experimental && options.experimental.enableGetRumData)
833
- this._setString(opts, 'experimental.exporter', options.experimental && options.experimental.exporter)
834
- this._setBoolean(opts, 'experimental.runtimeId', options.experimental && options.experimental.runtimeId)
878
+ this._setBoolean(opts, 'experimental.enableGetRumData', options.experimental?.enableGetRumData)
879
+ this._setString(opts, 'experimental.exporter', options.experimental?.exporter)
880
+ this._setBoolean(opts, 'experimental.runtimeId', options.experimental?.runtimeId)
835
881
  this._setValue(opts, 'flushInterval', maybeInt(options.flushInterval))
836
882
  this._optsUnprocessed.flushInterval = options.flushInterval
837
883
  this._setValue(opts, 'flushMinSpans', maybeInt(options.flushMinSpans))
@@ -862,7 +908,10 @@ class Config {
862
908
  this._setValue(opts, 'peerServiceMapping', options.peerServiceMapping)
863
909
  this._setBoolean(opts, 'plugins', options.plugins)
864
910
  this._setString(opts, 'port', options.port)
865
- this._setBoolean(opts, 'profiling.enabled', options.profiling)
911
+ const strProfiling = String(options.profiling)
912
+ if (['true', 'false', 'auto'].includes(strProfiling)) {
913
+ this._setString(opts, 'profiling.enabled', strProfiling)
914
+ }
866
915
  this._setString(opts, 'protocolVersion', options.protocolVersion)
867
916
  if (options.remoteConfig) {
868
917
  this._setValue(opts, 'remoteConfig.pollInterval', maybeFloat(options.remoteConfig.pollInterval))
@@ -885,10 +934,6 @@ class Config {
885
934
  this._setBoolean(opts, 'spanRemoveIntegrationFromService', options.spanRemoveIntegrationFromService)
886
935
  this._setBoolean(opts, 'startupLogs', options.startupLogs)
887
936
  this._setTags(opts, 'tags', tags)
888
- const hasTelemetryLogsUsingFeatures =
889
- (options.iast && (options.iast === true || options.iast?.enabled === true)) ||
890
- (options.profiling && options.profiling === true)
891
- this._setBoolean(opts, 'telemetry.logCollection', hasTelemetryLogsUsingFeatures)
892
937
  this._setBoolean(opts, 'traceId128BitGenerationEnabled', options.traceId128BitGenerationEnabled)
893
938
  this._setBoolean(opts, 'traceId128BitLoggingEnabled', options.traceId128BitLoggingEnabled)
894
939
  this._setString(opts, 'version', options.version || tags.version)
@@ -958,10 +1003,10 @@ class Config {
958
1003
  }
959
1004
 
960
1005
  _isCiVisibilityManualApiEnabled () {
961
- return isTrue(coalesce(
1006
+ return coalesce(
962
1007
  process.env.DD_CIVISIBILITY_MANUAL_API_ENABLED,
963
- false
964
- ))
1008
+ true
1009
+ )
965
1010
  }
966
1011
 
967
1012
  _isTraceStatsComputationEnabled () {
@@ -987,7 +1032,10 @@ class Config {
987
1032
 
988
1033
  const {
989
1034
  DD_CIVISIBILITY_AGENTLESS_URL,
990
- DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED
1035
+ DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED,
1036
+ DD_CIVISIBILITY_FLAKY_RETRY_ENABLED,
1037
+ DD_CIVISIBILITY_FLAKY_RETRY_COUNT,
1038
+ DD_TEST_SESSION_NAME
991
1039
  } = process.env
992
1040
 
993
1041
  if (DD_CIVISIBILITY_AGENTLESS_URL) {
@@ -998,8 +1046,12 @@ class Config {
998
1046
  if (this._isCiVisibility()) {
999
1047
  this._setBoolean(calc, 'isEarlyFlakeDetectionEnabled',
1000
1048
  coalesce(DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED, true))
1049
+ this._setBoolean(calc, 'isFlakyTestRetriesEnabled',
1050
+ coalesce(DD_CIVISIBILITY_FLAKY_RETRY_ENABLED, true))
1051
+ this._setValue(calc, 'flakyTestRetriesCount', coalesce(maybeInt(DD_CIVISIBILITY_FLAKY_RETRY_COUNT), 5))
1001
1052
  this._setBoolean(calc, 'isIntelligentTestRunnerEnabled', isTrue(this._isCiVisibilityItrEnabled()))
1002
- this._setBoolean(calc, 'isManualApiEnabled', this._isCiVisibilityManualApiEnabled())
1053
+ this._setBoolean(calc, 'isManualApiEnabled', !isFalse(this._isCiVisibilityManualApiEnabled()))
1054
+ this._setString(calc, 'ciVisibilityTestSessionName', DD_TEST_SESSION_NAME)
1003
1055
  }
1004
1056
  this._setString(calc, 'dogstatsd.hostname', this._getHostname())
1005
1057
  this._setBoolean(calc, 'isGitUploadEnabled',
@@ -1019,6 +1071,13 @@ class Config {
1019
1071
  calc['tracePropagationStyle.inject'] = calc['tracePropagationStyle.inject'] || defaultPropagationStyle
1020
1072
  calc['tracePropagationStyle.extract'] = calc['tracePropagationStyle.extract'] || defaultPropagationStyle
1021
1073
  }
1074
+
1075
+ const iastEnabled = coalesce(this._options['iast.enabled'], this._env['iast.enabled'])
1076
+ const profilingEnabled = coalesce(this._options['profiling.enabled'], this._env['profiling.enabled'])
1077
+ const injectionIncludesProfiler = (this._env.injectionEnabled || []).includes('profiler')
1078
+ if (iastEnabled || ['auto', 'true'].includes(profilingEnabled) || injectionIncludesProfiler) {
1079
+ this._setBoolean(calc, 'telemetry.logCollection', true)
1080
+ }
1022
1081
  }
1023
1082
 
1024
1083
  _applyRemote (options) {
@@ -1143,17 +1202,18 @@ class Config {
1143
1202
  for (const name in this._defaults) {
1144
1203
  for (let i = 0; i < containers.length; i++) {
1145
1204
  const container = containers[i]
1146
- const origin = origins[i]
1147
- const unprocessed = unprocessedValues[i]
1205
+ const value = container[name]
1148
1206
 
1149
- if ((container[name] !== null && container[name] !== undefined) || container === this._defaults) {
1150
- if (get(this, name) === container[name] && has(this, name)) break
1207
+ if ((value !== null && value !== undefined) || container === this._defaults) {
1208
+ if (get(this, name) === value && has(this, name)) break
1151
1209
 
1152
- let value = container[name]
1153
1210
  set(this, name, value)
1154
- value = unprocessed[name] || value
1155
1211
 
1156
- changes.push({ name, value, origin })
1212
+ changes.push({
1213
+ name,
1214
+ value: unprocessedValues[i][name] || value,
1215
+ origin: origins[i]
1216
+ })
1157
1217
 
1158
1218
  break
1159
1219
  }
@@ -34,5 +34,15 @@ module.exports = {
34
34
  SCI_REPOSITORY_URL: '_dd.git.repository_url',
35
35
  SCI_COMMIT_SHA: '_dd.git.commit.sha',
36
36
  APM_TRACING_ENABLED_KEY: '_dd.apm.enabled',
37
- APPSEC_PROPAGATION_KEY: '_dd.p.appsec'
37
+ APPSEC_PROPAGATION_KEY: '_dd.p.appsec',
38
+ PAYLOAD_TAG_REQUEST_PREFIX: 'aws.request.body',
39
+ PAYLOAD_TAG_RESPONSE_PREFIX: 'aws.response.body',
40
+ PAYLOAD_TAGGING_MAX_TAGS: 758,
41
+ SCHEMA_DEFINITION: 'schema.definition',
42
+ SCHEMA_WEIGHT: 'schema.weight',
43
+ SCHEMA_TYPE: 'schema.type',
44
+ SCHEMA_ID: 'schema.id',
45
+ SCHEMA_TOPIC: 'schema.topic',
46
+ SCHEMA_OPERATION: 'schema.operation',
47
+ SCHEMA_NAME: 'schema.name'
38
48
  }
@@ -1,4 +1,5 @@
1
1
  const { storage } = require('../../datadog-core')
2
+ const log = require('./log')
2
3
 
3
4
  function getDataStreamsContext () {
4
5
  const store = storage.getStore()
@@ -6,6 +7,8 @@ function getDataStreamsContext () {
6
7
  }
7
8
 
8
9
  function setDataStreamsContext (dataStreamsContext) {
10
+ log.debug(() => `Setting new DSM Context: ${JSON.stringify(dataStreamsContext)}.`)
11
+
9
12
  if (dataStreamsContext) storage.enterWith({ ...(storage.getStore()), dataStreamsContext })
10
13
  }
11
14
 
@@ -0,0 +1,23 @@
1
+ const FNV_64_PRIME = BigInt('0x100000001B3')
2
+ const FNV1_64_INIT = BigInt('0xCBF29CE484222325')
3
+
4
+ function fnv (data, hvalInit, fnvPrime, fnvSize) {
5
+ let hval = hvalInit
6
+ for (const byte of data) {
7
+ hval = (hval * fnvPrime) % fnvSize
8
+ hval = hval ^ BigInt(byte)
9
+ }
10
+ return hval
11
+ }
12
+
13
+ function fnv64 (data) {
14
+ if (!Buffer.isBuffer(data)) {
15
+ data = Buffer.from(data, 'utf-8')
16
+ }
17
+ const byteArray = new Uint8Array(data)
18
+ return fnv(byteArray, FNV1_64_INIT, FNV_64_PRIME, BigInt(2) ** BigInt(64))
19
+ }
20
+
21
+ module.exports = {
22
+ fnv64
23
+ }
@@ -4,6 +4,8 @@
4
4
  const crypto = require('crypto')
5
5
  const { encodeVarint, decodeVarint } = require('./encoding')
6
6
  const LRUCache = require('lru-cache')
7
+ const log = require('../log')
8
+ const pick = require('../../../datadog-core/src/utils/src/pick')
7
9
 
8
10
  const options = { max: 500 }
9
11
  const cache = new LRUCache(options)
@@ -11,6 +13,8 @@ const cache = new LRUCache(options)
11
13
  const CONTEXT_PROPAGATION_KEY = 'dd-pathway-ctx'
12
14
  const CONTEXT_PROPAGATION_KEY_BASE64 = 'dd-pathway-ctx-base64'
13
15
 
16
+ const logKeys = [CONTEXT_PROPAGATION_KEY, CONTEXT_PROPAGATION_KEY_BASE64]
17
+
14
18
  function shaHash (checkpointString) {
15
19
  const hash = crypto.createHash('md5').update(checkpointString).digest('hex').slice(0, 16)
16
20
  return Buffer.from(hash, 'hex')
@@ -80,9 +84,13 @@ class DsmPathwayCodec {
80
84
  return
81
85
  }
82
86
  carrier[CONTEXT_PROPAGATION_KEY_BASE64] = encodePathwayContextBase64(dataStreamsContext)
87
+
88
+ log.debug(() => `Injected into DSM carrier: ${JSON.stringify(pick(carrier, logKeys))}.`)
83
89
  }
84
90
 
85
91
  static decode (carrier) {
92
+ log.debug(() => `Attempting extract from DSM carrier: ${JSON.stringify(pick(carrier, logKeys))}.`)
93
+
86
94
  if (carrier == null) return
87
95
 
88
96
  let ctx
@@ -97,13 +105,12 @@ class DsmPathwayCodec {
97
105
  // pass
98
106
  }
99
107
  // cover case where base64 context was received under wrong key
100
- if (!ctx) ctx = decodePathwayContextBase64(carrier[CONTEXT_PROPAGATION_KEY])
108
+ if (!ctx && CONTEXT_PROPAGATION_KEY in carrier) {
109
+ ctx = decodePathwayContextBase64(carrier[CONTEXT_PROPAGATION_KEY])
110
+ }
101
111
  }
102
- return ctx
103
- }
104
112
 
105
- static contextExists (carrier) {
106
- return CONTEXT_PROPAGATION_KEY_BASE64 in carrier || CONTEXT_PROPAGATION_KEY in carrier
113
+ return ctx
107
114
  }
108
115
  }
109
116
 
@@ -9,6 +9,9 @@ const { DataStreamsWriter } = require('./writer')
9
9
  const { computePathwayHash } = require('./pathway')
10
10
  const { types } = require('util')
11
11
  const { PATHWAY_HASH } = require('../../../../ext/tags')
12
+ const { SchemaBuilder } = require('./schemas/schema_builder')
13
+ const { SchemaSampler } = require('./schemas/schema_sampler')
14
+ const log = require('../log')
12
15
 
13
16
  const ENTRY_PARENT_HASH = Buffer.from('0000000000000000', 'hex')
14
17
 
@@ -194,6 +197,7 @@ class DataStreamsProcessor {
194
197
  this.version = version || ''
195
198
  this.sequence = 0
196
199
  this.flushInterval = flushInterval
200
+ this._schemaSamplers = {}
197
201
 
198
202
  if (this.enabled) {
199
203
  this.timer = setInterval(this.onInterval.bind(this), flushInterval)
@@ -269,6 +273,11 @@ class DataStreamsProcessor {
269
273
  closestOppositeDirectionHash = parentHash
270
274
  closestOppositeDirectionEdgeStart = edgeStartNs
271
275
  }
276
+ log.debug(
277
+ () => `Setting DSM Checkpoint from extracted parent context with hash: ${parentHash} and edge tags: ${edgeTags}`
278
+ )
279
+ } else {
280
+ log.debug(() => 'Setting DSM Checkpoint with empty parent context.')
272
281
  }
273
282
  const hash = computePathwayHash(this.service, this.env, edgeTags, parentHash)
274
283
  const edgeLatencyNs = nowNs - edgeStartNs
@@ -352,6 +361,32 @@ class DataStreamsProcessor {
352
361
  setUrl (url) {
353
362
  this.writer.setUrl(url)
354
363
  }
364
+
365
+ trySampleSchema (topic) {
366
+ const nowMs = Date.now()
367
+
368
+ if (!this._schemaSamplers[topic]) {
369
+ this._schemaSamplers[topic] = new SchemaSampler()
370
+ }
371
+
372
+ const sampler = this._schemaSamplers[topic]
373
+ return sampler.trySample(nowMs)
374
+ }
375
+
376
+ canSampleSchema (topic) {
377
+ const nowMs = Date.now()
378
+
379
+ if (!this._schemaSamplers[topic]) {
380
+ this._schemaSamplers[topic] = new SchemaSampler()
381
+ }
382
+
383
+ const sampler = this._schemaSamplers[topic]
384
+ return sampler.canSample(nowMs)
385
+ }
386
+
387
+ getSchema (schemaName, iterator) {
388
+ return SchemaBuilder.getSchema(schemaName, iterator)
389
+ }
355
390
  }
356
391
 
357
392
  module.exports = {
@@ -0,0 +1,8 @@
1
+ class Schema {
2
+ constructor (definition, id) {
3
+ this.definition = definition
4
+ this.id = id
5
+ }
6
+ }
7
+
8
+ module.exports = { Schema }
@@ -0,0 +1,125 @@
1
+ const LRUCache = require('lru-cache')
2
+ const { fnv64 } = require('../fnv')
3
+ const { Schema } = require('./schema')
4
+
5
+ const maxDepth = 10
6
+ const maxProperties = 1000
7
+ const CACHE = new LRUCache({ max: 32 })
8
+
9
+ class SchemaBuilder {
10
+ constructor (iterator) {
11
+ this.schema = new OpenApiSchema()
12
+ this.iterator = iterator
13
+ this.proerties = 0
14
+ }
15
+
16
+ addProperty (schemaName, fieldName, isArray, type, description, ref, format, enumValues) {
17
+ if (this.properties >= maxProperties) {
18
+ return false
19
+ }
20
+ this.properties += 1
21
+ let property = new OpenApiSchema.PROPERTY(type, description, ref, format, enumValues, null)
22
+ if (isArray) {
23
+ property = new OpenApiSchema.PROPERTY('array', null, null, null, null, property)
24
+ }
25
+ this.schema.components.schemas[schemaName].properties[fieldName] = property
26
+ return true
27
+ }
28
+
29
+ build () {
30
+ this.iterator.iterateOverSchema(this)
31
+ const noNones = convertToJsonCompatible(this.schema)
32
+ const definition = jsonStringify(noNones)
33
+ const id = fnv64(Buffer.from(definition, 'utf-8')).toString()
34
+ return new Schema(definition, id)
35
+ }
36
+
37
+ shouldExtractSchema (schemaName, depth) {
38
+ if (depth > maxDepth) {
39
+ return false
40
+ }
41
+ if (schemaName in this.schema.components.schemas) {
42
+ return false
43
+ }
44
+ this.schema.components.schemas[schemaName] = new OpenApiSchema.SCHEMA()
45
+ return true
46
+ }
47
+
48
+ static getSchema (schemaName, iterator) {
49
+ if (!CACHE.has(schemaName)) {
50
+ CACHE.set(schemaName, new SchemaBuilder(iterator).build())
51
+ }
52
+ return CACHE.get(schemaName)
53
+ }
54
+ }
55
+
56
+ class OpenApiSchema {
57
+ constructor () {
58
+ this.openapi = '3.0.0'
59
+ this.components = new OpenApiComponents()
60
+ }
61
+ }
62
+
63
+ OpenApiSchema.SCHEMA = class {
64
+ constructor () {
65
+ this.type = 'object'
66
+ this.properties = {}
67
+ }
68
+ }
69
+
70
+ OpenApiSchema.PROPERTY = class {
71
+ constructor (type, description = null, ref = null, format = null, enumValues = null, items = null) {
72
+ this.type = type
73
+ this.description = description
74
+ this.$ref = ref
75
+ this.format = format
76
+ this.enum = enumValues
77
+ this.items = items
78
+ }
79
+ }
80
+
81
+ class OpenApiComponents {
82
+ constructor () {
83
+ this.schemas = {}
84
+ }
85
+ }
86
+
87
+ function convertToJsonCompatible (obj) {
88
+ if (Array.isArray(obj)) {
89
+ return obj.filter(item => item !== null).map(item => convertToJsonCompatible(item))
90
+ } else if (obj && typeof obj === 'object') {
91
+ const jsonObj = {}
92
+ for (const [key, value] of Object.entries(obj)) {
93
+ if (value !== null) {
94
+ jsonObj[key] = convertToJsonCompatible(value)
95
+ }
96
+ }
97
+ return jsonObj
98
+ }
99
+ return obj
100
+ }
101
+
102
+ function convertKey (key) {
103
+ if (key === 'enumValues') {
104
+ return 'enum'
105
+ }
106
+ return key
107
+ }
108
+
109
+ function jsonStringify (obj, indent = 2) {
110
+ // made to stringify json exactly similar to python / java in order for hashing to be the same
111
+ const jsonString = JSON.stringify(obj, (_, value) => value, indent)
112
+ return jsonString.replace(/^ +/gm, ' ') // Replace leading spaces with single space
113
+ .replace(/\n/g, '') // Remove newlines
114
+ .replace(/{ /g, '{') // Remove space after '{'
115
+ .replace(/ }/g, '}') // Remove space before '}'
116
+ .replace(/\[ /g, '[') // Remove space after '['
117
+ .replace(/ \]/g, ']') // Remove space before ']'
118
+ }
119
+
120
+ module.exports = {
121
+ SchemaBuilder,
122
+ OpenApiSchema,
123
+ convertToJsonCompatible,
124
+ convertKey
125
+ }
@@ -0,0 +1,29 @@
1
+ const SAMPLE_INTERVAL_MILLIS = 30 * 1000
2
+
3
+ class SchemaSampler {
4
+ constructor () {
5
+ this.weight = 0
6
+ this.lastSampleMs = 0
7
+ }
8
+
9
+ trySample (currentTimeMs) {
10
+ if (currentTimeMs >= this.lastSampleMs + SAMPLE_INTERVAL_MILLIS) {
11
+ if (currentTimeMs >= this.lastSampleMs + SAMPLE_INTERVAL_MILLIS) {
12
+ this.lastSampleMs = currentTimeMs
13
+ const weight = this.weight
14
+ this.weight = 0
15
+ return weight
16
+ }
17
+ }
18
+ return 0
19
+ }
20
+
21
+ canSample (currentTimeMs) {
22
+ this.weight += 1
23
+ return currentTimeMs >= this.lastSampleMs + SAMPLE_INTERVAL_MILLIS
24
+ }
25
+ }
26
+
27
+ module.exports = {
28
+ SchemaSampler
29
+ }
@@ -0,0 +1,24 @@
1
+ 'use strict'
2
+
3
+ const { workerData: { config: parentConfig, parentThreadId, configPort } } = require('node:worker_threads')
4
+ const { format } = require('node:url')
5
+ const log = require('../../log')
6
+
7
+ const config = module.exports = {
8
+ runtimeId: parentConfig.tags['runtime-id'],
9
+ service: parentConfig.service,
10
+ parentThreadId
11
+ }
12
+
13
+ updateUrl(parentConfig)
14
+
15
+ configPort.on('message', updateUrl)
16
+ configPort.on('messageerror', (err) => log.error(err))
17
+
18
+ function updateUrl (updates) {
19
+ config.url = updates.url || format({
20
+ protocol: 'http:',
21
+ hostname: updates.hostname || 'localhost',
22
+ port: updates.port
23
+ })
24
+ }