dd-trace 5.101.0 → 5.103.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 (235) hide show
  1. package/ext/exporters.js +1 -0
  2. package/package.json +20 -17
  3. package/packages/datadog-esbuild/src/utils.js +2 -2
  4. package/packages/datadog-instrumentations/src/aerospike.js +2 -2
  5. package/packages/datadog-instrumentations/src/ai.js +9 -9
  6. package/packages/datadog-instrumentations/src/amqplib.js +6 -7
  7. package/packages/datadog-instrumentations/src/anthropic.js +10 -10
  8. package/packages/datadog-instrumentations/src/apollo-server-core.js +3 -3
  9. package/packages/datadog-instrumentations/src/apollo-server.js +5 -5
  10. package/packages/datadog-instrumentations/src/avsc.js +6 -6
  11. package/packages/datadog-instrumentations/src/aws-sdk.js +151 -67
  12. package/packages/datadog-instrumentations/src/azure-durable-functions.js +8 -8
  13. package/packages/datadog-instrumentations/src/bluebird.js +2 -2
  14. package/packages/datadog-instrumentations/src/body-parser.js +2 -2
  15. package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
  16. package/packages/datadog-instrumentations/src/child_process.js +12 -12
  17. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +41 -24
  18. package/packages/datadog-instrumentations/src/connect.js +7 -7
  19. package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
  20. package/packages/datadog-instrumentations/src/cookie.js +2 -2
  21. package/packages/datadog-instrumentations/src/couchbase.js +73 -238
  22. package/packages/datadog-instrumentations/src/crypto.js +4 -4
  23. package/packages/datadog-instrumentations/src/cucumber.js +78 -17
  24. package/packages/datadog-instrumentations/src/dns.js +0 -3
  25. package/packages/datadog-instrumentations/src/elasticsearch.js +8 -11
  26. package/packages/datadog-instrumentations/src/electron/preload.js +42 -0
  27. package/packages/datadog-instrumentations/src/electron.js +240 -0
  28. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +6 -6
  29. package/packages/datadog-instrumentations/src/express-session.js +4 -4
  30. package/packages/datadog-instrumentations/src/express.js +10 -11
  31. package/packages/datadog-instrumentations/src/fastify.js +2 -2
  32. package/packages/datadog-instrumentations/src/fetch.js +5 -5
  33. package/packages/datadog-instrumentations/src/fs.js +14 -14
  34. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +5 -7
  35. package/packages/datadog-instrumentations/src/google-genai.js +4 -4
  36. package/packages/datadog-instrumentations/src/graphql.js +13 -12
  37. package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
  38. package/packages/datadog-instrumentations/src/hapi.js +2 -2
  39. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +9 -9
  40. package/packages/datadog-instrumentations/src/helpers/hook.js +4 -1
  41. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  42. package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
  43. package/packages/datadog-instrumentations/src/helpers/kafka.js +41 -0
  44. package/packages/datadog-instrumentations/src/helpers/promise.js +2 -2
  45. package/packages/datadog-instrumentations/src/hono.js +2 -2
  46. package/packages/datadog-instrumentations/src/http/client.js +6 -6
  47. package/packages/datadog-instrumentations/src/http/server.js +9 -9
  48. package/packages/datadog-instrumentations/src/ioredis.js +16 -12
  49. package/packages/datadog-instrumentations/src/jest.js +382 -81
  50. package/packages/datadog-instrumentations/src/kafkajs.js +165 -174
  51. package/packages/datadog-instrumentations/src/knex.js +17 -17
  52. package/packages/datadog-instrumentations/src/koa.js +12 -12
  53. package/packages/datadog-instrumentations/src/ldapjs.js +5 -5
  54. package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
  55. package/packages/datadog-instrumentations/src/limitd-client.js +4 -4
  56. package/packages/datadog-instrumentations/src/lodash.js +4 -4
  57. package/packages/datadog-instrumentations/src/mariadb.js +13 -13
  58. package/packages/datadog-instrumentations/src/memcached.js +2 -2
  59. package/packages/datadog-instrumentations/src/microgateway-core.js +2 -2
  60. package/packages/datadog-instrumentations/src/mocha/common.js +3 -3
  61. package/packages/datadog-instrumentations/src/mocha/main.js +85 -11
  62. package/packages/datadog-instrumentations/src/mocha/utils.js +133 -16
  63. package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
  64. package/packages/datadog-instrumentations/src/mongodb-core.js +42 -30
  65. package/packages/datadog-instrumentations/src/mongodb.js +5 -5
  66. package/packages/datadog-instrumentations/src/mongoose.js +21 -21
  67. package/packages/datadog-instrumentations/src/mquery.js +5 -5
  68. package/packages/datadog-instrumentations/src/multer.js +4 -4
  69. package/packages/datadog-instrumentations/src/mysql.js +16 -16
  70. package/packages/datadog-instrumentations/src/mysql2.js +4 -4
  71. package/packages/datadog-instrumentations/src/net.js +14 -8
  72. package/packages/datadog-instrumentations/src/nyc.js +5 -5
  73. package/packages/datadog-instrumentations/src/openai.js +19 -19
  74. package/packages/datadog-instrumentations/src/oracledb.js +6 -6
  75. package/packages/datadog-instrumentations/src/passport-utils.js +5 -5
  76. package/packages/datadog-instrumentations/src/pg.js +39 -25
  77. package/packages/datadog-instrumentations/src/pino.js +6 -10
  78. package/packages/datadog-instrumentations/src/playwright.js +445 -68
  79. package/packages/datadog-instrumentations/src/protobufjs.js +16 -16
  80. package/packages/datadog-instrumentations/src/redis.js +20 -12
  81. package/packages/datadog-instrumentations/src/restify.js +2 -2
  82. package/packages/datadog-instrumentations/src/router.js +12 -12
  83. package/packages/datadog-instrumentations/src/stripe.js +12 -12
  84. package/packages/datadog-instrumentations/src/vitest.js +107 -26
  85. package/packages/datadog-instrumentations/src/winston.js +4 -4
  86. package/packages/datadog-instrumentations/src/ws.js +7 -7
  87. package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -21
  88. package/packages/datadog-plugin-aws-sdk/src/base.js +70 -28
  89. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  90. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +20 -13
  91. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +46 -36
  92. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +34 -23
  93. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  94. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
  95. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +14 -15
  96. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +74 -55
  97. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +20 -18
  98. package/packages/datadog-plugin-aws-sdk/src/util.js +22 -0
  99. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -6
  100. package/packages/datadog-plugin-couchbase/src/index.js +58 -52
  101. package/packages/datadog-plugin-cucumber/src/index.js +5 -0
  102. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +215 -26
  103. package/packages/datadog-plugin-cypress/src/support.js +13 -1
  104. package/packages/datadog-plugin-electron/src/index.js +17 -0
  105. package/packages/datadog-plugin-electron/src/ipc.js +143 -0
  106. package/packages/datadog-plugin-electron/src/net.js +82 -0
  107. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -5
  108. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +27 -18
  109. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +3 -1
  110. package/packages/datadog-plugin-graphql/src/execute.js +6 -28
  111. package/packages/datadog-plugin-graphql/src/resolve.js +30 -35
  112. package/packages/datadog-plugin-graphql/src/tools/signature.js +32 -7
  113. package/packages/datadog-plugin-graphql/src/tools/transforms.js +118 -100
  114. package/packages/datadog-plugin-graphql/src/utils.js +29 -0
  115. package/packages/datadog-plugin-grpc/src/client.js +6 -7
  116. package/packages/datadog-plugin-grpc/src/util.js +57 -22
  117. package/packages/datadog-plugin-http/src/client.js +3 -7
  118. package/packages/datadog-plugin-jest/src/index.js +92 -50
  119. package/packages/datadog-plugin-jest/src/util.js +1 -2
  120. package/packages/datadog-plugin-mocha/src/index.js +5 -0
  121. package/packages/datadog-plugin-mongodb-core/src/index.js +36 -69
  122. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  123. package/packages/datadog-plugin-openai/src/services.js +2 -1
  124. package/packages/datadog-plugin-openai/src/tracing.js +12 -23
  125. package/packages/datadog-plugin-pg/src/index.js +3 -3
  126. package/packages/datadog-plugin-playwright/src/index.js +5 -1
  127. package/packages/datadog-plugin-redis/src/index.js +18 -23
  128. package/packages/datadog-plugin-vitest/src/index.js +8 -1
  129. package/packages/datadog-shimmer/src/shimmer.js +7 -1
  130. package/packages/dd-trace/src/aiguard/index.js +3 -1
  131. package/packages/dd-trace/src/aiguard/sdk.js +36 -30
  132. package/packages/dd-trace/src/aiguard/tags.js +20 -11
  133. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
  134. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +81 -81
  135. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
  136. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +2 -2
  137. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +4 -4
  138. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -2
  139. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -0
  140. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -3
  141. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +83 -48
  142. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
  143. package/packages/dd-trace/src/appsec/index.js +21 -24
  144. package/packages/dd-trace/src/appsec/reporter.js +3 -1
  145. package/packages/dd-trace/src/appsec/rule_manager.js +4 -2
  146. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +31 -16
  147. package/packages/dd-trace/src/azure_metadata.js +17 -6
  148. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +4 -4
  149. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -2
  150. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +6 -4
  151. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +1 -1
  152. package/packages/dd-trace/src/config/defaults.js +3 -14
  153. package/packages/dd-trace/src/config/generated-config-types.d.ts +3 -1
  154. package/packages/dd-trace/src/config/git_properties.js +2 -2
  155. package/packages/dd-trace/src/config/helper.js +4 -0
  156. package/packages/dd-trace/src/config/index.js +2 -2
  157. package/packages/dd-trace/src/config/major-overrides.js +98 -0
  158. package/packages/dd-trace/src/config/parsers.js +7 -1
  159. package/packages/dd-trace/src/config/supported-configurations.json +51 -38
  160. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
  161. package/packages/dd-trace/src/datastreams/index.js +2 -1
  162. package/packages/dd-trace/src/datastreams/manager.js +1 -1
  163. package/packages/dd-trace/src/datastreams/processor.js +3 -4
  164. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +2 -2
  165. package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +1 -0
  166. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
  167. package/packages/dd-trace/src/debugger/devtools_client/state.js +2 -1
  168. package/packages/dd-trace/src/debugger/index.js +7 -7
  169. package/packages/dd-trace/src/dogstatsd.js +2 -2
  170. package/packages/dd-trace/src/encode/0.4.js +748 -232
  171. package/packages/dd-trace/src/encode/0.5.js +47 -10
  172. package/packages/dd-trace/src/encode/agentless-json.js +1 -1
  173. package/packages/dd-trace/src/exporter.js +2 -0
  174. package/packages/dd-trace/src/exporters/agent/index.js +2 -1
  175. package/packages/dd-trace/src/exporters/agentless/index.js +3 -2
  176. package/packages/dd-trace/src/exporters/agentless/writer.js +2 -2
  177. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -1
  178. package/packages/dd-trace/src/exporters/common/request.js +1 -1
  179. package/packages/dd-trace/src/exporters/electron/index.js +49 -0
  180. package/packages/dd-trace/src/external-logger/src/index.js +2 -1
  181. package/packages/dd-trace/src/git_metadata.js +10 -8
  182. package/packages/dd-trace/src/lambda/handler-paths.js +52 -0
  183. package/packages/dd-trace/src/lambda/index.js +62 -14
  184. package/packages/dd-trace/src/lambda/runtime/patch.js +21 -46
  185. package/packages/dd-trace/src/llmobs/index.js +13 -2
  186. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -2
  187. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +45 -15
  188. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +6 -3
  189. package/packages/dd-trace/src/llmobs/sdk.js +24 -26
  190. package/packages/dd-trace/src/llmobs/span_processor.js +25 -5
  191. package/packages/dd-trace/src/llmobs/util.js +1 -0
  192. package/packages/dd-trace/src/llmobs/writers/base.js +2 -1
  193. package/packages/dd-trace/src/msgpack/chunk.js +6 -3
  194. package/packages/dd-trace/src/openfeature/noop.js +40 -36
  195. package/packages/dd-trace/src/openfeature/writers/base.js +2 -1
  196. package/packages/dd-trace/src/openfeature/writers/exposures.js +33 -52
  197. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
  198. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +1 -2
  199. package/packages/dd-trace/src/opentelemetry/tracer.js +0 -22
  200. package/packages/dd-trace/src/opentracing/propagation/text_map.js +20 -9
  201. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -11
  202. package/packages/dd-trace/src/payload-tagging/config/index.js +2 -2
  203. package/packages/dd-trace/src/plugins/ci_plugin.js +49 -4
  204. package/packages/dd-trace/src/plugins/database.js +54 -12
  205. package/packages/dd-trace/src/plugins/index.js +1 -0
  206. package/packages/dd-trace/src/plugins/plugin.js +2 -4
  207. package/packages/dd-trace/src/plugins/util/ci.js +9 -9
  208. package/packages/dd-trace/src/plugins/util/git-cache.js +23 -23
  209. package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -2
  210. package/packages/dd-trace/src/plugins/util/test.js +56 -12
  211. package/packages/dd-trace/src/plugins/util/url.js +1 -3
  212. package/packages/dd-trace/src/plugins/util/user-provided-git.js +18 -16
  213. package/packages/dd-trace/src/plugins/util/web.js +5 -7
  214. package/packages/dd-trace/src/priority_sampler.js +1 -1
  215. package/packages/dd-trace/src/profiling/profiler.js +1 -1
  216. package/packages/dd-trace/src/profiling/profilers/events.js +3 -23
  217. package/packages/dd-trace/src/profiling/profilers/wall.js +5 -6
  218. package/packages/dd-trace/src/profiling/ssi-heuristics.js +1 -1
  219. package/packages/dd-trace/src/rate_limiter.js +1 -1
  220. package/packages/dd-trace/src/remote_config/scheduler.js +1 -1
  221. package/packages/dd-trace/src/ritm.js +2 -1
  222. package/packages/dd-trace/src/runtime_metrics/index.js +2 -2
  223. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -8
  224. package/packages/dd-trace/src/scope.js +3 -10
  225. package/packages/dd-trace/src/serverless.js +6 -6
  226. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +27 -1
  227. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
  228. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +24 -0
  229. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
  230. package/packages/dd-trace/src/span_stats.js +1 -1
  231. package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
  232. package/packages/dd-trace/src/telemetry/endpoints.js +1 -1
  233. package/packages/dd-trace/src/telemetry/telemetry.js +2 -2
  234. package/packages/dd-trace/src/tracer.js +7 -7
  235. package/packages/dd-trace/src/lambda/runtime/ritm.js +0 -133
