dd-trace 5.61.0 → 5.62.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 (192) hide show
  1. package/package.json +1 -1
  2. package/packages/datadog-instrumentations/src/apollo-server.js +50 -8
  3. package/packages/datadog-instrumentations/src/aws-sdk.js +49 -60
  4. package/packages/datadog-instrumentations/src/fastify.js +61 -55
  5. package/packages/datadog-instrumentations/src/graphql.js +90 -122
  6. package/packages/datadog-instrumentations/src/http2/server.js +14 -20
  7. package/packages/datadog-instrumentations/src/microgateway-core.js +16 -15
  8. package/packages/datadog-instrumentations/src/mongodb-core.js +34 -29
  9. package/packages/datadog-instrumentations/src/mongodb.js +9 -13
  10. package/packages/datadog-instrumentations/src/mongoose.js +25 -29
  11. package/packages/datadog-instrumentations/src/openai.js +0 -2
  12. package/packages/datadog-instrumentations/src/oracledb.js +39 -33
  13. package/packages/datadog-instrumentations/src/router.js +1 -1
  14. package/packages/datadog-plugin-aerospike/src/index.js +5 -9
  15. package/packages/datadog-plugin-amqp10/src/consumer.js +2 -2
  16. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  17. package/packages/datadog-plugin-amqp10/src/producer.js +3 -3
  18. package/packages/datadog-plugin-amqplib/src/client.js +3 -3
  19. package/packages/datadog-plugin-amqplib/src/consumer.js +2 -2
  20. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  21. package/packages/datadog-plugin-amqplib/src/producer.js +2 -2
  22. package/packages/datadog-plugin-apollo/src/gateway/execute.js +2 -4
  23. package/packages/datadog-plugin-apollo/src/gateway/fetch.js +2 -4
  24. package/packages/datadog-plugin-apollo/src/gateway/index.js +1 -1
  25. package/packages/datadog-plugin-apollo/src/gateway/plan.js +2 -4
  26. package/packages/datadog-plugin-apollo/src/gateway/postprocessing.js +2 -4
  27. package/packages/datadog-plugin-apollo/src/gateway/request.js +2 -4
  28. package/packages/datadog-plugin-apollo/src/gateway/validate.js +2 -4
  29. package/packages/datadog-plugin-apollo/src/index.js +1 -1
  30. package/packages/datadog-plugin-avsc/src/index.js +2 -2
  31. package/packages/datadog-plugin-aws-sdk/src/base.js +70 -46
  32. package/packages/datadog-plugin-aws-sdk/src/index.js +1 -3
  33. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +1 -3
  34. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +1 -1
  35. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  36. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +3 -3
  37. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
  38. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +22 -20
  39. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
  40. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  41. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -3
  42. package/packages/datadog-plugin-aws-sdk/src/services/sfn.js +1 -1
  43. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -3
  44. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +17 -15
  45. package/packages/datadog-plugin-aws-sdk/src/services/states.js +1 -1
  46. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
  47. package/packages/datadog-plugin-azure-functions/src/index.js +5 -5
  48. package/packages/datadog-plugin-azure-service-bus/src/index.js +1 -1
  49. package/packages/datadog-plugin-azure-service-bus/src/producer.js +2 -2
  50. package/packages/datadog-plugin-bunyan/src/index.js +3 -5
  51. package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -3
  52. package/packages/datadog-plugin-child_process/src/index.js +2 -2
  53. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -3
  54. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -3
  55. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  56. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -3
  57. package/packages/datadog-plugin-connect/src/index.js +1 -3
  58. package/packages/datadog-plugin-couchbase/src/index.js +2 -2
  59. package/packages/datadog-plugin-cucumber/src/index.js +1 -3
  60. package/packages/datadog-plugin-cypress/src/index.js +1 -3
  61. package/packages/datadog-plugin-dd-trace-api/src/index.js +1 -3
  62. package/packages/datadog-plugin-dns/src/index.js +1 -1
  63. package/packages/datadog-plugin-dns/src/lookup.js +2 -2
  64. package/packages/datadog-plugin-dns/src/lookup_service.js +2 -2
  65. package/packages/datadog-plugin-dns/src/resolve.js +2 -2
  66. package/packages/datadog-plugin-dns/src/reverse.js +2 -2
  67. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  68. package/packages/datadog-plugin-express/src/code_origin.js +1 -3
  69. package/packages/datadog-plugin-express/src/index.js +1 -1
  70. package/packages/datadog-plugin-express/src/tracing.js +1 -3
  71. package/packages/datadog-plugin-fastify/src/code_origin.js +1 -3
  72. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  73. package/packages/datadog-plugin-fastify/src/tracing.js +18 -3
  74. package/packages/datadog-plugin-fetch/src/index.js +2 -2
  75. package/packages/datadog-plugin-find-my-way/src/index.js +1 -3
  76. package/packages/datadog-plugin-fs/src/index.js +2 -2
  77. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +3 -3
  78. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
  79. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
  80. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +2 -2
  81. package/packages/datadog-plugin-google-cloud-vertexai/src/index.js +1 -1
  82. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +2 -4
  83. package/packages/datadog-plugin-graphql/src/execute.js +16 -9
  84. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  85. package/packages/datadog-plugin-graphql/src/parse.js +12 -7
  86. package/packages/datadog-plugin-graphql/src/resolve.js +50 -16
  87. package/packages/datadog-plugin-graphql/src/validate.js +13 -7
  88. package/packages/datadog-plugin-grpc/src/client.js +4 -4
  89. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  90. package/packages/datadog-plugin-grpc/src/server.js +3 -3
  91. package/packages/datadog-plugin-hapi/src/index.js +1 -3
  92. package/packages/datadog-plugin-hono/src/index.js +1 -3
  93. package/packages/datadog-plugin-http/src/client.js +2 -2
  94. package/packages/datadog-plugin-http/src/index.js +1 -1
  95. package/packages/datadog-plugin-http/src/server.js +3 -7
  96. package/packages/datadog-plugin-http2/src/client.js +2 -2
  97. package/packages/datadog-plugin-http2/src/index.js +1 -1
  98. package/packages/datadog-plugin-http2/src/server.js +22 -11
  99. package/packages/datadog-plugin-ioredis/src/index.js +1 -3
  100. package/packages/datadog-plugin-iovalkey/src/index.js +2 -4
  101. package/packages/datadog-plugin-jest/src/index.js +1 -3
  102. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -2
  103. package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -2
  104. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  105. package/packages/datadog-plugin-kafkajs/src/producer.js +3 -3
  106. package/packages/datadog-plugin-koa/src/index.js +1 -3
  107. package/packages/datadog-plugin-langchain/src/index.js +2 -2
  108. package/packages/datadog-plugin-langchain/src/tracing.js +30 -48
  109. package/packages/datadog-plugin-mariadb/src/index.js +2 -2
  110. package/packages/datadog-plugin-memcached/src/index.js +1 -1
  111. package/packages/datadog-plugin-microgateway-core/src/index.js +4 -4
  112. package/packages/datadog-plugin-mocha/src/index.js +1 -3
  113. package/packages/datadog-plugin-moleculer/src/client.js +2 -2
  114. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  115. package/packages/datadog-plugin-moleculer/src/server.js +2 -2
  116. package/packages/datadog-plugin-mongodb-core/src/index.js +9 -5
  117. package/packages/datadog-plugin-mongoose/src/index.js +20 -0
  118. package/packages/datadog-plugin-mysql/src/index.js +2 -2
  119. package/packages/datadog-plugin-mysql2/src/index.js +1 -1
  120. package/packages/datadog-plugin-net/src/index.js +1 -1
  121. package/packages/datadog-plugin-net/src/ipc.js +2 -2
  122. package/packages/datadog-plugin-net/src/tcp.js +2 -2
  123. package/packages/datadog-plugin-next/src/index.js +1 -3
  124. package/packages/datadog-plugin-nyc/src/index.js +1 -3
  125. package/packages/datadog-plugin-openai/src/index.js +1 -1
  126. package/packages/datadog-plugin-openai/src/tracing.js +7 -411
  127. package/packages/datadog-plugin-opensearch/src/index.js +1 -3
  128. package/packages/datadog-plugin-oracledb/src/index.js +9 -5
  129. package/packages/datadog-plugin-pg/src/index.js +3 -3
  130. package/packages/datadog-plugin-pino/src/index.js +3 -5
  131. package/packages/datadog-plugin-playwright/src/index.js +1 -3
  132. package/packages/datadog-plugin-prisma/src/client.js +4 -6
  133. package/packages/datadog-plugin-prisma/src/engine.js +3 -3
  134. package/packages/datadog-plugin-prisma/src/index.js +1 -1
  135. package/packages/datadog-plugin-protobufjs/src/index.js +2 -6
  136. package/packages/datadog-plugin-redis/src/index.js +2 -2
  137. package/packages/datadog-plugin-restify/src/index.js +1 -3
  138. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  139. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  140. package/packages/datadog-plugin-rhea/src/producer.js +2 -2
  141. package/packages/datadog-plugin-router/src/index.js +1 -3
  142. package/packages/datadog-plugin-selenium/src/index.js +1 -3
  143. package/packages/datadog-plugin-sharedb/src/index.js +1 -1
  144. package/packages/datadog-plugin-tedious/src/index.js +3 -3
  145. package/packages/datadog-plugin-undici/src/index.js +2 -4
  146. package/packages/datadog-plugin-vitest/src/index.js +1 -3
  147. package/packages/datadog-plugin-web/src/index.js +1 -3
  148. package/packages/datadog-plugin-winston/src/index.js +3 -5
  149. package/packages/dd-trace/src/appsec/channels.js +1 -0
  150. package/packages/dd-trace/src/appsec/graphql.js +14 -12
  151. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
  152. package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
  153. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +1 -3
  154. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +1 -3
  155. package/packages/dd-trace/src/config.js +1 -1
  156. package/packages/dd-trace/src/datastreams/checkpointer.js +23 -2
  157. package/packages/dd-trace/src/datastreams/processor.js +4 -3
  158. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +30 -50
  159. package/packages/dd-trace/src/llmobs/plugins/openai.js +3 -5
  160. package/packages/dd-trace/src/llmobs/plugins/vertexai.js +3 -5
  161. package/packages/dd-trace/src/opentracing/propagation/text_map.js +25 -2
  162. package/packages/dd-trace/src/plugins/apollo.js +3 -3
  163. package/packages/dd-trace/src/plugins/cache.js +1 -1
  164. package/packages/dd-trace/src/plugins/client.js +3 -3
  165. package/packages/dd-trace/src/plugins/consumer.js +3 -3
  166. package/packages/dd-trace/src/plugins/database.js +2 -2
  167. package/packages/dd-trace/src/plugins/index.js +1 -0
  168. package/packages/dd-trace/src/plugins/log_plugin.js +1 -5
  169. package/packages/dd-trace/src/plugins/outbound.js +1 -1
  170. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  171. package/packages/dd-trace/src/plugins/producer.js +3 -3
  172. package/packages/dd-trace/src/plugins/server.js +3 -3
  173. package/packages/dd-trace/src/plugins/storage.js +1 -1
  174. package/packages/dd-trace/src/plugins/tracing.js +24 -6
  175. package/packages/dd-trace/src/plugins/util/ci.js +11 -7
  176. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +15 -19
  177. package/packages/dd-trace/src/plugins/util/tags.js +2 -0
  178. package/packages/dd-trace/src/plugins/util/web.js +26 -7
  179. package/packages/dd-trace/src/profiling/config.js +2 -0
  180. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -21
  181. package/packages/dd-trace/src/profiling/libuv-size.js +49 -0
  182. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +2 -6
  183. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +1 -3
  184. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +1 -3
  185. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +1 -3
  186. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +1 -3
  187. package/packages/dd-trace/src/profiling/profilers/event_plugins/fs.js +3 -9
  188. package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +3 -9
  189. package/packages/dd-trace/src/profiling/profilers/events.js +80 -62
  190. package/packages/dd-trace/src/profiling/profilers/poisson.js +105 -0
  191. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
  192. package/packages/dd-trace/src/remote_config/manager.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.61.0",
