dd-trace 5.61.1 → 5.63.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 (215) hide show
  1. package/README.md +0 -5
  2. package/package.json +2 -2
  3. package/packages/datadog-instrumentations/src/ai.js +140 -0
  4. package/packages/datadog-instrumentations/src/apollo-server.js +50 -8
  5. package/packages/datadog-instrumentations/src/aws-sdk.js +49 -60
  6. package/packages/datadog-instrumentations/src/couchbase.js +102 -65
  7. package/packages/datadog-instrumentations/src/fastify.js +61 -55
  8. package/packages/datadog-instrumentations/src/graphql.js +90 -122
  9. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  10. package/packages/datadog-instrumentations/src/helpers/register.js +2 -22
  11. package/packages/datadog-instrumentations/src/hono.js +11 -8
  12. package/packages/datadog-instrumentations/src/http2/server.js +14 -20
  13. package/packages/datadog-instrumentations/src/knex.js +15 -17
  14. package/packages/datadog-instrumentations/src/microgateway-core.js +16 -15
  15. package/packages/datadog-instrumentations/src/mongodb-core.js +35 -32
  16. package/packages/datadog-instrumentations/src/mongodb.js +9 -13
  17. package/packages/datadog-instrumentations/src/mongoose.js +25 -29
  18. package/packages/datadog-instrumentations/src/next.js +4 -8
  19. package/packages/datadog-instrumentations/src/openai.js +0 -2
  20. package/packages/datadog-instrumentations/src/oracledb.js +39 -33
  21. package/packages/datadog-instrumentations/src/pg.js +38 -48
  22. package/packages/datadog-plugin-aerospike/src/index.js +11 -11
  23. package/packages/datadog-plugin-ai/src/index.js +17 -0
  24. package/packages/datadog-plugin-ai/src/tracing.js +33 -0
  25. package/packages/datadog-plugin-ai/src/utils.js +28 -0
  26. package/packages/datadog-plugin-amqp10/src/consumer.js +2 -2
  27. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  28. package/packages/datadog-plugin-amqp10/src/producer.js +3 -3
  29. package/packages/datadog-plugin-amqplib/src/client.js +3 -3
  30. package/packages/datadog-plugin-amqplib/src/consumer.js +2 -2
  31. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  32. package/packages/datadog-plugin-amqplib/src/producer.js +2 -2
  33. package/packages/datadog-plugin-apollo/src/gateway/execute.js +2 -4
  34. package/packages/datadog-plugin-apollo/src/gateway/fetch.js +2 -4
  35. package/packages/datadog-plugin-apollo/src/gateway/index.js +1 -1
  36. package/packages/datadog-plugin-apollo/src/gateway/plan.js +2 -4
  37. package/packages/datadog-plugin-apollo/src/gateway/postprocessing.js +2 -4
  38. package/packages/datadog-plugin-apollo/src/gateway/request.js +2 -4
  39. package/packages/datadog-plugin-apollo/src/gateway/validate.js +2 -4
  40. package/packages/datadog-plugin-apollo/src/index.js +1 -1
  41. package/packages/datadog-plugin-avsc/src/index.js +2 -2
  42. package/packages/datadog-plugin-aws-sdk/src/base.js +70 -46
  43. package/packages/datadog-plugin-aws-sdk/src/index.js +1 -3
  44. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +1 -3
  45. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +1 -1
  46. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  47. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +3 -3
  48. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  49. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +22 -20
  50. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
  51. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  52. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -3
  53. package/packages/datadog-plugin-aws-sdk/src/services/sfn.js +1 -1
  54. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -3
  55. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +17 -15
  56. package/packages/datadog-plugin-aws-sdk/src/services/states.js +1 -1
  57. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
  58. package/packages/datadog-plugin-azure-functions/src/index.js +5 -5
  59. package/packages/datadog-plugin-azure-service-bus/src/index.js +1 -1
  60. package/packages/datadog-plugin-azure-service-bus/src/producer.js +2 -2
  61. package/packages/datadog-plugin-bunyan/src/index.js +3 -5
  62. package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -3
  63. package/packages/datadog-plugin-child_process/src/index.js +2 -2
  64. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -3
  65. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -3
  66. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  67. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -3
  68. package/packages/datadog-plugin-connect/src/index.js +1 -3
  69. package/packages/datadog-plugin-couchbase/src/index.js +39 -19
  70. package/packages/datadog-plugin-cucumber/src/index.js +1 -3
  71. package/packages/datadog-plugin-cypress/src/index.js +1 -3
  72. package/packages/datadog-plugin-dd-trace-api/src/index.js +1 -3
  73. package/packages/datadog-plugin-dns/src/index.js +1 -1
  74. package/packages/datadog-plugin-dns/src/lookup.js +2 -2
  75. package/packages/datadog-plugin-dns/src/lookup_service.js +2 -2
  76. package/packages/datadog-plugin-dns/src/resolve.js +2 -2
  77. package/packages/datadog-plugin-dns/src/reverse.js +2 -2
  78. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  79. package/packages/datadog-plugin-express/src/code_origin.js +1 -3
  80. package/packages/datadog-plugin-express/src/index.js +1 -1
  81. package/packages/datadog-plugin-express/src/tracing.js +1 -3
  82. package/packages/datadog-plugin-fastify/src/code_origin.js +1 -3
  83. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  84. package/packages/datadog-plugin-fastify/src/tracing.js +18 -3
  85. package/packages/datadog-plugin-fetch/src/index.js +2 -2
  86. package/packages/datadog-plugin-find-my-way/src/index.js +1 -3
  87. package/packages/datadog-plugin-fs/src/index.js +2 -2
  88. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +3 -3
  89. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
  90. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
  91. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +2 -2
  92. package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +1 -1
  93. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +2 -4
  94. package/packages/datadog-plugin-graphql/src/execute.js +16 -9
  95. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  96. package/packages/datadog-plugin-graphql/src/parse.js +12 -7
  97. package/packages/datadog-plugin-graphql/src/resolve.js +50 -16
  98. package/packages/datadog-plugin-graphql/src/validate.js +13 -7
  99. package/packages/datadog-plugin-grpc/src/client.js +4 -4
  100. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  101. package/packages/datadog-plugin-grpc/src/server.js +3 -3
  102. package/packages/datadog-plugin-hapi/src/index.js +1 -3
  103. package/packages/datadog-plugin-hono/src/index.js +1 -3
  104. package/packages/datadog-plugin-http/src/client.js +2 -2
  105. package/packages/datadog-plugin-http/src/index.js +1 -1
  106. package/packages/datadog-plugin-http/src/server.js +3 -7
  107. package/packages/datadog-plugin-http2/src/client.js +2 -2
  108. package/packages/datadog-plugin-http2/src/index.js +1 -1
  109. package/packages/datadog-plugin-http2/src/server.js +22 -11
  110. package/packages/datadog-plugin-ioredis/src/index.js +1 -3
  111. package/packages/datadog-plugin-iovalkey/src/index.js +2 -4
  112. package/packages/datadog-plugin-jest/src/index.js +1 -3
  113. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -2
  114. package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -2
  115. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  116. package/packages/datadog-plugin-kafkajs/src/producer.js +3 -3
  117. package/packages/datadog-plugin-koa/src/index.js +1 -3
  118. package/packages/datadog-plugin-langchain/src/index.js +2 -2
  119. package/packages/datadog-plugin-langchain/src/tracing.js +30 -48
  120. package/packages/datadog-plugin-mariadb/src/index.js +2 -2
  121. package/packages/datadog-plugin-memcached/src/index.js +1 -1
  122. package/packages/datadog-plugin-microgateway-core/src/index.js +4 -4
  123. package/packages/datadog-plugin-mocha/src/index.js +1 -3
  124. package/packages/datadog-plugin-moleculer/src/client.js +2 -2
  125. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  126. package/packages/datadog-plugin-moleculer/src/server.js +2 -2
  127. package/packages/datadog-plugin-mongodb-core/src/index.js +9 -5
  128. package/packages/datadog-plugin-mongoose/src/index.js +20 -0
  129. package/packages/datadog-plugin-mysql/src/index.js +2 -2
  130. package/packages/datadog-plugin-mysql2/src/index.js +1 -1
  131. package/packages/datadog-plugin-net/src/index.js +1 -1
  132. package/packages/datadog-plugin-net/src/ipc.js +2 -2
  133. package/packages/datadog-plugin-net/src/tcp.js +2 -2
  134. package/packages/datadog-plugin-next/src/index.js +1 -3
  135. package/packages/datadog-plugin-nyc/src/index.js +1 -3
  136. package/packages/datadog-plugin-openai/src/index.js +1 -1
  137. package/packages/datadog-plugin-openai/src/tracing.js +7 -411
  138. package/packages/datadog-plugin-opensearch/src/index.js +1 -3
  139. package/packages/datadog-plugin-oracledb/src/index.js +9 -5
  140. package/packages/datadog-plugin-pg/src/index.js +8 -5
  141. package/packages/datadog-plugin-pino/src/index.js +3 -5
  142. package/packages/datadog-plugin-playwright/src/index.js +1 -3
  143. package/packages/datadog-plugin-prisma/src/client.js +4 -6
  144. package/packages/datadog-plugin-prisma/src/engine.js +3 -3
  145. package/packages/datadog-plugin-prisma/src/index.js +1 -1
  146. package/packages/datadog-plugin-protobufjs/src/index.js +2 -6
  147. package/packages/datadog-plugin-redis/src/index.js +2 -2
  148. package/packages/datadog-plugin-restify/src/index.js +1 -3
  149. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  150. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  151. package/packages/datadog-plugin-rhea/src/producer.js +2 -2
  152. package/packages/datadog-plugin-router/src/index.js +1 -3
  153. package/packages/datadog-plugin-selenium/src/index.js +1 -3
  154. package/packages/datadog-plugin-sharedb/src/index.js +1 -1
  155. package/packages/datadog-plugin-tedious/src/index.js +3 -3
  156. package/packages/datadog-plugin-undici/src/index.js +2 -4
  157. package/packages/datadog-plugin-vitest/src/index.js +1 -3
  158. package/packages/datadog-plugin-web/src/index.js +1 -3
  159. package/packages/datadog-plugin-winston/src/index.js +3 -5
  160. package/packages/dd-trace/src/appsec/channels.js +1 -0
  161. package/packages/dd-trace/src/appsec/graphql.js +14 -12
  162. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +14 -7
  163. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +4 -4
  164. package/packages/dd-trace/src/appsec/recommended.json +271 -2
  165. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  166. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +1 -3
  167. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +1 -3
  168. package/packages/dd-trace/src/config.js +1 -1
  169. package/packages/dd-trace/src/datastreams/checkpointer.js +23 -2
  170. package/packages/dd-trace/src/datastreams/processor.js +4 -3
  171. package/packages/dd-trace/src/guardrails/telemetry.js +18 -2
  172. package/packages/dd-trace/src/llmobs/plugins/ai/index.js +351 -0
  173. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +179 -0
  174. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +30 -50
  175. package/packages/dd-trace/src/llmobs/plugins/openai.js +3 -5
  176. package/packages/dd-trace/src/llmobs/plugins/vertexai.js +3 -5
  177. package/packages/dd-trace/src/llmobs/writers/base.js +3 -2
  178. package/packages/dd-trace/src/opentracing/propagation/text_map.js +25 -2
  179. package/packages/dd-trace/src/opentracing/span_context.js +4 -0
  180. package/packages/dd-trace/src/plugin_manager.js +8 -4
  181. package/packages/dd-trace/src/plugins/apollo.js +3 -3
  182. package/packages/dd-trace/src/plugins/cache.js +1 -1
  183. package/packages/dd-trace/src/plugins/client.js +3 -3
  184. package/packages/dd-trace/src/plugins/consumer.js +3 -3
  185. package/packages/dd-trace/src/plugins/database.js +2 -2
  186. package/packages/dd-trace/src/plugins/index.js +2 -0
  187. package/packages/dd-trace/src/plugins/log_plugin.js +1 -5
  188. package/packages/dd-trace/src/plugins/outbound.js +1 -1
  189. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  190. package/packages/dd-trace/src/plugins/producer.js +3 -3
  191. package/packages/dd-trace/src/plugins/server.js +3 -3
  192. package/packages/dd-trace/src/plugins/storage.js +1 -1
  193. package/packages/dd-trace/src/plugins/tracing.js +24 -6
  194. package/packages/dd-trace/src/plugins/util/ci.js +11 -7
  195. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +15 -19
  196. package/packages/dd-trace/src/plugins/util/ip_extractor.js +44 -3
  197. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  198. package/packages/dd-trace/src/plugins/util/web.js +26 -7
  199. package/packages/dd-trace/src/profiling/config.js +2 -0
  200. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -21
  201. package/packages/dd-trace/src/profiling/libuv-size.js +49 -0
  202. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +2 -6
  203. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +1 -3
  204. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +1 -3
  205. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +1 -3
  206. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +1 -3
  207. package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +24 -23
  208. package/packages/dd-trace/src/profiling/profilers/event_plugins/fs.js +3 -9
  209. package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +3 -9
  210. package/packages/dd-trace/src/profiling/profilers/events.js +83 -64
  211. package/packages/dd-trace/src/profiling/profilers/poisson.js +105 -0
  212. package/packages/dd-trace/src/profiling/profilers/wall.js +3 -3
  213. package/packages/dd-trace/src/remote_config/manager.js +1 -1
  214. package/packages/dd-trace/src/supported-configurations.json +2 -0
  215. package/packages/dd-trace/src/tracer_metadata.js +1 -1
