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,175 +1,579 @@
1
1
  'use strict'
2
2
 
3
- const Activation = require('../appsec/activation')
4
-
5
- const RemoteConfigManager = require('./manager')
6
- const RemoteConfigCapabilities = require('./capabilities')
7
- const { setCollectionMode } = require('../appsec/user_tracking')
3
+ const { URL, format } = require('url')
4
+ const uuid = require('../../../../vendor/dist/crypto-randomuuid')
5
+ const tracerVersion = require('../../../../package.json').version
6
+ const request = require('../exporters/common/request')
8
7
  const log = require('../log')
9
- const { updateConfig } = require('../telemetry')
8
+ const { getExtraServices } = require('../service-naming/extra-services')
9
+ const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../plugins/util/tags')
10
+ const tagger = require('../tagger')
11
+ const defaults = require('../config_defaults')
12
+ const processTags = require('../process-tags')
13
+ const Scheduler = require('./scheduler')
14
+ const { UNACKNOWLEDGED, ACKNOWLEDGED, ERROR } = require('./apply_states')
15
+
16
+ const clientId = uuid()
17
+
18
+ const DEFAULT_CAPABILITY = Buffer.alloc(1).toString('base64') // 0x00
19
+
20
+ const kSupportsAckCallback = Symbol('kSupportsAckCallback')
10
21
 