3
+ "version": "5.62.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -6,6 +6,7 @@ const { addHook } = require('./helpers/instrument')
6
6
  const shimmer = require('../../datadog-shimmer')
7
7
 
8
8
  const graphqlMiddlewareChannel = dc.tracingChannel('datadog:apollo:middleware')
9
+ const apolloHttpServerChannel = dc.tracingChannel('datadog:apollo:httpserver')
9
10
 
10
11
  const requestChannel = dc.tracingChannel('datadog:apollo:request')
11
12
 
@@ -77,17 +78,58 @@ function apolloServerHook (apolloServer) {
77
78
  return apolloServer
78
79
  }
79
80
 
80
- addHook(
81
- { name: '@apollo/server', file: 'dist/cjs/ApolloServer.js', versions: ['>=4.0.0 <5.0.0'] },
82
- apolloServerHook
83
- )
81
+ function wrapEmit (emit) {
82
+ return function wrappedEmit (event, req, res) {
83
+ if (event === 'request' && req && res && apolloHttpServerChannel.start.hasSubscribers) {
84
+ return apolloHttpServerChannel.traceSync(emit, { req }, this, ...arguments)
85
+ }
86
+
87
+ return emit.apply(this, arguments)
88
+ }
89
+ }
90
+
91
+ function wrapListen (originalListen) {
92
+ return function wrappedListen () {
93
+ shimmer.wrap(this, 'emit', wrapEmit)
94
+
95
+ return originalListen.apply(this, arguments)
96
+ }
97
+ }
98
+
99
+ function wrapHttpServer (original) {
100
+ return function wrappedHttpServer (options) {
101
+ if (options.httpServer && typeof options.httpServer.listen === 'function') {
102
+ shimmer.wrap(options.httpServer, 'listen', wrapListen)
103
+ }
104
+
105
+ return original.apply(this, arguments)
106
+ }
107
+ }
108
+
109
+ function apolloDrainHttpServerHook (drainModule) {
110
+ shimmer.wrap(drainModule, 'ApolloServerPluginDrainHttpServer', wrapHttpServer)
111
+
112
+ return drainModule
113
+ }
114
+
115
+ addHook({ name: '@apollo/server', file: 'dist/cjs/ApolloServer.js', versions: ['4'] }, apolloServerHook)
116
+
117
+ addHook({ name: '@apollo/server', file: 'dist/cjs/express4/index.js', versions: ['4'] }, apolloExpress4Hook)
118
+
119
+ addHook({ name: '@apollo/server', file: 'dist/cjs/utils/HeaderMap.js', versions: ['4'] }, apolloHeaderMapHook)
84
120
 
