dd-trace 5.61.1 → 5.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/README.md +0 -5
  2. package/package.json +2 -2
  3. package/packages/datadog-instrumentations/src/ai.js +140 -0
  4. package/packages/datadog-instrumentations/src/apollo-server.js +50 -8
  5. package/packages/datadog-instrumentations/src/aws-sdk.js +49 -60
  6. package/packages/datadog-instrumentations/src/couchbase.js +102 -65
  7. package/packages/datadog-instrumentations/src/fastify.js +61 -55
  8. package/packages/datadog-instrumentations/src/graphql.js +90 -122
  9. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  10. package/packages/datadog-instrumentations/src/helpers/register.js +2 -22
  11. package/packages/datadog-instrumentations/src/hono.js +11 -8
  12. package/packages/datadog-instrumentations/src/http2/server.js +14 -20
  13. package/packages/datadog-instrumentations/src/knex.js +15 -17
  14. package/packages/datadog-instrumentations/src/microgateway-core.js +16 -15
  15. package/packages/datadog-instrumentations/src/mongodb-core.js +35 -32
  16. package/packages/datadog-instrumentations/src/mongodb.js +9 -13
  17. package/packages/datadog-instrumentations/src/mongoose.js +25 -29
  18. package/packages/datadog-instrumentations/src/next.js +4 -8
  19. package/packages/datadog-instrumentations/src/openai.js +0 -2
  20. package/packages/datadog-instrumentations/src/oracledb.js +39 -33
  21. package/packages/datadog-instrumentations/src/pg.js +38 -48
  22. package/packages/datadog-plugin-aerospike/src/index.js +11 -11
  23. package/packages/datadog-plugin-ai/src/index.js +17 -0
  24. package/packages/datadog-plugin-ai/src/tracing.js +33 -0
  25. package/packages/datadog-plugin-ai/src/utils.js +28 -0
  26. package/packages/datadog-plugin-amqp10/src/consumer.js +2 -2
  27. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  28. package/packages/datadog-plugin-amqp10/src/producer.js +3 -3
  29. package/packages/datadog-plugin-amqplib/src/client.js +3 -3
  30. package/packages/datadog-plugin-amqplib/src/consumer.js +2 -2
  31. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  32. package/packages/datadog-plugin-amqplib/src/producer.js +2 -2
  33. package/packages/datadog-plugin-apollo/src/gateway/execute.js +2 -4
  34. package/packages/datadog-plugin-apollo/src/gateway/fetch.js +2 -4
  35. package/packages/datadog-plugin-apollo/src/gateway/index.js +1 -1
  36. package/packages/datadog-plugin-apollo/src/gateway/plan.js +2 -4
  37. package/packages/datadog-plugin-apollo/src/gateway/postprocessing.js +2 -4
  38. package/packages/datadog-plugin-apollo/src/gateway/request.js +2 -4
  39. package/packages/datadog-plugin-apollo/src/gateway/validate.js +2 -4
  40. package/packages/datadog-plugin-apollo/src/index.js +1 -1
  41. package/packages/datadog-plugin-avsc/src/index.js +2 -2
  42. package/packages/datadog-plugin-aws-sdk/src/base.js +70 -46
  43. package/packages/datadog-plugin-aws-sdk/src/index.js +1 -3
  44. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +1 -3
  45. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +1 -1
  46. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  47. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +3 -3
  48. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  49. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +22 -20
  50. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
  51. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  52. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -3
  53. package/packages/datadog-plugin-aws-sdk/src/services/sfn.js +1 -1
  54. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -3
  55. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +17 -15
  56. package/packages/datadog-plugin-aws-sdk/src/services/states.js +1 -1
  57. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
  58. package/packages/datadog-plugin-azure-functions/src/index.js +5 -5
  59. package/packages/datadog-plugin-azure-service-bus/src/index.js +1 -1
  60. package/packages/datadog-plugin-azure-service-bus/src/producer.js +2 -2
  61. package/packages/datadog-plugin-bunyan/src/index.js +3 -5
  62. package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -3
  63. package/packages/datadog-plugin-child_process/src/index.js +2 -2
  64. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -3
  65. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -3
  66. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  67. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -3
  68. package/packages/datadog-plugin-connect/src/index.js +1 -3
  69. package/packages/datadog-plugin-couchbase/src/index.js +39 -19
  70. package/packages/datadog-plugin-cucumber/src/index.js +1 -3
  71. package/packages/datadog-plugin-cypress/src/index.js +1 -3
  72. package/packages/datadog-plugin-dd-trace-api/src/index.js +1 -3
  73. package/packages/datadog-plugin-dns/src/index.js +1 -1
  74. package/packages/datadog-plugin-dns/src/lookup.js +2 -2
  75. package/packages/datadog-plugin-dns/src/lookup_service.js +2 -2
  76. package/packages/datadog-plugin-dns/src/resolve.js +2 -2
  77. package/packages/datadog-plugin-dns/src/reverse.js +2 -2
  78. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  79. package/packages/datadog-plugin-express/src/code_origin.js +1 -3
  80. package/packages/datadog-plugin-express/src/index.js +1 -1
  81. package/packages/datadog-plugin-express/src/tracing.js +1 -3
  82. package/packages/datadog-plugin-fastify/src/code_origin.js +1 -3
  83. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  84. package/packages/datadog-plugin-fastify/src/tracing.js +18 -3
  85. package/packages/datadog-plugin-fetch/src/index.js +2 -2
  86. package/packages/datadog-plugin-find-my-way/src/index.js +1 -3
  87. package/packages/datadog-plugin-fs/src/index.js +2 -2
  88. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +3 -3
  89. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
  90. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
  91. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +2 -2
  92. package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +1 -1
  93. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +2 -4
  94. package/packages/datadog-plugin-graphql/src/execute.js +16 -9
  95. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  96. package/packages/datadog-plugin-graphql/src/parse.js +12 -7
  97. package/packages/datadog-plugin-graphql/src/resolve.js +50 -16
  98. package/packages/datadog-plugin-graphql/src/validate.js +13 -7
  99. package/packages/datadog-plugin-grpc/src/client.js +4 -4
  100. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  101. package/packages/datadog-plugin-grpc/src/server.js +3 -3
  102. package/packages/datadog-plugin-hapi/src/index.js +1 -3
  103. package/packages/datadog-plugin-hono/src/index.js +1 -3
  104. package/packages/datadog-plugin-http/src/client.js +2 -2
  105. package/packages/datadog-plugin-http/src/index.js +1 -1
  106. package/packages/datadog-plugin-http/src/server.js +3 -7
  107. package/packages/datadog-plugin-http2/src/client.js +2 -2
  108. package/packages/datadog-plugin-http2/src/index.js +1 -1
  109. package/packages/datadog-plugin-http2/src/server.js +22 -11
  110. package/packages/datadog-plugin-ioredis/src/index.js +1 -3
  111. package/packages/datadog-plugin-iovalkey/src/index.js +2 -4
  112. package/packages/datadog-plugin-jest/src/index.js +1 -3
  113. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -2
  114. package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -2
  115. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  116. package/packages/datadog-plugin-kafkajs/src/producer.js +3 -3
  117. package/packages/datadog-plugin-koa/src/index.js +1 -3
  118. package/packages/datadog-plugin-langchain/src/index.js +2 -2
  119. package/packages/datadog-plugin-langchain/src/tracing.js +30 -48
  120. package/packages/datadog-plugin-mariadb/src/index.js +2 -2
  121. package/packages/datadog-plugin-memcached/src/index.js +1 -1
  122. package/packages/datadog-plugin-microgateway-core/src/index.js +4 -4
  123. package/packages/datadog-plugin-mocha/src/index.js +1 -3
  124. package/packages/datadog-plugin-moleculer/src/client.js +2 -2
  125. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  126. package/packages/datadog-plugin-moleculer/src/server.js +2 -2
  127. package/packages/datadog-plugin-mongodb-core/src/index.js +9 -5
  128. package/packages/datadog-plugin-mongoose/src/index.js +20 -0
  129. package/packages/datadog-plugin-mysql/src/index.js +2 -2
  130. package/packages/datadog-plugin-mysql2/src/index.js +1 -1
  131. package/packages/datadog-plugin-net/src/index.js +1 -1
  132. package/packages/datadog-plugin-net/src/ipc.js +2 -2
  133. package/packages/datadog-plugin-net/src/tcp.js +2 -2
  134. package/packages/datadog-plugin-next/src/index.js +1 -3
  135. package/packages/datadog-plugin-nyc/src/index.js +1 -3
  136. package/packages/datadog-plugin-openai/src/index.js +1 -1
  137. package/packages/datadog-plugin-openai/src/tracing.js +7 -411
  138. package/packages/datadog-plugin-opensearch/src/index.js +1 -3
  139. package/packages/datadog-plugin-oracledb/src/index.js +9 -5
  140. package/packages/datadog-plugin-pg/src/index.js +8 -5
  141. package/packages/datadog-plugin-pino/src/index.js +3 -5
  142. package/packages/datadog-plugin-playwright/src/index.js +1 -3
  143. package/packages/datadog-plugin-prisma/src/client.js +4 -6
  144. package/packages/datadog-plugin-prisma/src/engine.js +3 -3
  145. package/packages/datadog-plugin-prisma/src/index.js +1 -1
  146. package/packages/datadog-plugin-protobufjs/src/index.js +2 -6
  147. package/packages/datadog-plugin-redis/src/index.js +2 -2
  148. package/packages/datadog-plugin-restify/src/index.js +1 -3
  149. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  150. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  151. package/packages/datadog-plugin-rhea/src/producer.js +2 -2
  152. package/packages/datadog-plugin-router/src/index.js +1 -3
  153. package/packages/datadog-plugin-selenium/src/index.js +1 -3
  154. package/packages/datadog-plugin-sharedb/src/index.js +1 -1
  155. package/packages/datadog-plugin-tedious/src/index.js +3 -3
  156. package/packages/datadog-plugin-undici/src/index.js +2 -4
  157. package/packages/datadog-plugin-vitest/src/index.js +1 -3
  158. package/packages/datadog-plugin-web/src/index.js +1 -3
  159. package/packages/datadog-plugin-winston/src/index.js +3 -5
  160. package/packages/dd-trace/src/appsec/channels.js +1 -0
  161. package/packages/dd-trace/src/appsec/graphql.js +14 -12
  162. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +14 -7
  163. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +4 -4
  164. package/packages/dd-trace/src/appsec/recommended.json +271 -2
  165. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  166. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +1 -3
  167. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +1 -3
  168. package/packages/dd-trace/src/config.js +1 -1
  169. package/packages/dd-trace/src/datastreams/checkpointer.js +23 -2
  170. package/packages/dd-trace/src/datastreams/processor.js +4 -3
  171. package/packages/dd-trace/src/guardrails/telemetry.js +18 -2
  172. package/packages/dd-trace/src/llmobs/plugins/ai/index.js +351 -0
  173. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +179 -0
  174. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +30 -50
  175. package/packages/dd-trace/src/llmobs/plugins/openai.js +3 -5
  176. package/packages/dd-trace/src/llmobs/plugins/vertexai.js +3 -5
  177. package/packages/dd-trace/src/llmobs/writers/base.js +3 -2
  178. package/packages/dd-trace/src/opentracing/propagation/text_map.js +25 -2
  179. package/packages/dd-trace/src/opentracing/span_context.js +4 -0
  180. package/packages/dd-trace/src/plugin_manager.js +8 -4
  181. package/packages/dd-trace/src/plugins/apollo.js +3 -3
  182. package/packages/dd-trace/src/plugins/cache.js +1 -1
  183. package/packages/dd-trace/src/plugins/client.js +3 -3
  184. package/packages/dd-trace/src/plugins/consumer.js +3 -3
  185. package/packages/dd-trace/src/plugins/database.js +2 -2
  186. package/packages/dd-trace/src/plugins/index.js +2 -0
  187. package/packages/dd-trace/src/plugins/log_plugin.js +1 -5
  188. package/packages/dd-trace/src/plugins/outbound.js +1 -1
  189. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  190. package/packages/dd-trace/src/plugins/producer.js +3 -3
  191. package/packages/dd-trace/src/plugins/server.js +3 -3
  192. package/packages/dd-trace/src/plugins/storage.js +1 -1
  193. package/packages/dd-trace/src/plugins/tracing.js +24 -6
  194. package/packages/dd-trace/src/plugins/util/ci.js +11 -7
  195. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +15 -19
  196. package/packages/dd-trace/src/plugins/util/ip_extractor.js +44 -3
  197. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  198. package/packages/dd-trace/src/plugins/util/web.js +26 -7
  199. package/packages/dd-trace/src/profiling/config.js +2 -0
  200. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -21
  201. package/packages/dd-trace/src/profiling/libuv-size.js +49 -0
  202. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +2 -6
  203. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +1 -3
  204. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +1 -3
  205. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +1 -3
  206. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +1 -3
  207. package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +24 -23
  208. package/packages/dd-trace/src/profiling/profilers/event_plugins/fs.js +3 -9
  209. package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +3 -9
  210. package/packages/dd-trace/src/profiling/profilers/events.js +83 -64
  211. package/packages/dd-trace/src/profiling/profilers/poisson.js +105 -0
  212. package/packages/dd-trace/src/profiling/profilers/wall.js +3 -3
  213. package/packages/dd-trace/src/remote_config/manager.js +1 -1
  214. package/packages/dd-trace/src/supported-configurations.json +2 -0
  215. package/packages/dd-trace/src/tracer_metadata.js +1 -1
