dd-trace 5.81.0 → 5.82.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 (321) hide show
  1. package/index.d.ts +7 -0
  2. package/loader-hook.mjs +7 -2
  3. package/package.json +13 -18
  4. package/packages/datadog-core/src/utils/src/parse-tags.js +1 -1
  5. package/packages/datadog-esbuild/index.js +8 -7
  6. package/packages/datadog-esbuild/src/utils.js +14 -2
  7. package/packages/datadog-instrumentations/src/aerospike.js +3 -2
  8. package/packages/datadog-instrumentations/src/ai.js +2 -2
  9. package/packages/datadog-instrumentations/src/amqp10.js +1 -1
  10. package/packages/datadog-instrumentations/src/amqplib.js +4 -4
  11. package/packages/datadog-instrumentations/src/anthropic.js +2 -2
  12. package/packages/datadog-instrumentations/src/apollo-server-core.js +2 -2
  13. package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
  14. package/packages/datadog-instrumentations/src/apollo.js +3 -2
  15. package/packages/datadog-instrumentations/src/avsc.js +1 -1
  16. package/packages/datadog-instrumentations/src/aws-sdk.js +1 -1
  17. package/packages/datadog-instrumentations/src/azure-event-hubs.js +4 -3
  18. package/packages/datadog-instrumentations/src/azure-functions.js +2 -2
  19. package/packages/datadog-instrumentations/src/azure-service-bus.js +3 -4
  20. package/packages/datadog-instrumentations/src/bluebird.js +1 -1
  21. package/packages/datadog-instrumentations/src/bullmq.js +11 -0
  22. package/packages/datadog-instrumentations/src/bunyan.js +1 -1
  23. package/packages/datadog-instrumentations/src/cassandra-driver.js +1 -1
  24. package/packages/datadog-instrumentations/src/child_process.js +2 -2
  25. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +3 -3
  26. package/packages/datadog-instrumentations/src/couchbase.js +1 -1
  27. package/packages/datadog-instrumentations/src/crypto.js +1 -1
  28. package/packages/datadog-instrumentations/src/cucumber.js +12 -13
  29. package/packages/datadog-instrumentations/src/cypress.js +1 -1
  30. package/packages/datadog-instrumentations/src/dns.js +1 -1
  31. package/packages/datadog-instrumentations/src/elasticsearch.js +1 -1
  32. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +1 -1
  33. package/packages/datadog-instrumentations/src/express.js +1 -1
  34. package/packages/datadog-instrumentations/src/fs.js +1 -1
  35. package/packages/datadog-instrumentations/src/generic-pool.js +1 -1
  36. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +137 -15
  37. package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +2 -3
  38. package/packages/datadog-instrumentations/src/google-genai.js +3 -3
  39. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  40. package/packages/datadog-instrumentations/src/grpc/client.js +1 -1
  41. package/packages/datadog-instrumentations/src/grpc/server.js +1 -1
  42. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +1 -1
  43. package/packages/datadog-instrumentations/src/helpers/hook.js +1 -1
  44. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -1
  45. package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
  46. package/packages/datadog-instrumentations/src/helpers/register.js +6 -4
  47. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -2
  48. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/bullmq.json +106 -0
  49. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -1
  50. package/packages/datadog-instrumentations/src/helpers/router-helper.js +1 -1
  51. package/packages/datadog-instrumentations/src/helpers/shared-utils.js +9 -0
  52. package/packages/datadog-instrumentations/src/hono.js +55 -10
  53. package/packages/datadog-instrumentations/src/ioredis.js +1 -1
  54. package/packages/datadog-instrumentations/src/iovalkey.js +1 -1
  55. package/packages/datadog-instrumentations/src/jest.js +2 -2
  56. package/packages/datadog-instrumentations/src/kafkajs.js +3 -3
  57. package/packages/datadog-instrumentations/src/knex.js +1 -1
  58. package/packages/datadog-instrumentations/src/ldapjs.js +1 -1
  59. package/packages/datadog-instrumentations/src/light-my-request.js +93 -0
  60. package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
  61. package/packages/datadog-instrumentations/src/lodash.js +1 -2
  62. package/packages/datadog-instrumentations/src/mariadb.js +1 -2
  63. package/packages/datadog-instrumentations/src/memcached.js +1 -1
  64. package/packages/datadog-instrumentations/src/mongodb-core.js +1 -1
  65. package/packages/datadog-instrumentations/src/mongodb.js +1 -1
  66. package/packages/datadog-instrumentations/src/mongoose.js +1 -1
  67. package/packages/datadog-instrumentations/src/mquery.js +1 -1
  68. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  69. package/packages/datadog-instrumentations/src/mysql2.js +1 -1
  70. package/packages/datadog-instrumentations/src/net.js +1 -1
  71. package/packages/datadog-instrumentations/src/next.js +1 -1
  72. package/packages/datadog-instrumentations/src/nyc.js +1 -1
  73. package/packages/datadog-instrumentations/src/openai.js +2 -2
  74. package/packages/datadog-instrumentations/src/opensearch.js +1 -1
  75. package/packages/datadog-instrumentations/src/oracledb.js +1 -1
  76. package/packages/datadog-instrumentations/src/otel-sdk-trace.js +1 -1
  77. package/packages/datadog-instrumentations/src/pg.js +3 -3
  78. package/packages/datadog-instrumentations/src/pino.js +1 -1
  79. package/packages/datadog-instrumentations/src/playwright.js +1 -1
  80. package/packages/datadog-instrumentations/src/prisma.js +52 -37
  81. package/packages/datadog-instrumentations/src/process.js +1 -1
  82. package/packages/datadog-instrumentations/src/promise-js.js +1 -1
  83. package/packages/datadog-instrumentations/src/promise.js +1 -1
  84. package/packages/datadog-instrumentations/src/protobufjs.js +1 -1
  85. package/packages/datadog-instrumentations/src/q.js +1 -1
  86. package/packages/datadog-instrumentations/src/redis.js +1 -1
  87. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  88. package/packages/datadog-instrumentations/src/selenium.js +1 -1
  89. package/packages/datadog-instrumentations/src/sequelize.js +1 -2
  90. package/packages/datadog-instrumentations/src/sharedb.js +1 -1
  91. package/packages/datadog-instrumentations/src/tedious.js +1 -1
  92. package/packages/datadog-instrumentations/src/undici.js +4 -4
  93. package/packages/datadog-instrumentations/src/url.js +1 -1
  94. package/packages/datadog-instrumentations/src/vitest.js +1 -1
  95. package/packages/datadog-instrumentations/src/vm.js +1 -1
  96. package/packages/datadog-instrumentations/src/when.js +1 -1
  97. package/packages/datadog-instrumentations/src/winston.js +1 -1
  98. package/packages/datadog-instrumentations/src/ws.js +3 -2
  99. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  100. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  101. package/packages/datadog-plugin-anthropic/src/index.js +1 -1
  102. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +1 -1
  103. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +4 -4
  104. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  105. package/packages/datadog-plugin-aws-sdk/src/util.js +3 -3
  106. package/packages/datadog-plugin-azure-event-hubs/src/index.js +1 -1
  107. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +19 -5
  108. package/packages/datadog-plugin-azure-service-bus/src/index.js +1 -1
  109. package/packages/datadog-plugin-azure-service-bus/src/producer.js +4 -0
  110. package/packages/datadog-plugin-bullmq/src/consumer.js +60 -0
  111. package/packages/datadog-plugin-bullmq/src/index.js +18 -0
  112. package/packages/datadog-plugin-bullmq/src/producer.js +178 -0
  113. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  114. package/packages/datadog-plugin-cypress/src/plugin.js +1 -1
  115. package/packages/datadog-plugin-express/src/index.js +1 -1
  116. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  117. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +13 -3
  118. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +171 -12
  119. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -2
  120. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +160 -13
  121. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +217 -0
  122. package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +1 -1
  123. package/packages/datadog-plugin-google-genai/src/index.js +1 -1
  124. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  125. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  126. package/packages/datadog-plugin-http/src/client.js +2 -1
  127. package/packages/datadog-plugin-http/src/index.js +25 -5
  128. package/packages/datadog-plugin-http2/src/client.js +2 -2
  129. package/packages/datadog-plugin-http2/src/index.js +1 -1
  130. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  131. package/packages/datadog-plugin-langchain/src/index.js +1 -1
  132. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  133. package/packages/datadog-plugin-mongodb-core/src/index.js +6 -2
  134. package/packages/datadog-plugin-openai/src/index.js +1 -1
  135. package/packages/datadog-plugin-openai/src/stream-helpers.js +30 -10
  136. package/packages/datadog-plugin-openai/src/tracing.js +2 -2
  137. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  138. package/packages/datadog-plugin-ws/src/close.js +56 -3
  139. package/packages/datadog-plugin-ws/src/index.js +4 -0
  140. package/packages/datadog-plugin-ws/src/producer.js +39 -4
  141. package/packages/datadog-plugin-ws/src/receiver.js +39 -3
  142. package/packages/datadog-plugin-ws/src/server.js +13 -1
  143. package/packages/datadog-plugin-ws/src/util.js +107 -0
  144. package/packages/datadog-shimmer/src/shimmer.js +2 -2
  145. package/packages/dd-trace/src/aiguard/sdk.js +3 -3
  146. package/packages/dd-trace/src/appsec/graphql.js +2 -2
  147. package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +1 -1
  148. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +1 -1
  149. package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +1 -1
  150. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
  151. package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +1 -1
  152. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +1 -1
  153. package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +3 -3
  154. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +1 -1
  155. package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +1 -1
  156. package/packages/dd-trace/src/appsec/iast/analyzers/untrusted-deserialization-analyzer.js +1 -1
  157. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +1 -1
  158. package/packages/dd-trace/src/appsec/iast/analyzers/weak-cipher-analyzer.js +1 -1
  159. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +3 -2
  160. package/packages/dd-trace/src/appsec/iast/analyzers/weak-randomness-analyzer.js +1 -1
  161. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +3 -3
  162. package/packages/dd-trace/src/appsec/iast/index.js +5 -5
  163. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +1 -1
  164. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +1 -2
  165. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +1 -1
  166. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
  167. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +10 -14
  168. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
  169. package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +1 -1
  170. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +3 -3
  171. package/packages/dd-trace/src/appsec/index.js +8 -8
  172. package/packages/dd-trace/src/appsec/rasp/command_injection.js +1 -1
  173. package/packages/dd-trace/src/appsec/rasp/index.js +1 -1
  174. package/packages/dd-trace/src/appsec/rasp/lfi.js +1 -1
  175. package/packages/dd-trace/src/appsec/rc-products.js +10 -0
  176. package/packages/dd-trace/src/appsec/recommended.json +230 -3
  177. package/packages/dd-trace/src/appsec/remote_config.js +177 -0
  178. package/packages/dd-trace/src/appsec/reporter.js +3 -3
  179. package/packages/dd-trace/src/appsec/rule_manager.js +37 -20
  180. package/packages/dd-trace/src/appsec/sdk/index.js +1 -1
  181. package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
  182. package/packages/dd-trace/src/appsec/sdk/track_event.js +2 -2
  183. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
  184. package/packages/dd-trace/src/appsec/user_tracking.js +2 -2
  185. package/packages/dd-trace/src/appsec/waf/index.js +17 -3
  186. package/packages/dd-trace/src/appsec/waf/waf_manager.js +11 -0
  187. package/packages/dd-trace/src/azure_metadata.js +8 -2
  188. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +6 -0
  189. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +2 -2
  190. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +1 -1
  191. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +1 -1
  192. package/packages/dd-trace/src/config/remote_config.js +34 -0
  193. package/packages/dd-trace/src/config.js +29 -28
  194. package/packages/dd-trace/src/config_defaults.js +2 -1
  195. package/packages/dd-trace/src/constants.js +5 -0
  196. package/packages/dd-trace/src/crashtracking/crashtracker.js +10 -1
  197. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
  198. package/packages/dd-trace/src/datastreams/index.js +1 -1
  199. package/packages/dd-trace/src/datastreams/pathway.js +7 -7
  200. package/packages/dd-trace/src/datastreams/processor.js +2 -2
  201. package/packages/dd-trace/src/datastreams/writer.js +2 -2
  202. package/packages/dd-trace/src/debugger/config.js +1 -0
  203. package/packages/dd-trace/src/debugger/devtools_client/config.js +1 -1
  204. package/packages/dd-trace/src/debugger/devtools_client/index.js +7 -2
  205. package/packages/dd-trace/src/debugger/devtools_client/send.js +3 -3
  206. package/packages/dd-trace/src/debugger/devtools_client/session.js +1 -1
  207. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +5 -5
  208. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
  209. package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -1
  210. package/packages/dd-trace/src/debugger/devtools_client/status.js +2 -2
  211. package/packages/dd-trace/src/debugger/index.js +1 -1
  212. package/packages/dd-trace/src/dogstatsd.js +3 -2
  213. package/packages/dd-trace/src/encode/0.4.js +1 -1
  214. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +2 -2
  215. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +1 -1
  216. package/packages/dd-trace/src/encode/span-stats.js +6 -1
  217. package/packages/dd-trace/src/exporter.js +2 -2
  218. package/packages/dd-trace/src/exporters/agent/index.js +1 -1
  219. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +1 -1
  220. package/packages/dd-trace/src/exporters/common/request.js +2 -2
  221. package/packages/dd-trace/src/exporters/common/writer.js +1 -1
  222. package/packages/dd-trace/src/exporters/span-stats/index.js +1 -1
  223. package/packages/dd-trace/src/external-logger/src/index.js +1 -2
  224. package/packages/dd-trace/src/flare/index.js +1 -1
  225. package/packages/dd-trace/src/guardrails/index.js +6 -3
  226. package/packages/dd-trace/src/id.js +1 -1
  227. package/packages/dd-trace/src/index.js +1 -1
  228. package/packages/dd-trace/src/lambda/handler.js +4 -4
  229. package/packages/dd-trace/src/lambda/index.js +1 -1
  230. package/packages/dd-trace/src/lambda/runtime/patch.js +4 -4
  231. package/packages/dd-trace/src/lambda/runtime/ritm.js +1 -1
  232. package/packages/dd-trace/src/llmobs/constants/tags.js +7 -1
  233. package/packages/dd-trace/src/llmobs/index.js +8 -9
  234. package/packages/dd-trace/src/llmobs/plugins/ai/index.js +38 -7
  235. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +30 -9
  236. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +3 -3
  237. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +2 -2
  238. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +1 -1
  239. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +1 -1
  240. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/embedding.js +1 -1
  241. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/llm.js +1 -1
  242. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +1 -1
  243. package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +16 -0
  244. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +16 -1
  245. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +22 -10
  246. package/packages/dd-trace/src/llmobs/plugins/vertexai.js +1 -1
  247. package/packages/dd-trace/src/llmobs/sdk.js +15 -22
  248. package/packages/dd-trace/src/llmobs/span_processor.js +9 -13
  249. package/packages/dd-trace/src/llmobs/telemetry.js +3 -4
  250. package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
  251. package/packages/dd-trace/src/llmobs/writers/spans.js +1 -2
  252. package/packages/dd-trace/src/log/index.js +1 -1
  253. package/packages/dd-trace/src/noop/proxy.js +2 -2
  254. package/packages/dd-trace/src/noop/span.js +1 -1
  255. package/packages/dd-trace/src/openfeature/index.js +2 -2
  256. package/packages/dd-trace/src/openfeature/noop.js +14 -14
  257. package/packages/dd-trace/src/openfeature/remote_config.js +31 -0
  258. package/packages/dd-trace/src/openfeature/writers/base.js +5 -5
  259. package/packages/dd-trace/src/openfeature/writers/exposures.js +9 -9
  260. package/packages/dd-trace/src/opentelemetry/context_manager.js +2 -2
  261. package/packages/dd-trace/src/opentelemetry/logs/logger.js +1 -1
  262. package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +4 -4
  263. package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +9 -8
  264. package/packages/dd-trace/src/opentelemetry/metrics/instruments.js +3 -3
  265. package/packages/dd-trace/src/opentelemetry/metrics/meter.js +2 -2
  266. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +4 -4
  267. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +36 -11
  268. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +11 -10
  269. package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +1 -1
  270. package/packages/dd-trace/src/opentelemetry/span.js +2 -2
  271. package/packages/dd-trace/src/opentelemetry/tracer.js +3 -3
  272. package/packages/dd-trace/src/opentracing/propagation/text_map.js +24 -8
  273. package/packages/dd-trace/src/opentracing/span.js +3 -3
  274. package/packages/dd-trace/src/opentracing/tracer.js +5 -5
  275. package/packages/dd-trace/src/payload-tagging/index.js +6 -2
  276. package/packages/dd-trace/src/plugin_manager.js +1 -1
  277. package/packages/dd-trace/src/plugins/apollo.js +1 -1
  278. package/packages/dd-trace/src/plugins/ci_plugin.js +27 -27
  279. package/packages/dd-trace/src/plugins/database.js +1 -1
  280. package/packages/dd-trace/src/plugins/index.js +5 -1
  281. package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
  282. package/packages/dd-trace/src/plugins/outbound.js +1 -1
  283. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  284. package/packages/dd-trace/src/plugins/util/ci.js +1 -1
  285. package/packages/dd-trace/src/plugins/util/git.js +8 -8
  286. package/packages/dd-trace/src/plugins/util/stacktrace.js +1 -1
  287. package/packages/dd-trace/src/plugins/util/test.js +24 -24
  288. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
  289. package/packages/dd-trace/src/plugins/util/web.js +8 -5
  290. package/packages/dd-trace/src/priority_sampler.js +15 -16
  291. package/packages/dd-trace/src/process-tags/index.js +31 -29
  292. package/packages/dd-trace/src/profiling/config.js +32 -21
  293. package/packages/dd-trace/src/profiling/exporter_cli.js +4 -4
  294. package/packages/dd-trace/src/profiling/exporters/agent.js +5 -5
  295. package/packages/dd-trace/src/profiling/index.js +1 -1
  296. package/packages/dd-trace/src/profiling/libuv-size.js +1 -1
  297. package/packages/dd-trace/src/profiling/profiler.js +4 -5
  298. package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +1 -1
  299. package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
  300. package/packages/dd-trace/src/profiling/profilers/wall.js +4 -4
  301. package/packages/dd-trace/src/proxy.js +12 -18
  302. package/packages/dd-trace/src/remote_config/index.js +541 -137
  303. package/packages/dd-trace/src/require-package-json.js +1 -1
  304. package/packages/dd-trace/src/ritm.js +50 -27
  305. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +1 -1
  306. package/packages/dd-trace/src/serverless.js +16 -0
  307. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +8 -0
  308. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
  309. package/packages/dd-trace/src/span_format.js +1 -1
  310. package/packages/dd-trace/src/span_processor.js +2 -2
  311. package/packages/dd-trace/src/span_stats.js +6 -4
  312. package/packages/dd-trace/src/standalone/index.js +1 -1
  313. package/packages/dd-trace/src/startup-log.js +3 -3
  314. package/packages/dd-trace/src/supported-configurations.json +3 -0
  315. package/packages/dd-trace/src/telemetry/dependencies.js +3 -3
  316. package/packages/dd-trace/src/telemetry/endpoints.js +8 -8
  317. package/packages/dd-trace/src/telemetry/logs/index.js +1 -1
  318. package/packages/dd-trace/src/telemetry/telemetry.js +11 -6
  319. package/packages/dd-trace/src/tracer.js +3 -3
  320. package/packages/dd-trace/src/tracer_metadata.js +19 -15
  321. package/packages/dd-trace/src/remote_config/manager.js +0 -368