85
121
  addHook(
86
- { name: '@apollo/server', file: 'dist/cjs/express4/index.js', versions: ['>=4.0.0 <5.0.0'] },
87
- apolloExpress4Hook
122
+ { name: '@apollo/server', file: 'dist/cjs/plugin/drainHttpServer/index.js', versions: ['>=5.0.0'] },
123
+ apolloDrainHttpServerHook
88
124
  )
89
125
 
90
126
  addHook(
91
- { name: '@apollo/server', file: 'dist/cjs/utils/HeaderMap.js', versions: ['>=4.0.0 <5.0.0'] },
92
- apolloHeaderMapHook
127
+ { name: '@apollo/server', file: 'dist/cjs/runHttpQuery.js', versions: ['>=5.0.0'] },
128
+ (runHttpQueryModule) => {
129
+ shimmer.wrap(runHttpQueryModule, 'runHttpQuery', function wrapRunHttpQuery (originalRunHttpQuery) {
130
+ return wrapExecuteHTTPGraphQLRequest(originalRunHttpQuery)
131
+ })
132
+
133
+ return runHttpQueryModule
134
+ }
93
135
  )
@@ -1,10 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const {
4
- channel,
5
- addHook,
6
- AsyncResource
7
- } = require('./helpers/instrument')
3
+ const { channel, addHook } = require('./helpers/instrument')
8
4
  const shimmer = require('../../datadog-shimmer')
