dd-trace 2.7.1 → 2.9.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 (77) hide show
  1. package/LICENSE-3rdparty.csv +1 -2
  2. package/ci/init.js +22 -6
  3. package/ci/jest/env.js +19 -7
  4. package/ext/tags.d.ts +1 -0
  5. package/ext/tags.js +2 -1
  6. package/index.d.ts +4 -2
  7. package/package.json +3 -5
  8. package/packages/datadog-core/src/storage/async_resource.js +1 -1
  9. package/packages/datadog-instrumentations/index.js +2 -0
  10. package/packages/datadog-instrumentations/src/amqp10.js +33 -32
  11. package/packages/datadog-instrumentations/src/amqplib.js +16 -11
  12. package/packages/datadog-instrumentations/src/aws-sdk.js +5 -4
  13. package/packages/datadog-instrumentations/src/cassandra-driver.js +53 -51
  14. package/packages/datadog-instrumentations/src/connect.js +5 -5
  15. package/packages/datadog-instrumentations/src/couchbase.js +41 -39
  16. package/packages/datadog-instrumentations/src/cucumber.js +38 -38
  17. package/packages/datadog-instrumentations/src/dns.js +20 -19
  18. package/packages/datadog-instrumentations/src/elasticsearch.js +30 -32
  19. package/packages/datadog-instrumentations/src/fastify.js +84 -92
  20. package/packages/datadog-instrumentations/src/hapi.js +210 -0
  21. package/packages/datadog-instrumentations/src/http/client.js +44 -44
  22. package/packages/datadog-instrumentations/src/http/server.js +15 -13
  23. package/packages/datadog-instrumentations/src/ioredis.js +16 -17
  24. package/packages/datadog-instrumentations/src/jest.js +5 -5
  25. package/packages/datadog-instrumentations/src/koa.js +13 -10
  26. package/packages/datadog-instrumentations/src/memcached.js +14 -12
  27. package/packages/datadog-instrumentations/src/mocha.js +37 -39
  28. package/packages/datadog-instrumentations/src/moleculer/client.js +46 -0
  29. package/packages/datadog-instrumentations/src/moleculer/server.js +59 -0
  30. package/packages/datadog-instrumentations/src/moleculer.js +4 -0
  31. package/packages/datadog-instrumentations/src/mongodb-core.js +29 -33
  32. package/packages/datadog-instrumentations/src/mysql.js +30 -29
  33. package/packages/datadog-instrumentations/src/mysql2.js +8 -9
  34. package/packages/datadog-instrumentations/src/net.js +23 -24
  35. package/packages/datadog-instrumentations/src/pg.js +30 -30
  36. package/packages/datadog-instrumentations/src/redis.js +49 -47
  37. package/packages/datadog-instrumentations/src/rhea.js +51 -49
  38. package/packages/datadog-instrumentations/src/router.js +5 -5
  39. package/packages/datadog-instrumentations/src/sharedb.js +20 -20
  40. package/packages/datadog-instrumentations/src/tedious.js +19 -19
  41. package/packages/datadog-plugin-amqp10/src/index.js +2 -7
  42. package/packages/datadog-plugin-amqplib/src/index.js +1 -2
  43. package/packages/datadog-plugin-cassandra-driver/src/index.js +1 -5
  44. package/packages/datadog-plugin-couchbase/src/index.js +3 -4
  45. package/packages/datadog-plugin-cucumber/src/index.js +1 -9
  46. package/packages/datadog-plugin-dns/src/index.js +3 -4
  47. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -5
  48. package/packages/datadog-plugin-hapi/src/index.js +34 -3
  49. package/packages/datadog-plugin-http/src/client.js +1 -3
  50. package/packages/datadog-plugin-http/src/server.js +0 -4
  51. package/packages/datadog-plugin-http2/src/server.js +3 -1
  52. package/packages/datadog-plugin-jest/src/index.js +2 -3
  53. package/packages/datadog-plugin-kafkajs/src/index.js +0 -4
  54. package/packages/datadog-plugin-memcached/src/index.js +1 -5
  55. package/packages/datadog-plugin-mocha/src/index.js +3 -7
  56. package/packages/datadog-plugin-moleculer/src/client.js +34 -44
  57. package/packages/datadog-plugin-moleculer/src/index.js +32 -3
  58. package/packages/datadog-plugin-moleculer/src/server.js +28 -50
  59. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -5
  60. package/packages/datadog-plugin-mysql/src/index.js +19 -12
  61. package/packages/datadog-plugin-net/src/index.js +3 -7
  62. package/packages/datadog-plugin-pg/src/index.js +1 -5
  63. package/packages/datadog-plugin-redis/src/index.js +1 -5
  64. package/packages/datadog-plugin-rhea/src/index.js +1 -5
  65. package/packages/datadog-plugin-router/src/index.js +1 -1
  66. package/packages/datadog-plugin-sharedb/src/index.js +1 -5
  67. package/packages/datadog-plugin-tedious/src/index.js +1 -5
  68. package/packages/dd-trace/lib/version.js +1 -1
  69. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +2 -1
  70. package/packages/dd-trace/src/appsec/index.js +3 -3
  71. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +3 -1
  72. package/packages/dd-trace/src/plugins/plugin.js +0 -8
  73. package/packages/dd-trace/src/plugins/util/test.js +5 -1
  74. package/packages/dd-trace/src/plugins/util/web.js +3 -1
  75. package/scripts/install_plugin_modules.js +25 -15
  76. package/packages/datadog-plugin-hapi/src/route.js +0 -75
  77. package/packages/datadog-plugin-hapi/src/server.js +0 -204