@@ -1,5 +1,7 @@
1
1
  'use strict'
2
2
 
3
+ const { URL } = require('url')
4
+
3
5
  const ClientPlugin = require('../../dd-trace/src/plugins/client')
4
6
  const { storage } = require('../../datadog-core')
5
7
  const tags = require('../../../ext/tags')
@@ -9,7 +11,6 @@ const HTTP_HEADERS = formats.HTTP_HEADERS
9
11
  const urlFilter = require('../../dd-trace/src/plugins/util/urlfilter')
10
12
  const log = require('../../dd-trace/src/log')
11
13
  const { CLIENT_PORT_KEY, COMPONENT, ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
12
- const { URL } = require('url')
13
14
 
14
15
  const HTTP_STATUS_CODE = tags.HTTP_STATUS_CODE
15
16
  const HTTP_REQUEST_HEADERS = tags.HTTP_REQUEST_HEADERS
@@ -1,16 +1,36 @@
1
1
  'use strict'
2
2
 
3
- const HttpServerPlugin = require('./server')
4
- const HttpClientPlugin = require('./client')
3
+ const PushSubscriptionPlugin = require('../../datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription')
5
4
  const CompositePlugin = require('../../dd-trace/src/plugins/composite')
5
+ const { enableGCPPubSubPushSubscription } = require('../../dd-trace/src/serverless')
6
+ const log = require('../../dd-trace/src/log')
7
+ const HttpClientPlugin = require('./client')
8
+ const HttpServerPlugin = require('./server')
6
9
 
10
+ /**
11
+ * HTTP Plugin loads server/client plugins with optional GCP Pub/Sub Push support.
12
+ * Plugin order is critical: PushSubscriptionPlugin must load FIRST to intercept
13
+ * Pub/Sub push requests and activate delivery spans before HTTP spans are created.
14
+ */
7
15
  class HttpPlugin extends CompositePlugin {
8
16
  static id = 'http'
9
17
  static get plugins () {
10
- return {
11
- server: HttpServerPlugin,
12
- client: HttpClientPlugin
18
+ const plugins = {}
19
+
20
+ // Load push subscription plugin first (if enabled) for GCP Cloud Run
21
+ if (enableGCPPubSubPushSubscription()) {
22
+ try {
23
+ plugins['pubsub-push-subscription'] = PushSubscriptionPlugin
24
+ log.debug('Loaded GCP Pub/Sub Push Subscription plugin for HTTP requests')
25
+ } catch (e) {
26
+ log.debug(`Failed to load GCP Pub/Sub Push Subscription plugin: ${e.message}`)
27
+ }
13
28
  }
29
+
30
+ plugins.server = HttpServerPlugin
31
+ plugins.client = HttpClientPlugin
32
+
33
+ return plugins
14
34
  }
15
35
  }
16
36
 
@@ -1,9 +1,9 @@
1
1
  'use strict'
2
2
 
3
+ const URL = require('url').URL
4
+
3
5
  const { storage } = require('../../datadog-core')
4
6
  const ClientPlugin = require('../../dd-trace/src/plugins/client')
5
-
6
- const URL = require('url').URL
7
7
  const log = require('../../dd-trace/src/log')
8
8
  const tags = require('../../../ext/tags')
9
9
  const kinds = require('../../../ext/kinds')
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
3
4
  const Http2ServerPlugin = require('./server')
4
5
  const Http2ClientPlugin = require('./client')
5
- const CompositePlugin = require('../../dd-trace/src/plugins/composite')
6
6
 
7
7
  class Http2Plugin extends CompositePlugin {
8
8
  static id = 'http2'
@@ -1,9 +1,9 @@
1
1
  'use strict'
2
2
 
3
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
3
4
  const ProducerPlugin = require('./producer')
4
5
  const ConsumerPlugin = require('./consumer')
5
6
  const BatchConsumerPlugin = require('./batch-consumer')
6
- const CompositePlugin = require('../../dd-trace/src/plugins/composite')
7
7
 
8
8
  class KafkajsPlugin extends CompositePlugin {
9
9
  static id = 'kafkajs'
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
- const langChainTracingPlugins = require('./tracing')
4
3
  const langChainLLMObsPlugins = require('../../dd-trace/src/llmobs/plugins/langchain')
5
4
  const CompositePlugin = require('../../dd-trace/src/plugins/composite')
5
+ const langChainTracingPlugins = require('./tracing')
6
6
 
7
7
  const plugins = {}
8
8
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  // TODO: support https://moleculer.services/docs/0.13/actions.html#Streaming
4
4
 
5
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
5
6
  const MoleculerServerPlugin = require('./server')
6
7
  const MoleculerClientPlugin = require('./client')
7
- const CompositePlugin = require('../../dd-trace/src/plugins/composite')
8
8
 
9
9
  class MoleculerPlugin extends CompositePlugin {
10
10
  static id = 'moleculer'
@@ -204,8 +204,12 @@ function isBinary (val) {
204
204
  }
205
205
 
206
206
  function isHeartbeat (ops, config) {
207
- // Check if it's a heartbeat command hello: 1 or helloOk: 1
208
- return ops && typeof ops === 'object' && (ops.hello === 1 || ops.helloOk === true)
207
+ // Check if it's a heartbeat command https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.md
208
+ return (
209
+ ops &&
210
+ typeof ops === 'object' &&
211
+ (ops.hello === 1 || ops.helloOk === true || ops.ismaster === 1 || ops.isMaster === 1)
212
+ )
209
213
  }
210
214
 
211
215
  module.exports = MongodbCorePlugin
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
3
  const CompositePlugin = require('../../dd-trace/src/plugins/composite')
4
- const OpenAiTracingPlugin = require('./tracing')
5
4
  const OpenAiLLMObsPlugin = require('../../dd-trace/src/llmobs/plugins/openai')
5
+ const OpenAiTracingPlugin = require('./tracing')
6
6
 
7
7
  class OpenAiPlugin extends CompositePlugin {
8
8
  static id = 'openai'
@@ -1,10 +1,30 @@
1
1
  'use strict'
2
2
 
3
+ /**
4
+ * @typedef {Record<string, unknown>} JsonObject
5
+ *
6
+ * @typedef {{ function: { arguments: string } }} ToolCall
7
+ * @typedef {{ content?: string, tool_calls?: ToolCall[] }} ChatDelta
8
+ *
9
+ * @typedef {{
10
+ * index: number,
11
+ * finish_reason?: string | null,
12
+ * text?: string,
13
+ * delta?: ChatDelta
14
+ * }} StreamChoice
15
+ *
16
+ * @typedef {JsonObject & { choices: StreamChoice[], usage?: unknown }} StreamChunk
17
+ * @typedef {JsonObject & { choices: Array<StreamChoice | undefined>, usage?: unknown }} StreamResponseBody
18
+ *
19
+ * @typedef {JsonObject & { status?: string }} ResponsesApiResponse
20
+ * @typedef {JsonObject & { response?: ResponsesApiResponse }} ResponsesApiChunk
21
+ */
22
+
3
23
  /**
4
24
  * Combines legacy OpenAI streamed chunks into a single object.
5
25
  * These legacy chunks are returned as buffers instead of individual objects.
6
26
  * @param {readonly Uint8Array[]} chunks
7
- * @returns {Array<Record<string, any>>}
27
+ * @returns {JsonObject[]}
8
28
  */
9
29
  function convertBuffersToObjects (chunks) {
10
30
  return Buffer
@@ -21,10 +41,10 @@ function convertBuffersToObjects (chunks) {
21
41
  * The shared logic will add a new choice index entry if it doesn't exist, and otherwise
22
42
  * hand off to a onChoice handler to add that choice to the previously stored choice.
23
43
  *
24
- * @param {Array<Record<string, any>>} chunks
44
+ * @param {StreamChunk[]} chunks
25
45
  * @param {number} n
26
- * @param {function(Record<string, any>, Record<string, any>): void} onChoice
27
- * @returns {Record<string, any>}
46
+ * @param {(newChoice: StreamChoice, existingChoice: StreamChoice) => void} onChoice
47
+ * @returns {StreamResponseBody}
28
48
  */
29
49
  function constructResponseFromStreamedChunks (chunks, n, onChoice) {
30
50
  const body = { ...chunks[0], choices: Array.from({ length: n }) }
@@ -54,9 +74,9 @@ function constructResponseFromStreamedChunks (chunks, n, onChoice) {
54
74
  /**
55
75
  * Constructs the entire response from a stream of OpenAI completion chunks,
56
76
  * mainly combining the text choices of each chunk into a single string per choice.
57
- * @param {Array<Record<string, any>>} chunks
77
+ * @param {StreamChunk[]} chunks
58
78
  * @param {number} n the number of choices to expect in the response
59
- * @returns {Record<string, any>}
79
+ * @returns {StreamResponseBody}
60
80
  */
61
81
  function constructCompletionResponseFromStreamedChunks (chunks, n) {
62
82
  return constructResponseFromStreamedChunks(chunks, n, (choice, oldChoice) => {
@@ -74,9 +94,9 @@ function constructCompletionResponseFromStreamedChunks (chunks, n) {
74
94
  /**
75
95
  * Constructs the entire response from a stream of OpenAI chat completion chunks,
76
96
  * mainly combining the text choices of each chunk into a single string per choice.
77
- * @param {Array<Record<string, any>>} chunks
97
+ * @param {StreamChunk[]} chunks
78
98
  * @param {number} n the number of choices to expect in the response
79
- * @returns {Record<string, any>}
99
+ * @returns {StreamResponseBody}
80
100
  */
81
101
  function constructChatCompletionResponseFromStreamedChunks (chunks, n) {
82
102
  return constructResponseFromStreamedChunks(chunks, n, (choice, oldChoice) => {
@@ -110,8 +130,8 @@ function constructChatCompletionResponseFromStreamedChunks (chunks, n) {
110
130
  /**
111
131
  * Constructs the entire response from a stream of OpenAI responses chunks.
112
132
  * The responses API uses event-based streaming with delta chunks.
113
- * @param {Array<Record<string, any>>} chunks
114
- * @returns {Record<string, any>|undefined}
133
+ * @param {ResponsesApiChunk[]} chunks
134
+ * @returns {ResponsesApiResponse|undefined}
115
135
  */
116
136
  function constructResponseResponseFromStreamedChunks (chunks) {
117
137
  // The responses API streams events with different types:
@@ -4,10 +4,10 @@ const path = require('path')
4
4
 
5
5
  const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
6
6
  const { storage } = require('../../datadog-core')
7
- const services = require('./services')
8
7
  const Sampler = require('../../dd-trace/src/sampler')
9
8
  const { MEASURED } = require('../../../ext/tags')
10
9
 
10
+ const { DD_MAJOR } = require('../../../version')
11
11
  const {
12
12
  convertBuffersToObjects,
13
13
  constructCompletionResponseFromStreamedChunks,
@@ -15,7 +15,7 @@ const {
15
15
  constructResponseResponseFromStreamedChunks
16
16
  } = require('./stream-helpers')
17
17
 
18
- const { DD_MAJOR } = require('../../../version')
18
+ const services = require('./services')
19
19
 
20
20
  class OpenAiTracingPlugin extends TracingPlugin {
21
21
  static id = 'openai'
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
3
4
  const ProducerPlugin = require('./producer')
4
5
  const ConsumerPlugin = require('./consumer')
5
- const CompositePlugin = require('../../dd-trace/src/plugins/composite')
6
6
 
7
7
  class RheaPlugin extends CompositePlugin {
8
8
  static id = 'rhea'
@@ -1,6 +1,16 @@
1
1
  'use strict'
2
2
 
3
3
  const TracingPlugin = require('../../dd-trace/src/plugins/tracing.js')
4
+ const {
5
+ WEBSOCKET_PTR_KIND,
6
+ SPAN_POINTER_DIRECTION,
7
+ SPAN_POINTER_DIRECTION_NAME
8
+ } = require('../../dd-trace/src/constants')
9
+ const {
10
+ incrementWebSocketCounter,
11
+ buildWebSocketSpanPointerHash,
12
+ hasDistributedTracingContext
13
+ } = require('./util')
4
14
 
5
15
  class WSClosePlugin extends TracingPlugin {
6
16
  static get id () { return 'ws' }
@@ -10,11 +20,9 @@ class WSClosePlugin extends TracingPlugin {
10
20
 
11
21
  bindStart (ctx) {
12
22
  const {
13
- traceWebsocketMessagesEnabled,
14
23
  traceWebsocketMessagesInheritSampling,
15
24
  traceWebsocketMessagesSeparateTraces
16
25
  } = this.config
17
- if (!traceWebsocketMessagesEnabled) return
18
26
 
19
27
  const { code, data, socket, isPeerClose } = ctx
20
28
  if (!socket?.spanContext) return
@@ -60,7 +68,52 @@ class WSClosePlugin extends TracingPlugin {
60
68
  end (ctx) {
61
69
  if (!Object.hasOwn(ctx, 'result') || !ctx.span) return
62
70
 
63
- if (ctx.socket.spanContext) ctx.span.addLink({ context: ctx.socket.spanContext })
71
+ if (ctx.socket.spanContext) {
72
+ const linkAttributes = {}
73
+
74
+ // Determine link kind based on whether this is peer close (incoming) or self close (outgoing)
75
+ const isIncoming = ctx.isPeerClose
76
+ linkAttributes['dd.kind'] = isIncoming ? 'executed_by' : 'resuming'
77
+
78
+ // Add span pointer for context propagation
79
+ if (this.config.traceWebsocketMessagesEnabled && ctx.socket.handshakeSpan) {
80
+ const handshakeSpan = ctx.socket.handshakeSpan
81
+
82
+ // Only add span pointers if distributed tracing is enabled and handshake has distributed context
83
+ if (hasDistributedTracingContext(handshakeSpan, ctx.socket)) {
84
+ const counterType = isIncoming ? 'receiveCounter' : 'sendCounter'
85
+ const counter = incrementWebSocketCounter(ctx.socket, counterType)
86
+ const handshakeContext = handshakeSpan.context()
87
+
88
+ const ptrHash = buildWebSocketSpanPointerHash(
89
+ handshakeContext._traceId,
90
+ handshakeContext._spanId,
91
+ counter,
92
+ true, // isServer
93
+ isIncoming
94
+ )
95
+
96
+ const directionName = isIncoming
97
+ ? SPAN_POINTER_DIRECTION_NAME.UPSTREAM
98
+ : SPAN_POINTER_DIRECTION_NAME.DOWNSTREAM
99
+ const direction = isIncoming
100
+ ? SPAN_POINTER_DIRECTION.UPSTREAM
101
+ : SPAN_POINTER_DIRECTION.DOWNSTREAM
102
+
103
+ // Add span pointer attributes to link
104
+ linkAttributes['link.name'] = directionName
105
+ linkAttributes['dd.kind'] = 'span-pointer'
106
+ linkAttributes['ptr.kind'] = WEBSOCKET_PTR_KIND
107
+ linkAttributes['ptr.dir'] = direction
108
+ linkAttributes['ptr.hash'] = ptrHash
109
+ }
110
+ }
111
+
112
+ ctx.span.addLink({
113
+ context: ctx.socket.spanContext,
114
+ attributes: linkAttributes
115
+ })
116
+ }
64
117
 
65
118
  ctx.span.finish()
66
119
  }
@@ -19,6 +19,10 @@ class WSPlugin extends CompositePlugin {
19
19
  }
20
20
 
21
21
  configure (config) {
22
+ if (!config.traceWebsocketMessagesEnabled) {
23
+ super.configure(false)
24
+ return
25
+ }
22
26
  return super.configure(config)
23
27
  }
24
28
  }
@@ -1,6 +1,16 @@
1
1
  'use strict'
2
2
 
3
3
  const TracingPlugin = require('../../dd-trace/src/plugins/tracing.js')
4
+ const {
5
+ WEBSOCKET_PTR_KIND,
6
+ SPAN_POINTER_DIRECTION,
7
+ SPAN_POINTER_DIRECTION_NAME
8
+ } = require('../../dd-trace/src/constants')
9
+ const {
10
+ incrementWebSocketCounter,
11
+ buildWebSocketSpanPointerHash,
12
+ hasDistributedTracingContext
13
+ } = require('./util')
4
14
 
5
15
  class WSProducerPlugin extends TracingPlugin {
6
16
  static get id () { return 'ws' }
@@ -9,9 +19,6 @@ class WSProducerPlugin extends TracingPlugin {
9
19
  static get kind () { return 'producer' }
10
20
 
11
21
  bindStart (ctx) {
12
- const messagesEnabled = this.config.traceWebsocketMessagesEnabled
13
- if (!messagesEnabled) return
14
-
15
22
  const { byteLength, socket, binary } = ctx
16
23
  if (!socket.spanContext) return
17
24
 
@@ -51,9 +58,37 @@ class WSProducerPlugin extends TracingPlugin {
51
58
  if (!Object.hasOwn(ctx, 'result') || !ctx.span) return
52
59
 
53
60
  if (ctx.socket.spanContext) {
61
+ const linkAttributes = { 'dd.kind': 'resuming' }
62
+
63
+ // Add span pointer for context propagation
64
+ if (this.config.traceWebsocketMessagesEnabled && ctx.socket.handshakeSpan) {
65
+ const handshakeSpan = ctx.socket.handshakeSpan
66
+
67
+ // Only add span pointers if distributed tracing is enabled and handshake has distributed context
68
+ if (hasDistributedTracingContext(handshakeSpan, ctx.socket)) {
69
+ const counter = incrementWebSocketCounter(ctx.socket, 'sendCounter')
70
+ const handshakeContext = handshakeSpan.context()
71
+
72
+ const ptrHash = buildWebSocketSpanPointerHash(
73
+ handshakeContext._traceId,
74
+ handshakeContext._spanId,
75
+ counter,
76
+ true, // isServer
77
+ false // isIncoming (this is outgoing)
78
+ )
79
+
80
+ // Add span pointer attributes to link
81
+ linkAttributes['link.name'] = SPAN_POINTER_DIRECTION_NAME.DOWNSTREAM
82
+ linkAttributes['dd.kind'] = 'span-pointer'
83
+ linkAttributes['ptr.kind'] = WEBSOCKET_PTR_KIND
84
+ linkAttributes['ptr.dir'] = SPAN_POINTER_DIRECTION.DOWNSTREAM
85
+ linkAttributes['ptr.hash'] = ptrHash
86
+ }
87
+ }
88
+
54
89
  ctx.span.addLink({
55
90
  context: ctx.socket.spanContext,
56
- attributes: { 'dd.kind': 'resuming' },
91
+ attributes: linkAttributes,
57
92
  })
58
93
  }
59
94
 
@@ -1,6 +1,16 @@
1
1
  'use strict'
2
2
 
3
3
  const TracingPlugin = require('../../dd-trace/src/plugins/tracing.js')
4
+ const {
5
+ WEBSOCKET_PTR_KIND,
6
+ SPAN_POINTER_DIRECTION,
7
+ SPAN_POINTER_DIRECTION_NAME
8
+ } = require('../../dd-trace/src/constants')
9
+ const {
10
+ incrementWebSocketCounter,
11
+ buildWebSocketSpanPointerHash,
12
+ hasDistributedTracingContext
13
+ } = require('./util')
4
14
 
5
15
  class WSReceiverPlugin extends TracingPlugin {
6
16
  static get id () { return 'ws' }
@@ -10,11 +20,9 @@ class WSReceiverPlugin extends TracingPlugin {
10
20
 
11
21
  bindStart (ctx) {
12
22
  const {
13
- traceWebsocketMessagesEnabled,
14
23
  traceWebsocketMessagesInheritSampling,
15
24
  traceWebsocketMessagesSeparateTraces
16
25
  } = this.config
17
- if (!traceWebsocketMessagesEnabled) return
18
26
 
19
27
  const { byteLength, socket, binary } = ctx
20
28
  if (!socket.spanContext) return
@@ -61,9 +69,37 @@ class WSReceiverPlugin extends TracingPlugin {
61
69
  if (!Object.hasOwn(ctx, 'result') || !ctx.span) return
62
70
 
63
71
  if (ctx.socket.spanContext) {
72
+ const linkAttributes = { 'dd.kind': 'executed_by' }
73
+
74
+ // Add span pointer for context propagation
75
+ if (this.config.traceWebsocketMessagesEnabled && ctx.socket.handshakeSpan) {
76
+ const handshakeSpan = ctx.socket.handshakeSpan
77
+
78
+ // Only add span pointers if distributed tracing is enabled and handshake has distributed context
79
+ if (hasDistributedTracingContext(handshakeSpan, ctx.socket)) {
80
+ const counter = incrementWebSocketCounter(ctx.socket, 'receiveCounter')
81
+ const handshakeContext = handshakeSpan.context()
82
+
83
+ const ptrHash = buildWebSocketSpanPointerHash(
84
+ handshakeContext._traceId,
85
+ handshakeContext._spanId,
86
+ counter,
87
+ true, // isServer
88
+ true // isIncoming
89
+ )
90
+
91
+ // Add span pointer attributes to link
92
+ linkAttributes['link.name'] = SPAN_POINTER_DIRECTION_NAME.UPSTREAM
93
+ linkAttributes['dd.kind'] = 'span-pointer'
94
+ linkAttributes['ptr.kind'] = WEBSOCKET_PTR_KIND
95
+ linkAttributes['ptr.dir'] = SPAN_POINTER_DIRECTION.UPSTREAM
96
+ linkAttributes['ptr.hash'] = ptrHash
97
+ }
98
+ }
99
+
64
100
  ctx.span.addLink({
65
101
  context: ctx.socket.spanContext,
66
- attributes: { 'dd.kind': 'executed_by' },
102
+ attributes: linkAttributes,
67
103
  })
68
104
  }
69
105
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  const TracingPlugin = require('../../dd-trace/src/plugins/tracing.js')
4
4
  const tags = require('../../../ext/tags.js')
5
+ const { FORMAT_HTTP_HEADERS } = require('../../../ext/formats')
6
+ const { initWebSocketMessageCounters } = require('./util')
5
7
 
6
8
  const HTTP_STATUS_CODE = tags.HTTP_STATUS_CODE
7
9
 
@@ -28,9 +30,13 @@ class WSServerPlugin extends TracingPlugin {
28
30
 
29
31
  ctx.args = { options }
30
32
 
33
+ // Extract distributed tracing context from request headers
34
+ const childOf = this.tracer.extract(FORMAT_HTTP_HEADERS, req.headers)
35
+
31
36
  const service = this.serviceName({ pluginConfig: this.config })
32
37
  const span = this.startSpan(this.operationName(), {
33
38
  service,
39
+ childOf,
34
40
  meta: {
35
41
  'span.type': 'websocket',
36
42
  'http.upgraded': 'websocket',
@@ -38,7 +44,6 @@ class WSServerPlugin extends TracingPlugin {
38
44
  'http.url': uri,
39
45
  'resource.name': `${options.method} ${route}`,
40
46
  'span.kind': 'server'
41
-
42
47
  }
43
48
 
44
49
  }, ctx)
@@ -46,6 +51,13 @@ class WSServerPlugin extends TracingPlugin {
46
51
 
47
52
  ctx.socket.spanContext = ctx.span._spanContext
48
53
  ctx.socket.spanContext.spanTags = ctx.span._spanContext._tags
54
+ // Store the handshake span for use in message span pointers
55
+ ctx.socket.handshakeSpan = ctx.span
56
+ // Store the request headers for distributed tracing check
57
+ ctx.socket.requestHeaders = req.headers
58
+
59
+ // Initialize message counters for span pointers
60
+ initWebSocketMessageCounters(ctx.socket)
49
61
 
50
62
  return ctx.currentStore
51
63
  }
@@ -0,0 +1,107 @@
1
+ 'use strict'
2
+
3
+ // WeakMap to store message counters per socket without mutating the socket object
4
+ const socketCounters = new WeakMap()
5
+
6
+ /**
7
+ * Initializes WebSocket message counters for a socket.
8
+ * @param {object} socket - The WebSocket socket object
9
+ */
10
+ function initWebSocketMessageCounters (socket) {
11
+ if (!socketCounters.has(socket)) {
12
+ socketCounters.set(socket, {
13
+ receiveCounter: 0,
14
+ sendCounter: 0
15
+ })
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Increments and returns the WebSocket message counter.
21
+ * @param {object} socket - The WebSocket socket object
22
+ * @param {string} counterType - Either 'receiveCounter' or 'sendCounter'
23
+ * @returns {number} The incremented counter value
24
+ */
25
+ function incrementWebSocketCounter (socket, counterType) {
26
+ if (!socketCounters.has(socket)) {
27
+ initWebSocketMessageCounters(socket)
28
+ }
29
+ const counters = socketCounters.get(socket)
30
+ counters[counterType]++
31
+ return counters[counterType]
32
+ }
33
+
34
+ /**
35
+ * Builds a WebSocket span pointer hash.
36
+ *
37
+ * Format: <prefix><128 bit hex trace id><64 bit hex span id><32 bit hex counter>
38
+ * Prefix: 'S' for server outgoing or client incoming, 'C' for server incoming or client outgoing
39
+ *
40
+ * @param {bigint} handshakeTraceId - The trace ID from the handshake span (as a BigInt)
41
+ * @param {bigint} handshakeSpanId - The span ID from the handshake span (as a BigInt)
42
+ * @param {number} counter - The message counter
43
+ * @param {boolean} isServer - Whether this is a server (true) or client (false)
44
+ * @param {boolean} isIncoming - Whether this is an incoming message (true) or outgoing (false)
45
+ * @returns {string} The span pointer hash
46
+ */
47
+ function buildWebSocketSpanPointerHash (handshakeTraceId, handshakeSpanId, counter, isServer, isIncoming) {
48
+ // Determine prefix based on server/client and incoming/outgoing
49
+ // Server outgoing or client incoming: 'S'
50
+ // Server incoming or client outgoing: 'C'
51
+ const prefix = (isServer && !isIncoming) || (!isServer && isIncoming) ? 'S' : 'C'
52
+
53
+ // Pad trace ID to 32 hex chars (128 bits)
54
+ const traceIdHex = handshakeTraceId.toString(16).padStart(32, '0')
55
+
56
+ // Pad span ID to 16 hex chars (64 bits)
57
+ const spanIdHex = handshakeSpanId.toString(16).padStart(16, '0')
58
+
59
+ // Pad counter to 8 hex chars (32 bits)
60
+ const counterHex = counter.toString(16).padStart(8, '0')
61
+
62
+ return `${prefix}${traceIdHex}${spanIdHex}${counterHex}`
63
+ }
64
+
65
+ /**
66
+ * Checks if the handshake span has extracted distributed tracing context.
67
+ * A websocket server must not set the span pointer if the handshake has not extracted a context.
68
+ *
69
+ * A span has distributed tracing context if it has a parent context that was
70
+ * extracted from headers (remote parent).
71
+ *
72
+ * @param {object} span - The handshake span
73
+ * @param {object} socket - The WebSocket socket object
74
+ * @returns {boolean} True if the span has distributed tracing context
75
+ */
76
+ function hasDistributedTracingContext (span, socket) {
77
+ if (!span) return false
78
+ const context = span.context()
79
+ if (!context) return false
80
+
81
+ // Check if this span has a parent. If the parent was extracted from remote headers,
82
+ // then this span is part of a distributed trace.
83
+ // We check if the span has a parent by looking at _parentId.
84
+ // In the JavaScript tracer, when a context is extracted from headers and a child span
85
+ // is created, the child will have _parentId set to the extracted parent's span ID.
86
+ //
87
+ // For testing purposes, we also check if Datadog trace headers are present in the socket's
88
+ // upgrade request, which indicates distributed tracing context was sent by the client.
89
+ if (context._parentId !== null) {
90
+ return true
91
+ }
92
+
93
+ // Fallback check: look for distributed tracing headers in the stored request headers
94
+ if (socket && socket.requestHeaders) {
95
+ const headers = socket.requestHeaders
96
+ return !!(headers['x-datadog-trace-id'] || headers.traceparent)
97
+ }
98
+
99
+ return false
100
+ }
101
+
102
+ module.exports = {
103
+ initWebSocketMessageCounters,
104
+ incrementWebSocketCounter,
105
+ buildWebSocketSpanPointerHash,
106
+ hasDistributedTracingContext
107
+ }
@@ -91,7 +91,7 @@ function wrapFunction (original, wrapper) {
91
91
  * @param {Record<string | symbol, unknown> | Function | undefined} target - The target
92
92
  * object.
93
93
  * @param {string | symbol} name - The property key of the method to wrap.
94
- * @param {(original: Function) => (...args: unknown[]) => any} wrapper - The wrapper function.
94
+ * @param {(original: Function) => (...args: unknown[]) => unknown} wrapper - The wrapper function.
95
95
  * @param {{ replaceGetter?: boolean }} [options] - If `replaceGetter` is set to
96
96
  * true, the getter is accessed and the getter is replaced with one that just
97
97
  * returns the earlier retrieved value. Use with care! This may only be done in
@@ -214,7 +214,7 @@ function wrap (target, name, wrapper, options) {
214
214
  * Record<string | symbol, unknown> |
215
215
  * Function} targets - The target objects.
216
216
  * @param {Array<string | symbol> | string | symbol} names - The property keys of the methods to wrap.
217
- * @param {(original: Function) => (...args: unknown[]) => any} wrapper - The wrapper function.
217
+ * @param {(original: Function) => (...args: unknown[]) => unknown} wrapper - The wrapper function.
218
218
  */
219
219
  function massWrap (targets, names, wrapper) {
220
220
  targets = toArray(targets)