@@ -8,9 +8,12 @@ const TraceState = require('./tracestate')
8
8
  const tags = require('../../../../../ext/tags')
9
9
  const { channel } = require('dc-polyfill')
10
10
  const { setBaggageItem, getAllBaggageItems, removeAllBaggageItems } = require('../../baggage')
11
+ const telemetryMetrics = require('../../telemetry/metrics')
11
12
 
12
13
  const { AUTO_KEEP, AUTO_REJECT, USER_KEEP } = require('../../../../../ext/priority')
13
14
 
15
+ const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
16
+
14
17
  const injectCh = channel('dd-trace:span:inject')
15
18
  const extractCh = channel('dd-trace:span:extract')
16
19
 
@@ -142,12 +145,27 @@ class TextMapPropagator {
142
145
  const item = `${this._encodeOtelBaggageKey(String(key).trim())}=${encodeURIComponent(String(value).trim())},`
143
146
  itemCounter += 1
144
147
  byteCounter += Buffer.byteLength(item)
145
- if (itemCounter > this._config.baggageMaxItems || byteCounter > this._config.baggageMaxBytes) break
148
+
149
+ // Check for item count limit exceeded
150
+ if (itemCounter > this._config.baggageMaxItems) {
151
+ tracerMetrics.count('context_header_style.truncated', ['truncation_reason:baggage_item_count_exceeded']).inc()
152
+ break
153
+ }
154
+
155
+ // Check for byte count limit exceeded
156
+ if (byteCounter > this._config.baggageMaxBytes) {
157
+ tracerMetrics.count('context_header_style.truncated', ['truncation_reason:baggage_byte_count_exceeded']).inc()
158
+ break
159
+ }
160
+
146
161
  baggage += item
147
162
  }