11
- let rc
22
+ // There MUST NOT exist separate instances of RC clients in a tracer making separate ClientGetConfigsRequest
23
+ // with their own separated Client.ClientState.
24
+ class RemoteConfig {
25
+ #handlers = new Map()
26
+ #products = new Set()
27
+ #batchHandlers = new Map()
12
28
 
13
- function enable (config, appsec) {
14
- rc = new RemoteConfigManager(config)
15
- rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_CUSTOM_TAGS, true)
16
- rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_HTTP_HEADER_TAGS, true)
17
- rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_LOGS_INJECTION, true)
18
- rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RATE, true)
19
- rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLED, true)
20
- rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RULES, true)
21
- rc.updateCapabilities(RemoteConfigCapabilities.FFE_FLAG_CONFIGURATION_RULES, true)
29
+ constructor (config) {
30
+ const pollInterval = Math.floor(config.remoteConfig.pollInterval * 1000)
22
31
 
23
- const activation = Activation.fromConfig(config)
32
+ this.url = config.url || new URL(format({
33
+ protocol: 'http:',
34
+ hostname: config.hostname || defaults.hostname,
35
+ port: config.port
36
+ }))
37
+
38
+ tagger.add(config.tags, {
39
+ '_dd.rc.client_id': clientId
40
+ })
41
+
42
+ const tags = config.repositoryUrl
43
+ ? {
44
+ ...config.tags,
45
+ [GIT_REPOSITORY_URL]: config.repositoryUrl,
46
+ [GIT_COMMIT_SHA]: config.commitSHA
47
+ }
48
+ : config.tags
24
49
 
25
- if (activation !== Activation.DISABLED) {
26
- if (activation === Activation.ONECLICK) {
27
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_ACTIVATION, true)
50
+ const appliedConfigs = this.appliedConfigs = new Map()
51
+
52
+ this.scheduler = new Scheduler((cb) => this.poll(cb), pollInterval)
53
+
54
+ this.state = {
55
+ client: {
56
+ state: { // updated by `parseConfig()` and `poll()`
57
+ root_version: 1,
58
+ targets_version: 0,
59
+ // Use getter so `apply_*` can be updated async and still affect the content of `config_states`
60
+ get config_states () {
61
+ const configs = []
62
+ for (const conf of appliedConfigs.values()) {
63
+ configs.push({
64
+ id: conf.id,
65
+ version: conf.version,
66
+ product: conf.product,
67
+ apply_state: conf.apply_state,
68
+ apply_error: conf.apply_error
69
+ })
70
+ }
71
+ return configs
72
+ },
73
+ has_error: false,
74
+ error: '',
75
+ backend_client_state: ''
76
+ },
77
+ id: clientId,
78
+ products: /** @type {string[]} */ ([]), // updated by `updateProducts()`
79
+ is_tracer: true,
80
+ client_tracer: {
81
+ runtime_id: config.tags['runtime-id'],
82
+ language: 'node',
83
+ tracer_version: tracerVersion,
84
+ service: config.service,
85
+ env: config.env,
86
+ app_version: config.version,
87
+ extra_services: /** @type {string[]} */ ([]),
88
+ tags: Object.entries(tags).map((pair) => pair.join(':')),
89
+ [processTags.REMOTE_CONFIG_FIELD_NAME]: processTags.tagsArray
90
+ },
91
+ capabilities: DEFAULT_CAPABILITY // updated by `updateCapabilities()`
92
+ },
93
+ cached_target_files: /** @type {RcCachedTargetFile[]} */ ([]) // updated by `parseConfig()`
28
94
  }
95
+ }
29
96
 
30
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_AUTO_USER_INSTRUM_MODE, true)
97
+ /**
98
+ * @param {bigint} mask
99
+ * @param {boolean} value
100
+ */
101
+ updateCapabilities (mask, value) {
102
+ const hex = Buffer.from(this.state.client.capabilities, 'base64').toString('hex')
31
103
 
32
- let autoUserInstrumModeId
104
+ let num = BigInt(`0x${hex}`)
33
105
 
34
- rc.setProductHandler('ASM_FEATURES', (action, rcConfig, configId) => {
35
- if (!rcConfig) return
106
+ if (value) {
107
+ num |= mask
108
+ } else {
109
+ num &= ~mask
110
+ }
36
111
 
37
- // this is put before other handlers because it can reject the config
38
- if (typeof rcConfig.auto_user_instrum?.mode === 'string') {
39
- if (action === 'apply' || action === 'modify') {
40
- // check if there is already a config applied with this field
41
- if (autoUserInstrumModeId && configId !== autoUserInstrumModeId) {
42
- log.error('[RC] Multiple auto_user_instrum received in ASM_FEATURES. Discarding config')
43
- // eslint-disable-next-line no-throw-literal
44
- throw 'Multiple auto_user_instrum.mode received in ASM_FEATURES'
45
- }
112
+ let str = num.toString(16)
46
113
 
47
- setCollectionMode(rcConfig.auto_user_instrum.mode)
48
- autoUserInstrumModeId = configId
49
- } else if (configId === autoUserInstrumModeId) {
50
- setCollectionMode(config.appsec.eventTracking.mode)
51
- autoUserInstrumModeId = null
52
- }
114
+ if (str.length % 2) str = `0${str}`
115
+
116
+ this.state.client.capabilities = Buffer.from(str, 'hex').toString('base64')
117
+ }
118
+
119
+ /**
120
+ * Subscribe to a product and register a per-config handler.
121
+ *
122
+ * This is the common API for products that can be handled one config at a time.
123
+ * It **implies subscription** (equivalent to calling `subscribeProducts(product)`).
124
+ *
125
+ * @param {string} product
126
+ * @param {Function} handler
127
+ */
128
+ setProductHandler (product, handler) {
129
+ this.#handlers.set(product, handler)
130
+ this.subscribeProducts(product)
131
+ }
132
+
133
+ /**
134
+ * Remove the per-config handler for a product and unsubscribe from it.
135
+ *
136
+ * If you only want to stop receiving configs (but keep the handler attached for later),
137
+ * call `unsubscribeProducts(product)` instead.
138
+ *
139
+ * @param {string} product
140
+ */
141
+ removeProductHandler (product) {
142
+ this.#handlers.delete(product)
143
+ this.unsubscribeProducts(product)
144
+ }
145
+
146
+ /**
147
+ * Subscribe to one or more products with Remote Config (receive configs for them).
148
+ *
149
+ * This only affects subscription/polling and does **not** register any handler.
150
+ *
151
+ * @param {...string} products
152
+ */
153
+ subscribeProducts (...products) {
154
+ const hadProducts = this.#products.size > 0
155
+ for (const product of products) {
156
+ this.#products.add(product)
157
+ }
158
+ this.updateProducts()
159
+ if (!hadProducts && this.#products.size > 0) {
160
+ this.scheduler.start()
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Unsubscribe from one or more products (stop receiving configs for them).
166
+ *
167
+ * This does **not** remove registered handlers; use `removeProductHandler(product)`
168
+ * if you want to detach a handler as well.
169
+ *
170
+ * @param {...string} products
171
+ */
172
+ unsubscribeProducts (...products) {
173
+ const hadProducts = this.#products.size > 0
174
+ for (const product of products) {
175
+ this.#products.delete(product)
176
+ }
177
+ this.updateProducts()
178
+ if (hadProducts && this.#products.size === 0) {
179
+ this.scheduler.stop()
180
+ }
181
+ }
182
+
183
+ updateProducts () {
184
+ this.state.client.products = [...this.#products]
185
+ }
186
+
187
+ /**
188
+ * Register a handler that will be invoked once per RC update, with the update batch filtered
189
+ * down to the specified products. This is useful for consumers that need to process multiple
190
+ * configs at once (e.g. WAF updates spanning ASM/ASM_DD/ASM_DATA) and then do one-time reconciliation.
191
+ *
192
+ * This does **not** implicitly subscribe to the products; call `subscribeProducts()` separately.
193
+ *
194
+ * @param {string[]} products
195
+ * @param {(transaction: RcBatchUpdateTransaction) => void} handler
196
+ */
197
+ setBatchHandler (products, handler) {
198
+ this.#batchHandlers.set(handler, new Set(products))
199
+ }
200
+
201
+ /**
202
+ * Remove a previously-registered batch handler.
203
+ *
204
+ * @param {Function} handler
205
+ */
206
+ removeBatchHandler (handler) {
207
+ this.#batchHandlers.delete(handler)
208
+ }
209
+
210
+ // TODO: Cache the return value of this method, to avoid recomputing it on every poll
211
+ getPayload () {
212
+ this.state.client.client_tracer.extra_services = getExtraServices()
213
+
214
+ return JSON.stringify(this.state)
215
+ }
216
+
217
+ poll (cb) {
218
+ const options = {
219
+ url: this.url,
220
+ method: 'POST',
221
+ path: '/v0.7/config',
222
+ headers: {
223
+ 'Content-Type': 'application/json; charset=utf-8'
53
224
  }
225
+ }
226
+
227
+ request(this.getPayload(), options, (err, data, statusCode) => {
228
+ // 404 means RC is disabled, ignore it
229
+ if (statusCode === 404) return cb()
54
230
 
55
- if (activation === Activation.ONECLICK) {
56
- enableOrDisableAppsec(action, rcConfig, config, appsec)
231
+ if (err) {
232
+ log.errorWithoutTelemetry('[RC] Error in request', err)
233
+ return cb()
57
234
  }
235
+
236
+ // if error was just sent, reset the state
237
+ if (this.state.client.state.has_error) {
238
+ this.state.client.state.has_error = false
239
+ this.state.client.state.error = ''
240
+ }
241
+
242
+ if (data && data !== '{}') { // '{}' means the tracer is up to date
243
+ try {
244
+ this.parseConfig(JSON.parse(data))
245
+ } catch (err) {
246
+ log.error('[RC] Could not parse remote config response', err)
247
+
248
+ this.state.client.state.has_error = true
249
+ this.state.client.state.error = err.toString()
250
+ }
251
+ }
252
+
253
+ cb()
58
254
  })
59
255
  }
60
256
 
61
- return rc
62
- }
257
+ // `client_configs` is the list of config paths to have applied
258
+ // `targets` is the signed index with metadata for config files
259
+ // `target_files` is the list of config files containing the actual config data
260
+ parseConfig ({
261
+ client_configs: clientConfigs = [],
262
+ targets,
263
+ target_files: targetFiles = []
264
+ }) {
265
+ const toUnapply = /** @type {RcConfigState[]} */ ([])
266
+ const toApply = /** @type {RcConfigState[]} */ ([])
267
+ const toModify = /** @type {RcConfigState[]} */ ([])
268
+ const transactionByPath = new Map()
269
+ const transactionHandledPaths = new Set()
270
+ const transactionOutcomes = new Map()
271
+
272
+ for (const appliedConfig of this.appliedConfigs.values()) {
273
+ if (!clientConfigs.includes(appliedConfig.path)) {
274
+ toUnapply.push(appliedConfig)
275
+ transactionByPath.set(appliedConfig.path, appliedConfig)
276
+ }
277
+ }
63
278
 
64
- function enableOrDisableAppsec (action, rcConfig, config, appsec) {
65
- if (typeof rcConfig.asm?.enabled === 'boolean') {
66
- const isRemoteConfigControlling = action === 'apply' || action === 'modify'
67
- const shouldEnable = isRemoteConfigControlling
68
- ? rcConfig.asm.enabled // take control
69
- : config.appsec.enabled // give back control to local config
279
+ targets = fromBase64JSON(targets)
70
280
 
71
- if (shouldEnable) {
72
- appsec.enable(config)
73
- } else {
74
- appsec.disable()
281
+ if (targets) {
282
+ for (const path of clientConfigs) {
283
+ const meta = targets.signed.targets[path]
284
+ if (!meta) throw new Error(`Unable to find target for path ${path}`)
285
+
286
+ const current = this.appliedConfigs.get(path)
287
+
288
+ const newConf = /** @type {RcConfigState} */ ({})
289
+
290
+ if (current) {
291
+ if (current.hashes.sha256 === meta.hashes.sha256) continue
292
+
293
+ toModify.push(newConf)
294
+ } else {
295
+ toApply.push(newConf)
296
+ }
297
+
298
+ const file = targetFiles.find(file => file.path === path)
299
+ if (!file) throw new Error(`Unable to find file for path ${path}`)
300
+
301
+ // TODO: verify signatures
302
+ // verify length
303
+ // verify hash
304
+ // verify _type
305
+ // TODO: new Date(meta.signed.expires) ignore the Targets data if it has expired ?
306
+
307
+ const { product, id } = parseConfigPath(path)
308
+
309
+ Object.assign(newConf, {
310
+ path,
311
+ product,
312
+ id,
313
+ version: meta.custom.v,
314
+ apply_state: UNACKNOWLEDGED,
315
+ apply_error: '',
316
+ length: meta.length,
317
+ hashes: meta.hashes,
318
+ file: fromBase64JSON(file.raw)
319
+ })
320
+ transactionByPath.set(path, newConf)
321
+ }
322
+
323
+ this.state.client.state.targets_version = targets.signed.version
324
+ this.state.client.state.backend_client_state = targets.signed.custom.opaque_backend_state
75
325
  }
76
326
 
77
- updateConfig([
78
- {
79
- name: 'appsec.enabled',
80
- origin: isRemoteConfigControlling ? 'remote_config' : config.getOrigin('appsec.enabled'),
81
- value: shouldEnable
327
+ if (toUnapply.length || toApply.length || toModify.length) {
328
+ const transaction = createUpdateTransaction(
329
+ { toUnapply, toApply, toModify },
330
+ transactionHandledPaths,
331
+ transactionOutcomes
332
+ )
333
+
334
+ if (this.#batchHandlers.size) {
335
+ for (const [handler, products] of this.#batchHandlers) {
336
+ const transactionView = filterTransactionByProducts(transaction, products)
337
+ if (transactionView.toUnapply.length || transactionView.toApply.length || transactionView.toModify.length) {
338
+ handler(transactionView)
339
+ }
340
+ }
341
+ }
342
+
343
+ applyOutcomes(transactionByPath, transactionOutcomes)
344
+
345
+ this.dispatch(toUnapply, 'unapply', transactionHandledPaths)
346
+ this.dispatch(toApply, 'apply', transactionHandledPaths)
347
+ this.dispatch(toModify, 'modify', transactionHandledPaths)
348
+
349
+ this.state.cached_target_files = /** @type {RcCachedTargetFile[]} */ ([])
350
+
351
+ for (const conf of this.appliedConfigs.values()) {
352
+ const hashes = []
353
+ for (const hash of Object.entries(conf.hashes)) {
354
+ hashes.push({ algorithm: hash[0], hash: hash[1] })
355
+ }
356
+ this.state.cached_target_files.push({
357
+ path: conf.path,
358
+ length: conf.length,
359
+ hashes
360
+ })
361
+ }
362
+ }
363
+ }
364
+
365
+ /**
366
+ * Dispatch a list of config changes to per-product handlers, skipping any paths
367
+ * marked as handled by a batch handler.
368
+ *
369
+ * @param {RcConfigState[]} list
370
+ * @param {'apply' | 'modify' | 'unapply'} action
371
+ * @param {Set<string>} handledPaths
372
+ */
373
+ dispatch (list, action, handledPaths) {
374
+ for (const item of list) {
375
+ if (!handledPaths.has(item.path)) {
376
+ this.#callHandlerFor(action, item)
377
+ }
378
+
379
+ if (action === 'unapply') {
380
+ this.appliedConfigs.delete(item.path)
381
+ } else {
382
+ this.appliedConfigs.set(item.path, item)
383
+ }
384
+ }
385
+ }
386
+
387
+ /**
388
+ * @param {'apply' | 'modify' | 'unapply'} action
389
+ * @param {RcConfigState} item
390
+ */
391
+ #callHandlerFor (action, item) {
392
+ // in case the item was already handled by a batch hook
393
+ if (item.apply_state !== UNACKNOWLEDGED && action !== 'unapply') return
394
+
395
+ const handler = this.#handlers.get(item.product)
396
+
397
+ if (!handler) return
398
+
399
+ try {
400
+ if (supportsAckCallback(handler)) {
401
+ // If the handler accepts an `ack` callback, expect that to be called and set `apply_state` accordingly
402
+ // TODO: do we want to pass old and new config ?
403
+ handler(action, item.file, item.id, (err) => {
404
+ if (err) {
405
+ item.apply_state = ERROR
406
+ item.apply_error = err.toString()
407
+ } else if (item.apply_state !== ERROR) {
408
+ item.apply_state = ACKNOWLEDGED
409
+ }
410
+ })
411
+ } else {
412
+ // If the handler doesn't accept an `ack` callback, assume `apply_state` is `ACKNOWLEDGED`,
413
+ // unless it returns a promise, in which case we wait for the promise to be resolved or rejected.
414
+ // TODO: do we want to pass old and new config ?
415
+ const result = handler(action, item.file, item.id)
416
+ if (result instanceof Promise) {
417
+ result.then(
418
+ () => { item.apply_state = ACKNOWLEDGED },
419
+ (err) => {
420
+ item.apply_state = ERROR
421
+ item.apply_error = err.toString()
422
+ }
423
+ )
424
+ } else {
425
+ item.apply_state = ACKNOWLEDGED
426
+ }
82
427
  }
83
- ], config)
428
+ } catch (err) {
429
+ item.apply_state = ERROR
430
+ item.apply_error = err.toString()
431
+ }
84
432
  }
85
433
  }
86
434
 
87
- // TODO: all appsec specific stuff should be moved back in the appsec folder
88
- function enableWafUpdate (appsecConfig) {
89
- if (rc && appsecConfig && !appsecConfig.rules) {
90
- // dirty require to make startup faster for serverless
91
- const RuleManager = require('../appsec/rule_manager')
92
-
93
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_IP_BLOCKING, true)
94
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_USER_BLOCKING, true)
95
- // TODO: we should have a different capability for rule override
96
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_DD_RULES, true)
97
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXCLUSIONS, true)
98
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_REQUEST_BLOCKING, true)
99
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RESPONSE_BLOCKING, true)
100
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_RULES, true)
101
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_BLOCKING_RESPONSE, true)
102
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_TRUSTED_IPS, true)
103
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_PROCESSOR_OVERRIDES, true)
104
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_DATA_SCANNERS, true)
105
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXCLUSION_DATA, true)
106
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_ENDPOINT_FINGERPRINT, true)
107
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_SESSION_FINGERPRINT, true)
108
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_NETWORK_FINGERPRINT, true)
109
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_HEADER_FINGERPRINT, true)
110
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_DD_MULTICONFIG, true)
111
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_TRACE_TAGGING_RULES, true)
112
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXTENDED_DATA_COLLECTION, true)
113
-
114
- if (appsecConfig.rasp?.enabled) {
115
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SQLI, true)
116
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SSRF, true)
117
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_LFI, true)
118
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SHI, true)
119
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_CMDI, true)
435
+ /**
436
+ * Remote Config “applied config” state tracked by the RC manager.
437
+ * This is the mutable shape stored in `this.appliedConfigs` and passed to per-product handlers.
438
+ *
439
+ * @typedef {object} RcConfigState
440
+ * @property {string} path
441
+ * @property {string} product
442
+ * @property {string} id
443
+ * @property {number} version
444
+ * @property {unknown} file
445
+ * @property {number} apply_state
446
+ * @property {string} apply_error
447
+ * @property {number} length
448
+ * @property {Record<string, string>} hashes
449
+ */
450
+
451
+ /**
452
+ * Target file metadata cached in `state.cached_target_files` and sent back to the agent.
453
+ *
454
+ * @typedef {object} RcCachedTargetFile
455
+ * @property {string} path
456
+ * @property {number} length
457
+ * @property {Array<{algorithm: string, hash: string}>} hashes
458
+ */
459
+
460
+ /**
461
+ * Remote Config batch update transaction passed to batch handlers registered via
462
+ * `RemoteConfig.setBatchHandler()`.
463
+ *
464
+ * @typedef {object} RcBatchUpdateTransaction
465
+ * @property {RcConfigState[]} toUnapply
466
+ * @property {RcConfigState[]} toApply
467
+ * @property {RcConfigState[]} toModify
468
+ * @property {(path: string) => void} ack
469
+ * @property {(path: string, err: unknown) => void} error
470
+ */
471
+
472
+ /**
473
+ * Create an immutable "view" of the batch changes and attach explicit outcome reporting.
474
+ *
475
+ * @param {{toUnapply: RcConfigState[], toApply: RcConfigState[], toModify: RcConfigState[]}} changes
476
+ * @param {Set<string>} handledPaths
477
+ * @param {Map<string, {state: number, error: string}>} outcomes
478
+ * @returns {RcBatchUpdateTransaction}
479
+ */
480
+ function createUpdateTransaction ({ toUnapply, toApply, toModify }, handledPaths, outcomes) {
481
+ return {
482
+ toUnapply,
483
+ toApply,
484
+ toModify,
485
+ ack (path) {
486
+ outcomes.set(path, { state: ACKNOWLEDGED, error: '' })
487
+ handledPaths.add(path)
488
+ },
489
+ error (path, err) {
490
+ outcomes.set(path, { state: ERROR, error: err ? err.toString() : 'Error' })
491
+ handledPaths.add(path)
120
492
  }
493
+ }
494
+ }
121
495
 
