dd-trace 5.80.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 (460) hide show
  1. package/LICENSE-3rdparty.csv +79 -88
  2. package/ext/tags.d.ts +1 -0
  3. package/ext/tags.js +1 -0
  4. package/index.d.ts +42 -35
  5. package/loader-hook.mjs +16 -4
  6. package/package.json +33 -56
  7. package/packages/datadog-core/src/utils/src/parse-tags.js +1 -1
  8. package/packages/datadog-esbuild/index.js +44 -26
  9. package/packages/datadog-esbuild/src/utils.js +14 -2
  10. package/packages/datadog-instrumentations/index.js +1 -0
  11. package/packages/datadog-instrumentations/src/aerospike.js +3 -2
  12. package/packages/datadog-instrumentations/src/ai.js +2 -2
  13. package/packages/datadog-instrumentations/src/amqp10.js +1 -1
  14. package/packages/datadog-instrumentations/src/amqplib.js +4 -4
  15. package/packages/datadog-instrumentations/src/anthropic.js +14 -2
  16. package/packages/datadog-instrumentations/src/apollo-server-core.js +2 -2
  17. package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
  18. package/packages/datadog-instrumentations/src/apollo.js +3 -2
  19. package/packages/datadog-instrumentations/src/avsc.js +1 -1
  20. package/packages/datadog-instrumentations/src/aws-sdk.js +6 -2
  21. package/packages/datadog-instrumentations/src/azure-event-hubs.js +4 -3
  22. package/packages/datadog-instrumentations/src/azure-functions.js +2 -2
  23. package/packages/datadog-instrumentations/src/azure-service-bus.js +3 -4
  24. package/packages/datadog-instrumentations/src/bluebird.js +1 -1
  25. package/packages/datadog-instrumentations/src/bullmq.js +11 -0
  26. package/packages/datadog-instrumentations/src/bunyan.js +1 -1
  27. package/packages/datadog-instrumentations/src/cassandra-driver.js +1 -1
  28. package/packages/datadog-instrumentations/src/child_process.js +2 -2
  29. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +3 -3
  30. package/packages/datadog-instrumentations/src/couchbase.js +1 -1
  31. package/packages/datadog-instrumentations/src/crypto.js +1 -1
  32. package/packages/datadog-instrumentations/src/cucumber.js +12 -13
  33. package/packages/datadog-instrumentations/src/cypress.js +1 -1
  34. package/packages/datadog-instrumentations/src/dns.js +1 -1
  35. package/packages/datadog-instrumentations/src/elasticsearch.js +1 -1
  36. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +1 -1
  37. package/packages/datadog-instrumentations/src/express.js +1 -1
  38. package/packages/datadog-instrumentations/src/find-my-way.js +6 -5
  39. package/packages/datadog-instrumentations/src/fs.js +1 -1
  40. package/packages/datadog-instrumentations/src/generic-pool.js +1 -1
  41. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +137 -15
  42. package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +2 -3
  43. package/packages/datadog-instrumentations/src/google-genai.js +120 -0
  44. package/packages/datadog-instrumentations/src/graphql.js +21 -1
  45. package/packages/datadog-instrumentations/src/grpc/client.js +1 -1
  46. package/packages/datadog-instrumentations/src/grpc/server.js +1 -1
  47. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +1 -1
  48. package/packages/datadog-instrumentations/src/helpers/hook.js +1 -1
  49. package/packages/datadog-instrumentations/src/helpers/hooks.js +5 -1
  50. package/packages/datadog-instrumentations/src/helpers/instrument.js +11 -1
  51. package/packages/datadog-instrumentations/src/helpers/register.js +12 -5
  52. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +27 -0
  53. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +152 -0
  54. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/bullmq.json +106 -0
  55. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +6 -0
  56. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langchain.js +237 -0
  57. package/packages/datadog-instrumentations/src/helpers/rewriter/loader.js +9 -0
  58. package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +11 -0
  59. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +139 -0
  60. package/packages/datadog-instrumentations/src/helpers/router-helper.js +1 -1
  61. package/packages/datadog-instrumentations/src/helpers/shared-utils.js +9 -0
  62. package/packages/datadog-instrumentations/src/hono.js +55 -10
  63. package/packages/datadog-instrumentations/src/ioredis.js +1 -1
  64. package/packages/datadog-instrumentations/src/iovalkey.js +1 -1
  65. package/packages/datadog-instrumentations/src/jest.js +2 -2
  66. package/packages/datadog-instrumentations/src/kafkajs.js +3 -3
  67. package/packages/datadog-instrumentations/src/knex.js +1 -1
  68. package/packages/datadog-instrumentations/src/langchain.js +3 -109
  69. package/packages/datadog-instrumentations/src/ldapjs.js +1 -1
  70. package/packages/datadog-instrumentations/src/light-my-request.js +93 -0
  71. package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
  72. package/packages/datadog-instrumentations/src/lodash.js +1 -2
  73. package/packages/datadog-instrumentations/src/mariadb.js +1 -2
  74. package/packages/datadog-instrumentations/src/memcached.js +1 -1
  75. package/packages/datadog-instrumentations/src/mocha/main.js +1 -1
  76. package/packages/datadog-instrumentations/src/mongodb-core.js +1 -1
  77. package/packages/datadog-instrumentations/src/mongodb.js +1 -1
  78. package/packages/datadog-instrumentations/src/mongoose.js +1 -1
  79. package/packages/datadog-instrumentations/src/mquery.js +1 -1
  80. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  81. package/packages/datadog-instrumentations/src/mysql2.js +2 -2
  82. package/packages/datadog-instrumentations/src/net.js +1 -1
  83. package/packages/datadog-instrumentations/src/next.js +1 -1
  84. package/packages/datadog-instrumentations/src/nyc.js +1 -1
  85. package/packages/datadog-instrumentations/src/openai.js +2 -2
  86. package/packages/datadog-instrumentations/src/opensearch.js +1 -1
  87. package/packages/datadog-instrumentations/src/oracledb.js +1 -1
  88. package/packages/datadog-instrumentations/src/otel-sdk-trace.js +1 -1
  89. package/packages/datadog-instrumentations/src/pg.js +3 -3
  90. package/packages/datadog-instrumentations/src/pino.js +1 -1
  91. package/packages/datadog-instrumentations/src/playwright.js +46 -17
  92. package/packages/datadog-instrumentations/src/prisma.js +52 -37
  93. package/packages/datadog-instrumentations/src/process.js +1 -1
  94. package/packages/datadog-instrumentations/src/promise-js.js +1 -1
  95. package/packages/datadog-instrumentations/src/promise.js +1 -1
  96. package/packages/datadog-instrumentations/src/protobufjs.js +1 -1
  97. package/packages/datadog-instrumentations/src/q.js +1 -1
  98. package/packages/datadog-instrumentations/src/redis.js +1 -1
  99. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  100. package/packages/datadog-instrumentations/src/router.js +1 -1
  101. package/packages/datadog-instrumentations/src/selenium.js +4 -2
  102. package/packages/datadog-instrumentations/src/sequelize.js +1 -2
  103. package/packages/datadog-instrumentations/src/sharedb.js +1 -1
  104. package/packages/datadog-instrumentations/src/tedious.js +1 -1
  105. package/packages/datadog-instrumentations/src/undici.js +4 -4
  106. package/packages/datadog-instrumentations/src/url.js +1 -1
  107. package/packages/datadog-instrumentations/src/vitest.js +1 -1
  108. package/packages/datadog-instrumentations/src/vm.js +1 -1
  109. package/packages/datadog-instrumentations/src/when.js +1 -1
  110. package/packages/datadog-instrumentations/src/winston.js +1 -1
  111. package/packages/datadog-instrumentations/src/ws.js +38 -19
  112. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  113. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  114. package/packages/datadog-plugin-anthropic/src/index.js +1 -1
  115. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +1 -1
  116. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +4 -4
  117. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  118. package/packages/datadog-plugin-aws-sdk/src/util.js +3 -3
  119. package/packages/datadog-plugin-azure-event-hubs/src/index.js +1 -1
  120. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +19 -5
  121. package/packages/datadog-plugin-azure-service-bus/src/index.js +1 -1
  122. package/packages/datadog-plugin-azure-service-bus/src/producer.js +4 -0
  123. package/packages/datadog-plugin-bullmq/src/consumer.js +60 -0
  124. package/packages/datadog-plugin-bullmq/src/index.js +18 -0
  125. package/packages/datadog-plugin-bullmq/src/producer.js +178 -0
  126. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -1
  127. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  128. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +23 -2
  129. package/packages/datadog-plugin-cypress/src/plugin.js +2 -2
  130. package/packages/datadog-plugin-cypress/src/support.js +73 -31
  131. package/packages/datadog-plugin-express/src/index.js +1 -1
  132. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  133. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +13 -3
  134. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +171 -12
  135. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -2
  136. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +160 -13
  137. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +217 -0
  138. package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +1 -1
  139. package/packages/datadog-plugin-google-genai/src/index.js +17 -0
  140. package/packages/datadog-plugin-google-genai/src/tracing.js +41 -0
  141. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  142. package/packages/datadog-plugin-graphql/src/tools/transforms.js +5 -4
  143. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  144. package/packages/datadog-plugin-http/src/client.js +2 -1
  145. package/packages/datadog-plugin-http/src/index.js +25 -5
  146. package/packages/datadog-plugin-http2/src/client.js +2 -2
  147. package/packages/datadog-plugin-http2/src/index.js +1 -1
  148. package/packages/datadog-plugin-jest/src/util.js +1 -1
  149. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  150. package/packages/datadog-plugin-langchain/src/index.js +1 -1
  151. package/packages/datadog-plugin-langchain/src/tracing.js +7 -3
  152. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  153. package/packages/datadog-plugin-mongodb-core/src/index.js +6 -2
  154. package/packages/datadog-plugin-next/src/index.js +11 -3
  155. package/packages/datadog-plugin-openai/src/index.js +1 -1
  156. package/packages/datadog-plugin-openai/src/stream-helpers.js +30 -10
  157. package/packages/datadog-plugin-openai/src/tracing.js +2 -2
  158. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  159. package/packages/datadog-plugin-ws/src/close.js +56 -3
  160. package/packages/datadog-plugin-ws/src/index.js +4 -0
  161. package/packages/datadog-plugin-ws/src/producer.js +39 -4
  162. package/packages/datadog-plugin-ws/src/receiver.js +39 -3
  163. package/packages/datadog-plugin-ws/src/server.js +13 -1
  164. package/packages/datadog-plugin-ws/src/util.js +107 -0
  165. package/packages/datadog-shimmer/src/shimmer.js +2 -2
  166. package/packages/dd-trace/src/aiguard/sdk.js +21 -13
  167. package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
  168. package/packages/dd-trace/src/appsec/graphql.js +2 -2
  169. package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +1 -1
  170. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +1 -1
  171. package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +1 -1
  172. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
  173. package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +1 -1
  174. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +1 -1
  175. package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +3 -3
  176. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +1 -1
  177. package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +1 -1
  178. package/packages/dd-trace/src/appsec/iast/analyzers/untrusted-deserialization-analyzer.js +1 -1
  179. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +1 -1
  180. package/packages/dd-trace/src/appsec/iast/analyzers/weak-cipher-analyzer.js +1 -1
  181. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +3 -2
  182. package/packages/dd-trace/src/appsec/iast/analyzers/weak-randomness-analyzer.js +1 -1
  183. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +3 -3
  184. package/packages/dd-trace/src/appsec/iast/index.js +5 -5
  185. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
  186. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +1 -1
  187. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +1 -2
  188. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +1 -1
  189. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
  190. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -1
  191. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +11 -16
  192. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
  193. package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +1 -1
  194. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -4
  195. package/packages/dd-trace/src/appsec/index.js +8 -8
  196. package/packages/dd-trace/src/appsec/rasp/command_injection.js +1 -1
  197. package/packages/dd-trace/src/appsec/rasp/index.js +1 -1
  198. package/packages/dd-trace/src/appsec/rasp/lfi.js +1 -1
  199. package/packages/dd-trace/src/appsec/rc-products.js +10 -0
  200. package/packages/dd-trace/src/appsec/recommended.json +230 -3
  201. package/packages/dd-trace/src/appsec/remote_config.js +177 -0
  202. package/packages/dd-trace/src/appsec/reporter.js +3 -7
  203. package/packages/dd-trace/src/appsec/rule_manager.js +37 -20
  204. package/packages/dd-trace/src/appsec/sdk/index.js +1 -1
  205. package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
  206. package/packages/dd-trace/src/appsec/sdk/track_event.js +2 -2
  207. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
  208. package/packages/dd-trace/src/appsec/user_tracking.js +2 -2
  209. package/packages/dd-trace/src/appsec/waf/index.js +17 -3
  210. package/packages/dd-trace/src/appsec/waf/waf_manager.js +11 -0
  211. package/packages/dd-trace/src/azure_metadata.js +8 -2
  212. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +8 -6
  213. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +2 -2
  214. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +1 -1
  215. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +1 -1
  216. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +4 -2
  217. package/packages/dd-trace/src/config/remote_config.js +34 -0
  218. package/packages/dd-trace/src/config.js +109 -34
  219. package/packages/dd-trace/src/config_defaults.js +16 -3
  220. package/packages/dd-trace/src/constants.js +5 -0
  221. package/packages/dd-trace/src/crashtracking/crashtracker.js +10 -1
  222. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
  223. package/packages/dd-trace/src/datastreams/encoding.js +23 -6
  224. package/packages/dd-trace/src/datastreams/index.js +1 -1
  225. package/packages/dd-trace/src/datastreams/pathway.js +41 -2
  226. package/packages/dd-trace/src/datastreams/processor.js +3 -3
  227. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -1
  228. package/packages/dd-trace/src/datastreams/writer.js +2 -2
  229. package/packages/dd-trace/src/debugger/config.js +1 -0
  230. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +15 -5
  231. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
  232. package/packages/dd-trace/src/debugger/devtools_client/config.js +3 -1
  233. package/packages/dd-trace/src/debugger/devtools_client/index.js +37 -17
  234. package/packages/dd-trace/src/debugger/devtools_client/inspector_promises_polyfill.js +2 -0
  235. package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +24 -18
  236. package/packages/dd-trace/src/debugger/devtools_client/send.js +21 -11
  237. package/packages/dd-trace/src/debugger/devtools_client/session.js +1 -1
  238. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +103 -15
  239. package/packages/dd-trace/src/debugger/devtools_client/snapshot/constants.js +25 -0
  240. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +56 -25
  241. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +64 -23
  242. package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +3 -1
  243. package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +404 -0
  244. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
  245. package/packages/dd-trace/src/debugger/devtools_client/state.js +8 -3
  246. package/packages/dd-trace/src/debugger/devtools_client/status.js +3 -3
  247. package/packages/dd-trace/src/debugger/index.js +2 -2
  248. package/packages/dd-trace/src/dogstatsd.js +3 -2
  249. package/packages/dd-trace/src/encode/0.4.js +1 -1
  250. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +2 -2
  251. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +1 -1
  252. package/packages/dd-trace/src/encode/span-stats.js +13 -2
  253. package/packages/dd-trace/src/exporter.js +2 -2
  254. package/packages/dd-trace/src/exporters/agent/index.js +1 -1
  255. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +1 -1
  256. package/packages/dd-trace/src/exporters/common/request.js +2 -2
  257. package/packages/dd-trace/src/exporters/common/writer.js +1 -1
  258. package/packages/dd-trace/src/exporters/span-stats/index.js +1 -1
  259. package/packages/dd-trace/src/external-logger/src/index.js +1 -2
  260. package/packages/dd-trace/src/flare/index.js +1 -1
  261. package/packages/dd-trace/src/guardrails/index.js +6 -3
  262. package/packages/dd-trace/src/histogram.js +1 -1
  263. package/packages/dd-trace/src/id.js +60 -0
  264. package/packages/dd-trace/src/index.js +1 -1
  265. package/packages/dd-trace/src/lambda/handler.js +4 -4
  266. package/packages/dd-trace/src/lambda/index.js +1 -1
  267. package/packages/dd-trace/src/lambda/runtime/patch.js +4 -4
  268. package/packages/dd-trace/src/lambda/runtime/ritm.js +2 -2
  269. package/packages/dd-trace/src/llmobs/constants/tags.js +8 -1
  270. package/packages/dd-trace/src/llmobs/index.js +8 -9
  271. package/packages/dd-trace/src/llmobs/plugins/ai/index.js +38 -7
  272. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +30 -9
  273. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +3 -3
  274. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +104 -0
  275. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +486 -0
  276. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +1 -1
  277. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +1 -1
  278. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/embedding.js +1 -1
  279. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/llm.js +1 -1
  280. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +1 -1
  281. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +2 -2
  282. package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +16 -0
  283. package/packages/dd-trace/src/llmobs/plugins/{openai.js → openai/index.js} +63 -6
  284. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +126 -0
  285. package/packages/dd-trace/src/llmobs/plugins/vertexai.js +1 -1
  286. package/packages/dd-trace/src/llmobs/sdk.js +20 -22
  287. package/packages/dd-trace/src/llmobs/span_processor.js +15 -14
  288. package/packages/dd-trace/src/llmobs/tagger.js +4 -0
  289. package/packages/dd-trace/src/llmobs/telemetry.js +3 -4
  290. package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
  291. package/packages/dd-trace/src/llmobs/writers/spans.js +1 -2
  292. package/packages/dd-trace/src/log/index.js +1 -1
  293. package/packages/dd-trace/src/noop/proxy.js +2 -2
  294. package/packages/dd-trace/src/noop/span.js +1 -1
  295. package/packages/dd-trace/src/openfeature/index.js +2 -2
  296. package/packages/dd-trace/src/openfeature/noop.js +14 -14
  297. package/packages/dd-trace/src/openfeature/remote_config.js +31 -0
  298. package/packages/dd-trace/src/openfeature/writers/base.js +5 -5
  299. package/packages/dd-trace/src/openfeature/writers/exposures.js +9 -9
  300. package/packages/dd-trace/src/opentelemetry/context_manager.js +2 -2
  301. package/packages/dd-trace/src/opentelemetry/logs/index.js +2 -2
  302. package/packages/dd-trace/src/opentelemetry/logs/logger.js +3 -2
  303. package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +4 -4
  304. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +5 -3
  305. package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +17 -16
  306. package/packages/dd-trace/src/opentelemetry/metrics/constants.js +34 -0
  307. package/packages/dd-trace/src/opentelemetry/metrics/index.js +81 -0
  308. package/packages/dd-trace/src/opentelemetry/metrics/instruments.js +225 -0
  309. package/packages/dd-trace/src/opentelemetry/metrics/meter.js +171 -0
  310. package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +54 -0
  311. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +62 -0
  312. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +251 -0
  313. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +557 -0
  314. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +10 -18
  315. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +47 -32
  316. package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +1 -1
  317. package/packages/dd-trace/src/opentelemetry/span.js +3 -3
  318. package/packages/dd-trace/src/opentelemetry/tracer.js +4 -4
  319. package/packages/dd-trace/src/opentelemetry/tracer_provider.js +1 -1
  320. package/packages/dd-trace/src/opentracing/propagation/text_map.js +24 -8
  321. package/packages/dd-trace/src/opentracing/span.js +3 -3
  322. package/packages/dd-trace/src/opentracing/tracer.js +5 -5
  323. package/packages/dd-trace/src/payload-tagging/index.js +8 -4
  324. package/packages/dd-trace/src/plugin_manager.js +5 -3
  325. package/packages/dd-trace/src/plugins/apollo.js +1 -1
  326. package/packages/dd-trace/src/plugins/ci_plugin.js +27 -27
  327. package/packages/dd-trace/src/plugins/database.js +1 -1
  328. package/packages/dd-trace/src/plugins/index.js +6 -1
  329. package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
  330. package/packages/dd-trace/src/plugins/outbound.js +1 -1
  331. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  332. package/packages/dd-trace/src/plugins/util/ci.js +1 -1
  333. package/packages/dd-trace/src/plugins/util/git.js +8 -8
  334. package/packages/dd-trace/src/plugins/util/stacktrace.js +1 -1
  335. package/packages/dd-trace/src/plugins/util/test.js +27 -27
  336. package/packages/dd-trace/src/plugins/util/url.js +119 -1
  337. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
  338. package/packages/dd-trace/src/plugins/util/web.js +18 -46
  339. package/packages/dd-trace/src/priority_sampler.js +15 -16
  340. package/packages/dd-trace/src/process-tags/index.js +83 -0
  341. package/packages/dd-trace/src/profiling/config.js +33 -22
  342. package/packages/dd-trace/src/profiling/exporter_cli.js +4 -4
  343. package/packages/dd-trace/src/profiling/exporters/agent.js +5 -5
  344. package/packages/dd-trace/src/profiling/index.js +1 -1
  345. package/packages/dd-trace/src/profiling/libuv-size.js +1 -1
  346. package/packages/dd-trace/src/profiling/profiler.js +4 -5
  347. package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +1 -1
  348. package/packages/dd-trace/src/profiling/profilers/events.js +11 -2
  349. package/packages/dd-trace/src/profiling/profilers/wall.js +4 -4
  350. package/packages/dd-trace/src/proxy.js +17 -18
  351. package/packages/dd-trace/src/rate_limiter.js +1 -1
  352. package/packages/dd-trace/src/remote_config/index.js +541 -137
  353. package/packages/dd-trace/src/require-package-json.js +1 -1
  354. package/packages/dd-trace/src/ritm.js +50 -27
  355. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +1 -1
  356. package/packages/dd-trace/src/serverless.js +16 -0
  357. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +8 -0
  358. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
  359. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
  360. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
  361. package/packages/dd-trace/src/span_format.js +10 -5
  362. package/packages/dd-trace/src/span_processor.js +8 -3
  363. package/packages/dd-trace/src/span_stats.js +21 -8
  364. package/packages/dd-trace/src/spanleak.js +1 -1
  365. package/packages/dd-trace/src/standalone/index.js +1 -1
  366. package/packages/dd-trace/src/startup-log.js +3 -3
  367. package/packages/dd-trace/src/supported-configurations.json +16 -0
  368. package/packages/dd-trace/src/telemetry/dependencies.js +4 -4
  369. package/packages/dd-trace/src/telemetry/endpoints.js +8 -8
  370. package/packages/dd-trace/src/telemetry/logs/index.js +1 -1
  371. package/packages/dd-trace/src/telemetry/telemetry.js +22 -8
  372. package/packages/dd-trace/src/tracer.js +3 -3
  373. package/packages/dd-trace/src/tracer_metadata.js +19 -15
  374. package/vendor/dist/@datadog/sketches-js/LICENSE +39 -0
  375. package/vendor/dist/@datadog/sketches-js/index.js +1 -0
  376. package/vendor/dist/@datadog/source-map/LICENSE +28 -0
  377. package/vendor/dist/@datadog/source-map/index.js +1 -0
  378. package/vendor/dist/@isaacs/ttlcache/LICENSE +55 -0
  379. package/vendor/dist/@isaacs/ttlcache/index.js +1 -0
  380. package/vendor/dist/@opentelemetry/core/LICENSE +201 -0
  381. package/vendor/dist/@opentelemetry/core/index.js +1 -0
  382. package/vendor/dist/@opentelemetry/resources/LICENSE +201 -0
  383. package/vendor/dist/@opentelemetry/resources/index.js +1 -0
  384. package/vendor/dist/astring/LICENSE +19 -0
  385. package/vendor/dist/astring/index.js +1 -0
  386. package/vendor/dist/crypto-randomuuid/index.js +1 -0
  387. package/vendor/dist/escape-string-regexp/LICENSE +9 -0
  388. package/vendor/dist/escape-string-regexp/index.js +1 -0
  389. package/vendor/dist/esquery/LICENSE +24 -0
  390. package/vendor/dist/esquery/index.js +1 -0
  391. package/vendor/dist/ignore/LICENSE +21 -0
  392. package/vendor/dist/ignore/index.js +1 -0
  393. package/vendor/dist/istanbul-lib-coverage/LICENSE +24 -0
  394. package/vendor/dist/istanbul-lib-coverage/index.js +1 -0
  395. package/vendor/dist/jest-docblock/LICENSE +21 -0
  396. package/vendor/dist/jest-docblock/index.js +1 -0
  397. package/vendor/dist/jsonpath-plus/LICENSE +22 -0
  398. package/vendor/dist/jsonpath-plus/index.js +1 -0
  399. package/vendor/dist/limiter/LICENSE +19 -0
  400. package/vendor/dist/limiter/index.js +1 -0
  401. package/vendor/dist/lodash.sortby/LICENSE +47 -0
  402. package/vendor/dist/lodash.sortby/index.js +1 -0
  403. package/vendor/dist/lru-cache/LICENSE +15 -0
  404. package/vendor/dist/lru-cache/index.js +1 -0
  405. package/vendor/dist/meriyah/LICENSE +7 -0
  406. package/vendor/dist/meriyah/index.js +1 -0
  407. package/vendor/dist/module-details-from-path/LICENSE +21 -0
  408. package/vendor/dist/module-details-from-path/index.js +1 -0
  409. package/vendor/dist/mutexify/promise/LICENSE +21 -0
  410. package/vendor/dist/mutexify/promise/index.js +1 -0
  411. package/vendor/dist/opentracing/LICENSE +201 -0
  412. package/vendor/dist/opentracing/binary_carrier.d.ts +11 -0
  413. package/vendor/dist/opentracing/constants.d.ts +61 -0
  414. package/vendor/dist/opentracing/examples/demo/demo.d.ts +2 -0
  415. package/vendor/dist/opentracing/ext/tags.d.ts +90 -0
  416. package/vendor/dist/opentracing/functions.d.ts +20 -0
  417. package/vendor/dist/opentracing/global_tracer.d.ts +14 -0
  418. package/vendor/dist/opentracing/index.d.ts +12 -0
  419. package/vendor/dist/opentracing/index.js +1 -0
  420. package/vendor/dist/opentracing/mock_tracer/index.d.ts +5 -0
  421. package/vendor/dist/opentracing/mock_tracer/mock_context.d.ts +13 -0
  422. package/vendor/dist/opentracing/mock_tracer/mock_report.d.ts +16 -0
  423. package/vendor/dist/opentracing/mock_tracer/mock_span.d.ts +50 -0
  424. package/vendor/dist/opentracing/mock_tracer/mock_tracer.d.ts +26 -0
  425. package/vendor/dist/opentracing/noop.d.ts +8 -0
  426. package/vendor/dist/opentracing/reference.d.ts +33 -0
  427. package/vendor/dist/opentracing/span.d.ts +147 -0
  428. package/vendor/dist/opentracing/span_context.d.ts +26 -0
  429. package/vendor/dist/opentracing/test/api_compatibility.d.ts +16 -0
  430. package/vendor/dist/opentracing/test/mocktracer_implemenation.d.ts +3 -0
  431. package/vendor/dist/opentracing/test/noop_implementation.d.ts +4 -0
  432. package/vendor/dist/opentracing/test/opentracing_api.d.ts +3 -0
  433. package/vendor/dist/opentracing/test/unittest.d.ts +2 -0
  434. package/vendor/dist/opentracing/tracer.d.ts +127 -0
  435. package/vendor/dist/path-to-regexp/LICENSE +21 -0
  436. package/vendor/dist/path-to-regexp/index.js +1 -0
  437. package/vendor/dist/pprof-format/LICENSE +8 -0
  438. package/vendor/dist/pprof-format/index.js +1 -0
  439. package/vendor/dist/protobufjs/LICENSE +39 -0
  440. package/vendor/dist/protobufjs/index.js +1 -0
  441. package/vendor/dist/protobufjs/minimal/LICENSE +39 -0
  442. package/vendor/dist/protobufjs/minimal/index.js +1 -0
  443. package/vendor/dist/retry/LICENSE +21 -0
  444. package/vendor/dist/retry/index.js +1 -0
  445. package/vendor/dist/rfdc/LICENSE +15 -0
  446. package/vendor/dist/rfdc/index.js +1 -0
  447. package/vendor/dist/semifies/LICENSE +201 -0
  448. package/vendor/dist/semifies/index.js +1 -0
  449. package/vendor/dist/shell-quote/LICENSE +24 -0
  450. package/vendor/dist/shell-quote/index.js +1 -0
  451. package/vendor/dist/source-map/LICENSE +28 -0
  452. package/vendor/dist/source-map/index.js +1 -0
  453. package/vendor/dist/source-map/lib/util/LICENSE +28 -0
  454. package/vendor/dist/source-map/lib/util/index.js +1 -0
  455. package/vendor/dist/source-map/mappings.wasm +0 -0
  456. package/vendor/dist/tlhunter-sorted-set/LICENSE +21 -0
  457. package/vendor/dist/tlhunter-sorted-set/index.js +1 -0
  458. package/vendor/dist/ttl-set/LICENSE +21 -0
  459. package/vendor/dist/ttl-set/index.js +1 -0
  460. package/packages/dd-trace/src/remote_config/manager.js +0 -368
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
3
4
  const ExpressTracingPlugin = require('./tracing')