@@ -8,8 +8,7 @@ const {
8
8
  const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  const startCh = channel('apm:redis:command:start')
11
- const asyncEndCh = channel('apm:redis:command:async-end')
12
- const endCh = channel('apm:redis:command:end')
11
+ const finishCh = channel('apm:redis:command:finish')
13
12
  const errorCh = channel('apm:redis:command:error')
14
13
 
15
14
  addHook({ name: '@node-redis/client', file: 'dist/lib/client/commands-queue.js', versions: ['>=1'] }, redis => {
@@ -21,16 +20,18 @@ addHook({ name: '@node-redis/client', file: 'dist/lib/client/commands-queue.js',
21
20
  const name = command[0]
22
21
  const args = command.slice(1)
23
22
 
24
- start(this, name, args)
25
-
26
- const res = addCommand.apply(this, arguments)
27
23
  const asyncResource = new AsyncResource('bound-anonymous-fn')
28
- const onResolve = asyncResource.bind(() => finish(asyncEndCh, errorCh))
29
- const onReject = asyncResource.bind(err => finish(asyncEndCh, errorCh, err))
24
+ return asyncResource.runInAsyncScope(() => {
25
+ start(this, name, args)
26
+
27
+ const res = addCommand.apply(this, arguments)
28
+ const onResolve = asyncResource.bind(() => finish(finishCh, errorCh))
29
+ const onReject = asyncResource.bind(err => finish(finishCh, errorCh, err))
30
+
31
+ res.then(onResolve, onReject)
30
32
 
31
- res.then(onResolve, onReject)
32
- endCh.publish(undefined)
33
- return res
33
+ return res
34
+ })
34
35
  })
35
36
  return redis
36
37
  })
@@ -41,23 +42,23 @@ addHook({ name: 'redis', versions: ['>=2.6 <4'] }, redis => {
41
42
 
42
43
  if (!options.callback) return internalSendCommand.apply(this, arguments)
43
44
 
45
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
44
46
  const asyncResource = new AsyncResource('bound-anonymous-fn')
47
+ const cb = callbackResource.bind(options.callback)
45
48
 
46
- const cb = asyncResource.bind(options.callback)
49
+ return asyncResource.runInAsyncScope(() => {
50
+ start(this, options.command, options.args)
47
51
 
48
- start(this, options.command, options.args)
52
+ options.callback = asyncResource.bind(wrapCallback(finishCh, errorCh, cb))
49
53
 
50
- options.callback = AsyncResource.bind(wrapCallback(asyncEndCh, errorCh, cb))
54
+ try {
55
+ return internalSendCommand.apply(this, arguments)
56
+ } catch (err) {
57
+ errorCh.publish(err)
51
58
 
52
- try {
53
- return internalSendCommand.apply(this, arguments)
54
- } catch (err) {
55
- errorCh.publish(err)
56
-
57
- throw err
58
- } finally {
59
- endCh.publish(undefined)
60
- }
59
+ throw err
60
+ }
61
+ })
61
62
  })
62
63
  return redis
63
64
  })