@@ -3,8 +3,7 @@
3
3
  const { errorMonitor } = require('events')
4
4
  const {
5
5
  channel,
6
- addHook,
7
- AsyncResource
6
+ addHook
8
7
  } = require('./helpers/instrument')
9
8
  const shimmer = require('../../datadog-shimmer')
10
9
 
@@ -24,31 +23,50 @@ function wrapAllNames (names, action) {
24
23
  names.forEach(name => action(name))
25
24
  }
26
25
 
27
- // semver >=2 <3
28
- function wrapMaybeInvoke (_maybeInvoke) {
29
- const wrapped = function (fn, args) {
30
- if (!Array.isArray(args)) return _maybeInvoke.apply(this, arguments)
31
-
32
- const callbackIndex = args.length - 1
33
- const callback = args[callbackIndex]
26
+ function wrapCallback (callback, ctx, channelPrefix) {
27
+ const callbackStartCh = channel(`${channelPrefix}:callback:start`)
28
+ const callbackFinishCh = channel(`${channelPrefix}:callback:finish`)
34
29
 
35
- if (typeof callback === 'function') {
36
- args[callbackIndex] = AsyncResource.bind(callback)
30
+ const wrapped = callbackStartCh.runStores(ctx, () => {
31
+ return function (...args) {
32
+ return callbackFinishCh.runStores(ctx, () => {
33
+ return callback.apply(this, args)
34
+ })
37
35
  }
38
-
39
- return _maybeInvoke.apply(this, arguments)
40
- }
36
+ })
37
+ Object.defineProperty(wrapped, '_dd_wrapped', { value: true })
41
38
  return wrapped
42
39
  }
43
40
 
44
41
  function wrapQuery (query) {
45
- const wrapped = function (q, params, callback) {
46
- if (typeof arguments[arguments.length - 1] === 'function') {
47
- arguments[arguments.length - 1] = AsyncResource.bind(arguments[arguments.length - 1])
42
+ return function (q, params, callback) {
43
+ const cb = arguments[arguments.length - 1]
44
+ if (typeof cb === 'function') {
45
+ const ctx = {}
46
+ arguments[arguments.length - 1] = wrapCallback(cb, ctx, 'apm:couchbase:query')
48
47
  }
49
48
 
50
49
  return query.apply(this, arguments)
51
50
  }
51
+ }
52
+
53
+ function wrapCallbackFinish (callback, thisArg, _args, errorCh, finishCh, ctx, channelPrefix) {
54
+ const callbackStartCh = channel(`${channelPrefix}:callback:start`)
55
+ const callbackFinishCh = channel(`${channelPrefix}:callback:finish`)
56
+
57
+ const wrapped = callbackStartCh.runStores(ctx, () => {
58
+ return function finish (error, result) {
59
+ return callbackFinishCh.runStores(ctx, () => {
60
+ if (error) {
61
+ ctx.error = error
62
+ errorCh.publish(ctx)
63
+ }
64
+ finishCh.publish(ctx)
65
+ return callback.apply(thisArg, [error, result])
66
+ })
67
+ }
68
+ })
69
+ Object.defineProperty(wrapped, '_dd_wrapped', { value: true })
52
70
  return wrapped
53
71
  }
54
72
 
@@ -62,31 +80,24 @@ function wrap (prefix, fn) {
62
80
  return fn.apply(this, arguments)
63
81
  }
64
82
 
65
- const callbackIndex = findCallbackIndex(arguments)
83
+ const callbackIndex = findCallbackIndex(arguments, 1)
66
84
 
67
85
  if (callbackIndex < 0) return fn.apply(this, arguments)
68
86
 
69
- const callbackResource = new AsyncResource('bound-anonymous-fn')
70
- const asyncResource = new AsyncResource('bound-anonymous-fn')
71
-
72
- return asyncResource.runInAsyncScope(() => {
73
- const cb = callbackResource.bind(arguments[callbackIndex])
87
+ const ctx = { bucket: { name: this.name || this._name }, seedNodes: this._dd_hosts }
88
+ return startCh.runStores(ctx, () => {
89
+ const cb = arguments[callbackIndex]
74
90
 
75
- startCh.publish({ bucket: { name: this.name || this._name }, seedNodes: this._dd_hosts })
76
-
77
- arguments[callbackIndex] = shimmer.wrapFunction(cb, cb => asyncResource.bind(function (error, result) {
78
- if (error) {
79
- errorCh.publish(error)
80
- }
81
- finishCh.publish(result)
82
- return cb.apply(this, arguments)
83
- }))
91
+ arguments[callbackIndex] = shimmer.wrapFunction(cb, (cb) => {
92
+ return wrapCallbackFinish(cb, this, arguments, errorCh, finishCh, ctx, prefix)
93
+ })
84
94
 
85
95
  try {
86
96
  return fn.apply(this, arguments)
87
97
  } catch (error) {
98
+ ctx.error = error
88
99
  error.stack // trigger getting the stack at the original throwing point
89
- errorCh.publish(error)
100
+ errorCh.publish(ctx)
90
101
 
91
102
  throw error
92
103
  }
@@ -95,6 +106,26 @@ function wrap (prefix, fn) {
95
106
  return wrapped
96
107
  }
97
108
 
109
+ // semver >=2 <3
110
+ function wrapMaybeInvoke (_maybeInvoke, channelPrefix) {
111
+ return function (fn, args) {
112
+ if (!Array.isArray(args)) return _maybeInvoke.apply(this, arguments)
113
+
114
+ const callbackIndex = findCallbackIndex(args, 0)
115
+
116
+ if (callbackIndex === -1) return _maybeInvoke.apply(this, arguments)
117
+
118
+ const callback = args[callbackIndex]
119
+
120
+ if (typeof callback === 'function' && !callback._dd_wrapped) {
121
+ const ctx = {}
122
+ args[callbackIndex] = wrapCallback(callback, ctx, channelPrefix)
123
+ }
124
+
125
+ return _maybeInvoke.apply(this, arguments)
126
+ }
127
+ }
128
+
98
129
  // semver >=3
99
130
 
100
131
  function wrapCBandPromise (fn, name, startData, thisArg, args) {
@@ -104,36 +135,36 @@ function wrapCBandPromise (fn, name, startData, thisArg, args) {
104
135
 
105
136
  if (!startCh.hasSubscribers) return fn.apply(thisArg, args)
106
137
 
107
- const asyncResource = new AsyncResource('bound-anonymous-fn')
108
- const callbackResource = new AsyncResource('bound-anonymous-fn')
109
-
110
- return asyncResource.runInAsyncScope(() => {
111
- startCh.publish(startData)
112
-
138
+ const ctx = startData
139
+ return startCh.runStores(ctx, () => {
113
140
  try {
114
141
  const cbIndex = findCallbackIndex(args, 1)
115
142
  if (cbIndex >= 0) {
116
143
  // v3 offers callback or promises event handling
117
144
  // NOTE: this does not work with v3.2.0-3.2.1 cluster.query, as there is a bug in the couchbase source code
118
- const cb = callbackResource.bind(args[cbIndex])
119
- args[cbIndex] = shimmer.wrapFunction(cb, cb => asyncResource.bind(function (error, result) {
120
- if (error) {
121
- errorCh.publish(error)
122
- }
123
- finishCh.publish({ result })
124
- return cb.apply(thisArg, arguments)
125
- }))
145
+ args[cbIndex] = shimmer.wrapFunction(args[cbIndex], (cb) => {
146
+ return wrapCallbackFinish(cb, thisArg, args, errorCh, finishCh, ctx, `apm:couchbase:${name}`)
147
+ })
126
148
  }
127
149
  const res = fn.apply(thisArg, args)
128
150
 
129
151
  // semver >=3 will always return promise by default
130
152
  res.then(
131
- asyncResource.bind((result) => finishCh.publish({ result })),
132
- asyncResource.bind((err) => errorCh.publish(err)))
153
+ (result) => {
154
+ ctx.result = result
155
+ finishCh.publish(ctx)
156
+ },
157
+ (err) => {
158
+ ctx.error = err
159
+ errorCh.publish(ctx)
160
+ finishCh.publish(ctx)
161
+ }
162
+ )
133
163
  return res
134
164
  } catch (e) {
135
165
  e.stack
136
- errorCh.publish(e)
166
+ ctx.error = e
167
+ errorCh.publish(ctx)
137
168
  throw e
138
169
  }
139
170
  })
@@ -160,11 +191,14 @@ function wrapV3Query (query) {
160
191
 
161
192
  // semver >=2 <3
162
193
  addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.12'] }, Bucket => {
194
+ shimmer.wrap(Bucket.prototype, '_maybeInvoke', maybeInvoke => {
195
+ return wrapMaybeInvoke(maybeInvoke, 'apm:couchbase:bucket:maybeInvoke')
196
+ })
197
+
163
198
  const startCh = channel('apm:couchbase:query:start')
164
199
  const finishCh = channel('apm:couchbase:query:finish')
165
200
  const errorCh = channel('apm:couchbase:query:error')
166
201
 
167
- shimmer.wrap(Bucket.prototype, '_maybeInvoke', maybeInvoke => wrapMaybeInvoke(maybeInvoke))
168
202
  shimmer.wrap(Bucket.prototype, 'query', query => wrapQuery(query))
169
203
 
170
204
  shimmer.wrap(Bucket.prototype, '_n1qlReq', _n1qlReq => function (host, q, adhoc, emitter) {
@@ -176,24 +210,25 @@ addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.12'] }, Buc
176
210
 
177
211
  const n1qlQuery = getQueryResource(q)
178
212
 
179
- const asyncResource = new AsyncResource('bound-anonymous-fn')
180
- return asyncResource.runInAsyncScope(() => {
181
- startCh.publish({ resource: n1qlQuery, bucket: { name: this.name || this._name }, seedNodes: this._dd_hosts })
182
-
183
- emitter.once('rows', asyncResource.bind(() => {
184
- finishCh.publish()
185
- }))
213
+ const ctx = { resource: n1qlQuery, bucket: { name: this.name || this._name }, seedNodes: this._dd_hosts }
214
+ return startCh.runStores(ctx, () => {
215
+ emitter.once('rows', () => {
216
+ finishCh.publish(ctx)
217
+ })
186
218
 
187
- emitter.once(errorMonitor, asyncResource.bind((error) => {
188
- errorCh.publish(error)
189
- finishCh.publish()
190
- }))
219
+ emitter.once(errorMonitor, (error) => {
220
+ if (!error) return
221
+ ctx.error = error
222
+ errorCh.publish(ctx)
223
+ finishCh.publish(ctx)
224
+ })
191
225
 
192
226
  try {
193
227
  return _n1qlReq.apply(this, arguments)
194
228
  } catch (err) {
195
229
  err.stack // trigger getting the stack at the original throwing point
196
- errorCh.publish(err)
230
+ ctx.error = err
231
+ errorCh.publish(ctx)
197
232
 
198
233
  throw err
199
234
  }
@@ -208,9 +243,11 @@ addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.12'] }, Buc
208
243
  })
209
244
 
210
245
  addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.12'] }, Cluster => {
211
- shimmer.wrap(Cluster.prototype, '_maybeInvoke', maybeInvoke => wrapMaybeInvoke(maybeInvoke))
212
- shimmer.wrap(Cluster.prototype, 'query', query => wrapQuery(query))
246
+ shimmer.wrap(Cluster.prototype, '_maybeInvoke', maybeInvoke => {
247
+ return wrapMaybeInvoke(maybeInvoke, 'apm:couchbase:cluster:maybeInvoke')
248
+ })
213
249
 
250
+ shimmer.wrap(Cluster.prototype, 'query', query => wrapQuery(query))
214
251
  shimmer.wrap(Cluster.prototype, 'openBucket', openBucket => {
215
252
  return function () {
216
253
  const bucket = openBucket.apply(this, arguments)
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const shimmer = require('../../datadog-shimmer')
4
- const { addHook, channel, AsyncResource } = require('./helpers/instrument')
4
+ const { addHook, channel } = require('./helpers/instrument')
5
5
 
6
6
  const errorChannel = channel('apm:fastify:middleware:error')
7
7
  const handleChannel = channel('apm:fastify:request:handle')
@@ -13,7 +13,12 @@ const responsePayloadReadCh = channel('datadog:fastify:response:finish')
13
13
  const pathParamsReadCh = channel('datadog:fastify:path-params:finish')
14
14
  const finishSetHeaderCh = channel('datadog:fastify:set-header:finish')
15
15
 
16
- const parsingResources = new WeakMap()
16
+ // context management channels
17
+ const preParsingCh = channel('datadog:fastify:pre-parsing:start')
18
+ const preValidationCh = channel('datadog:fastify:pre-validation:start')
19
+ const callbackFinishCh = channel('datadog:fastify:callback:execute')
20
+
21
+ const parsingContexts = new WeakMap()
17
22
  const cookiesPublished = new WeakSet()
18
23
  const bodyPublished = new WeakSet()
19
24
 
@@ -51,6 +56,7 @@ function wrapAddHook (addHook) {
51
56
 
52
57
  arguments[arguments.length - 1] = shimmer.wrapFunction(fn, fn => function (request, reply, done) {
53
58
  const req = getReq(request)
59
+ const ctx = { req }
54
60
 
55
61
  try {
56
62
  // done callback is always the last argument
@@ -58,32 +64,26 @@ function wrapAddHook (addHook) {
58
64
 
59
65
  if (typeof doneCallback === 'function') {
60
66
  arguments[arguments.length - 1] = function (err) {
61
- publishError(err, req)
67
+ ctx.error = err
68
+ publishError(ctx)
62
69
 
63
70
  const hasCookies = request.cookies && Object.keys(request.cookies).length > 0
64
71
 
65
72
  if (cookieParserReadCh.hasSubscribers && hasCookies && !cookiesPublished.has(req)) {
66
- const res = getRes(reply)
67
- const abortController = new AbortController()
68
-
69
- cookieParserReadCh.publish({
70
- req,
71
- res,
72
- abortController,
73
- cookies: request.cookies
74
- })
73
+ ctx.res = getRes(reply)
74
+ ctx.abortController = new AbortController()
75
+ ctx.cookies = request.cookies
75
76
 
77
+ cookieParserReadCh.publish(ctx)
76
78
  cookiesPublished.add(req)
77
79
 
78
- if (abortController.signal.aborted) return
80
+ if (ctx.abortController.signal.aborted) return
79
81
  }
80
82
 
81
83
  if (name === 'onRequest' || name === 'preParsing') {
82
- const parsingResource = new AsyncResource('bound-anonymous-fn')
83
-
84
- parsingResources.set(req, parsingResource)
84
+ parsingContexts.set(req, ctx)
85
85
 
86
- return parsingResource.runInAsyncScope(() => {
86
+ return callbackFinishCh.runStores(ctx, () => {
87
87
  return doneCallback.apply(this, arguments)
88
88
  })
89
89
  }
@@ -96,12 +96,16 @@ function wrapAddHook (addHook) {
96
96
  const promise = fn.apply(this, arguments)
97
97
 
98
98
  if (promise && typeof promise.catch === 'function') {
99
- return promise.catch(err => publishError(err, req))
99
+ return promise.catch(err => {
100
+ ctx.error = err
101
+ return publishError(ctx)
102
+ })
100
103
  }
101
104
 
102
105
  return promise
103
106
  } catch (e) {
104
- throw publishError(e, req)
107
+ ctx.error = e
108
+ throw publishError(ctx)
105
109
  }
106
110
  })
107
111
 
@@ -116,7 +120,8 @@ function onRequest (request, reply, done) {
116
120
  const res = getRes(reply)
117
121
  const routeConfig = getRouteConfig(request)
118
122
 
119
- handleChannel.publish({ req, res, routeConfig })
123
+ const ctx = { req, res, routeConfig }
124
+ handleChannel.publish(ctx)
120
125
 
121
126
  return done()
122
127
  }
@@ -127,18 +132,18 @@ function preHandler (request, reply, done) {
127
132
 
128
133
  const req = getReq(request)
129
134
  const res = getRes(reply)
135
+ const ctx = { req, res }
130
136
 
131
137
  const hasBody = request.body && Object.keys(request.body).length > 0
132
138
 
133
139
  // For multipart/form-data, the body is not available until after preValidation hook
134
140
  if (bodyParserReadCh.hasSubscribers && hasBody && !bodyPublished.has(req)) {
135
- const abortController = new AbortController()
136
-
137
- bodyParserReadCh.publish({ req, res, body: request.body, abortController })
138
-
141
+ ctx.abortController = new AbortController()
142
+ ctx.body = request.body
143
+ bodyParserReadCh.publish(ctx)
139
144
  bodyPublished.add(req)
140
145
 
141
- if (abortController.signal.aborted) return
146
+ if (ctx.abortController.signal.aborted) return
142
147
  }
143
148
 
144
149
  reply.send = wrapSend(reply.send, req)
@@ -149,20 +154,17 @@ function preHandler (request, reply, done) {
149
154
  function preValidation (request, reply, done) {
150
155
  const req = getReq(request)
151
156
  const res = getRes(reply)
152
- const parsingResource = parsingResources.get(req)
157
+ const ctx = parsingContexts.get(req)
158
+ ctx.res = res
153
159
 
154
160
  const processInContext = () => {
155
161
  let abortController
156
162
 
157
163
  if (queryParamsReadCh.hasSubscribers && request.query) {
158
164
  abortController ??= new AbortController()
159
-
160
- queryParamsReadCh.publish({
161
- req,
162
- res,
163
- abortController,
164
- query: request.query
165
- })
165
+ ctx.abortController = abortController
166
+ ctx.query = request.query
167
+ queryParamsReadCh.publish(ctx)
166
168
 
167
169
  if (abortController.signal.aborted) return
168
170
  }
@@ -170,8 +172,9 @@ function preValidation (request, reply, done) {
170
172
  // Analyze body before schema validation
171
173
  if (bodyParserReadCh.hasSubscribers && request.body && !bodyPublished.has(req)) {
172
174
  abortController ??= new AbortController()
173
-
174
- bodyParserReadCh.publish({ req, res, body: request.body, abortController })
175
+ ctx.abortController = abortController
176
+ ctx.body = request.body
177
+ bodyParserReadCh.publish(ctx)
175
178
 
176
179
  bodyPublished.add(req)
177
180
 
@@ -180,13 +183,9 @@ function preValidation (request, reply, done) {
180
183
 
181
184
  if (pathParamsReadCh.hasSubscribers && request.params) {
182
185
  abortController ??= new AbortController()
183
-
184
- pathParamsReadCh.publish({
185
- req,
186
- res,
187
- abortController,
188
- params: request.params
189
- })
186
+ ctx.abortController = abortController
187
+ ctx.params = request.params
188
+ pathParamsReadCh.publish(ctx)
190
189
 
191
190
  if (abortController.signal.aborted) return
192
191
  }
@@ -194,9 +193,9 @@ function preValidation (request, reply, done) {
194
193
  done()
195
194
  }
196
195
 
197
- if (!parsingResource) return processInContext()
196
+ if (!ctx) return processInContext()
198
197
 
199
- parsingResource.runInAsyncScope(processInContext)
198
+ preValidationCh.runStores(ctx, processInContext)
200
199
  }
201
200
 
202
201
  function preParsing (request, reply, payload, done) {
@@ -205,19 +204,24 @@ function preParsing (request, reply, payload, done) {
205
204
  }
206
205
 
207
206
  const req = getReq(request)
208
- const parsingResource = new AsyncResource('bound-anonymous-fn')
207
+ const ctx = { req }
208
+
209
+ parsingContexts.set(req, ctx)
209
210
 
210
- parsingResources.set(req, parsingResource)
211
- parsingResource.runInAsyncScope(() => done())
211
+ preParsingCh.runStores(ctx, () => done())
212
212
  }
213
213
 
214
214
  function wrapSend (send, req) {
215
215
  return function sendWithTrace (payload) {
216
+ const ctx = { req }
216
217
  if (payload instanceof Error) {
217
- errorChannel.publish({ req, error: payload })
218
+ ctx.error = payload
219
+ errorChannel.publish(ctx)
218
220
  } else if (canPublishResponsePayload(payload)) {
219
221
  const res = getRes(this)
220
- responsePayloadReadCh.publish({ req, res, body: payload })
222
+ ctx.res = res
223
+ ctx.body = payload
224
+ responsePayloadReadCh.publish(ctx)
221
225
  }
222
226
 
223
227
  return send.apply(this, arguments)
@@ -236,16 +240,17 @@ function getRouteConfig (request) {
236
240
  return request?.routeOptions?.config
237
241
  }
238
242
 
239
- function publishError (error, req) {
240
- if (error) {
241
- errorChannel.publish({ error, req })
243
+ function publishError (ctx) {
244
+ if (ctx.error) {
245
+ errorChannel.publish(ctx)
242
246
  }
243
247
 
244
- return error
248
+ return ctx.error
245
249
  }
246
250
 
247
251
  function onRoute (routeOptions) {
248
- routeAddedChannel.publish({ routeOptions, onRoute })
252
+ const ctx = { routeOptions, onRoute }
253
+ routeAddedChannel.publish(ctx)
249
254
  }
250
255
 
251
256
  // send() payload types: https://fastify.dev/docs/latest/Reference/Reply/#senddata
@@ -282,7 +287,8 @@ function wrapReplyHeader (Reply) {
282
287
  const result = header.apply(this, arguments)
283
288
 
284
289
  if (finishSetHeaderCh.hasSubscribers && key && value) {
285
- finishSetHeaderCh.publish({ name: key, value, res: getRes(this) })
290
+ const ctx = { name: key, value, res: getRes(this) }
291
+ finishSetHeaderCh.publish(ctx)
286
292
  }
287
293
 
288
294
  return result