dd-trace 3.3.1 → 3.12.1

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 (198) hide show
  1. package/LICENSE-3rdparty.csv +8 -0
  2. package/README.md +108 -43
  3. package/ci/init.js +6 -1
  4. package/ext/exporters.d.ts +2 -1
  5. package/ext/exporters.js +2 -1
  6. package/index.d.ts +129 -36
  7. package/package.json +18 -9
  8. package/packages/datadog-instrumentations/src/body-parser.js +26 -0
  9. package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
  10. package/packages/datadog-instrumentations/src/child-process.js +30 -0
  11. package/packages/datadog-instrumentations/src/connect.js +15 -15
  12. package/packages/datadog-instrumentations/src/cucumber.js +1 -3
  13. package/packages/datadog-instrumentations/src/elasticsearch.js +51 -47
  14. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +1 -1
  15. package/packages/datadog-instrumentations/src/helpers/hooks.js +9 -0
  16. package/packages/datadog-instrumentations/src/helpers/register.js +5 -0
  17. package/packages/datadog-instrumentations/src/http/server.js +20 -12
  18. package/packages/datadog-instrumentations/src/http2/server.js +67 -1
  19. package/packages/datadog-instrumentations/src/jest.js +182 -25
  20. package/packages/datadog-instrumentations/src/koa.js +32 -32
  21. package/packages/datadog-instrumentations/src/ldapjs.js +91 -0
  22. package/packages/datadog-instrumentations/src/mariadb.js +63 -0
  23. package/packages/datadog-instrumentations/src/memcached.js +1 -4
  24. package/packages/datadog-instrumentations/src/mocha.js +135 -24
  25. package/packages/datadog-instrumentations/src/next.js +10 -2
  26. package/packages/datadog-instrumentations/src/opensearch.js +10 -0
  27. package/packages/datadog-instrumentations/src/oracledb.js +8 -8
  28. package/packages/datadog-instrumentations/src/pg.js +7 -3
  29. package/packages/datadog-instrumentations/src/qs.js +24 -0
  30. package/packages/datadog-instrumentations/src/redis.js +12 -3
  31. package/packages/datadog-instrumentations/src/restify.js +5 -1
  32. package/packages/datadog-instrumentations/src/rhea.js +29 -15
  33. package/packages/datadog-instrumentations/src/router.js +23 -23
  34. package/packages/datadog-plugin-amqp10/src/consumer.js +32 -0
  35. package/packages/datadog-plugin-amqp10/src/index.js +11 -101
  36. package/packages/datadog-plugin-amqp10/src/producer.js +34 -0
  37. package/packages/datadog-plugin-amqp10/src/util.js +15 -0
  38. package/packages/datadog-plugin-amqplib/src/client.js +38 -0
  39. package/packages/datadog-plugin-amqplib/src/consumer.js +40 -0
  40. package/packages/datadog-plugin-amqplib/src/index.js +14 -102
  41. package/packages/datadog-plugin-amqplib/src/producer.js +37 -0
  42. package/packages/datadog-plugin-amqplib/src/util.js +14 -0
  43. package/packages/datadog-plugin-cassandra-driver/src/index.js +22 -60
  44. package/packages/datadog-plugin-cucumber/src/index.js +14 -33
  45. package/packages/datadog-plugin-cypress/src/plugin.js +2 -1
  46. package/packages/datadog-plugin-dns/src/index.js +16 -91
  47. package/packages/datadog-plugin-dns/src/lookup.js +40 -0
  48. package/packages/datadog-plugin-dns/src/lookup_service.js +24 -0
  49. package/packages/datadog-plugin-dns/src/resolve.js +24 -0
  50. package/packages/datadog-plugin-dns/src/reverse.js +21 -0
  51. package/packages/datadog-plugin-elasticsearch/src/index.js +24 -60
  52. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +24 -0
  53. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +41 -0
  54. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +14 -99
  55. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +33 -0
  56. package/packages/datadog-plugin-graphql/src/execute.js +73 -0
  57. package/packages/datadog-plugin-graphql/src/index.js +14 -176
  58. package/packages/datadog-plugin-graphql/src/parse.js +32 -0
  59. package/packages/datadog-plugin-graphql/src/resolve.js +70 -76
  60. package/packages/datadog-plugin-graphql/src/validate.js +28 -0
  61. package/packages/datadog-plugin-grpc/src/client.js +46 -55
  62. package/packages/datadog-plugin-grpc/src/index.js +7 -24
  63. package/packages/datadog-plugin-grpc/src/server.js +50 -52
  64. package/packages/datadog-plugin-grpc/src/util.js +15 -14
  65. package/packages/datadog-plugin-http/src/client.js +15 -5
  66. package/packages/datadog-plugin-http/src/index.js +7 -22
  67. package/packages/datadog-plugin-http/src/server.js +19 -3
  68. package/packages/datadog-plugin-http2/src/client.js +20 -1
  69. package/packages/datadog-plugin-http2/src/index.js +8 -26
  70. package/packages/datadog-plugin-http2/src/server.js +44 -0
  71. package/packages/datadog-plugin-jest/src/index.js +41 -65
  72. package/packages/datadog-plugin-kafkajs/src/consumer.js +42 -0
  73. package/packages/datadog-plugin-kafkajs/src/index.js +11 -87
  74. package/packages/datadog-plugin-kafkajs/src/producer.js +31 -0
  75. package/packages/datadog-plugin-mariadb/src/index.js +10 -0
  76. package/packages/datadog-plugin-memcached/src/index.js +17 -52
  77. package/packages/datadog-plugin-mocha/src/index.js +40 -60
  78. package/packages/datadog-plugin-moleculer/src/client.js +22 -36
  79. package/packages/datadog-plugin-moleculer/src/index.js +8 -26
  80. package/packages/datadog-plugin-moleculer/src/server.js +18 -30
  81. package/packages/datadog-plugin-mongodb-core/src/index.js +23 -51
  82. package/packages/datadog-plugin-mysql/src/index.js +23 -52
  83. package/packages/datadog-plugin-mysql2/src/index.js +1 -3
  84. package/packages/datadog-plugin-net/src/index.js +4 -0
  85. package/packages/datadog-plugin-net/src/ipc.js +21 -0
  86. package/packages/datadog-plugin-net/src/tcp.js +46 -0
  87. package/packages/datadog-plugin-next/src/index.js +3 -0
  88. package/packages/datadog-plugin-opensearch/src/index.js +11 -0
  89. package/packages/datadog-plugin-oracledb/src/index.js +29 -55
  90. package/packages/datadog-plugin-pg/src/index.js +27 -51
  91. package/packages/datadog-plugin-redis/src/index.js +29 -60
  92. package/packages/datadog-plugin-rhea/src/consumer.js +55 -0
  93. package/packages/datadog-plugin-rhea/src/index.js +11 -96
  94. package/packages/datadog-plugin-rhea/src/producer.js +45 -0
  95. package/packages/datadog-plugin-router/src/index.js +13 -2
  96. package/packages/datadog-plugin-sharedb/src/index.js +22 -39
  97. package/packages/datadog-plugin-tedious/src/index.js +20 -41
  98. package/packages/dd-trace/src/appsec/addresses.js +3 -1
  99. package/packages/dd-trace/src/appsec/blocking.js +44 -0
  100. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +8 -6
  101. package/packages/dd-trace/src/appsec/gateway/engine/engine.js +1 -1
  102. package/packages/dd-trace/src/appsec/gateway/engine/index.js +7 -2
  103. package/packages/dd-trace/src/appsec/gateway/engine/runner.js +0 -1
  104. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +4 -1
  105. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +11 -0
  106. package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +19 -0
  107. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +11 -0
  108. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +13 -0
  109. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +43 -5
  110. package/packages/dd-trace/src/appsec/iast/iast-context.js +3 -1
  111. package/packages/dd-trace/src/appsec/iast/index.js +24 -8
  112. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +20 -1
  113. package/packages/dd-trace/src/appsec/iast/path-line.js +17 -6
  114. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +17 -0
  115. package/packages/dd-trace/src/appsec/iast/taint-tracking/filter.js +16 -0
  116. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +18 -0
  117. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +98 -0
  118. package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +4 -0
  119. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +38 -0
  120. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +67 -0
  121. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +103 -0
  122. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +98 -30
  123. package/packages/dd-trace/src/appsec/index.js +79 -25
  124. package/packages/dd-trace/src/{plugins/util → appsec}/ip_blocklist.js +0 -0
  125. package/packages/dd-trace/src/appsec/ip_extractor.js +98 -0
  126. package/packages/dd-trace/src/appsec/recommended.json +134 -53
  127. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +7 -0
  128. package/packages/dd-trace/src/appsec/remote_config/index.js +56 -0
  129. package/packages/dd-trace/src/appsec/remote_config/manager.js +264 -0
  130. package/packages/dd-trace/src/{exporters → appsec/remote_config}/scheduler.js +9 -9
  131. package/packages/dd-trace/src/appsec/rule_manager.js +61 -1
  132. package/packages/dd-trace/src/appsec/templates/blocked.html +99 -0
  133. package/packages/dd-trace/src/appsec/templates/blocked.json +8 -0
  134. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +66 -0
  135. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +9 -5
  136. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +19 -51
  137. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +10 -5
  138. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +202 -0
  139. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +51 -62
  140. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +89 -0
  141. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +82 -0
  142. package/packages/dd-trace/src/config.js +119 -35
  143. package/packages/dd-trace/src/constants.js +9 -1
  144. package/packages/dd-trace/src/dogstatsd.js +42 -10
  145. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +10 -2
  146. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
  147. package/packages/dd-trace/src/exporter.js +3 -0
  148. package/packages/dd-trace/src/exporters/agent/index.js +10 -2
  149. package/packages/dd-trace/src/exporters/agent/writer.js +2 -9
  150. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +82 -0
  151. package/packages/dd-trace/src/exporters/common/request.js +51 -1
  152. package/packages/dd-trace/src/exporters/span-stats/index.js +6 -2
  153. package/packages/dd-trace/src/format.js +29 -10
  154. package/packages/dd-trace/src/lambda/handler.js +72 -0
  155. package/packages/dd-trace/src/lambda/index.js +5 -0
  156. package/packages/dd-trace/src/lambda/runtime/errors.js +20 -0
  157. package/packages/dd-trace/src/lambda/runtime/patch.js +74 -0
  158. package/packages/dd-trace/src/lambda/runtime/ritm.js +138 -0
  159. package/packages/dd-trace/src/metrics.js +15 -2
  160. package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -5
  161. package/packages/dd-trace/src/opentracing/span.js +2 -1
  162. package/packages/dd-trace/src/opentracing/span_context.js +9 -0
  163. package/packages/dd-trace/src/plugin_manager.js +11 -17
  164. package/packages/dd-trace/src/plugins/cache.js +9 -0
  165. package/packages/dd-trace/src/plugins/ci_plugin.js +97 -0
  166. package/packages/dd-trace/src/plugins/client.js +9 -0
  167. package/packages/dd-trace/src/plugins/composite.js +26 -0
  168. package/packages/dd-trace/src/plugins/consumer.js +9 -0
  169. package/packages/dd-trace/src/plugins/database.js +55 -0
  170. package/packages/dd-trace/src/plugins/incoming.js +7 -0
  171. package/packages/dd-trace/src/plugins/index.js +3 -0
  172. package/packages/dd-trace/src/plugins/log_plugin.js +2 -2
  173. package/packages/dd-trace/src/plugins/outgoing.js +31 -0
  174. package/packages/dd-trace/src/plugins/plugin.js +3 -0
  175. package/packages/dd-trace/src/plugins/producer.js +9 -0
  176. package/packages/dd-trace/src/plugins/server.js +9 -0
  177. package/packages/dd-trace/src/plugins/storage.js +21 -0
  178. package/packages/dd-trace/src/plugins/tracing.js +94 -0
  179. package/packages/dd-trace/src/plugins/util/ci.js +40 -4
  180. package/packages/dd-trace/src/plugins/util/git.js +58 -18
  181. package/packages/dd-trace/src/plugins/util/test.js +71 -8
  182. package/packages/dd-trace/src/plugins/util/user-provided-git.js +14 -1
  183. package/packages/dd-trace/src/plugins/util/web.js +11 -114
  184. package/packages/dd-trace/src/priority_sampler.js +6 -2
  185. package/packages/dd-trace/src/profiling/config.js +11 -6
  186. package/packages/dd-trace/src/profiling/exporters/agent.js +4 -0
  187. package/packages/dd-trace/src/profiling/index.js +2 -2
  188. package/packages/dd-trace/src/profiling/profiler.js +43 -7
  189. package/packages/dd-trace/src/proxy.js +8 -16
  190. package/packages/dd-trace/src/ritm.js +25 -14
  191. package/packages/dd-trace/src/span_processor.js +17 -0
  192. package/packages/dd-trace/src/span_sampler.js +77 -0
  193. package/packages/dd-trace/src/span_stats.js +2 -2
  194. package/packages/dd-trace/src/telemetry/dependencies.js +21 -7
  195. package/packages/dd-trace/src/telemetry/index.js +7 -1
  196. package/packages/dd-trace/src/telemetry/send-data.js +3 -1
  197. package/packages/dd-trace/src/tracer.js +10 -5
  198. package/packages/dd-trace/src/util.js +43 -1