122
- // TODO: delete noop handlers and kPreUpdate and replace with batched handlers
123
- rc.setProductHandler('ASM_DATA', noop)
124
- rc.setProductHandler('ASM_DD', noop)
125
- rc.setProductHandler('ASM', noop)
496
+ /**
497
+ * Create a filtered "view" of the transaction for a given product set, while preserving
498
+ * the outcome methods (ack/error).
499
+ *
500
+ * @param {RcBatchUpdateTransaction} transaction
501
+ * @param {Set<string>} products
502
+ * @returns {RcBatchUpdateTransaction}
503
+ */
504
+ function filterTransactionByProducts (transaction, products) {
505
+ const toUnapply = []
506
+ const toApply = []
507
+ const toModify = []
126
508
 
127
- rc.on(RemoteConfigManager.kPreUpdate, RuleManager.updateWafFromRC)
509
+ for (const item of transaction.toUnapply) {
510
+ if (products.has(item.product)) toUnapply.push(item)
511
+ }
512
+
513
+ for (const item of transaction.toApply) {
514
+ if (products.has(item.product)) toApply.push(item)
515
+ }
516
+
517
+ for (const item of transaction.toModify) {
518
+ if (products.has(item.product)) toModify.push(item)
519
+ }
520
+
521
+ return {
522
+ toUnapply,
523
+ toApply,
524
+ toModify,
525
+ ack: transaction.ack,
526
+ error: transaction.error
128
527
  }
129
528
  }