148
163
 
149
164
  baggage = baggage.slice(0, -1)
150
- if (baggage) carrier.baggage = baggage
165
+ if (baggage) {
166
+ carrier.baggage = baggage
167
+ tracerMetrics.count('context_header_style.injected', ['header_style:baggage']).inc()
168
+ }
151
169
  }
152
170
  }
153
171
 
@@ -635,6 +653,7 @@ class TextMapPropagator {
635
653
  : new Set(this._config.baggageTagKeys.split(','))
636
654
  for (const keyValue of baggages) {
637
655
  if (!keyValue.includes('=')) {
656
+ tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
638
657
  removeAllBaggageItems()
639
658
  return
640
659
  }
@@ -642,6 +661,7 @@ class TextMapPropagator {
642
661
  key = this._decodeOtelBaggageKey(key.trim())
643
662
  value = decodeURIComponent(value.trim())
644
663
  if (!key || !value) {
664
+ tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
645
665
  removeAllBaggageItems()
646
666
  return
647
667
  }
@@ -650,6 +670,9 @@ class TextMapPropagator {
650
670
  }
651
671
  setBaggageItem(key, value)
652
672
  }
673
+
674
+ // Successfully extracted baggage
675
+ tracerMetrics.count('context_header_style.extracted', ['header_style:baggage']).inc()
653
676
  }
654
677
 
655
678
  _extractSamplingPriority (carrier, spanContext) {
@@ -59,6 +59,10 @@ class DatadogSpanContext {
59
59
  return this._spanId.toString(10)
60
60
  }
61
61
 
62
+ toBigIntSpanId () {
63
+ return this._spanId.toBigInt()
64
+ }
65
+
62
66
  toTraceparent () {
63
67
  const flags = this._sampling.priority >= AUTO_KEEP ? '01' : '00'
64
68
  const traceId = this.toTraceId(true)
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { channel } = require('dc-polyfill')
4
- const { isFalse, normalizePluginEnvName } = require('./util')
4
+ const { isFalse, isTrue, normalizePluginEnvName } = require('./util')
5
5
  const plugins = require('./plugins')
6
6
  const log = require('./log')
7
7
  const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
@@ -32,8 +32,7 @@ loadChannel.subscribe(({ name }) => {
32
32
  function maybeEnable (Plugin) {
33
33
  if (!Plugin || typeof Plugin !== 'function') return
34
34
  if (!pluginClasses[Plugin.id]) {
35
- const envName = `DD_TRACE_${Plugin.id.toUpperCase()}_ENABLED`
36
- const enabled = getEnvironmentVariable(normalizePluginEnvName(envName))
35
+ const enabled = getEnvEnabled(Plugin)
37
36
 
38
37
  // TODO: remove the need to load the plugin class in order to disable the plugin
39
38
  if (isFalse(enabled) || disabledPlugins.has(Plugin.id)) {
@@ -46,6 +45,11 @@ function maybeEnable (Plugin) {
46
45
  }
47
46
  }
48
47
 
48
+ function getEnvEnabled (Plugin) {
49
+ const envName = `DD_TRACE_${Plugin.id.toUpperCase()}_ENABLED`
50
+ return getEnvironmentVariable(normalizePluginEnvName(envName))
51
+ }
52
+
49
53
  // TODO this must always be a singleton.
50
54
  module.exports = class PluginManager {
51
55
  constructor (tracer) {
@@ -74,7 +78,7 @@ module.exports = class PluginManager {
74
78
  this._pluginsByName[name] = new Plugin(this._tracer, this._tracerConfig)
75
79
  }
76
80
  const pluginConfig = this._configsByName[name] || {
77
- enabled: this._tracerConfig.plugins !== false
81
+ enabled: this._tracerConfig.plugins !== false && (!Plugin.experimental || isTrue(getEnvEnabled(Plugin)))
78
82
  }
79
83
 
80
84
  // extracts predetermined configuration from tracer and combines it with plugin-specific config
@@ -4,9 +4,9 @@ const TracingPlugin = require('./tracing')
4
4
  const { storage } = require('../../../datadog-core')
5
5
 
6
6
  class ApolloBasePlugin extends TracingPlugin {
7
- static get id () { return 'apollo.gateway' }
8
- static get type () { return 'web' }
9
- static get kind () { return 'server' }
7
+ static id = 'apollo.gateway'
8
+ static type = 'web'
9
+ static kind = 'server'
10
10
 
11
11
  bindStart (ctx) {
12
12
  const store = storage('legacy').getStore()
@@ -3,7 +3,7 @@
3
3
  const StoragePlugin = require('./storage')
4
4
 
5
5
  class CachePlugin extends StoragePlugin {
6
- static get operation () { return 'command' }
6
+ static operation = 'command'
7
7
 
8
8
  startSpan (options, ctx) {
9
9
  if (!options.kind) {
@@ -3,9 +3,9 @@
3
3
  const OutboundPlugin = require('./outbound')
4
4
 
5
5
  class ClientPlugin extends OutboundPlugin {
6
- static get operation () { return 'request' }
7
- static get kind () { return 'client' }
8
- static get type () { return 'web' } // overridden by storage and other client type plugins
6
+ static operation = 'request'
7
+ static kind = 'client'
8
+ static type = 'web' // overridden by storage and other client type plugins
9
9
  }
10
10
 
11
11
  module.exports = ClientPlugin
@@ -3,9 +3,9 @@
3
3
  const InboundPlugin = require('./inbound')
4
4
 
5
5
  class ConsumerPlugin extends InboundPlugin {
6
- static get operation () { return 'receive' }
7
- static get kind () { return 'consumer' }
8
- static get type () { return 'messaging' }
6
+ static operation = 'receive'
7
+ static kind = 'consumer'
8
+ static type = 'messaging'
9
9
 
10
10
  startSpan (options, enterOrCtx) {
11
11
  if (!options.service) {
@@ -4,8 +4,8 @@ const StoragePlugin = require('./storage')
4
4
  const { PEER_SERVICE_KEY, PEER_SERVICE_SOURCE_KEY } = require('../constants')
5
5
 
6
6
  class DatabasePlugin extends StoragePlugin {
7
- static get operation () { return 'query' }
8
- static get peerServicePrecursors () { return ['db.name'] }
7
+ static operation = 'query'
8
+ static peerServicePrecursors = ['db.name']
9
9
 
10
10
  constructor (...args) {
11
11
  super(...args)
@@ -26,6 +26,7 @@ module.exports = {
26
26
  get '@smithy/smithy-client' () { return require('../../../datadog-plugin-aws-sdk/src') },
27
27
  get '@vitest/runner' () { return require('../../../datadog-plugin-vitest/src') },
28
28
  get aerospike () { return require('../../../datadog-plugin-aerospike/src') },
29
+ get ai () { return require('../../../datadog-plugin-ai/src') },
29
30
  get amqp10 () { return require('../../../datadog-plugin-amqp10/src') },
30
31
  get amqplib () { return require('../../../datadog-plugin-amqplib/src') },
31
32
  get avsc () { return require('../../../datadog-plugin-avsc/src') },
@@ -75,6 +76,7 @@ module.exports = {
75
76
  get moleculer () { return require('../../../datadog-plugin-moleculer/src') },
76
77
  get mongodb () { return require('../../../datadog-plugin-mongodb-core/src') },
77
78
  get 'mongodb-core' () { return require('../../../datadog-plugin-mongodb-core/src') },
79
+ get mongoose () { return require('../../../datadog-plugin-mongoose/src') },
78
80
  get mysql () { return require('../../../datadog-plugin-mysql/src') },
79
81
  get mysql2 () { return require('../../../datadog-plugin-mysql2/src') },
80
82
  get net () { return require('../../../datadog-plugin-net/src') },
@@ -45,14 +45,10 @@ module.exports = class LogPlugin extends Plugin {
45
45
  })
46
46
  }
47
47
 
48
- _isEnabled (config) {
49
- return config.enabled && (config.logInjection === true || config.ciVisAgentlessLogSubmissionEnabled)
50
- }
51
-
52
48
  configure (config) {
53
49
  return super.configure({
54
50
  ...config,
55
- enabled: this._isEnabled(config)
51
+ enabled: config.enabled && (config.logInjection || config.ciVisAgentlessLogSubmissionEnabled)
56
52
  })
57
53
  }
58
54
  }
@@ -17,7 +17,7 @@ const COMMON_PEER_SVC_SOURCE_TAGS = [
17
17
 
18
18
  // TODO: Exit span on finish when AsyncResource instances are removed.
19
19
  class OutboundPlugin extends TracingPlugin {
20
- static get peerServicePrecursors () { return [] }
20
+ static peerServicePrecursors = []
21
21
 
22
22
  constructor (...args) {
23
23
  super(...args)
@@ -60,7 +60,7 @@ module.exports = class Plugin {
60
60
  }
61
61
 
62
62
  get tracer () {
63
- return this._tracer._tracer
63
+ return this._tracer?._tracer || this._tracer
64
64
  }
65
65
 
66
66
  enter (span, store) {
@@ -3,9 +3,9 @@
3
3
  const OutboundPlugin = require('./outbound')
4
4
 
5
5
  class ProducerPlugin extends OutboundPlugin {
6
- static get operation () { return 'publish' }
7
- static get kind () { return 'producer' }
8
- static get type () { return 'messaging' }
6
+ static operation = 'publish'
7
+ static kind = 'producer'
8
+ static type = 'messaging'
9
9
 
10
10
  startSpan (options, enterOrCtx) {
11
11
  const spanDefaults = {
@@ -3,9 +3,9 @@
3
3
  const InboundPlugin = require('./inbound')
4
4
 
5
5
  class ServerPlugin extends InboundPlugin {
6
- static get operation () { return 'request' }
7
- static get kind () { return 'server' }
8
- static get type () { return 'web' } // a default that may eventually be overriden by nonweb servers
6
+ static operation = 'request'
7
+ static kind = 'server'
8
+ static type = 'web' // a default that may eventually be overriden by nonweb servers
9
9
  }
10
10
 
11
11
  module.exports = ServerPlugin
@@ -3,7 +3,7 @@
3
3
  const ClientPlugin = require('./client')
4
4
 
5
5
  class StoragePlugin extends ClientPlugin {
6
- static get type () { return 'storage' }
6
+ static type = 'storage'
7
7
 
8
8
  constructor (...args) {
9
9
  super(...args)
@@ -102,28 +102,46 @@ class TracingPlugin extends Plugin {
102
102
  }
103
103
  }
104
104
 
105
- startSpan (name, { childOf, kind, meta, metrics, service, resource, type } = {}, enterOrCtx = true) {
105
+ startSpan (name, options = {}, enterOrCtx = true) {
106
+ // TODO: modularize this code to a helper function
107
+ let {
108
+ component = this.component,
109
+ childOf,
110
+ integrationName,
111
+ kind,
112
+ meta,
113
+ metrics,
114
+ service,
115
+ startTime,
116
+ resource,
117
+ type
118
+ } = options
119
+
120
+ const tracer = options.tracer || this.tracer
121
+ const config = options.config || this.config
122
+
106
123
  const store = storage('legacy').getStore()
107
124
  if (store && childOf === undefined) {
108
125
  childOf = store.span
109
126
  }
110
127
 
111
- const span = this.tracer.startSpan(name, {
128
+ const span = tracer.startSpan(name, {
129
+ startTime,
112
130
  childOf,
113
131
  tags: {
114
- [COMPONENT]: this.component,
115
- 'service.name': service || this.tracer._service,
132
+ [COMPONENT]: component,
133
+ 'service.name': service || meta?.service || tracer._service,
116
134
  'resource.name': resource,
117
135
  'span.kind': kind,
118
136
  'span.type': type,
119
137
  ...meta,
120
138
  ...metrics
121
139
  },
122
- integrationName: this.component,
140
+ integrationName: integrationName || component,
123
141
  links: childOf?._links
124
142
  })
125
143
 
126
- analyticsSampler.sample(span, this.config.measured)
144
+ analyticsSampler.sample(span, config.measured)
127
145
 
128
146
  // TODO: Remove this after migration to TracingChannel is done.
129
147
  if (enterOrCtx === true) {
@@ -28,7 +28,8 @@ const {
28
28
  CI_NODE_LABELS,
29
29
  CI_NODE_NAME,
30
30
  PR_NUMBER,
31
- CI_JOB_ID
31
+ CI_JOB_ID,
32
+ GIT_PULL_REQUEST_BASE_BRANCH_HEAD_SHA
32
33
  } = require('./tags')
33
34
  const { filterSensitiveInfoFromRepository } = require('./url')
34
35
  const { getEnvironmentVariable, getEnvironmentVariables } = require('../../config-helper')
@@ -187,7 +188,9 @@ module.exports = {
187
188
  CI_RUNNER_ID,
188
189
  CI_RUNNER_TAGS,
189
190
  CI_MERGE_REQUEST_TARGET_BRANCH_NAME,
190
- CI_MERGE_REQUEST_IID
191
+ CI_MERGE_REQUEST_IID,
192
+ CI_MERGE_REQUEST_TARGET_BRANCH_SHA,
193
+ CI_MERGE_REQUEST_DIFF_BASE_SHA
191
194
  } = env
192
195
 
193
196
  const { name, email } = parseEmailAndName(CI_COMMIT_AUTHOR)
@@ -219,7 +222,9 @@ module.exports = {
219
222
  [CI_NODE_NAME]: CI_RUNNER_ID,
220
223
  [GIT_PULL_REQUEST_BASE_BRANCH]: CI_MERGE_REQUEST_TARGET_BRANCH_NAME,
221
224
  [PR_NUMBER]: CI_MERGE_REQUEST_IID,
222
- [CI_JOB_ID]: GITLAB_CI_JOB_ID
225
+ [CI_JOB_ID]: GITLAB_CI_JOB_ID,
226
+ [GIT_PULL_REQUEST_BASE_BRANCH_SHA]: CI_MERGE_REQUEST_DIFF_BASE_SHA,
227
+ [GIT_PULL_REQUEST_BASE_BRANCH_HEAD_SHA]: CI_MERGE_REQUEST_TARGET_BRANCH_SHA
223
228
  }
224
229
  }
225
230
 
@@ -315,7 +320,7 @@ module.exports = {
315
320
  tags[GIT_PULL_REQUEST_BASE_BRANCH] = GITHUB_BASE_REF
316
321
  try {
317
322
  const eventContent = getGitHubEventPayload()
318
- tags[GIT_PULL_REQUEST_BASE_BRANCH_SHA] = eventContent.pull_request.base.sha
323
+ tags[GIT_PULL_REQUEST_BASE_BRANCH_HEAD_SHA] = eventContent.pull_request.base.sha
319
324
  tags[GIT_COMMIT_HEAD_SHA] = eventContent.pull_request.head.sha
320
325
  } catch {
321
326
  // ignore malformed event content
@@ -522,8 +527,7 @@ module.exports = {
522
527
  BUILDKITE_MESSAGE,
523
528
  BUILDKITE_AGENT_ID,
524
529
  BUILDKITE_PULL_REQUEST,
525
- BUILDKITE_PULL_REQUEST_BASE_BRANCH,
526
- BUILDKITE_CI_JOB_ID
530
+ BUILDKITE_PULL_REQUEST_BASE_BRANCH
527
531
  } = env
528
532
 
529
533
  const extraTags = Object.keys(env).filter(envVar =>
@@ -555,7 +559,7 @@ module.exports = {
555
559
  [CI_NODE_NAME]: BUILDKITE_AGENT_ID,
556
560
  [CI_NODE_LABELS]: JSON.stringify(extraTags),
557
561
  [PR_NUMBER]: BUILDKITE_PULL_REQUEST,
558
- [CI_JOB_ID]: BUILDKITE_CI_JOB_ID
562
+ [CI_JOB_ID]: BUILDKITE_JOB_ID
559
563
  }
560
564
 
561
565
  if (BUILDKITE_PULL_REQUEST) {
@@ -22,7 +22,7 @@ const supportedProxies = {
22
22
  }
23
23
  }
24
24
 
25
- function createInferredProxySpan (headers, childOf, tracer, context) {
25
+ function createInferredProxySpan (headers, childOf, tracer, reqCtx, traceCtx, config, startSpanHelper) {
26
26
  if (!headers) {
27
27
  return null
28
28
  }
@@ -41,26 +41,22 @@ function createInferredProxySpan (headers, childOf, tracer, context) {
41
41
 
42
42
  log.debug('Successfully extracted inferred span info %s for proxy:', proxyContext, proxyContext.proxySystemName)
43
43
 
44
- const span = tracer.startSpan(
45
- proxySpanInfo.spanName,
46
- {
47
- childOf,
48
- type: 'web',
49
- startTime: proxyContext.requestTime,
50
- integrationName: proxySpanInfo.component,
51
- tags: {
52
- service: proxyContext.domainName || tracer._config.service,
53
- component: proxySpanInfo.component,
54
- [SPAN_TYPE]: 'web',
55
- [HTTP_METHOD]: proxyContext.method,
56
- [HTTP_URL]: proxyContext.domainName + proxyContext.path,
57
- stage: proxyContext.stage
58
- }
44
+ const span = startSpanHelper(tracer, proxySpanInfo.spanName, {
45
+ childOf,
46
+ type: 'web',
47
+ startTime: proxyContext.requestTime,
48
+ integrationName: proxySpanInfo.component,
49
+ meta: {
50
+ service: proxyContext.domainName || tracer._config.service,
51
+ component: proxySpanInfo.component,
52
+ [SPAN_TYPE]: 'web',
53
+ [HTTP_METHOD]: proxyContext.method,
54
+ [HTTP_URL]: proxyContext.domainName + proxyContext.path,
55
+ stage: proxyContext.stage
59
56
  }
60
- )
57
+ }, traceCtx, config)
61
58
 
62
- tracer.scope().activate(span)
63
- context.inferredProxySpan = span
59
+ reqCtx.inferredProxySpan = span
64
60
  childOf = span
65
61
 
66
62
  log.debug('Successfully created inferred proxy span.')
@@ -3,11 +3,14 @@
3
3
  const { BlockList } = require('net')
4
4
  const net = require('net')
5
5
 
6
+ const FORWARED_HEADER_NAME = 'forwarded'
7
+
6
8
  const ipHeaderList = [
7
9
  'x-forwarded-for',
8
10
  'x-real-ip',
9
11
  'true-client-ip',
10
12
  'x-client-ip',
13
+ FORWARED_HEADER_NAME,
11
14
  'forwarded-for',
12
15
  'x-cluster-client-ip',
13
16
  'fastly-client-ip',
@@ -49,7 +52,8 @@ function extractIp (config, req) {
49
52
  let firstPrivateIp
50
53
  if (headers) {
51
54
  for (const ipHeaderName of ipHeaderList) {
52
- const firstIp = findFirstIp(headers[ipHeaderName])
55
+ const header = headers[ipHeaderName]
56
+ const firstIp = ipHeaderName === FORWARED_HEADER_NAME ? findFirstIpForwardedFormat(header) : findFirstIp(header)
53
57
 
54
58
  if (firstIp.public) {
55
59
  return firstIp.public
@@ -62,6 +66,10 @@ function extractIp (config, req) {
62
66
  return firstPrivateIp || req.socket?.remoteAddress
63
67
  }
64
68
 
69
+ function isPublicIp (ip, type) {
70
+ return !privateIPMatcher.check(ip, type === 6 ? 'ipv6' : 'ipv4')
71
+ }
72
+
65
73
  function findFirstIp (str) {
66
74
  const result = {}
67
75
  if (!str) return result
@@ -76,10 +84,10 @@ function findFirstIp (str) {
76
84
  const type = net.isIP(chunk)
77
85
  if (!type) continue
78
86
 
79
- if (!privateIPMatcher.check(chunk, type === 6 ? 'ipv6' : 'ipv4')) {
87
+ if (isPublicIp(chunk, type)) {
80
88
  // it's public, return it immediately
81
89
  result.public = chunk
82
- break
90
+ return result
83
91
  }
84
92
 
85
93
  // it's private, only save the first one found
@@ -89,6 +97,39 @@ function findFirstIp (str) {
89
97
  return result
90
98
  }
91
99
 
100
+ const forwardedForRegexp = /for="?\[?(([0-9]+\.)+[0-9]+|[0-9a-f:]*:[0-9a-f]*)/i
101
+ const forwardedByRegexp = /by="?\[?(([0-9]+\.)+[0-9]+|[0-9a-f:]*:[0-9a-f]*)/i
102
+ const forwardedRegexps = [forwardedForRegexp, forwardedByRegexp]
103
+
104
+ function findFirstIpForwardedFormat (str) {
105
+ const result = {}
106
+ if (!str) return result
107
+
108
+ const splitted = str.split(',')
109
+
110
+ for (const part of splitted) {
111
+ const chunk = part.trim()
112
+
113
+ for (const regex of forwardedRegexps) {
114
+ const ip = regex.exec(chunk)?.[1]
115
+
116
+ const type = net.isIP(ip)
117
+ if (!type) continue
118
+
119
+ if (isPublicIp(ip, type)) {
120
+ // it's public, return it immediately
121
+ result.public = ip
122
+ return result
123
+ }
124
+
125
+ // it's private, only save the first one found
126
+ if (!result.private) result.private = ip
127
+ }
128
+ }
129
+
130
+ return result
131
+ }
132
+
92
133
  module.exports = {
93
134
  extractIp,
94
135
  ipHeaderList
@@ -21,6 +21,7 @@ const GIT_COMMIT_HEAD_COMMITTER_EMAIL = 'git.commit.head.committer.email'
21
21
  const GIT_COMMIT_HEAD_COMMITTER_NAME = 'git.commit.head.committer.name'
22
22
 
23
23
  const GIT_PULL_REQUEST_BASE_BRANCH_SHA = 'git.pull_request.base_branch_sha'
24
+ const GIT_PULL_REQUEST_BASE_BRANCH_HEAD_SHA = 'git.pull_request.base_branch_head_sha'
24
25
  const GIT_PULL_REQUEST_BASE_BRANCH = 'git.pull_request.base_branch'
25
26
 
26
27
  const CI_PIPELINE_ID = 'ci.pipeline.id'
@@ -61,6 +62,7 @@ module.exports = {
61
62
  GIT_COMMIT_HEAD_COMMITTER_EMAIL,
62
63
  GIT_COMMIT_HEAD_COMMITTER_NAME,
63
64
  GIT_PULL_REQUEST_BASE_BRANCH_SHA,
65
+ GIT_PULL_REQUEST_BASE_BRANCH_HEAD_SHA,
64
66
  GIT_PULL_REQUEST_BASE_BRANCH,
65
67
  CI_PIPELINE_ID,
66
68
  CI_PIPELINE_NAME,
@@ -10,6 +10,7 @@ const kinds = require('../../../../../ext/kinds')
10
10
  const urlFilter = require('./urlfilter')
11
11
  const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../constants')
12
12
  const { createInferredProxySpan, finishInferredProxySpan } = require('./inferred_proxy')
13
+ const TracingPlugin = require('../tracing')
13
14
 
14
15
  let extractIp
15
16
 
@@ -37,8 +38,25 @@ const HTTP2_HEADER_PATH = ':path'
37
38
  const contexts = new WeakMap()
38
39
  const ends = new WeakMap()
39
40
 
41
+ // TODO: change this to no longer rely on creating a dummy plugin to be able to access startSpan
42
+ function createWebPlugin (tracer, config = {}) {
43
+ const plugin = new TracingPlugin(tracer, tracer._config)
44
+ plugin.component = 'web'
45
+ plugin.config = config
46
+ return plugin
47
+ }
48
+
49
+ function startSpanHelper (tracer, name, options, traceCtx, config = {}) {
50
+ if (!web.plugin) {
51
+ web.plugin = createWebPlugin(tracer, config)
52
+ }
53
+
54
+ return web.plugin.startSpan(name, { ...options, tracer, config }, traceCtx)
55
+ }
56
+
40
57
  const web = {
41
58
  TYPE: WEB,
59
+ plugin: null,
42
60
 
43
61
  // Ensure the configuration has the correct structure and defaults.
44
62
  normalizeConfig (config) {
@@ -93,7 +111,7 @@ const web = {
93
111
  analyticsSampler.sample(span, config.measured, true)
94
112
  },
95
113
 
96
- startSpan (tracer, config, req, res, name) {
114
+ startSpan (tracer, config, req, res, name, traceCtx) {
97
115
  const context = this.patch(req)
98
116
 
99
117
  let span
@@ -102,7 +120,7 @@ const web = {
102
120
  context.span.context()._name = name
103
121
  span = context.span
104
122
  } else {
105
- span = web.startChildSpan(tracer, name, req)
123
+ span = web.startChildSpan(tracer, config, name, req, traceCtx)
106
124
  }
107
125
 
108
126
  context.tracer = tracer
@@ -163,10 +181,11 @@ const web = {
163
181
  const tracer = context.tracer
164
182
  const childOf = this.active(req)
165
183
  const config = context.config
184
+ const traceCtx = context.traceCtx
166
185
 
167
186
  if (config.middleware === false) return this.bindAndWrapMiddlewareErrors(fn, req, tracer, childOf)
168
187
 
169
- const span = tracer.startSpan(name, { childOf })
188
+ const span = startSpanHelper(tracer, name, { childOf }, traceCtx, config)
170
189
 
171
190
  analyticsSampler.sample(span, config.measured)
172
191
 
@@ -258,20 +277,20 @@ const web = {
258
277
  },
259
278
 
260
279
  // Extract the parent span from the headers and start a new span as its child
261
- startChildSpan (tracer, name, req) {
280
+ startChildSpan (tracer, config, name, req, traceCtx) {
262
281
  const headers = req.headers
263
- const context = contexts.get(req)
282
+ const reqCtx = contexts.get(req)
264
283
  let childOf = tracer.extract(FORMAT_HTTP_HEADERS, headers)
265
284
 
266
285
  // we may have headers signaling a router proxy span should be created (such as for AWS API Gateway)
267
286
  if (tracer._config?.inferredProxyServicesEnabled) {
268
- const proxySpan = createInferredProxySpan(headers, childOf, tracer, context)
287
+ const proxySpan = createInferredProxySpan(headers, childOf, tracer, reqCtx, traceCtx, config, startSpanHelper)
269
288
  if (proxySpan) {
270
289
  childOf = proxySpan
271
290
  }
272
291
  }
273
292
 
274
- const span = tracer.startSpan(name, { childOf, links: childOf?._links })
293
+ const span = startSpanHelper(tracer, name, { childOf }, traceCtx, config)
275
294
 
276
295
  return span
277
296
  },
@@ -171,6 +171,8 @@ class Config {
171
171
  samplingContextsAvailable))
172
172
  checkOptionWithSamplingContextAllowed(this.cpuProfilingEnabled, 'CPU profiling')
173
173
 
174
+ this.samplingInterval = coalesce(options.samplingInterval, 1e3 / 99) // 99hz in millis
175
+
174
176
  this.heapSamplingInterval = coalesce(options.heapSamplingInterval,
175
177
  Number(DD_PROFILING_HEAP_SAMPLING_INTERVAL))
176
178
  const uploadCompression0 = coalesce(options.uploadCompression, DD_PROFILING_DEBUG_UPLOAD_COMPRESSION, 'on')