@@ -11,8 +11,8 @@ const startCh = channel('apm:redis:command:start')
11
11
  const finishCh = channel('apm:redis:command:finish')
12
12
  const errorCh = channel('apm:redis:command:error')
13
13
 
14
- addHook({ name: '@node-redis/client', file: 'dist/lib/client/commands-queue.js', versions: ['>=1'] }, redis => {
15
- shimmer.wrap(redis.default.prototype, 'addCommand', addCommand => function (command) {
14
+ function wrapAddCommand (addCommand) {
15
+ return function (command) {
16
16
  if (!startCh.hasSubscribers) {
17
17
  return addCommand.apply(this, arguments)
18
18
  }
@@ -32,7 +32,16 @@ addHook({ name: '@node-redis/client', file: 'dist/lib/client/commands-queue.js',
32
32
 
33
33
  return res
34
34
  })
35
- })
35
+ }
36
+ }
37
+
38
+ addHook({ name: '@redis/client', file: 'dist/lib/client/commands-queue.js', versions: ['>=1.1'] }, redis => {
39
+ shimmer.wrap(redis.default.prototype, 'addCommand', wrapAddCommand)
40
+ return redis
41
+ })
42
+
43
+ addHook({ name: '@node-redis/client', file: 'dist/lib/client/commands-queue.js', versions: ['>=1'] }, redis => {
44
+ shimmer.wrap(redis.default.prototype, 'addCommand', wrapAddCommand)
36
45
  return redis
37
46
  })
38
47
 
@@ -9,6 +9,7 @@ const handleChannel = channel('apm:restify:request:handle')
9
9
  const errorChannel = channel('apm:restify:middleware:error')
10
10
  const enterChannel = channel('apm:restify:middleware:enter')
11
11
  const exitChannel = channel('apm:restify:middleware:exit')
12
+ const finishChannel = channel('apm:restify:middleware:finish')
12
13
  const nextChannel = channel('apm:restify:middleware:next')
13
14
 
14
15
  function wrapSetupRequest (setupRequest) {
@@ -53,6 +54,9 @@ function wrapFn (fn) {
53
54
  } catch (error) {
54
55
  errorChannel.publish({ req, error })
55
56
  nextChannel.publish({ req })
57
+ finishChannel.publish({ req })
58
+ throw error
59
+ } finally {
56
60
  exitChannel.publish({ req })
57
61
  }
58
62
  }
@@ -61,7 +65,7 @@ function wrapFn (fn) {
61
65
  function wrapNext (req, next) {
62
66
  return function () {
63
67
  nextChannel.publish({ req })
64
- exitChannel.publish({ req })
68
+ finishChannel.publish({ req })
65
69
 
66
70
  next.apply(this, arguments)
67
71
  }
@@ -11,16 +11,29 @@ const circularBufferConstructor = Symbol('circularBufferConstructor')
11
11
  const inFlightDeliveries = Symbol('inFlightDeliveries')
12
12
 
13
13
  const patched = new WeakSet()
14
- const dispatchCh = channel('apm:rhea:dispatch')
15
- const errorCh = channel('apm:rhea:error')
16
- const finishCh = channel('apm:rhea:finish')
14
+
15
+ const startSendCh = channel('apm:rhea:send:start')
16
+ const encodeSendCh = channel('apm:rhea:send:encode')
17
+ const errorSendCh = channel('apm:rhea:send:error')
18
+ const finishSendCh = channel('apm:rhea:send:finish')
19
+
20
+ const startReceiveCh = channel('apm:rhea:receive:start')
21
+ const dispatchReceiveCh = channel('apm:rhea:receive:dispatch')
22
+ const errorReceiveCh = channel('apm:rhea:receive:error')
23
+ const finishReceiveCh = channel('apm:rhea:receive:finish')
17
24
 
18
25
  const contexts = new WeakMap()
19
26
 
20
- addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/link.js' }, obj => {
21
- const startSendCh = channel('apm:rhea:send:start')
22
- const startReceiveCh = channel('apm:rhea:receive:start')
27
+ addHook({ name: 'rhea', versions: ['>=1'] }, rhea => {
28
+ shimmer.wrap(rhea.message, 'encode', encode => function (msg) {
29
+ encodeSendCh.publish(msg)
30
+ return encode.apply(this, arguments)
31
+ })
23
32
 
33
+ return rhea
34
+ })
35
+
36
+ addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/link.js' }, obj => {
24
37
  const Sender = obj.Sender
25
38
  const Receiver = obj.Receiver
26
39
  shimmer.wrap(Sender.prototype, 'send', send => function (msg, tag, format) {
@@ -47,7 +60,7 @@ addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/link.js' }, obj => {
47
60
  try {
48
61
  return delivery
49
62
  } catch (err) {
50
- errorCh.publish(err)
63
+ errorSendCh.publish(err)
51
64
 
52
65
  throw err
53
66
  }
@@ -76,7 +89,7 @@ addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/link.js' }, obj => {
76
89
  try {
77
90
  return dispatch.apply(this, arguments)
78
91
  } catch (err) {
79
- errorCh.publish(err)
92
+ errorReceiveCh.publish(err)
80
93
 
81
94
  throw err
82
95
  }
@@ -100,8 +113,9 @@ addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/connection.js' }, Connecti
100
113
  if (!asyncResource) return
101
114
 
102
115
  asyncResource.runInAsyncScope(() => {
103
- errorCh.publish(error)
104
- finish(delivery, null)
116
+ errorReceiveCh.publish(error)
117
+ beforeFinish(delivery, null)
118
+ finishReceiveCh.publish()
105
119
  })
106
120
  })
107
121
  }
@@ -137,7 +151,7 @@ function wrapDeliveryUpdate (obj, update) {
137
151
  const cb = asyncResource.bind(update)
138
152
  return AsyncResource.bind(function wrappedUpdate (settled, stateData) {
139
153
  const state = getStateFromData(stateData)
140
- dispatchCh.publish({ state })
154
+ dispatchReceiveCh.publish({ state })
141
155
  return cb.apply(this, arguments)
142
156
  })
143
157
  }
@@ -173,7 +187,8 @@ function patchCircularBuffer (proto, Session) {
173
187
  const state = remoteState && remoteState.constructor
174
188
  ? entry.remote_state.constructor.composite_type : undefined
175
189
  asyncResource.runInAsyncScope(() => {
176
- return finish(entry, state)
190
+ beforeFinish(entry, state)
191
+ finishSendCh.publish()
177
192
  })
178
193
  }
179
194
 
@@ -201,13 +216,12 @@ function addToInFlightDeliveries (connection, delivery) {
201
216
  deliveries.add(delivery)
202
217
  }
203
218
 
204
- function finish (delivery, state) {
219
+ function beforeFinish (delivery, state) {
205
220
  const obj = contexts.get(delivery)
206
221
  if (obj) {
207
222
  if (state) {
208
- dispatchCh.publish({ state })
223
+ dispatchReceiveCh.publish({ state })
209
224
  }
210
- finishCh.publish(undefined)
211
225
  if (obj.connection && obj.connection[inFlightDeliveries]) {
212
226
  obj.connection[inFlightDeliveries].delete(delivery)
213
227
  }
@@ -3,11 +3,12 @@
3
3
  const METHODS = require('methods').concat('all')
4
4
  const pathToRegExp = require('path-to-regexp')
5
5
  const shimmer = require('../../datadog-shimmer')
6
- const { addHook, channel, AsyncResource } = require('./helpers/instrument')
6
+ const { addHook, channel } = require('./helpers/instrument')
7
7
 
8
8
  function createWrapRouterMethod (name) {
9
9
  const enterChannel = channel(`apm:${name}:middleware:enter`)
10
10
  const exitChannel = channel(`apm:${name}:middleware:exit`)
11
+ const finishChannel = channel(`apm:${name}:middleware:finish`)
11
12
  const errorChannel = channel(`apm:${name}:middleware:error`)
12
13
  const nextChannel = channel(`apm:${name}:middleware:next`)
13
14
 
@@ -21,7 +22,6 @@ function createWrapRouterMethod (name) {
21
22
  if (!enterChannel.hasSubscribers) return original.apply(this, arguments)
22
23
 
23
24
  const matchers = layerMatchers.get(layer)
24
- const middlewareResource = new AsyncResource('bound-anonymous-fn')
25
25
  const lastIndex = arguments.length - 1
26
26
  const name = original._name || original.name
27
27
  const req = arguments[arguments.length > 3 ? 1 : 0]
@@ -31,32 +31,32 @@ function createWrapRouterMethod (name) {
31
31
  arguments[lastIndex] = wrapNext(req, next)
32
32
  }
33
33
 
34
- return middlewareResource.runInAsyncScope(() => {
35
- let route
34
+ let route
36
35
 
37
- if (matchers) {
38
- // Try to guess which path actually matched
39
- for (let i = 0; i < matchers.length; i++) {
40
- if (matchers[i].test(layer)) {
41
- route = matchers[i].path
36
+ if (matchers) {
37
+ // Try to guess which path actually matched
38
+ for (let i = 0; i < matchers.length; i++) {
39
+ if (matchers[i].test(layer)) {
40
+ route = matchers[i].path
42
41
 
43
- break
44
- }
42
+ break
45
43
  }
46
44
  }
45
+ }
47
46
 
48
- enterChannel.publish({ name, req, route })
47
+ enterChannel.publish({ name, req, route })
49
48
 
50
- try {
51
- return original.apply(this, arguments)
52
- } catch (error) {
53
- errorChannel.publish({ req, error })
54
- nextChannel.publish({ req })
55
- exitChannel.publish({ req })
49
+ try {
50
+ return original.apply(this, arguments)
51
+ } catch (error) {
52
+ errorChannel.publish({ req, error })
53
+ nextChannel.publish({ req })
54
+ finishChannel.publish({ req })
56
55
 
57
- throw error
58
- }
59
- })
56
+ throw error
57
+ } finally {
58
+ exitChannel.publish({ req })
59
+ }
60
60
  })
61
61
 
62
62
  // This is a workaround for the `loopback` library so that it can find the correct express layer
@@ -90,12 +90,12 @@ function createWrapRouterMethod (name) {
90
90
 
91
91
  function wrapNext (req, next) {
92
92
  return function (error) {
93
- if (error) {
93
+ if (error && error !== 'route' && error !== 'router') {
94
94
  errorChannel.publish({ req, error })
95
95
  }
96
96
 
97
97
  nextChannel.publish({ req })
98
- exitChannel.publish({ req })
98
+ finishChannel.publish({ req })
99
99
 
100
100
  next.apply(this, arguments)
101
101
  }
@@ -0,0 +1,32 @@
1
+ 'use strict'
2
+
3
+ const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
4
+ const { getAddress, getShortName } = require('./util')
5
+
6
+ class Amqp10ConsumerPlugin extends ConsumerPlugin {
7
+ static get name () { return 'amqp10' }
8
+ static get system () { return 'amqp' }
9
+
10
+ start ({ link }) {
11
+ const source = getShortName(link)
12
+ const address = getAddress(link)
13
+
14
+ this.startSpan('amqp.receive', {
15
+ service: this.config.service || `${this.tracer._service}-amqp`,
16
+ resource: ['receive', source].filter(v => v).join(' '),
17
+ type: 'worker',
18
+ kind: 'consumer',
19
+ meta: {
20
+ 'amqp.link.source.address': source,
21
+ 'amqp.link.role': 'receiver',
22
+ 'amqp.link.name': link.name,
23
+ 'amqp.link.handle': link.handle,
24
+ 'amqp.connection.host': address.host,
25
+ 'amqp.connection.port': address.port,
26
+ 'amqp.connection.user': address.user
27
+ }
28
+ })
29
+ }
30
+ }
31
+
32
+ module.exports = Amqp10ConsumerPlugin
@@ -1,107 +1,17 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../dd-trace/src/plugins/plugin')
4
- const { storage } = require('../../datadog-core')
5
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
6
-
7
- class Amqp10Plugin extends Plugin {
8
- static get name () {
9
- return 'amqp10'
3
+ const ProducerPlugin = require('./producer')
4
+ const ConsumerPlugin = require('./consumer')
5
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
6
+
7
+ class Amqp10Plugin extends CompositePlugin {
8
+ static get name () { return 'amqp10' }
9
+ static get plugins () {
10
+ return {
11
+ producer: ProducerPlugin,
12
+ consumer: ConsumerPlugin
13
+ }
10
14
  }
11
-
12
- constructor (...args) {
13
- super(...args)
14
-
15
- this.addSub(`apm:amqp10:send:start`, ({ link }) => {
16
- const address = getAddress(link)
17
- const target = getShortName(link)
18
-
19
- const store = storage.getStore()
20
- const childOf = store ? store.span : store
21
-
22
- const span = this.tracer.startSpan('amqp.send', {
23
- childOf,
24
- tags: {
25
- 'resource.name': ['send', target].filter(v => v).join(' '),
26
- 'span.kind': 'producer',
27
- 'amqp.link.target.address': target,
28
- 'amqp.link.role': 'sender',
29
- 'out.host': address.host,
30
- 'out.port': address.port,
31
- 'service.name': this.config.service || `${this.tracer._service}-amqp`,
32
- 'amqp.link.name': link.name,
33
- 'amqp.link.handle': link.handle,
34
- 'amqp.connection.host': address.host,
35
- 'amqp.connection.port': address.port,
36
- 'amqp.connection.user': address.user
37
- }
38
- })
39
-
40
- analyticsSampler.sample(span, this.config.measured)
41
-
42
- this.enter(span, store)
43
- })
44
-
45
- this.addSub(`apm:amqp10:send:error`, err => {
46
- const span = storage.getStore().span
47
- span.setTag('error', err)
48
- })
49
-
50
- this.addSub(`apm:amqp10:send:finish`, () => {
51
- const span = storage.getStore().span
52
- span.finish()
53
- })
54
-
55
- this.addSub(`apm:amqp10:receive:start`, ({ link }) => {
56
- const source = getShortName(link)
57
- const address = getAddress(link)
58
-
59
- const store = storage.getStore()
60
- const childOf = store ? store.span : store
61
-
62
- const span = this.tracer.startSpan('amqp.receive', {
63
- childOf,
64
- tags: {
65
- 'resource.name': ['receive', source].filter(v => v).join(' '),
66
- 'span.kind': 'consumer',
67
- 'span.type': 'worker',
68
- 'amqp.link.source.address': source,
69
- 'amqp.link.role': 'receiver',
70
- 'service.name': this.config.service || `${this.tracer._service}-amqp`,
71
- 'amqp.link.name': link.name,
72
- 'amqp.link.handle': link.handle,
73
- 'amqp.connection.host': address.host,
74
- 'amqp.connection.port': address.port,
75
- 'amqp.connection.user': address.user
76
- }
77
- })
78
-
79
- analyticsSampler.sample(span, this.config.measured)
80
-
81
- this.enter(span, store)
82
- })
83
-
84
- this.addSub(`apm:amqp10:receive:finish`, () => {
85
- storage.getStore().span.finish()
86
- })
87
-
88
- this.addSub(`apm:amqp10:receive:error`, err => {
89
- const span = storage.getStore().span
90
- span.setTag('error', err)
91
- })
92
- }
93
- }
94
-
95
- function getShortName (link) {
96
- if (!link || !link.name) return null
97
-
98
- return link.name.split('_').slice(0, -1).join('_')
99
- }
100
-
101
- function getAddress (link) {
102
- if (!link || !link.session || !link.session.connection) return {}
103
-
104
- return link.session.connection.address || {}
105
15
  }
106
16
 
107
17
  module.exports = Amqp10Plugin
@@ -0,0 +1,34 @@
1
+ 'use strict'
2
+
3
+ const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
4
+ const { getAddress, getShortName } = require('./util')
5
+
6
+ class Amqp10ProducerPlugin extends ProducerPlugin {
7
+ static get name () { return 'amqp10' }
8
+ static get operation () { return 'send' }
9
+ static get system () { return 'amqp' }
10
+
11
+ start ({ link }) {
12
+ const address = getAddress(link)
13
+ const target = getShortName(link)
14
+
15
+ this.startSpan('amqp.send', {
16
+ service: this.config.service || `${this.tracer._service}-amqp`,
17
+ resource: ['send', target].filter(v => v).join(' '),
18
+ kind: 'producer',
19
+ meta: {
20
+ 'amqp.link.target.address': target,
21
+ 'amqp.link.role': 'sender',
22
+ 'out.host': address.host,
23
+ 'out.port': address.port,
24
+ 'amqp.link.name': link.name,
25
+ 'amqp.link.handle': link.handle,
26
+ 'amqp.connection.host': address.host,
27
+ 'amqp.connection.port': address.port,
28
+ 'amqp.connection.user': address.user
29
+ }
30
+ })
31
+ }
32
+ }
33
+
34
+ module.exports = Amqp10ProducerPlugin
@@ -0,0 +1,15 @@
1
+ 'use strict'
2
+
3
+ function getAddress (link) {
4
+ if (!link || !link.session || !link.session.connection) return {}
5
+
6
+ return link.session.connection.address || {}
7
+ }
8
+
9
+ function getShortName (link) {
10
+ if (!link || !link.name) return null
11
+
12
+ return link.name.split('_').slice(0, -1).join('_')
13
+ }
14
+
15
+ module.exports = { getAddress, getShortName }
@@ -0,0 +1,38 @@
1
+ 'use strict'
2
+
3
+ const { TEXT_MAP } = require('../../../ext/formats')
4
+ const ClientPlugin = require('../../dd-trace/src/plugins/client')
5
+ const { getResourceName } = require('./util')
6
+
7
+ class AmqplibClientPlugin extends ClientPlugin {
8
+ static get name () { return 'amqplib' }
9
+ static get operation () { return 'command' }
10
+
11
+ start ({ channel = {}, method, fields }) {
12
+ if (method === 'basic.deliver' || method === 'basic.get') return
13
+ if (method === 'basic.publish') return
14
+
15
+ const stream = (channel.connection && channel.connection.stream) || {}
16
+ const span = this.startSpan('amqp.command', {
17
+ service: this.config.service || `${this.tracer._service}-amqp`,
18
+ resource: getResourceName(method, fields),
19
+ kind: 'client',
20
+ meta: {
21
+ 'out.host': stream._host,
22
+ 'out.port': stream.remotePort,
23
+ 'amqp.queue': fields.queue,
24
+ 'amqp.exchange': fields.exchange,
25
+ 'amqp.routingKey': fields.routingKey,
26
+ 'amqp.consumerTag': fields.consumerTag,
27
+ 'amqp.source': fields.source,
28
+ 'amqp.destination': fields.destination
29
+ }
30
+ })
31
+
32
+ fields.headers = fields.headers || {}
33
+
34
+ this.tracer.inject(span, TEXT_MAP, fields.headers)
35
+ }
36
+ }
37
+
38
+ module.exports = AmqplibClientPlugin
@@ -0,0 +1,40 @@
1
+ 'use strict'
2
+
3
+ const { TEXT_MAP } = require('../../../ext/formats')
4
+ const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
5
+ const { getResourceName } = require('./util')
6
+
7
+ class AmqplibConsumerPlugin extends ConsumerPlugin {
8
+ static get name () { return 'amqplib' }
9
+ static get operation () { return 'command' }
10
+
11
+ start ({ method, fields, message }) {
12
+ if (method !== 'basic.deliver' && method !== 'basic.get') return
13
+
14
+ const childOf = extract(this.tracer, message)
15
+
16
+ this.startSpan('amqp.command', {
17
+ childOf,
18
+ service: this.config.service || `${this.tracer._service}-amqp`,
19
+ resource: getResourceName(method, fields),
20
+ kind: 'consumer',
21
+ type: 'worker',
22
+ meta: {
23
+ 'amqp.queue': fields.queue,
24
+ 'amqp.exchange': fields.exchange,
25
+ 'amqp.routingKey': fields.routingKey,
26
+ 'amqp.consumerTag': fields.consumerTag,
27
+ 'amqp.source': fields.source,
28
+ 'amqp.destination': fields.destination
29
+ }
30
+ })
31
+ }
32
+ }
33
+
34
+ function extract (tracer, message) {
35
+ return message
36
+ ? tracer.extract(TEXT_MAP, message.properties.headers)
37
+ : null
38
+ }
39
+
40
+ module.exports = AmqplibConsumerPlugin
@@ -1,108 +1,20 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../dd-trace/src/plugins/plugin')
4
- const { storage } = require('../../datadog-core')
5
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
6
- const { TEXT_MAP } = require('../../../ext/formats')
7
-
8
- class AmqplibPlugin extends Plugin {
9
- static get name () {
10
- return 'amqplib'
11
- }
12
-
13
- constructor (...args) {
14
- super(...args)
15
-
16
- this.addSub(`apm:amqplib:command:start`, ({ channel, method, fields, message }) => {
17
- const store = storage.getStore()
18
- let childOf
19
-
20
- if (method === 'basic.deliver') {
21
- childOf = extract(this.tracer, message)
22
- } else {
23
- fields.headers = fields.headers || {}
24
- childOf = store ? store.span : store
25
- }
26
-
27
- const span = this.tracer.startSpan('amqp.command', {
28
- childOf,
29
- tags: {
30
- 'service.name': this.config.service || `${this.tracer._service}-amqp`,
31
- 'resource.name': getResourceName(method, fields)
32
- }
33
- })
34
-
35
- if (channel && channel.connection && channel.connection.stream) {
36
- span.addTags({
37
- 'out.host': channel.connection.stream._host,
38
- 'out.port': channel.connection.stream.remotePort
39
- })
40
- }
41
- const fieldNames = [
42
- 'queue',
43
- 'exchange',
44
- 'routingKey',
45
- 'consumerTag',
46
- 'source',
47
- 'destination'
48
- ]
49
-
50
- switch (method) {
51
- case 'basic.publish':
52
- span.setTag('span.kind', 'producer')
53
- break
54
- case 'basic.consume':
55
- case 'basic.get':
56
- case 'basic.deliver':
57
- span.addTags({
58
- 'span.kind': 'consumer',
59
- 'span.type': 'worker'
60
- })
61
- break
62
- default:
63
- span.setTag('span.kind', 'client')
64
- }
65
-
66
- fieldNames.forEach(field => {
67
- fields[field] !== undefined && span.setTag(`amqp.${field}`, fields[field])
68
- })
69
- if (method === 'basic.deliver') {
70
- analyticsSampler.sample(span, this.config.measured, true)
71
- } else {
72
- this.tracer.inject(span, TEXT_MAP, fields.headers)
73
- analyticsSampler.sample(span, this.config.measured)
74
- }
75
-
76
- this.enter(span, store)
77
- })
78
-
79
- this.addSub(`apm:amqplib:command:finish`, () => {
80
- const span = storage.getStore().span
81
- span.finish()
82
- })
83
-
84
- this.addSub(`apm:amqplib:command:error`, err => {
85
- const span = storage.getStore().span
86
- span.setTag('error', err)
87
- })
3
+ const ProducerPlugin = require('./producer')
4
+ const ConsumerPlugin = require('./consumer')
5
+ const ClientPlugin = require('./client')
6
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
7
+
8
+ // TODO: Consider splitting channels for publish/receive in the instrumentation.
9
+ class AmqplibPlugin extends CompositePlugin {
10
+ static get name () { return 'amqplib' }
11
+ static get plugins () {
12
+ return {
13
+ producer: ProducerPlugin,
14
+ consumer: ConsumerPlugin,
15
+ client: ClientPlugin
16
+ }
88
17
  }
89
18
  }
90
19
 
91
- function getResourceName (method, fields = {}) {
92
- return [
93
- method,
94
- fields.exchange,
95
- fields.routingKey,
96
- fields.queue,
97
- fields.source,
98
- fields.destination
99
- ].filter(val => val).join(' ')
100
- }
101
-
102
- function extract (tracer, message) {
103
- return message
104
- ? tracer.extract(TEXT_MAP, message.properties.headers)
105
- : null
106
- }
107
-
108
20
  module.exports = AmqplibPlugin