@@ -11,6 +11,14 @@ const startCh = channel('apm:mongodb:query:start')
11
11
  const finishCh = channel('apm:mongodb:query:finish')
12
12
  const errorCh = channel('apm:mongodb:query:error')
13
13
 
14
+ // Per-Connection cached topology shape (mongodb >= 4). The Connection's `address` is immutable
15
+ // for the lifetime of the connection, so we synthesize the `{ s: { options } }` envelope the
16
+ // plugin expects only once per connection. A WeakMap keeps the cache off the foreign Connection
17
+ // instance — no extra own-key visible to `Reflect.ownKeys`, `Object.freeze`, or another tracer's
18
+ // instrumentation walking the connection.
19
+ /** @type {WeakMap<object, { s: { options: { host?: string, port?: string } } }>} */
20
+ const topologyCache = new WeakMap()
21
+
14
22
  addHook({ name: 'mongodb-core', versions: ['2 - 3.1.9'] }, Server => {
15
23
  const serverProto = Server.Server.prototype
16
24
  shimmer.wrap(serverProto, 'command', command => wrapCommand(command, 'command'))
@@ -22,26 +30,22 @@ addHook({ name: 'mongodb-core', versions: ['2 - 3.1.9'] }, Server => {
22
30
  shimmer.wrap(cursorProto, '_getmore', _getmore => wrapCursor(_getmore, 'getMore', 'getMore'))
23
31
  shimmer.wrap(cursorProto, '_find', _find => wrapQuery(_find, '_find'))
24
32
  shimmer.wrap(cursorProto, 'kill', kill => wrapCursor(kill, 'killCursors', 'killCursors'))
25
- return Server
26
33
  })
27
34
 
28
35
  addHook({ name: 'mongodb', versions: ['>=4 <4.6.0'], file: 'lib/cmap/connection.js' }, Connection => {
29
36
  const proto = Connection.Connection.prototype
30
37
  shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command'))
31
38
  shimmer.wrap(proto, 'query', query => wrapConnectionCommand(query, 'query'))
32
- return Connection
33
39
  })
34
40
 
35
41
  addHook({ name: 'mongodb', versions: ['>=4.6.0 <6.4.0'], file: 'lib/cmap/connection.js' }, Connection => {
36
42
  const proto = Connection.Connection.prototype
37
43
  shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command'))
38
- return Connection
39
44
  })
40
45
 
41
46
  addHook({ name: 'mongodb', versions: ['>=6.4.0'], file: 'lib/cmap/connection.js' }, Connection => {
42
47
  const proto = Connection.Connection.prototype
43
48
  shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command', undefined, instrumentPromise))
44
- return Connection
45
49
  })
46
50
 
47
51
  addHook({ name: 'mongodb', versions: ['>=3.3 <4'], file: 'lib/core/wireprotocol/index.js' }, wp => wrapWp(wp))
@@ -50,12 +54,10 @@ addHook({ name: 'mongodb-core', versions: ['>=3.2'], file: 'lib/wireprotocol/ind
50
54
 
51
55
  addHook({ name: 'mongodb-core', versions: ['~3.1.10'], file: 'lib/wireprotocol/3_2_support.js' }, WireProtocol => {
52
56
  shimmer.wrap(WireProtocol.prototype, 'command', command => wrapUnifiedCommand(command, 'command'))
53
- return WireProtocol
54
57
  })
55
58
 
56
59
  addHook({ name: 'mongodb-core', versions: ['~3.1.10'], file: 'lib/wireprotocol/2_6_support.js' }, WireProtocol => {
57
60
  shimmer.wrap(WireProtocol.prototype, 'command', command => wrapUnifiedCommand(command, 'command'))
58
- return WireProtocol
59
61
  })
60
62
 
61
63
  addHook({ name: 'mongodb', versions: ['>=3.5.4 <4.11.0'], file: 'lib/utils.js' }, util => {
@@ -71,7 +73,6 @@ addHook({ name: 'mongodb', versions: ['>=3.5.4 <4.11.0'], file: 'lib/utils.js' }
71
73
 
72
74
  return maybePromise.apply(this, arguments)
73
75
  })
74
- return util
75
76
  })
76
77
 
77
78
  function wrapWp (wp) {
@@ -86,66 +87,75 @@ function wrapWp (wp) {
86
87
  }
87
88
 
88
89
  function wrapUnifiedCommand (command, operation, name) {
89
- const wrapped = function (server, ns, ops) {
90
+ return function (server, ns, ops) {
90
91
  if (!startCh.hasSubscribers) {
91
92
  return command.apply(this, arguments)
92
93
  }
93
94
  return instrument(operation, command, this, arguments, server, ns, ops, { name })
94
95
  }
95
- return wrapped
96
96
  }
97
97
 
98
98
  function wrapConnectionCommand (command, operation, name, instrumentFn = instrument) {
99
- const wrapped = function (ns, ops) {
99
+ const opts = { name }
100
+ return function (ns, ops) {
100
101
  if (!startCh.hasSubscribers) {
101
102
  return command.apply(this, arguments)
102
103
  }
103
- const hostParts = typeof this.address === 'string' ? this.address.split(':') : ''
104
- const options = hostParts.length === 2
105
- ? { host: hostParts[0], port: hostParts[1] }
106
- : {} // no port means the address is a random UUID so no host either
107
- const topology = { s: { options } }
108
-
109
- ns = `${ns.db}.${ns.collection}`
110
- return instrumentFn(operation, command, this, arguments, topology, ns, ops, { name })
104
+ let topology = topologyCache.get(this)
105
+ if (topology === undefined) {
106
+ topology = synthesizeTopology(this.address)
107
+ topologyCache.set(this, topology)
108
+ }
109
+ return instrumentFn(operation, command, this, arguments, topology, `${ns.db}.${ns.collection}`, ops, opts)
110
+ }
111
+ }
112
+
113
+ /**
114
+ * @param {string} address
115
+ * @returns {{ s: { options: { host?: string, port?: string } } }}
116
+ */
117
+ function synthesizeTopology (address) {
118
+ if (typeof address === 'string') {
119
+ const colon = address.indexOf(':')
120
+ // Match the previous `.split(':')` length-2 check: exactly one colon with non-empty parts on both sides.
121
+ if (colon > 0 && colon < address.length - 1 && !address.includes(':', colon + 1)) {
122
+ return { s: { options: { host: address.slice(0, colon), port: address.slice(colon + 1) } } }
123
+ }
111
124
  }
112
- return wrapped
125
+ // No port means the address is a random UUID, an IPv6 form, or otherwise unparseable, so no host either.
126
+ return { s: { options: {} } }
113
127
  }
114
128
 
115
129
  function wrapQuery (query, operation, name) {
116
- const wrapped = function () {
130
+ return function (...args) {
117
131
  if (!startCh.hasSubscribers) {
118
- return query.apply(this, arguments)
132
+ return query.apply(this, args)
119
133
  }
120
134
  const pool = this.server.s.pool
121
135
  const ns = this.ns
122
136
  const ops = this.cmd
123
- return instrument(operation, query, this, arguments, pool, ns, ops)
137
+ return instrument(operation, query, this, args, pool, ns, ops)
124
138
  }
125
-
126
- return wrapped
127
139
  }
128
140
 
129
141
  function wrapCursor (cursor, operation, name) {
130
- const wrapped = function () {
142
+ return function (...args) {
131
143
  if (!startCh.hasSubscribers) {
132
- return cursor.apply(this, arguments)
144
+ return cursor.apply(this, args)
133
145
  }
134
146
  const pool = this.server.s.pool
135
147
  const ns = this.ns
136
- return instrument(operation, cursor, this, arguments, pool, ns, {}, { name })
148
+ return instrument(operation, cursor, this, args, pool, ns, {}, { name })
137
149
  }
138
- return wrapped
139
150
  }
140
151
 
141
152
  function wrapCommand (command, operation, name) {
142
- const wrapped = function (ns, ops) {
153
+ return function (ns, ops) {
143
154
  if (!startCh.hasSubscribers) {
144
155
  return command.apply(this, arguments)
145
156
  }
146
157
  return instrument(operation, command, this, arguments, this, ns, ops, { name })
147
158
  }
148
- return wrapped
149
159
  }
150
160
 
151
161
  function instrument (operation, command, instance, args, server, ns, ops, options = {}) {
@@ -184,6 +194,8 @@ function instrument (operation, command, instance, args, server, ns, ops, option
184
194
  })
185
195
  }
186
196
 
197
+ module.exports = { synthesizeTopology }
198
+
187
199
  function instrumentPromise (operation, command, instance, args, server, ns, ops, options = {}) {
188
200
  const name = options.name || (ops && Object.keys(ops)[0])
189
201
 
@@ -35,22 +35,22 @@ addHook({ name: 'mongodb', versions: ['>=3.3 <5', '5', '>=6'] }, mongodb => {
35
35
  const useTwoArguments = collectionMethodsWithTwoFilters.includes(methodName)
36
36
 
37
37
  shimmer.wrap(mongodb.Collection.prototype, methodName, method => {
38
- return function () {
38
+ return function (...args) {
39
39
  if (!startCh.hasSubscribers) {
40
- return method.apply(this, arguments)
40
+ return method.apply(this, args)
41
41
  }
42
42
 
43
43
  const ctx = {
44
- filters: [arguments[0]],
44
+ filters: [args[0]],
45
45
  methodName,
46
46
  }
47
47
 
48
48
  if (useTwoArguments) {
49
- ctx.filters.push(arguments[1])
49
+ ctx.filters.push(args[1])
50
50
  }
51
51
 
52
52
  return startCh.runStores(ctx, () => {
53
- return method.apply(this, arguments)
53
+ return method.apply(this, args)
54
54
  })
55
55
  }
56
56
  })
@@ -66,14 +66,14 @@ addHook({
66
66
  if (!(methodName in Model)) continue
67
67
 
68
68
  shimmer.wrap(Model, methodName, method => {
69
- return function wrappedModelMethod () {
69
+ return function wrappedModelMethod (...args) {
70
70
  if (!startCh.hasSubscribers) {
71
- return method.apply(this, arguments)
71
+ return method.apply(this, args)
72
72
  }
73
73
 
74
- const filters = [arguments[0]]
74
+ const filters = [args[0]]
75
75
  if (useTwoArguments) {
76
- filters.push(arguments[1])
76
+ filters.push(args[1])
77
77
  }
78
78
 
79
79
  let callbackWrapped = false
@@ -84,10 +84,10 @@ addHook({
84
84
  if (typeof args[lastArgumentIndex] === 'function') {
85
85
  // is a callback, wrap it to execute finish()
86
86
  shimmer.wrap(args, lastArgumentIndex, originalCb => {
87
- return function () {
87
+ return function (...args) {
88
88
  finishCh.publish(ctx)
89
89
 
90
- return originalCb.apply(this, arguments)
90
+ return originalCb.apply(this, args)
91
91
  }
92
92
  })
93
93
 
@@ -101,19 +101,19 @@ addHook({
101
101
  }
102
102
 
103
103
  return startCh.runStores(ctx, () => {
104
- wrapCallbackIfExist(arguments, ctx)
104
+ wrapCallbackIfExist(args, ctx)
105
105
 
106
- const res = method.apply(this, arguments)
106
+ const res = method.apply(this, args)
107
107
 
108
108
  // if it is not callback, wrap exec method and its then
109
109
  if (!callbackWrapped) {
110
110
  shimmer.wrap(res, 'exec', originalExec => {
111
- return function wrappedExec () {
111
+ return function wrappedExec (...args) {
112
112
  if (!callbackWrapped) {
113
- wrapCallbackIfExist(arguments, ctx)
113
+ wrapCallbackIfExist(args, ctx)
114
114
  }
115
115
 
116
- const execResult = originalExec.apply(this, arguments)
116
+ const execResult = originalExec.apply(this, args)
117
117
 
118
118
  if (callbackWrapped || typeof execResult?.then !== 'function') {
119
119
  return execResult
@@ -121,27 +121,27 @@ addHook({
121
121
 
122
122
  // wrap them method, wrap resolve and reject methods
123
123
  shimmer.wrap(execResult, 'then', originalThen => {
124
- return function wrappedThen () {
125
- const resolve = arguments[0]
126
- const reject = arguments[1]
124
+ return function wrappedThen (...args) {
125
+ const resolve = args[0]
126
+ const reject = args[1]
127
127
 
128
- arguments[0] = shimmer.wrapFunction(resolve, resolve => function wrappedResolve () {
128
+ args[0] = shimmer.wrapFunction(resolve, resolve => function wrappedResolve (...args) {
129
129
  finishCh.publish(ctx)
130
130
 
131
131
  if (resolve) {
132
- return resolve.apply(this, arguments)
132
+ return resolve.apply(this, args)
133
133
  }
134
134
  })
135
135
 
136
- arguments[1] = shimmer.wrapFunction(reject, reject => function wrappedReject () {
136
+ args[1] = shimmer.wrapFunction(reject, reject => function wrappedReject (...args) {
137
137
  finishCh.publish(ctx)
138
138
 
139
139
  if (reject) {
140
- return reject.apply(this, arguments)
140
+ return reject.apply(this, args)
141
141
  }
142
142
  })
143
143
 
144
- return originalThen.apply(this, arguments)
144
+ return originalThen.apply(this, args)
145
145
  }
146
146
  })
147
147
 
@@ -165,8 +165,8 @@ addHook({
165
165
  versions: ['6', '>=7'],
166
166
  file: 'lib/helpers/query/sanitizeFilter.js',
167
167
  }, sanitizeFilter => {
168
- return shimmer.wrapFunction(sanitizeFilter, sanitizeFilter => function wrappedSanitizeFilter () {
169
- const sanitizedObject = sanitizeFilter.apply(this, arguments)
168
+ return shimmer.wrapFunction(sanitizeFilter, sanitizeFilter => function wrappedSanitizeFilter (...args) {
169
+ const sanitizedObject = sanitizeFilter.apply(this, args)
170
170
 
171
171
  if (sanitizeFilterFinishCh.hasSubscribers) {
172
172
  sanitizeFilterFinishCh.publish({
@@ -42,22 +42,22 @@ addHook({
42
42
  if (!(methodName in Query.prototype)) continue
43
43
 
44
44
  shimmer.wrap(Query.prototype, methodName, method => {
45
- return function () {
45
+ return function (...args) {
46
46
  if (prepareCh.hasSubscribers) {
47
- const filters = getFilters(arguments, methodName)
47
+ const filters = getFilters(args, methodName)
48
48
  if (filters?.length) {
49
49
  prepareCh.publish({ filters })
50
50
  }
51
51
  }
52
52
 
53
- return method.apply(this, arguments)
53
+ return method.apply(this, args)
54
54
  }
55
55
  })
56
56
  }
57
57
 
58
58
  shimmer.wrap(Query.prototype, 'exec', originalExec => {
59
- return function wrappedExec () {
60
- return tracingCh.tracePromise(originalExec, {}, this, arguments)
59
+ return function wrappedExec (...args) {
60
+ return tracingCh.tracePromise(originalExec, {}, this, args)
61
61
  }
62
62
  })
63
63
 
@@ -6,7 +6,7 @@ const { channel, addHook, AsyncResource } = require('./helpers/instrument')
6
6
  const multerReadCh = channel('datadog:multer:read:finish')
7
7
 
8
8
  function publishRequestBodyAndNext (req, res, next) {
9
- return shimmer.wrapFunction(next, next => function () {
9
+ return shimmer.wrapFunction(next, next => function (...args) {
10
10
  if (multerReadCh.hasSubscribers && req) {
11
11
  const abortController = new AbortController()
12
12
  const body = req.body
@@ -16,7 +16,7 @@ function publishRequestBodyAndNext (req, res, next) {
16
16
  if (abortController.signal.aborted) return
17
17
  }
18
18
 
19
- return next.apply(this, arguments)
19
+ return next.apply(this, args)
20
20
  })
21
21
  }
22
22
 
@@ -25,8 +25,8 @@ addHook({
25
25
  file: 'lib/make-middleware.js',
26
26
  versions: ['^1.4.4-lts.1'],
27
27
  }, makeMiddleware => {
28
- return shimmer.wrapFunction(makeMiddleware, makeMiddleware => function () {
29
- const middleware = makeMiddleware.apply(this, arguments)
28
+ return shimmer.wrapFunction(makeMiddleware, makeMiddleware => function (...args) {
29
+ const middleware = makeMiddleware.apply(this, args)
30
30
 
31
31
  return shimmer.wrapFunction(middleware, middleware => function wrapMulterMiddleware (req, res, next) {
32
32
  const nextResource = new AsyncResource('bound-anonymous-fn')
@@ -8,24 +8,24 @@ addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connect
8
8
  const finishCh = channel('apm:mysql:query:finish')
9
9
  const errorCh = channel('apm:mysql:query:error')
10
10
 
11
- shimmer.wrap(Connection.prototype, 'query', query => function () {
11
+ shimmer.wrap(Connection.prototype, 'query', query => function (...args) {
12
12
  if (!startCh.hasSubscribers) {
13
- return query.apply(this, arguments)
13
+ return query.apply(this, args)
14
14
  }
15
15
 
16
- const sql = arguments[0].sql || arguments[0]
16
+ const sql = args[0].sql || args[0]
17
17
  const conf = this.config
18
18
  const ctx = { sql, conf }
19
19
 
20
20
  return startCh.runStores(ctx, () => {
21
- if (arguments[0].sql) {
22
- arguments[0].sql = ctx.sql
21
+ if (args[0].sql) {
22
+ args[0].sql = ctx.sql
23
23
  } else {
24
- arguments[0] = ctx.sql
24
+ args[0] = ctx.sql
25
25
  }
26
26
 
27
27
  try {
28
- const res = query.apply(this, arguments)
28
+ const res = query.apply(this, args)
29
29
 
30
30
  if (res._callback) {
31
31
  const cb = res._callback
@@ -63,8 +63,8 @@ addHook({ name: 'mysql', file: 'lib/Pool.js', versions: ['>=2'] }, Pool => {
63
63
  const finishPoolQueryCh = channel('datadog:mysql:pool:query:finish')
64
64
 
65
65
  shimmer.wrap(Pool.prototype, 'getConnection', getConnection => function (cb) {
66
- arguments[0] = function () {
67
- return connectionFinishCh.runStores(ctx, cb, this, ...arguments)
66
+ arguments[0] = function (...args) {
67
+ return connectionFinishCh.runStores(ctx, cb, this, ...args)
68
68
  }
69
69
 
70
70
  const ctx = {}
@@ -74,24 +74,24 @@ addHook({ name: 'mysql', file: 'lib/Pool.js', versions: ['>=2'] }, Pool => {
74
74
  return getConnection.apply(this, arguments)
75
75
  })
76
76
 
77
- shimmer.wrap(Pool.prototype, 'query', query => function () {
77
+ shimmer.wrap(Pool.prototype, 'query', query => function (...args) {
78
78
  if (!startPoolQueryCh.hasSubscribers) {
79
- return query.apply(this, arguments)
79
+ return query.apply(this, args)
80
80
  }
81
81
 
82
- const sql = arguments[0].sql || arguments[0]
82
+ const sql = args[0].sql || args[0]
83
83
  const ctx = { sql }
84
84
  const finish = () => finishPoolQueryCh.publish(ctx)
85
85
 
86
86
  return startPoolQueryCh.runStores(ctx, () => {
87
- const cb = arguments[arguments.length - 1]
87
+ const cb = args[args.length - 1]
88
88
  if (typeof cb === 'function') {
89
- arguments[arguments.length - 1] = shimmer.wrapFunction(cb, cb => function () {
90
- return finishPoolQueryCh.runStores(ctx, cb, this, ...arguments)
89
+ args[args.length - 1] = shimmer.wrapFunction(cb, cb => function (...args) {
90
+ return finishPoolQueryCh.runStores(ctx, cb, this, ...args)
91
91
  })
92
92
  }
93
93
 
94
- const retval = query.apply(this, arguments)
94
+ const retval = query.apply(this, args)
95
95
 
96
96
  if (retval && retval.then) {
97
97
  retval.then(finish).catch(finish)
@@ -145,8 +145,8 @@ function wrapConnection (Connection, version) {
145
145
 
146
146
  if (cached === onResult) return
147
147
 
148
- const wrapped = function () {
149
- return commandFinishCh.runStores(ctx, onResult, this, ...arguments)
148
+ const wrapped = function (...args) {
149
+ return commandFinishCh.runStores(ctx, onResult, this, ...args)
150
150
  }
151
151
 
152
152
  wrappedOnResult.set(cmd, wrapped)
@@ -289,8 +289,8 @@ function wrapPoolCluster (PoolCluster) {
289
289
  const startOuterQueryCh = channel('datadog:mysql2:outerquery:start')
290
290
  const wrappedPoolNamespaces = new WeakSet()
291
291
 
292
- shimmer.wrap(PoolCluster.prototype, 'of', of => function () {
293
- const poolNamespace = of.apply(this, arguments)
292
+ shimmer.wrap(PoolCluster.prototype, 'of', of => function (...args) {
293
+ const poolNamespace = of.apply(this, args)
294
294
 
295
295
  if (startOuterQueryCh.hasSubscribers && !wrappedPoolNamespaces.has(poolNamespace)) {
296
296
  shimmer.wrap(poolNamespace, 'query', query => function (sql, values, cb) {
@@ -21,16 +21,16 @@ addHook({ name: 'net' }, (net) => {
21
21
  // so that we don't miss the dns calls
22
22
  require('node:dns')
23
23
 
24
- shimmer.wrap(net.Socket.prototype, 'connect', connect => function () {
24
+ shimmer.wrap(net.Socket.prototype, 'connect', connect => function (...args) {
25
25
  if (!startICPCh.hasSubscribers || !startTCPCh.hasSubscribers) {
26
- return connect.apply(this, arguments)
26
+ return connect.apply(this, args)
27
27
  }
28
28
 
29
- const options = getOptions(arguments)
30
- const lastIndex = arguments.length - 1
31
- const callback = arguments[lastIndex]
29
+ const options = getOptions(args)
30
+ const lastIndex = args.length - 1
31
+ const callback = args[lastIndex]
32
32
 
33
- if (!options) return connect.apply(this, arguments)
33
+ if (!options) return connect.apply(this, args)
34
34
 
35
35
  const protocol = options.path ? 'ipc' : 'tcp'
36
36
  const startCh = protocol === 'ipc' ? startICPCh : startTCPCh
@@ -39,7 +39,7 @@ addHook({ name: 'net' }, (net) => {
39
39
  const ctx = { options }
40
40
 
41
41
  if (typeof callback === 'function') {
42
- arguments[lastIndex] = function (...args) {
42
+ args[lastIndex] = function (...args) {
43
43
  return finishCh.runStores(ctx, callback, this, ...args)
44
44
  }
45
45
  }
@@ -48,20 +48,26 @@ addHook({ name: 'net' }, (net) => {
48
48
  setupListeners(this, protocol, ctx, finishCh, errorCh)
49
49
 
50
50
  const emit = this.emit
51
+ let pendingReadyEvents = 2
51
52
  this.emit = shimmer.wrapFunction(emit, emit => function (eventName) {
52
53
  switch (eventName) {
53
54
  case 'ready':
54
55
  case 'connect':
56
+ if (--pendingReadyEvents === 0) this.emit = emit
55
57
  return readyCh.runStores(ctx, () => {
56
58
  return emit.apply(this, arguments)
57
59
  })
60
+ case 'error':
61
+ case 'close':
62
+ this.emit = emit
63
+ return emit.apply(this, arguments)
58
64
  default:
59
65
  return emit.apply(this, arguments)
60
66
  }
61
67
  })
62
68
 
63
69
  try {
64
- return connect.apply(this, arguments)
70
+ return connect.apply(this, args)
65
71
  } catch (err) {
66
72
  errorCh.publish(err)
67
73
 
@@ -17,7 +17,7 @@ addHook({
17
17
  setupSettingsCachePath()
18
18
 
19
19
  // `wrap` is an async function
20
- shimmer.wrap(nycPackage.prototype, 'wrap', wrap => function () {
20
+ shimmer.wrap(nycPackage.prototype, 'wrap', wrap => function (...args) {
21
21
  // Only relevant if the config `all` is set to true (for untested code coverage)
22
22
  try {
23
23
  if (JSON.parse(getEnvironmentVariable('NYC_CONFIG')).all) {
@@ -27,16 +27,16 @@ addHook({
27
27
  // ignore errors
28
28
  }
29
29
 
30
- return wrap.apply(this, arguments)
30
+ return wrap.apply(this, args)
31
31
  })
32
32
 
33
33
  // `report` is an async function, so we wait for it to complete before publishing
34
- shimmer.wrap(nycPackage.prototype, 'report', report => function () {
34
+ shimmer.wrap(nycPackage.prototype, 'report', report => function (...args) {
35
35
  if (!codeCoverageReportCh.hasSubscribers) {
36
- return report.apply(this, arguments)
36
+ return report.apply(this, args)
37
37
  }
38
38
  const nycInstance = this
39
- const reportPromise = report.apply(this, arguments)
39
+ const reportPromise = report.apply(this, args)
40
40
 
41
41
  if (reportPromise && typeof reportPromise.then === 'function') {
42
42
  // Return a new promise that waits for both the report AND the coverage upload
@@ -150,18 +150,18 @@ addHook({ name: 'openai', file: 'dist/api.js', versions: ['>=3.0.0 <4'] }, expor
150
150
  methodNames.shift() // remove leading 'constructor' method
151
151
 
152
152
  for (const methodName of methodNames) {
153
- shimmer.wrap(exports.OpenAIApi.prototype, methodName, fn => function () {
153
+ shimmer.wrap(exports.OpenAIApi.prototype, methodName, fn => function (...args) {
154
154
  if (!ch.start.hasSubscribers) {
155
- return fn.apply(this, arguments)
155
+ return fn.apply(this, args)
156
156
  }
157
157
 
158
158
  const ctx = {
159
159
  methodName,
160
- args: arguments,
160
+ args,
161
161
  basePath: this.basePath,
162
162
  }
163
163
 
164
- return ch.tracePromise(fn, ctx, this, ...arguments)
164
+ return ch.tracePromise(fn, ctx, this, ...args)
165
165
  })
166
166
  }
167
167
 
@@ -175,10 +175,10 @@ addHook({ name: 'openai', file: 'dist/api.js', versions: ['>=3.0.0 <4'] }, expor
175
175
  */
176
176
  function wrapStreamIterator (response, options, ctx) {
177
177
  return function (itr) {
178
- return function () {
179
- const iterator = itr.apply(this, arguments)
180
- shimmer.wrap(iterator, 'next', next => function () {
181
- return next.apply(this, arguments)
178
+ return function (...args) {
179
+ const iterator = itr.apply(this, args)
180
+ shimmer.wrap(iterator, 'next', next => function (...args) {
181
+ return next.apply(this, args)
182
182
  .then(res => {
183
183
  const { done, value: chunk } = res
184
184
  onStreamedChunkCh.publish({ ctx, chunk, done })
@@ -215,38 +215,38 @@ for (const extension of extensions) {
215
215
  const targetPrototype = exports[targetClass].prototype
216
216
 
217
217
  for (const methodName of methods) {
218
- shimmer.wrap(targetPrototype, methodName, methodFn => function () {
218
+ shimmer.wrap(targetPrototype, methodName, methodFn => function (...args) {
219
219
  if (!ch.start.hasSubscribers) {
220
- return methodFn.apply(this, arguments)
220
+ return methodFn.apply(this, args)
221
221
  }
222
222
 
223
223
  // The OpenAI library lets you set `stream: true` on the options arg to any method
224
224
  // However, we only want to handle streamed responses in specific cases
225
225
  // chat.completions and completions
226
- const stream = streamedResponse && getOption(arguments, 'stream', false)
226
+ const stream = streamedResponse && getOption(args, 'stream', false)
227
227
 
228
228
  const client = this._client || this.client
229
229
 
230
230
  const ctx = {
231
231
  methodName: `${baseResource}.${methodName}`,
232
- args: arguments,
232
+ args,
233
233
  basePath: client.baseURL,
234
234
  }
235
235
 
236
236
  return ch.start.runStores(ctx, () => {
237
- const apiProm = methodFn.apply(this, arguments)
237
+ const apiProm = methodFn.apply(this, args)
238
238
 
239
239
  if (baseResource === 'chat.completions' && typeof apiProm._thenUnwrap === 'function') {
240
240
  // this should only ever be invoked from a client.beta.chat.completions.parse call
241
- shimmer.wrap(apiProm, '_thenUnwrap', origApiPromThenUnwrap => function () {
241
+ shimmer.wrap(apiProm, '_thenUnwrap', origApiPromThenUnwrap => function (...args) {
242
242
  // TODO(sam.brenner): I wonder if we can patch the APIPromise prototype instead, although
243
243
  // we might not have access to everything we need...
244
244
 
245
245
  // this is a new apipromise instance
246
- const unwrappedPromise = origApiPromThenUnwrap.apply(this, arguments)
246
+ const unwrappedPromise = origApiPromThenUnwrap.apply(this, args)
247
247
 
248
- shimmer.wrap(unwrappedPromise, 'parse', origApiPromParse => function () {
249
- const parsedPromise = origApiPromParse.apply(this, arguments)
248
+ shimmer.wrap(unwrappedPromise, 'parse', origApiPromParse => function (...args) {
249
+ const parsedPromise = origApiPromParse.apply(this, args)
250
250
  .then(body => Promise.all([this.responsePromise, body]))
251
251
 
252
252
  return handleUnwrappedAPIPromise(parsedPromise, ctx, stream)
@@ -258,8 +258,8 @@ for (const extension of extensions) {
258
258
 
259
259
  // wrapping `parse` avoids problematic wrapping of `then` when trying to call
260
260
  // `withResponse` in userland code after. This way, we can return the whole `APIPromise`
261
- shimmer.wrap(apiProm, 'parse', origApiPromParse => function () {
262
- const parsedPromise = origApiPromParse.apply(this, arguments)
261
+ shimmer.wrap(apiProm, 'parse', origApiPromParse => function (...args) {
262
+ const parsedPromise = origApiPromParse.apply(this, args)
263
263
  .then(body => Promise.all([this.responsePromise, body]))
264
264
 
265
265
  return handleUnwrappedAPIPromise(parsedPromise, ctx, stream)