@@ -68,29 +69,30 @@ addHook({ name: 'redis', versions: ['>=0.12 <2.6'] }, redis => {
68
69
  return sendCommand.apply(this, arguments)
69
70
  }
70
71
 
72
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
71
73
  const asyncResource = new AsyncResource('bound-anonymous-fn')
72
74
 
73
- start(this, command, args)
74
-
75
- if (typeof callback === 'function') {
76
- const cb = asyncResource.bind(callback)
77
- arguments[2] = AsyncResource.bind(wrapCallback(asyncEndCh, errorCh, cb))
78
- } else if (Array.isArray(args) && typeof args[args.length - 1] === 'function') {
79
- const cb = asyncResource.bind(args[args.length - 1])
80
- args[args.length - 1] = AsyncResource.bind(wrapCallback(asyncEndCh, errorCh, cb))
81
- } else {
82
- arguments[2] = AsyncResource.bind(wrapCallback(asyncEndCh, errorCh))
83
- }
84
-
85
- try {
86
- return sendCommand.apply(this, arguments)
87
- } catch (err) {
88
- errorCh.publish(err)
89
-
90
- throw err
91
- } finally {
92
- endCh.publish(undefined)
93
- }
75
+ return asyncResource.runInAsyncScope(() => {
76
+ start(this, command, args)
77
+
78
+ if (typeof callback === 'function') {
79
+ const cb = callbackResource.bind(callback)
80
+ arguments[2] = asyncResource.bind(wrapCallback(finishCh, errorCh, cb))
81
+ } else if (Array.isArray(args) && typeof args[args.length - 1] === 'function') {
82
+ const cb = callbackResource.bind(args[args.length - 1])
83
+ args[args.length - 1] = asyncResource.bind(wrapCallback(finishCh, errorCh, cb))
84
+ } else {
85
+ arguments[2] = asyncResource.bind(wrapCallback(finishCh, errorCh))
86
+ }
87
+
88
+ try {
89
+ return sendCommand.apply(this, arguments)
90
+ } catch (err) {
91
+ errorCh.publish(err)
92
+
93
+ throw err
94
+ }
95
+ })
94
96
  })
95
97
  return redis
96
98
  })
@@ -101,18 +103,18 @@ function start (client, command, args) {
101
103
  startCh.publish({ db, command, args, connectionOptions })
102
104
  }
103
105
 