130
529
 
131
- function disableWafUpdate () {
132
- if (rc) {
133
- const RuleManager = require('../appsec/rule_manager')
134
-
135
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_IP_BLOCKING, false)
136
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_USER_BLOCKING, false)
137
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_DD_RULES, false)
138
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXCLUSIONS, false)
139
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_REQUEST_BLOCKING, false)
140
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RESPONSE_BLOCKING, false)
141
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_RULES, false)
142
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_BLOCKING_RESPONSE, false)
143
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_TRUSTED_IPS, false)
144
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_PROCESSOR_OVERRIDES, false)
145
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_CUSTOM_DATA_SCANNERS, false)
146
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXCLUSION_DATA, false)
147
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_ENDPOINT_FINGERPRINT, false)
148
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_SESSION_FINGERPRINT, false)
149
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_NETWORK_FINGERPRINT, false)
150
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_HEADER_FINGERPRINT, false)
151
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_DD_MULTICONFIG, false)
152
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_TRACE_TAGGING_RULES, false)
153
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_EXTENDED_DATA_COLLECTION, false)
154
-
155
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SQLI, false)
156
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SSRF, false)
157
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_LFI, false)
158
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_SHI, false)
159
- rc.updateCapabilities(RemoteConfigCapabilities.ASM_RASP_CMDI, false)
160
-
161
- rc.removeProductHandler('ASM_DATA')
162
- rc.removeProductHandler('ASM_DD')
163
- rc.removeProductHandler('ASM')
164
-
165
- rc.off(RemoteConfigManager.kPreUpdate, RuleManager.updateWafFromRC)
530
+ function applyOutcomes (byPath, outcomes) {
531
+ for (const [path, outcome] of outcomes) {
532
+ const item = byPath.get(path)
533
+ if (item) {
534
+ item.apply_state = outcome.state
535
+ item.apply_error = outcome.error
536
+ }
166
537
  }
167
538
  }