9
5
 
10
6
  function wrapRequest (send) {
@@ -15,28 +11,26 @@ function wrapRequest (send) {
15
11
  const channelSuffix = getChannelSuffix(serviceIdentifier)
16
12
  const startCh = channel(`apm:aws:request:start:${channelSuffix}`)
17
13
  if (!startCh.hasSubscribers) return send.apply(this, arguments)
18
- const innerAr = new AsyncResource('apm:aws:request:inner')
19
- const outerAr = new AsyncResource('apm:aws:request:outer')
20
-
21
- return innerAr.runInAsyncScope(() => {
22
- this.on('complete', innerAr.bind(response => {
23
- const cbExists = typeof cb === 'function'
24
- channel(`apm:aws:request:complete:${channelSuffix}`).publish({ response, cbExists })
25
- }))
26
-
27
- startCh.publish({
28
- serviceIdentifier,
29
- operation: this.operation,
30
- awsRegion: this.service.config && this.service.config.region,
31
- awsService: this.service.api && this.service.api.className,
32
- request: this
33
- })
34
14
 
35
- if (typeof cb === 'function') {
36
- arguments[0] = wrapCb(cb, channelSuffix, this, outerAr)
37
- }
38
- return send.apply(this, arguments)
15
+ const ctx = {
16
+ serviceIdentifier,
17
+ operation: this.operation,
18
+ awsRegion: this.service.config && this.service.config.region,
19
+ awsService: this.service.api && this.service.api.className,
20
+ request: this,
21
+ cbExists: typeof cb === 'function'
22
+ }
23
+
24
+ this.on('complete', response => {
25
+ ctx.response = response
26
+ channel(`apm:aws:request:complete:${channelSuffix}`).publish(ctx)
39
27
  })
28
+
29
+ if (ctx.cbExists) {
30
+ arguments[0] = wrapCb(cb, channelSuffix, ctx)
31
+ }
32
+
33
+ return startCh.runStores(ctx, send, this, ...arguments)
40
34
  }
41
35
  }
42
36
 
@@ -55,8 +49,6 @@ function wrapDeserialize (deserialize, channelSuffix) {
55
49
  function wrapSmithySend (send) {
56
50
  return function (command, ...args) {
57
51
  const cb = args.at(-1)
58
- const innerAr = new AsyncResource('apm:aws:request:inner')
59
- const outerAr = new AsyncResource('apm:aws:request:outer')
60
52
  const serviceIdentifier = this.config.serviceId.toLowerCase()
61
53
  const channelSuffix = getChannelSuffix(serviceIdentifier)
62
54
  const commandName = command.constructor.name
@@ -77,46 +69,45 @@ function wrapSmithySend (send) {
77
69
  shimmer.wrap(command, 'deserialize', deserialize => wrapDeserialize(deserialize, channelSuffix))
78
70
  }
79
71
 
80
- return innerAr.runInAsyncScope(() => {
81
- startCh.publish({
82
- serviceIdentifier,
83
- operation,
84
- awsService: clientName,
85
- request
86
- })
72
+ const ctx = {
73
+ serviceIdentifier,
74
+ operation,
75
+ awsService: clientName,
76
+ request
77
+ }
87
78
 
79
+ return startCh.runStores(ctx, () => {
88
80
  // When the region is not set this never resolves so we can't await.
89
81
  this.config.region().then(region => {
90
- regionCh.publish(region)
82
+ ctx.region = region
83
+ regionCh.publish(ctx)
91
84
  })
92
85
 
93
86
  if (typeof cb === 'function') {
94
87
  args[args.length - 1] = shimmer.wrapFunction(cb, cb => function (err, result) {
95
- const message = getMessage(request, err, result)
88
+ addResponse(ctx, err, result)
96
89
 
97
- completeChannel.publish(message)
90
+ completeChannel.publish(ctx)
98
91
 
99
- outerAr.runInAsyncScope(() => {
100
- responseStartChannel.publish(message)
92
+ const responseCtx = { request, response: ctx.response }
101
93
 
94
+ responseStartChannel.runStores(responseCtx, () => {
102
95
  cb.apply(this, arguments)
103
96
 
104
- if (message.needsFinish) {
105
- responseFinishChannel.publish(message.response.error)
106
- }
97
+ responseFinishChannel.publish(responseCtx)
107
98
  })
108
99
  })
109
100
  } else { // always a promise
110
101
  return send.call(this, command, ...args)
111
102
  .then(
112
103
  result => {
113
- const message = getMessage(request, null, result)
114
- completeChannel.publish(message)
104
+ addResponse(ctx, null, result)
105
+ completeChannel.publish(ctx)
115
106
  return result
116
107
  },
117
108
  error => {
118
- const message = getMessage(request, error)
119
- completeChannel.publish(message)
109
+ addResponse(ctx, error)
110
+ completeChannel.publish(ctx)
120
111
  throw error
121
112
  }
122
113
  )
@@ -127,47 +118,45 @@ function wrapSmithySend (send) {
127
118
  }
128
119
  }
129
120
 
130
- function wrapCb (cb, serviceName, request, ar) {
121
+ function wrapCb (cb, serviceName, ctx) {
131
122
  // eslint-disable-next-line n/handle-callback-err
132
123
  return shimmer.wrapFunction(cb, cb => function wrappedCb (err, response) {
133
- const obj = { request, response }
134
- return ar.runInAsyncScope(() => {
135
- channel(`apm:aws:response:start:${serviceName}`).publish(obj)
136
- // TODO(bengl) make this work without needing a needsFinish property added to the object
137
- if (!obj.needsFinish) {
138
- return cb.apply(this, arguments)
139
- }
124
+ ctx = { request: ctx.request, response }
125
+ return channel(`apm:aws:response:start:${serviceName}`).runStores(ctx, () => {
140
126
  const finishChannel = channel(`apm:aws:response:finish:${serviceName}`)
141
127
  try {
142
128
  let result = cb.apply(this, arguments)
143
129
  if (result && result.then) {
144
130
  result = result.then(x => {
145
- finishChannel.publish()
131
+ finishChannel.publish(ctx)
146
132
  return x
147
133
  }, e => {
148
- finishChannel.publish(e)
134
+ ctx.error = e
135
+ finishChannel.publish(ctx)
149
136
  throw e
150
137
  })
151
138
  } else {
152
- finishChannel.publish()
139
+ finishChannel.publish(ctx)
153
140
  }
154
141
  return result
155
142
  } catch (e) {
156
- finishChannel.publish(e)
143
+ ctx.error = e
144
+ finishChannel.publish(ctx)
157
145
  throw e
158
146
  }
159
147
  })
160
148
  })
161
149
  }
162
150
 
163
- function getMessage (request, error, result) {
151
+ function addResponse (ctx, error, result) {
152
+ const request = ctx.request
164
153
  const response = { request, error, ...result }
165
154
 
166
155
  if (result && result.$metadata) {
167
156
  response.requestId = result.$metadata.requestId
168
157
  }
169
158
 
170
- return { request, response }
159
+ ctx.response = response
171
160
  }
172
161
 
173
162
  function getChannelSuffix (name) {
@@ -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