104
- function wrapCallback (asyncEndCh, errorCh, callback) {
106
+ function wrapCallback (finishCh, errorCh, callback) {
105
107
  return function (err) {
106
- finish(asyncEndCh, errorCh, err)
108
+ finish(finishCh, errorCh, err)
107
109
  if (callback) {
108
110
  return callback.apply(this, arguments)
109
111
  }
110
112
  }
111
113
  }
112
114
 
113
- function finish (asyncEndCh, errorCh, error) {
115
+ function finish (finishCh, errorCh, error) {
114
116
  if (error) {
115
117
  errorCh.publish(error)
116
118
  }
117
- asyncEndCh.publish(undefined)
119
+ finishCh.publish()
118
120
  }
@@ -13,8 +13,7 @@ const inFlightDeliveries = Symbol('inFlightDeliveries')
13
13
  const patched = new WeakSet()
14
14
  const dispatchCh = channel('apm:rhea:dispatch')
15
15
  const errorCh = channel('apm:rhea:error')
16
- const asyncEndCh = channel('apm:rhea:async-end')
17
- const endCh = channel('apm:rhea:end')
16
+ const finishCh = channel('apm:rhea:finish')
18
17
 
19
18
  const contexts = new WeakMap()
20
19
 
@@ -35,24 +34,24 @@ addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/link.js' }, obj => {
35
34
  const targetAddress = this.options && this.options.target &&
36
35
  this.options.target.address ? this.options.target.address : undefined
37
36
 
38
- startSendCh.publish({ targetAddress, host, port, msg })
39
- const delivery = send.apply(this, arguments)
40
37
  const asyncResource = new AsyncResource('bound-anonymous-fn')
41
- const context = {
42
- asyncResource
43
- }
44
- contexts.set(delivery, context)
38
+ return asyncResource.runInAsyncScope(() => {
39
+ startSendCh.publish({ targetAddress, host, port, msg })
40
+ const delivery = send.apply(this, arguments)
41
+ const context = {
42
+ asyncResource
43
+ }
44
+ contexts.set(delivery, context)
45
45
 
46
- addToInFlightDeliveries(this.connection, delivery)
47
- try {
48
- return delivery
49
- } catch (err) {
50
- errorCh.publish(err)
46
+ addToInFlightDeliveries(this.connection, delivery)
47
+ try {
48
+ return delivery
49
+ } catch (err) {
50
+ errorCh.publish(err)
51
51
 
52
- throw err
53
- } finally {
54
- endCh.publish(undefined)
55
- }
52
+ throw err
53
+ }
54
+ })
56
55
  })
57
56
 