168
539
 
169
- function noop () {}
540
+ function fromBase64JSON (str) {
541
+ if (!str) return null
170
542
 
171
- module.exports = {
172
- enable,
173
- enableWafUpdate,
174
- disableWafUpdate
543
+ return JSON.parse(Buffer.from(str, 'base64').toString())
175
544
  }
545
+
546
+ const configPathRegex = /^(?:datadog\/\d+|employee)\/([^/]+)\/([^/]+)\/[^/]+$/
547
+
548
+ function parseConfigPath (configPath) {
549
+ const match = configPathRegex.exec(configPath)
550
+
551
+ if (!match || !match[1] || !match[2]) {
552
+ throw new Error(`Unable to parse path ${configPath}`)
553
+ }
554
+
555
+ return {
556
+ product: match[1],
557
+ id: match[2]
558
+ }
559
+ }
560
+
561
+ function supportsAckCallback (handler) {
562
+ if (kSupportsAckCallback in handler) return handler[kSupportsAckCallback]
563
+
564
+ const numOfArgs = handler.length
565
+ let result = false
566
+
567
+ if (numOfArgs >= 4) {
568
+ result = true
569
+ } else if (numOfArgs !== 0) {
570
+ const source = handler.toString()
571
+ result = source.slice(0, source.indexOf(')')).includes('...')
572
+ }
573
+
574
+ handler[kSupportsAckCallback] = result
575
+
576
+ return result
577
+ }
578
+
579
+ module.exports = RemoteConfig