4
5
  const ExpressCodeOriginForSpansPlugin = require('./code_origin')
5
- const CompositePlugin = require('../../dd-trace/src/plugins/composite')
6
6
 
7
7
  class ExpressPlugin extends CompositePlugin {
8
8
  static id = 'express'
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
3
4
  const FastifyTracingPlugin = require('./tracing')
4
5
  const FastifyCodeOriginForSpansPlugin = require('./code_origin')
5
- const CompositePlugin = require('../../dd-trace/src/plugins/composite')
6
6
 
7
7
  class FastifyPlugin extends CompositePlugin {
8
8
  static id = 'fastify'
@@ -8,11 +8,11 @@ class GoogleCloudPubsubClientPlugin extends ClientPlugin {
8
8
  static operation = 'request'
9
9
 
10
10
  start (ctx) {
11
- const { request, api, projectId } = ctx
11
+ const { request, api, projectId, storedContext } = ctx
12
12
 
13
13
  if (api === 'publish') return
14
14
 
15
- this.startSpan(this.operationName(), {
15
+ const spanOptions = {
16
16
  service: this.config.service || this.serviceName(),
17
17
  resource: [api, request.name].filter(Boolean).join(' '),
18
18
  kind: this.constructor.kind,
@@ -20,7 +20,17 @@ class GoogleCloudPubsubClientPlugin extends ClientPlugin {
20
20
  'pubsub.method': api,
21
21
  'gcloud.project_id': projectId
22
22
  }
23
- }, ctx)
23
+ }
24
+
25
+ /**
26
+ * Use stored context from consumer plugin to link acknowledge span to message processing span.
27
+ * Without this, the acknowledge span would be orphaned (no async context available).
28
+ */
29
+ if (storedContext?.span) {
30
+ spanOptions.childOf = storedContext.span.context()
31
+ }
32
+
33
+ this.startSpan(this.operationName(), spanOptions, ctx)
24
34
 
25
35
  return ctx.currentStore
26
36
  }
@@ -2,30 +2,188 @@
2
2
 
3
3
  const { getMessageSize } = require('../../dd-trace/src/datastreams')
4
4
  const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
5
+ const SpanContext = require('../../dd-trace/src/opentracing/span_context')
6
+ const id = require('../../dd-trace/src/id')
7
+ const { storage } = require('../../datadog-core')
8
+
9
+ /**
10
+ * PULL SUBSCRIPTION: Service explicitly pulls messages from Pub/Sub and processes them.
11
+ * Async context storage for linking acknowledge() API calls back to original message spans.
12
+ *
13
+ * Problem: message.ack() is often called asynchronously outside the original handler,
14
+ * losing async context. The acknowledge() API only receives ackIds (strings), not Messages.
15
+ *
16
+ * Solution: Store context by Message (WeakMap), lookup by ackId (Map<ackId, WeakRef<Message>>).
17
+ * WeakRef allows Messages to be GC'd even if never acknowledged (network failures, crashes).
18
+ */
19
+ const messageToContext = new WeakMap() // Message -> context (auto-cleanup on GC)
20
+ const ackIdToMessage = new Map() // ackId -> WeakRef<Message> (needs cleanup)
21
+
22
+ const ackMapCleanup = new FinalizationRegistry((ackId) => {
23
+ ackIdToMessage.delete(ackId) // Remove orphaned ackId when Message is GC'd
24
+ })
5
25
 
6
26
  class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
7
27
  static id = 'google-cloud-pubsub'
8
28
  static operation = 'receive'
9
29
 
30
+ constructor (...args) {
31
+ super(...args)
32
+
33
+ /**
34
+ * Channel: message:ack-store
35
+ * When message.ack() is called, capture and store the current async context.
36
+ * Use WeakRef to allow Message GC even if never acknowledged.
37
+ */
38
+ this.addSub('apm:google-cloud-pubsub:message:ack-store', (ctx) => {
39
+ const { message, ackId } = ctx
40
+ const currentStore = storage('legacy').getStore()
41
+
42
+ if (currentStore) {
43
+ messageToContext.set(message, currentStore)
44
+ ackIdToMessage.set(ackId, new WeakRef(message))
45
+ ackMapCleanup.register(message, ackId, message)
46
+ }
47
+ })
48
+
49
+ /**
50
+ * Channel: message:ack-retrieve
51
+ * When acknowledge() API is called, retrieve stored context for the ackIds.
52
+ * Map: ackId -> WeakRef<Message> -> stored context.
53
+ * Clean up immediately after acknowledge (happy path), or via FinalizationRegistry (GC).
54
+ */
55
+ this.addSub('apm:google-cloud-pubsub:message:ack-retrieve', ({ ackIds, api, ctx }) => {
56
+ for (const ackId of ackIds) {
57
+ const weakRef = ackIdToMessage.get(ackId)
58
+ if (weakRef) {
59
+ const message = weakRef.deref()
60
+ if (message) {
61
+ const storedContext = messageToContext.get(message)
62
+ if (storedContext) {
63
+ ctx.storedContext = storedContext
64
+ break
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ if (api === 'acknowledge') {
71
+ ackIds.forEach(ackId => ackIdToMessage.delete(ackId))
72
+ }
73
+ })
74
+ }
75
+
76
+ #reconstructPubSubRequestContext (attrs) {
77
+ const traceIdLower = attrs['_dd.pubsub_request.trace_id']
78
+ const spanId = attrs['_dd.pubsub_request.span_id']
79
+ const traceIdUpper = attrs['_dd.pubsub_request.p.tid']
80
+
81
+ if (!traceIdLower || !spanId) return null
82
+
83
+ const traceId128 = traceIdUpper ? traceIdUpper + traceIdLower : traceIdLower.padStart(32, '0')
84
+ const traceId = id(traceId128, 16)
85
+ const parentId = id(spanId, 16)
86
+
87
+ const tags = {}
88
+ if (traceIdUpper) tags['_dd.p.tid'] = traceIdUpper
89
+
90
+ return new SpanContext({
91
+ traceId,
92
+ spanId: parentId,
93
+ tags
94
+ })
95
+ }
96
+
10
97
  bindStart (ctx) {
11
98
  const { message } = ctx
12
99
  const subscription = message._subscriber._subscription
13
- const topic = subscription.metadata && subscription.metadata.topic
14
- const childOf = this.tracer.extract('text_map', message.attributes) || null
100
+ const topic = subscription?.metadata?.topic || message.attributes?.['pubsub.topic']
101
+
102
+ const batchRequestTraceId = message.attributes?.['_dd.pubsub_request.trace_id']
103
+ const batchRequestSpanId = message.attributes?.['_dd.pubsub_request.span_id']
104
+
105
+ // Parse batch metadata once upfront for reuse
106
+ const batchSizeStr = message.attributes?.['_dd.batch.size']
107
+ const batchIndexStr = message.attributes?.['_dd.batch.index']
108
+ const batchSize = batchSizeStr ? Number(batchSizeStr) : undefined
109
+ const batchIndex = batchIndexStr ? Number(batchIndexStr) : undefined
110
+
111
+ let childOf = this.tracer.extract('text_map', message.attributes)
112
+
113
+ const isFirstMessage = batchIndex === 0
114
+ if (isFirstMessage && batchRequestSpanId) {
115
+ const pubsubRequestContext = this.#reconstructPubSubRequestContext(message.attributes)
116
+ if (pubsubRequestContext) {
117
+ childOf = pubsubRequestContext
118
+ }
119
+ }
120
+
121
+ const topicName = topic?.slice(topic.lastIndexOf('/') + 1) ??
122
+ subscription.name.slice(subscription.name.lastIndexOf('/') + 1)
123
+ const baseService = this.tracer._service || 'unknown'
124
+ const serviceName = this.config.service || `${baseService}-pubsub`
125
+ const meta = {
126
+ 'gcloud.project_id': subscription.pubsub.projectId,
127
+ 'pubsub.topic': topic,
128
+ 'span.kind': 'consumer',
129
+ 'pubsub.subscription_type': 'pull',
130
+ 'pubsub.span_type': 'message_processing',
131
+ 'messaging.operation': 'receive',
132
+ base_service: baseService,
133
+ service_override_type: 'custom'
134
+ }
135
+
136
+ if (batchRequestTraceId && batchRequestSpanId) {
137
+ meta['pubsub.batch.request_trace_id'] = batchRequestTraceId
138
+ // Use JSON format like producer for proper span link parsing
139
+ meta['_dd.span_links'] = JSON.stringify([{
140
+ trace_id: batchRequestTraceId,
141
+ span_id: batchRequestSpanId,
142
+ flags: 0
143
+ }])
144
+ }
145
+
146
+ const metrics = {
147
+ 'pubsub.ack': 0
148
+ }
149
+
150
+ if (batchSize) {
151
+ metrics['pubsub.batch.message_count'] = batchSize
152
+ metrics['pubsub.batch.size'] = batchSize
153
+ }
154
+ if (batchIndex !== undefined) {
155
+ metrics['pubsub.batch.message_index'] = batchIndex
156
+ metrics['pubsub.batch.index'] = batchIndex
157
+ }
158
+
159
+ if (batchSize && batchIndex !== undefined) {
160
+ meta['pubsub.batch.description'] = `Message ${batchIndex + 1} of ${batchSize}`
161
+ }
15
162
 
16
163
  const span = this.startSpan({
17
164
  childOf,
18
- resource: topic,
165
+ resource: `Message from ${topicName}`,
19
166
  type: 'worker',
20
- meta: {
21
- 'gcloud.project_id': subscription.pubsub.projectId,
22
- 'pubsub.topic': topic
23
- },
24
- metrics: {
25
- 'pubsub.ack': 0
26
- }
167
+ service: serviceName,
168
+ meta,
169
+ metrics
27
170
  }, ctx)
28
171
 
172
+ if (message.id) {
173
+ span.setTag('pubsub.message_id', message.id)
174
+ }
175
+ if (message.publishTime) {
176
+ span.setTag('pubsub.publish_time', message.publishTime.toISOString())
177
+ }
178
+
179
+ if (message.attributes) {
180
+ const publishStartTime = message.attributes['x-dd-publish-start-time']
181
+ if (publishStartTime) {
182
+ const deliveryDuration = Date.now() - Number(publishStartTime)
183
+ span.setTag('pubsub.delivery_duration_ms', deliveryDuration)
184
+ }
185
+ }
186
+
29
187
  if (this.config.dsmEnabled && message?.attributes) {
30
188
  const payloadSize = getMessageSize(message)
31
189
  this.tracer.decodeDataStreamsContext(message.attributes)
@@ -38,14 +196,15 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
38
196
 
39
197
  bindFinish (ctx) {
40
198
  const { message } = ctx
41
- const span = ctx.currentStore.span
199
+ const span = ctx.currentStore?.span
200
+
201
+ if (!span) return ctx.parentStore
42
202
 
43
203
  if (message?._handled) {
44
204
  span.setTag('pubsub.ack', 1)
45
205
  }
46
206
 
47
207
  super.finish()
48
-
49
208
  return ctx.parentStore
50
209
  }
51
210
  }
@@ -1,11 +1,10 @@
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 ClientPlugin = require('./client')
6
- const CompositePlugin = require('../../dd-trace/src/plugins/composite')
7
7
 
8
- // TODO: Consider splitting channels for publish/receive in the instrumentation.
9
8
  class GoogleCloudPubsubPlugin extends CompositePlugin {
10
9
  static id = 'google-cloud-pubsub'
11
10
  static get plugins () {
@@ -2,42 +2,189 @@
2
2
 
3
3
  const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
4
4
  const { DsmPathwayCodec, getHeadersSize } = require('../../dd-trace/src/datastreams')
5
+ const id = require('../../dd-trace/src/id')
5
6
 
6
7
  class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
7
8
  static id = 'google-cloud-pubsub'
8
9
  static operation = 'request'
9
10
 
11
+ constructor (...args) {
12
+ super(...args)
13
+
14
+ /**
15
+ * Inject trace context into individual messages published via Topic.publish() or
16
+ * Topic.publishMessage(). This happens before the batch publish API call, allowing
17
+ * each message to propagate trace context to consumers.
18
+ */
19
+ this.addSub('apm:google-cloud-pubsub:message:publish', this.handleMessagePublish.bind(this))
20
+ }
21
+
22
+ handleMessagePublish ({ attributes, pubsub, topicName }) {
23
+ // Skip if message already has trace context from upstream
24
+ if (attributes['x-datadog-trace-id'] || attributes.traceparent) return
25
+
26
+ const activeSpan = this.tracer.scope().active()
27
+ if (!activeSpan) return
28
+
29
+ // Inject current span's trace context into message attributes
30
+ this.tracer.inject(activeSpan, 'text_map', attributes)
31
+
32
+ const traceIdUpperBits = activeSpan.context()._trace.tags['_dd.p.tid']
33
+ if (traceIdUpperBits) attributes['_dd.p.tid'] = traceIdUpperBits
34
+
35
+ if (pubsub) attributes['gcloud.project_id'] = pubsub.projectId
36
+ if (topicName) attributes['pubsub.topic'] = topicName
37
+ }
38
+
10
39
  bindStart (ctx) {
11
40
  const { request, api, projectId } = ctx
12
-
13
41
  if (api !== 'publish') return
14
42
 
15
43
  const messages = request.messages || []
16
44
  const topic = request.topic
17
- const span = this.startSpan({ // TODO: rename
18
- resource: `${api} ${topic}`,
45
+ const messageCount = messages.length
46
+ const hasTraceContext = messages[0]?.attributes?.['x-datadog-trace-id']
47
+
48
+ /**
49
+ * Batch Publishing Strategy:
50
+ * - Create one "batch span" representing the entire publish operation
51
+ * - If messages already have trace context (from upstream), use the first message's
52
+ * context as the parent, and create span links for messages 2-N
53
+ * - Otherwise, use the current active span as parent
54
+ * - Inject batch span context + metadata into all message attributes for downstream
55
+ * consumers to reconstruct the trace and understand batch relationships
56
+ */
57
+ const spanLinkData = hasTraceContext
58
+ ? messages.slice(1).map(msg => this.#extractSpanLink(msg.attributes)).filter(Boolean)
59
+ : []
60
+
61
+ const firstAttrs = messages[0]?.attributes
62
+ const parentData = firstAttrs?.['x-datadog-trace-id'] && firstAttrs['x-datadog-parent-id']
63
+ ? {
64
+ traceId: firstAttrs['x-datadog-trace-id'],
65
+ spanId: firstAttrs['x-datadog-parent-id'],
66
+ traceIdUpper: firstAttrs['_dd.p.tid'],
67
+ samplingPriority: firstAttrs['x-datadog-sampling-priority']
68
+ }
69
+ : null
70
+
71
+ const lastSlash = topic.lastIndexOf('/')
72
+ const topicName = lastSlash === -1 ? topic : topic.slice(lastSlash + 1)
73
+ const batchSpan = this.startSpan({
74
+ childOf: parentData ? this.#extractParentContext(parentData) : undefined,
75
+ resource: `${api} to Topic ${topicName}`,
19
76
  meta: {
20
77
  'gcloud.project_id': projectId,
21
- 'pubsub.method': api, // TODO: remove
22
- 'pubsub.topic': topic
78
+ 'pubsub.method': api,
79
+ 'pubsub.topic': topic,
80
+ 'span.kind': 'producer',
81
+ '_dd.base_service': this.tracer._service,
82
+ '_dd.serviceoverride.type': 'integration',
83
+ 'pubsub.linked_message_count': spanLinkData.length || undefined,
84
+ operation: messageCount > 1 ? 'batched.pubsub.request' : 'pubsub.request'
85
+ },
86
+ metrics: {
87
+ 'pubsub.batch.message_count': messageCount,
88
+ 'pubsub.batch': messageCount > 1 ? true : undefined
23
89
  }
24
90
  }, ctx)
25
91
 
26
- for (const msg of messages) {
27
- if (!msg.attributes) {
28
- msg.attributes = {}
92
+ const spanCtx = batchSpan.context()
93
+ // Get 128-bit trace ID and span ID as hex strings
94
+ const fullTraceIdHex = spanCtx.toTraceId(true)
95
+ const batchSpanIdHex = spanCtx.toSpanId(true)
96
+ // Extract lower 64 bits (last 16 hex chars) for trace ID
97
+ const batchTraceIdHex = fullTraceIdHex.slice(-16)
98
+ const batchTraceIdUpper = spanCtx._trace.tags['_dd.p.tid']
99
+
100
+ if (spanLinkData.length) {
101
+ batchSpan.setTag('_dd.span_links', JSON.stringify(
102
+ spanLinkData.map(link => ({
103
+ trace_id: link.traceId,
104
+ span_id: link.spanId,
105
+ flags: link.samplingPriority || 0
106
+ }))
107
+ ))
108
+ }
109
+
110
+ messages.forEach((msg, i) => {
111
+ msg.attributes ??= {}
112
+
113
+ if (!hasTraceContext) {
114
+ this.tracer.inject(batchSpan, 'text_map', msg.attributes)
115
+ }
116
+
117
+ Object.assign(msg.attributes, {
118
+ '_dd.pubsub_request.trace_id': batchTraceIdHex,
119
+ '_dd.pubsub_request.span_id': batchSpanIdHex,
120
+ '_dd.batch.size': String(messageCount),
121
+ '_dd.batch.index': String(i),
122
+ 'gcloud.project_id': projectId,
123
+ 'pubsub.topic': topic,
124
+ 'x-dd-publish-start-time': String(Math.floor(batchSpan._startTime))
125
+ })
126
+
127
+ if (batchTraceIdUpper) {
128
+ msg.attributes['_dd.pubsub_request.p.tid'] = batchTraceIdUpper
29
129
  }
30
- this.tracer.inject(span, 'text_map', msg.attributes)
130
+
31
131
  if (this.config.dsmEnabled) {
32
- const payloadSize = getHeadersSize(msg)
33
- const dataStreamsContext = this.tracer
34
- .setCheckpoint(['direction:out', `topic:${topic}`, 'type:google-pubsub'], span, payloadSize)
132
+ const dataStreamsContext = this.tracer.setCheckpoint(
133
+ ['direction:out', `topic:${topic}`, 'type:google-pubsub'],
134
+ batchSpan,
135
+ getHeadersSize(msg)
136
+ )
35
137
  DsmPathwayCodec.encode(dataStreamsContext, msg.attributes)
36
138
  }
37
- }
139
+ })
38
140
 
141
+ ctx.batchSpan = batchSpan
39
142
  return ctx.currentStore
40
143
  }
144
+
145
+ bindFinish (ctx) {
146
+ if (ctx.batchSpan && !ctx.batchSpan._duration) ctx.batchSpan.finish()
147
+ return super.bindFinish(ctx)
148
+ }
149
+
150
+ bindError (ctx) {
151
+ if (ctx.error && ctx.batchSpan) {
152
+ ctx.batchSpan.setTag('error', ctx.error)
153
+ }
154
+ return ctx.parentStore
155
+ }
156
+
157
+ #extractSpanLink (attrs) {
158
+ if (!attrs?.['x-datadog-trace-id'] || !attrs['x-datadog-parent-id']) return null
159
+
160
+ // Convert to hex strings
161
+ const lowerHex = id(attrs['x-datadog-trace-id']).toString(16)
162
+ const spanIdHex = id(attrs['x-datadog-parent-id']).toString(16)
163
+
164
+ // Build full 128-bit trace ID
165
+ const traceIdHex = attrs['_dd.p.tid']
166
+ ? attrs['_dd.p.tid'] + lowerHex
167
+ : lowerHex.padStart(32, '0')
168
+
169
+ return {
170
+ traceId: traceIdHex,
171
+ spanId: spanIdHex,
172
+ samplingPriority: attrs['x-datadog-sampling-priority']
173
+ ? Number.parseInt(attrs['x-datadog-sampling-priority'], 10)
174
+ : undefined
175
+ }
176
+ }
177
+
178
+ #extractParentContext (data) {
179
+ const carrier = {
180
+ 'x-datadog-trace-id': data.traceId,
181
+ 'x-datadog-parent-id': data.spanId
182
+ }
183
+ if (data.traceIdUpper) carrier['_dd.p.tid'] = data.traceIdUpper
184
+ if (data.samplingPriority) carrier['x-datadog-sampling-priority'] = String(data.samplingPriority)
185
+
186
+ return this.tracer.extract('text_map', carrier)
187
+ }
41
188
  }
42
189
 
43
190
  module.exports = GoogleCloudPubsubProducerPlugin