58
57
  shimmer.wrap(Receiver.prototype, 'dispatch', dispatch => function (eventName, msgObj) {
@@ -62,26 +61,26 @@ addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/link.js' }, obj => {
62
61
  }
63
62
 
64
63
  if (eventName === 'message' && msgObj) {
65
- startReceiveCh.publish({ msgObj, connection: this.connection })
64
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
65
+ return asyncResource.runInAsyncScope(() => {
66
+ startReceiveCh.publish({ msgObj, connection: this.connection })
66
67
 
67
- if (msgObj.delivery) {
68
- const asyncResource = new AsyncResource('bound-anonymous-fn')
69
- const context = {
70
- asyncResource
68
+ if (msgObj.delivery) {
69
+ const context = {
70
+ asyncResource
71
+ }
72
+ contexts.set(msgObj.delivery, context)
73
+ msgObj.delivery.update = wrapDeliveryUpdate(msgObj.delivery, msgObj.delivery.update)
74
+ addToInFlightDeliveries(this.connection, msgObj.delivery)
71
75
  }
72
- contexts.set(msgObj.delivery, context)
73
- msgObj.delivery.update = wrapDeliveryUpdate(msgObj.delivery, msgObj.delivery.update)
74
- addToInFlightDeliveries(this.connection, msgObj.delivery)
75
- }
76
- try {
77
- return dispatch.apply(this, arguments)
78
- } catch (err) {
79
- errorCh.publish(err)
76
+ try {
77
+ return dispatch.apply(this, arguments)
78
+ } catch (err) {
79
+ errorCh.publish(err)
80
80
 
81
- throw err
82
- } finally {
83
- endCh.publish(undefined)
84
- }
81
+ throw err
82
+ }
83
+ })
85
84
  }
86
85
 
87
86
  return dispatch.apply(this, arguments)
@@ -96,7 +95,10 @@ addHook({ name: 'rhea', versions: ['>=1'], file: 'lib/connection.js' }, Connecti
96
95
  if (this[inFlightDeliveries]) {
97
96
  this[inFlightDeliveries].forEach(delivery => {
98
97
  const context = contexts.get(delivery)
99
- const asyncResource = context.asyncResource
98
+ const asyncResource = context && context.asyncResource
99
+
100
+ if (!asyncResource) return
101
+
100
102
  asyncResource.runInAsyncScope(() => {
101
103
  errorCh.publish(error)
102
104
  finish(delivery, null)
@@ -160,19 +162,19 @@ function patchCircularBuffer (proto, Session) {
160
162
  shimmer.wrap(CircularBuffer.prototype, 'pop_if', popIf => function (fn) {
161
163
  arguments[0] = AsyncResource.bind(function (entry) {
162
164
  const context = contexts.get(entry)
163
- const asyncResource = context.asyncResource
164
- let shouldPop
165
- if (asyncResource) {
166
- fn = asyncResource.bind(fn, this)
167
- shouldPop = fn(entry)
168
- if (shouldPop && asyncResource) {
169
- const remoteState = entry.remote_state
170
- const state = remoteState && remoteState.constructor
171
- ? entry.remote_state.constructor.composite_type : undefined
172
- asyncResource.runInAsyncScope(() => {
173
- return finish(entry, state)
174
- })
175
- }
165
+ const asyncResource = context && context.asyncResource
166
+
167
+ if (!asyncResource) return fn(entry)
168
+
169
+ const shouldPop = asyncResource.runInAsyncScope(() => fn(entry))
170
+
171
+ if (shouldPop) {
172
+ const remoteState = entry.remote_state
173
+ const state = remoteState && remoteState.constructor
174
+ ? entry.remote_state.constructor.composite_type : undefined
175
+ asyncResource.runInAsyncScope(() => {
176
+ return finish(entry, state)
177
+ })
176
178
  }
177
179
 
178
180
  return shouldPop
@@ -205,7 +207,7 @@ function finish (delivery, state) {
205
207
  if (state) {
206
208
  dispatchCh.publish({ state })
207
209
  }
208
- asyncEndCh.publish(undefined)
210
+ finishCh.publish(undefined)
209
211
  if (obj.connection && obj.connection[inFlightDeliveries]) {
210
212
  obj.connection[inFlightDeliveries].delete(delivery)
211
213
  }
@@ -8,7 +8,7 @@ const { addHook, channel, AsyncResource } = require('./helpers/instrument')
8
8
  function createWrapRouterMethod (name) {
9
9
  const enterChannel = channel(`apm:${name}:middleware:enter`)
10
10
  const errorChannel = channel(`apm:${name}:middleware:error`)
11
- const exitChannel = channel(`apm:${name}:middleware:exit`)
11
+ const nextChannel = channel(`apm:${name}:middleware:next`)
12
12
 
13
13
  const layerMatchers = new WeakMap()
14
14
  const regexpCache = Object.create(null)
@@ -24,10 +24,10 @@ function createWrapRouterMethod (name) {
24
24
  const lastIndex = arguments.length - 1
25
25
  const name = original._name || original.name
26
26
  const req = arguments[arguments.length > 3 ? 1 : 0]
27
- const next = AsyncResource.bind(arguments[lastIndex])
27
+ const next = arguments[lastIndex]
28
28
 
29
29
  if (typeof next === 'function') {
30
- arguments[lastIndex] = wrapNext(req, middlewareResource.bind(next))
30
+ arguments[lastIndex] = wrapNext(req, next)
31
31
  }
32
32
 
33
33
  return middlewareResource.runInAsyncScope(() => {
@@ -50,7 +50,7 @@ function createWrapRouterMethod (name) {
50
50
  return original.apply(this, arguments)
51
51
  } catch (e) {
52
52
  errorChannel.publish(e)
53
- exitChannel.publish({ req })
53
+ nextChannel.publish({ req })
54
54
 
55
55
  throw e
56
56
  }
@@ -92,7 +92,7 @@ function createWrapRouterMethod (name) {
92
92
  errorChannel.publish(error)
93
93
  }
94
94
 
95
- exitChannel.publish({ req })
95
+ nextChannel.publish({ req })
96
96
 
97
97
  next.apply(null, arguments)
98
98
  }
@@ -33,38 +33,38 @@ const READABLE_ACTION_NAMES = {
33
33
 
34
34
  addHook({ name: 'sharedb', versions: ['>=1'], file: 'lib/agent.js' }, Agent => {
35
35
  const startCh = channel('apm:sharedb:request:start')
36
- const asyncEndCh = channel('apm:sharedb:request:async-end')
37
- const endCh = channel('apm:sharedb:request:end')
36
+ const finishCh = channel('apm:sharedb:request:finish')
38
37
  const errorCh = channel('apm:sharedb:request:error')
39
38
 
40
39
  shimmer.wrap(Agent.prototype, '_handleMessage', origHandleMessageFn => function (request, callback) {
40
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
41
41
  const asyncResource = new AsyncResource('bound-anonymous-fn')
42
- const action = request.a
43
42
 
43
+ const action = request.a
44
44
  const actionName = getReadableActionName(action)
45
45
 
46
- startCh.publish({ actionName, request })
46
+ return asyncResource.runInAsyncScope(() => {
47
+ startCh.publish({ actionName, request })
47
48
 
48
- callback = asyncResource.bind(callback)
49
+ callback = callbackResource.bind(callback)
49
50
 
50
- arguments[1] = AsyncResource.bind(function (error, res) {
51
- if (error) {
52
- errorCh.publish(error)
53
- }
54
- asyncEndCh.publish({ request, res })
51
+ arguments[1] = asyncResource.bind(function (error, res) {
52
+ if (error) {
53
+ errorCh.publish(error)
54
+ }
55
+ finishCh.publish({ request, res })
55
56
 
56
- return callback.apply(this, arguments)
57
- })
57
+ return callback.apply(this, arguments)
58
+ })
58
59
 
59
- try {
60
- return origHandleMessageFn.apply(this, arguments)
61
- } catch (error) {
62
- errorCh.publish(error)
60
+ try {
61
+ return origHandleMessageFn.apply(this, arguments)
62
+ } catch (error) {
63
+ errorCh.publish(error)
63
64
 
64
- throw error
65
- } finally {
66
- endCh.publish(undefined)
67
- }
65
+ throw error
66
+ }
67
+ })
68
68
  })
69
69
  return Agent
70
70
  })
@@ -9,8 +9,7 @@ const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  addHook({ name: 'tedious', versions: [ '>=1.0.0' ] }, tedious => {
11
11
  const startCh = channel('apm:tedious:request:start')
12
- const asyncEndCh = channel('apm:tedious:request:async-end')
13
- const endCh = channel('apm:tedious:request:end')
12
+ const finishCh = channel('apm:tedious:request:finish')
14
13
  const errorCh = channel('apm:tedious:request:error')
15
14
  shimmer.wrap(tedious.Connection.prototype, 'makeRequest', makeRequest => function (request) {
16
15
  if (!startCh.hasSubscribers) {
@@ -23,31 +22,32 @@ addHook({ name: 'tedious', versions: [ '>=1.0.0' ] }, tedious => {
23
22
  return makeRequest.apply(this, arguments)
24
23
  }
25
24
 
25
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
26
26
  const asyncResource = new AsyncResource('bound-anonymous-fn')
27
27
 
28
28
  const connectionConfig = this.config
29
29
 
30
- startCh.publish({ queryOrProcedure, connectionConfig })
30
+ return asyncResource.runInAsyncScope(() => {
31
+ startCh.publish({ queryOrProcedure, connectionConfig })
31
32
 
32
- const cb = asyncResource.bind(request.callback, request)
33
- request.callback = AsyncResource.bind(function (error) {
34
- if (error) {
35
- errorCh.publish(error)
36
- }
37
- asyncEndCh.publish(undefined)
33
+ const cb = callbackResource.bind(request.callback, request)
34
+ request.callback = asyncResource.bind(function (error) {
35
+ if (error) {
36
+ errorCh.publish(error)
37
+ }
38
+ finishCh.publish(undefined)
38
39
 
39
- return cb.apply(this, arguments)
40
- }, null, request)
40
+ return cb.apply(this, arguments)
41
+ }, null, request)
41
42
 
42
- try {
43
- return makeRequest.apply(this, arguments)
44
- } catch (error) {
45
- errorCh.publish(error)
43
+ try {
44
+ return makeRequest.apply(this, arguments)
45
+ } catch (error) {
46
+ errorCh.publish(error)
46
47
 
47
- throw error
48
- } finally {
49
- endCh.publish(undefined)
50
- }
48
+ throw error
49
+ }
50
+ })
51
51
  })
52
52
 
53
53
  return tedious
@@ -42,16 +42,12 @@ class Amqp10Plugin extends Plugin {
42
42
  this.enter(span, store)
43
43
  })
44
44
 
45
- this.addSub(`apm:amqp10:send:end`, () => {
46
- this.exit()
47
- })
48
-
49
45
  this.addSub(`apm:amqp10:send:error`, err => {
50
46
  const span = storage.getStore().span
51
47
  span.setTag('error', err)
52
48
  })
53
49
 
54
- this.addSub(`apm:amqp10:send:async-end`, () => {
50
+ this.addSub(`apm:amqp10:send:finish`, () => {
55
51
  const span = storage.getStore().span
56
52
  span.finish()
57
53
  })
@@ -85,9 +81,8 @@ class Amqp10Plugin extends Plugin {
85
81
  this.enter(span, store)
86
82
  })
87
83
 
88
- this.addSub(`apm:amqp10:receive:end`, () => {
84
+ this.addSub(`apm:amqp10:receive:finish`, () => {
89
85
  storage.getStore().span.finish()
90
- this.exit()
91
86
  })
92
87
 
93
88
  this.addSub(`apm:amqp10:receive:error`, err => {
@@ -76,10 +76,9 @@ class AmqplibPlugin extends Plugin {
76
76
  this.enter(span, store)
77
77
  })
78
78
 
79
- this.addSub(`apm:amqplib:command:end`, () => {
79
+ this.addSub(`apm:amqplib:command:finish`, () => {
80
80
  const span = storage.getStore().span
81
81
  span.finish()
82
- this.exit()
83
82
  })
84
83
 
85
84
  this.addSub(`apm:amqplib:command:error`, err => {
@@ -43,15 +43,11 @@ class CassandraDriverPlugin extends Plugin {
43
43
  this.enter(span, store)
44
44
  })
45
45
 
46
- this.addSub(`apm:cassandra:query:end`, () => {
47
- this.exit()
48
- })
49
-
50
46
  this.addSub(`apm:cassandra:query:error`, err => {
51
47
  storage.getStore().span.setTag('error', err)
52
48
  })
53
49
 
54
- this.addSub(`apm:cassandra:query:async-end`, () => {
50
+ this.addSub(`apm:cassandra:query:finish`, () => {
55
51
  storage.getStore().span.finish()
56
52
  })
57
53
 
@@ -9,11 +9,10 @@ class CouchBasePlugin extends Plugin {
9
9
  return 'couchbase'
10
10
  }
11
11
 
12
- addSubs (func, start, asyncEnd = defaultAsyncEnd) {
12
+ addSubs (func, start, finish = defaultFinish) {
13
13
  this.addSub(`apm:couchbase:${func}:start`, start)
14
- this.addSub(`apm:couchbase:${func}:end`, this.exit.bind(this))
15
14
  this.addSub(`apm:couchbase:${func}:error`, errorHandler)
16
- this.addSub(`apm:couchbase:${func}:async-end`, asyncEnd)
15
+ this.addSub(`apm:couchbase:${func}:finish`, finish)
17
16
  }
18
17
 
19
18
  startSpan (operation, customTags, store, bucket) {
@@ -63,7 +62,7 @@ class CouchBasePlugin extends Plugin {
63
62
  }
64
63
  }
65
64
 
66
- function defaultAsyncEnd () {
65
+ function defaultFinish () {
67
66
  storage.getStore().span.finish()
68
67
  }
69
68
 
@@ -54,10 +54,6 @@ class CucumberPlugin extends Plugin {
54
54
  this.enter(span, store)
55
55
  })
56
56
 
57
- this.addSub('ci:cucumber:run:end', () => {
58
- this.exit()
59
- })
60
-
61
57
  this.addSub('ci:cucumber:run-step:start', ({ resource }) => {
62
58
  const store = storage.getStore()
63
59
  const childOf = store ? store.span : store
@@ -71,11 +67,7 @@ class CucumberPlugin extends Plugin {
71
67
  this.enter(span, store)
72
68
  })
73
69
 
74
- this.addSub('ci:cucumber:run-step:end', () => {
75
- this.exit()
76
- })
77
-
78
- this.addSub('ci:cucumber:run:async-end', ({ isStep, status, skipReason, errorMessage }) => {
70
+ this.addSub('ci:cucumber:run:finish', ({ isStep, status, skipReason, errorMessage }) => {
79
71
  const span = storage.getStore().span
80
72
  const statusTag = isStep ? 'step.status' : TEST_STATUS
81
73
 
@@ -9,11 +9,10 @@ class DNSPlugin extends Plugin {
9
9
  return 'dns'
10
10
  }
11
11
 
12
- addSubs (func, start, asyncEnd = defaultAsyncEnd) {
12
+ addSubs (func, start, finish = defaultFinish) {
13
13
  this.addSub(`apm:dns:${func}:start`, start)
14
- this.addSub(`apm:dns:${func}:end`, this.exit.bind(this))
15
14
  this.addSub(`apm:dns:${func}:error`, errorHandler)
16
- this.addSub(`apm:dns:${func}:async-end`, asyncEnd)
15
+ this.addSub(`apm:dns:${func}:finish`, finish)
17
16
  }
18
17
 
19
18
  startSpan (name, customTags, store) {
@@ -88,7 +87,7 @@ class DNSPlugin extends Plugin {
88
87
  }
89
88
  }
90
89
 
91
- function defaultAsyncEnd () {
90
+ function defaultFinish () {
92
91
  storage.getStore().span.finish()
93
92
  }
94
93
 
@@ -34,16 +34,12 @@ class ElasticsearchPlugin extends Plugin {
34
34
  this.enter(span, store)
35
35
  })
36
36
 
37
- this.addSub('apm:elasticsearch:query:end', () => {
38
- this.exit()
39
- })
40
-
41
37
  this.addSub('apm:elasticsearch:query:error', err => {
42
38
  const span = storage.getStore().span
43
39
  span.setTag('error', err)
44
40
  })
45
41
 
46
- this.addSub('apm:elasticsearch:query:async-end', ({ params }) => {
42
+ this.addSub('apm:elasticsearch:query:finish', ({ params }) => {
47
43
  const span = storage.getStore().span
48
44
  this.config.hooks.query(span, params)
49
45
  span.finish()
@@ -1,6 +1,37 @@
1
1
  'use strict'
2
2
 
3
- const route = require('./route')
4
- const server = require('./server')
3
+ const { storage } = require('../../datadog-core')
4
+ const RouterPlugin = require('../../datadog-plugin-router/src')
5
+ const web = require('../../dd-trace/src/plugins/util/web')
5
6
 
6
- module.exports = [].concat(route, server)
7
+ class HapiPlugin extends RouterPlugin {
8
+ static get name () {
9
+ return 'hapi'
10
+ }
11
+
12
+ constructor (...args) {
13
+ super(...args)
14
+
15
+ this._requestSpans = new WeakMap()
16
+
17
+ this.addSub('apm:hapi:request:handle', ({ req }) => {
18
+ const store = storage.getStore()
19
+ const span = store && store.span
20
+
21
+ this.setFramework(req, 'hapi', this.config)
22
+ this._requestSpans.set(req, span)
23
+ })
24
+
25
+ this.addSub('apm:hapi:request:route', ({ req, route }) => {
26
+ web.setRoute(req, route)
27
+ })
28
+
29
+ this.addSub(`apm:hapi:request:error`, this.addError)
30
+
31
+ this.addSub('apm:hapi:extension:enter', ({ req }) => {
32
+ this.enter(this._requestSpans.get(req))
33
+ })
34
+ }
35
+ }
36
+
37
+ module.exports = HapiPlugin
@@ -54,9 +54,7 @@ class HttpClientPlugin extends Plugin {
54
54
  this.enter(span, store)
55
55
  })
56
56
 
57
- this.addSub('apm:http:client:request:end', this.exit.bind(this))
58
-
59
- this.addSub('apm:http:client:request:async-end', ({ req, res }) => {
57
+ this.addSub('apm:http:client:request:finish', ({ req, res }) => {
60
58
  const span = storage.getStore().span
61
59
  if (res) {
62
60
  span.setTag(HTTP_STATUS_CODE, res.statusCode)