dd-trace 2.7.0 → 2.9.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 (91) 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 +3 -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 +105 -0
  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 +75 -87
  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-aws-sdk/src/base.js +146 -0
  44. package/packages/datadog-plugin-aws-sdk/src/index.js +16 -106
  45. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +4 -2
  46. package/packages/datadog-plugin-aws-sdk/src/services/default.js +7 -0
  47. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +3 -1
  48. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +5 -4
  49. package/packages/datadog-plugin-aws-sdk/src/services/index.js +12 -0
  50. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -3
  51. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +4 -3
  52. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -1
  53. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -1
  54. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +4 -3
  55. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +45 -6
  56. package/packages/datadog-plugin-cassandra-driver/src/index.js +1 -5
  57. package/packages/datadog-plugin-couchbase/src/index.js +3 -4
  58. package/packages/datadog-plugin-cucumber/src/index.js +1 -9
  59. package/packages/datadog-plugin-dns/src/index.js +3 -4
  60. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -5
  61. package/packages/datadog-plugin-hapi/src/index.js +34 -3
  62. package/packages/datadog-plugin-http/src/client.js +1 -3
  63. package/packages/datadog-plugin-http/src/server.js +0 -4
  64. package/packages/datadog-plugin-http2/src/server.js +3 -1
  65. package/packages/datadog-plugin-jest/src/index.js +2 -3
  66. package/packages/datadog-plugin-kafkajs/src/index.js +0 -4
  67. package/packages/datadog-plugin-memcached/src/index.js +1 -5
  68. package/packages/datadog-plugin-mocha/src/index.js +3 -7
  69. package/packages/datadog-plugin-moleculer/src/client.js +34 -44
  70. package/packages/datadog-plugin-moleculer/src/index.js +32 -3
  71. package/packages/datadog-plugin-moleculer/src/server.js +28 -50
  72. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -5
  73. package/packages/datadog-plugin-mysql/src/index.js +19 -12
  74. package/packages/datadog-plugin-net/src/index.js +3 -7
  75. package/packages/datadog-plugin-pg/src/index.js +1 -5
  76. package/packages/datadog-plugin-redis/src/index.js +1 -5
  77. package/packages/datadog-plugin-rhea/src/index.js +1 -5
  78. package/packages/datadog-plugin-router/src/index.js +1 -1
  79. package/packages/datadog-plugin-sharedb/src/index.js +1 -5
  80. package/packages/datadog-plugin-tedious/src/index.js +1 -5
  81. package/packages/dd-trace/lib/version.js +1 -1
  82. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +2 -1
  83. package/packages/dd-trace/src/appsec/index.js +3 -3
  84. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +3 -1
  85. package/packages/dd-trace/src/plugins/plugin.js +0 -8
  86. package/packages/dd-trace/src/plugins/util/test.js +5 -1
  87. package/packages/dd-trace/src/plugins/util/web.js +3 -1
  88. package/scripts/install_plugin_modules.js +25 -15
  89. package/packages/datadog-plugin-aws-sdk/src/helpers.js +0 -103
  90. package/packages/datadog-plugin-hapi/src/route.js +0 -75
  91. package/packages/datadog-plugin-hapi/src/server.js +0 -204
@@ -5,7 +5,7 @@ const { addHook, channel, AsyncResource } = require('./helpers/instrument')
5
5
 
6
6
  const enterChannel = channel('apm:connect:middleware:enter')
7
7
  const errorChannel = channel('apm:connect:middleware:error')
8
- const exitChannel = channel('apm:connect:middleware:exit')
8
+ const nextChannel = channel('apm:connect:middleware:next')
9
9
  const handleChannel = channel('apm:connect:request:handle')
10
10
 
11
11
  function wrapConnect (connect) {
@@ -64,10 +64,10 @@ function wrapLayerHandle (layer) {
64
64
  const lastIndex = arguments.length - 1
65
65
  const name = original._name || original.name
66
66
  const req = arguments[arguments.length > 3 ? 1 : 0]
67
- const next = AsyncResource.bind(arguments[lastIndex])
67
+ const next = arguments[lastIndex]
68
68
 
69
69
  if (typeof next === 'function') {
70
- arguments[lastIndex] = wrapNext(req, middlewareResource.bind(next))
70
+ arguments[lastIndex] = wrapNext(req, next)
71
71
  }
72
72
 
73
73
  return middlewareResource.runInAsyncScope(() => {
@@ -79,7 +79,7 @@ function wrapLayerHandle (layer) {
79
79
  return original.apply(this, arguments)
80
80
  } catch (e) {
81
81
  errorChannel.publish(e)
82
- exitChannel.publish({ req })
82
+ nextChannel.publish({ req })
83
83
 
84
84
  throw e
85
85
  }
@@ -93,7 +93,7 @@ function wrapNext (req, next) {
93
93
  errorChannel.publish(error)
94
94
  }
95
95
 
96
- exitChannel.publish({ req })
96
+ nextChannel.publish({ req })
97
97
 
98
98
  next.apply(null, arguments)
99
99
  }
@@ -9,8 +9,7 @@ const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.5'] }, Bucket => {
11
11
  const startCh = channel('apm:couchbase:query:start')
12
- const asyncEndCh = channel('apm:couchbase:query:async-end')
13
- const endCh = channel('apm:couchbase:query:end')
12
+ const finishCh = channel('apm:couchbase:query:finish')
14
13
  const errorCh = channel('apm:couchbase:query:error')
15
14
 
16
15
  Bucket.prototype._maybeInvoke = wrapMaybeInvoke(Bucket.prototype._maybeInvoke)
@@ -25,27 +24,28 @@ addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.5'] }, Buck
25
24
 
26
25
  const n1qlQuery = q && q.statement
27
26
 
28
- startCh.publish({ resource: n1qlQuery, bucket: this })
27
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
28
+ return asyncResource.runInAsyncScope(() => {
29
+ startCh.publish({ resource: n1qlQuery, bucket: this })
29
30
 
30
- emitter.once('rows', AsyncResource.bind(() => {
31
- asyncEndCh.publish(undefined)
32
- }))
31
+ emitter.once('rows', asyncResource.bind(() => {
32
+ finishCh.publish(undefined)
33
+ }))
33
34
 
34
- emitter.once('error', AsyncResource.bind((error) => {
35
- errorCh.publish(error)
36
- asyncEndCh.publish(undefined)
37
- }))
35
+ emitter.once('error', asyncResource.bind((error) => {
36
+ errorCh.publish(error)
37
+ finishCh.publish(undefined)
38
+ }))
38
39
 
39
- try {
40
- return _n1qlReq.apply(this, arguments)
41
- } catch (err) {
42
- err.stack // trigger getting the stack at the original throwing point
43
- errorCh.publish(err)
40
+ try {
41
+ return _n1qlReq.apply(this, arguments)
42
+ } catch (err) {
43
+ err.stack // trigger getting the stack at the original throwing point
44
+ errorCh.publish(err)
44
45
 
45
- throw err
46
- } finally {
47
- endCh.publish(undefined)
48
- }
46
+ throw err
47
+ }
48
+ })
49
49
  })
50
50
 
51
51
  Bucket.prototype.upsert = wrap('apm:couchbase:upsert', Bucket.prototype.upsert)
@@ -103,8 +103,7 @@ function wrapQuery (query) {
103
103
 
104
104
  function wrap (prefix, fn) {
105
105
  const startCh = channel(prefix + ':start')
106
- const endCh = channel(prefix + ':end')
107
- const asyncEndCh = channel(prefix + ':async-end')
106
+ const finishCh = channel(prefix + ':finish')
108
107
  const errorCh = channel(prefix + ':error')
109
108
 
110
109
  const wrapped = function (key, value, options, callback) {
@@ -116,28 +115,31 @@ function wrap (prefix, fn) {
116
115
 
117
116
  if (callbackIndex < 0) return fn.apply(this, arguments)
118
117
 
119
- const cb = arguments[callbackIndex]
118
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
119
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
120
120
 
121
- startCh.publish({ bucket: this })
121
+ return asyncResource.runInAsyncScope(() => {
122
+ const cb = callbackResource.bind(arguments[callbackIndex])
122
123
 
123
- arguments[callbackIndex] = function (error, result) {
124
- if (error) {
125
- errorCh.publish(error)
126
- }
127
- asyncEndCh.publish(result)
128
- return cb.apply(this, arguments)
129
- }
124
+ startCh.publish({ bucket: this })
130
125
 
131
- try {
132
- return fn.apply(this, arguments)
133
- } catch (error) {
134
- error.stack // trigger getting the stack at the original throwing point
135
- errorCh.publish(error)
126
+ arguments[callbackIndex] = asyncResource.bind(function (error, result) {
127
+ if (error) {
128
+ errorCh.publish(error)
129
+ }
130
+ finishCh.publish(result)
131
+ return cb.apply(this, arguments)
132
+ })
136
133
 
137
- throw error
138
- } finally {
139
- endCh.publish(undefined)
140
- }
134
+ try {
135
+ return fn.apply(this, arguments)
136
+ } catch (error) {
137
+ error.stack // trigger getting the stack at the original throwing point
138
+ errorCh.publish(error)
139
+
140
+ throw error
141
+ }
142
+ })
141
143
  }
142
144
  return shimmer.wrap(fn, wrapped)
143
145
  }
@@ -1,13 +1,11 @@
1
1
  'use strict'
2
2
 
3
- const { addHook, channel } = require('./helpers/instrument')
3
+ const { addHook, channel, AsyncResource } = require('./helpers/instrument')
4
4
  const shimmer = require('../../datadog-shimmer')
5
5
 
6
6
  const runStartCh = channel('ci:cucumber:run:start')
7
- const runEndCh = channel('ci:cucumber:run:end')
8
- const runAsyncEndCh = channel('ci:cucumber:run:async-end')
7
+ const runFinishCh = channel('ci:cucumber:run:finish')
9
8
  const runStepStartCh = channel('ci:cucumber:run-step:start')
10
- const runStepEndCh = channel('ci:cucumber:run-step:end')
11
9
  const errorCh = channel('ci:cucumber:error')
12
10
 
13
11
  // TODO: remove in a later major version
@@ -49,23 +47,24 @@ function wrapRun (pl, isLatestVersion) {
49
47
  return run.apply(this, arguments)
50
48
  }
51
49
 
52
- runStartCh.publish({ pickleName: this.pickle.name, pickleUri: this.pickle.uri })
53
- try {
54
- const promise = run.apply(this, arguments)
55
- promise.finally(() => {
56
- const result = this.getWorstStepResult()
57
- const { status, skipReason, errorMessage } = isLatestVersion
58
- ? getStatusFromResultLatest(result) : getStatusFromResult(result)
59
-
60
- runAsyncEndCh.publish({ status, skipReason, errorMessage })
61
- })
62
- return promise
63
- } catch (err) {
64
- errorCh.publish(err)
65
- throw err
66
- } finally {
67
- runEndCh.publish(undefined)
68
- }
50
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
51
+ return asyncResource.runInAsyncScope(() => {
52
+ runStartCh.publish({ pickleName: this.pickle.name, pickleUri: this.pickle.uri })
53
+ try {
54
+ const promise = run.apply(this, arguments)
55
+ promise.finally(() => {
56
+ const result = this.getWorstStepResult()
57
+ const { status, skipReason, errorMessage } = isLatestVersion
58
+ ? getStatusFromResultLatest(result) : getStatusFromResult(result)
59
+
60
+ runFinishCh.publish({ status, skipReason, errorMessage })
61
+ })
62
+ return promise
63
+ } catch (err) {
64
+ errorCh.publish(err)
65
+ throw err
66
+ }
67
+ })
69
68
  })
70
69
  shimmer.wrap(pl.prototype, 'runStep', runStep => function () {
71
70
  if (!runStepStartCh.hasSubscribers) {
@@ -80,23 +79,24 @@ function wrapRun (pl, isLatestVersion) {
80
79
  resource = testStep.isHook ? 'hook' : testStep.pickleStep.text
81
80
  }
82
81
 
83
- runStepStartCh.publish({ resource })
84
- try {
85
- const promise = runStep.apply(this, arguments)
86
-
87
- promise.then((result) => {
88
- const { status, skipReason, errorMessage } = isLatestVersion
89
- ? getStatusFromResultLatest(result) : getStatusFromResult(result)
90
-
91
- runAsyncEndCh.publish({ isStep: true, status, skipReason, errorMessage })
92
- })
93
- return promise
94
- } catch (err) {
95
- errorCh.publish(err)
96
- throw err
97
- } finally {
98
- runStepEndCh.publish(undefined)
99
- }
82
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
83
+ return asyncResource.runInAsyncScope(() => {
84
+ runStepStartCh.publish({ resource })
85
+ try {
86
+ const promise = runStep.apply(this, arguments)
87
+
88
+ promise.then((result) => {
89
+ const { status, skipReason, errorMessage } = isLatestVersion
90
+ ? getStatusFromResultLatest(result) : getStatusFromResult(result)
91
+
92
+ runFinishCh.publish({ isStep: true, status, skipReason, errorMessage })
93
+ })
94
+ return promise
95
+ } catch (err) {
96
+ errorCh.publish(err)
97
+ throw err
98
+ }
99
+ })
100
100
  })
101
101
  }
102
102
 
@@ -48,8 +48,7 @@ function patchResolveShorthands (prototype) {
48
48
 
49
49
  function wrap (prefix, fn, expectedArgs, rrtype) {
50
50
  const startCh = channel(prefix + ':start')
51
- const endCh = channel(prefix + ':end')
52
- const asyncEndCh = channel(prefix + ':async-end')
51
+ const finishCh = channel(prefix + ':finish')
53
52
  const errorCh = channel(prefix + ':error')
54
53
 
55
54
  const wrapped = function () {
@@ -67,27 +66,29 @@ function wrap (prefix, fn, expectedArgs, rrtype) {
67
66
  if (rrtype) {
68
67
  startArgs.push(rrtype)
69
68
  }
70
- startCh.publish(startArgs)
71
69
 
72
- arguments[arguments.length - 1] = function (error, result) {
73
- if (error) {
74
- errorCh.publish(error)
75
- }
76
- asyncEndCh.publish(result)
77
- cb.apply(this, arguments)
78
- }
70
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
71
+ return asyncResource.runInAsyncScope(() => {
72
+ startCh.publish(startArgs)
79
73
 
80
- try {
81
- return fn.apply(this, arguments)
74
+ arguments[arguments.length - 1] = asyncResource.bind(function (error, result) {
75
+ if (error) {
76
+ errorCh.publish(error)
77
+ }
78
+ finishCh.publish(result)
79
+ cb.apply(this, arguments)
80
+ })
81
+
82
+ try {
83
+ return fn.apply(this, arguments)
82
84
  // TODO deal with promise versions when we support `dns/promises`
83
- } catch (error) {
84
- error.stack // trigger getting the stack at the original throwing point
85
- errorCh.publish(error)
85
+ } catch (error) {
86
+ error.stack // trigger getting the stack at the original throwing point
87
+ errorCh.publish(error)
86
88
 
87
- throw error
88
- } finally {
89
- endCh.publish(undefined)
90
- }
89
+ throw error
90
+ }
91
+ })
91
92
  }
92
93
 
93
94
  return shimmer.wrap(fn, wrapped)
@@ -8,8 +8,7 @@ const {
8
8
  const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  const startCh = channel('apm:elasticsearch:query:start')
11
- const asyncEndCh = channel('apm:elasticsearch:query:async-end')
12
- const endCh = channel('apm:elasticsearch:query:end')
11
+ const finishCh = channel('apm:elasticsearch:query:finish')
13
12
  const errorCh = channel('apm:elasticsearch:query:error')
14
13
 
15
14
  addHook({ name: '@elastic/transport', file: 'lib/Transport.js', versions: ['>=8'] }, (exports) => {
@@ -36,43 +35,42 @@ function wrapRequest (request) {
36
35
  if (!params) return request.apply(this, arguments)
37
36
 
38
37
  const parentResource = new AsyncResource('bound-anonymous-fn')
39
-
40
- startCh.publish({ params })
41
-
42
38
  const asyncResource = new AsyncResource('bound-anonymous-fn')
43
39
 
44
- try {
45
- const lastIndex = arguments.length - 1
46
- cb = arguments[lastIndex]
40
+ return asyncResource.runInAsyncScope(() => {
41
+ startCh.publish({ params })
47
42
 
48
- if (typeof cb === 'function') {
49
- cb = parentResource.bind(cb)
43
+ try {
44
+ const lastIndex = arguments.length - 1
45
+ cb = arguments[lastIndex]
50
46
 
51
- arguments[lastIndex] = asyncResource.bind(function (error) {
52
- finish(params, error)
53
- return cb.apply(null, arguments)
54
- })
55
- return request.apply(this, arguments)
56
- } else {
57
- const promise = request.apply(this, arguments)
58
- if (promise && typeof promise.then === 'function') {
59
- const onResolve = asyncResource.bind(() => finish(params))
60
- const onReject = asyncResource.bind(e => finish(params, e))
47
+ if (typeof cb === 'function') {
48
+ cb = parentResource.bind(cb)
61
49
 
62
- promise.then(onResolve, onReject)
50
+ arguments[lastIndex] = asyncResource.bind(function (error) {
51
+ finish(params, error)
52
+ return cb.apply(null, arguments)
53
+ })
54
+ return request.apply(this, arguments)
63
55
  } else {
64
- finish(params)
56
+ const promise = request.apply(this, arguments)
57
+ if (promise && typeof promise.then === 'function') {
58
+ const onResolve = asyncResource.bind(() => finish(params))
59
+ const onReject = asyncResource.bind(e => finish(params, e))
60
+
61
+ promise.then(onResolve, onReject)
62
+ } else {
63
+ finish(params)
64
+ }
65
+ return promise
65
66
  }
66
- return promise
67
- }
68
- } catch (err) {
69
- err.stack // trigger getting the stack at the original throwing point
70
- errorCh.publish(err)
67
+ } catch (err) {
68
+ err.stack // trigger getting the stack at the original throwing point
69
+ errorCh.publish(err)
71
70
 
72
- throw err
73
- } finally {
74
- endCh.publish(undefined)
75
- }
71
+ throw err
72
+ }
73
+ })
76
74
  }
77
75
  }
78
76
 
@@ -80,5 +78,5 @@ function finish (params, error) {
80
78
  if (error) {
81
79
  errorCh.publish(error)
82
80
  }
83
- asyncEndCh.publish({ params })
81
+ finishCh.publish({ params })
84
82
  }
@@ -1,6 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const methods = require('methods').concat('all')
4
3
  const shimmer = require('../../datadog-shimmer')
5
4
  const { addHook, channel, AsyncResource } = require('./helpers/instrument')
6
5
 
@@ -8,26 +7,28 @@ const errorChannel = channel('apm:fastify:middleware:error')
8
7
  const handleChannel = channel('apm:fastify:request:handle')
9
8
 
10
9
  const requestResources = new WeakMap()
10
+ const parsingResources = new WeakMap()
11
11
 
12
- function wrapFastify (fastify) {
12
+ function wrapFastify (fastify, hasParsingEvents) {
13
13
  if (typeof fastify !== 'function') return fastify
14
14
 
15
15
  return function fastifyWithTrace () {
16
16
  const app = fastify.apply(this, arguments)
17
17
 
18
- if (!app) return app
18
+ if (!app || typeof app.addHook !== 'function') return app
19
19
 
20
- if (typeof app.addHook === 'function') {
21
- app.addHook('onRequest', onRequest)
22
- app.addHook = wrapAddHook(app.addHook)
23
- app.addHook('preHandler', preHandler)
24
- }
20
+ app.addHook('onRequest', onRequest)
21
+ app.addHook('preHandler', preHandler)
25
22
 
26
- methods.forEach(method => {
27
- app[method] = wrapMethod(app[method])
28
- })
23
+ if (hasParsingEvents) {
24
+ app.addHook('preParsing', preParsing)
25
+ app.addHook('preValidation', preValidation)
26
+ } else {
27
+ app.addHook('onRequest', preParsing)
28
+ app.addHook('preHandler', preValidation)
29
+ }
29
30
 
30
- app.route = wrapRoute(app.route)
31
+ app.addHook = wrapAddHook(app.addHook)
31
32
 
32
33
  return app
33
34
  }
@@ -45,36 +46,39 @@ function wrapAddHook (addHook) {
45
46
 
46
47
  if (!requestResource) return fn.apply(this, arguments)
47
48
 
48
- requestResource.runInAsyncScope(() => {
49
- const hookResource = new AsyncResource('bound-anonymous-fn')
49
+ try {
50
+ if (typeof done === 'function') {
51
+ done = arguments[arguments.length - 1]
50
52
 
51
- try {
52
- if (typeof done === 'function') {
53
- done = arguments[arguments.length - 1]
53
+ arguments[arguments.length - 1] = function (err) {
54
+ publishError(err, requestResource)
54
55
 
55
- arguments[arguments.length - 1] = hookResource.bind(function (err) {
56
- errorChannel.publish(err)
57
- return done.apply(this, arguments)
58
- })
56
+ if (name === 'onRequest' || name === 'preParsing') {
57
+ const parsingResource = new AsyncResource('bound-anonymous-fn')
59
58
 
60
- return hookResource.bind(fn).apply(this, arguments)
61
- } else {
62
- const promise = hookResource.bind(fn).apply(this, arguments)
59
+ parsingResources.set(req, parsingResource)
63
60
 
64
- if (promise && typeof promise.catch === 'function') {
65
- return promise.catch(err => {
66
- errorChannel.publish(err)
67
- throw err
61
+ return parsingResource.runInAsyncScope(() => {
62
+ return done.apply(this, arguments)
68
63
  })
64
+ } else {
65
+ return done.apply(this, arguments)
69
66
  }
67
+ }
70
68
 
71
- return promise
69
+ return fn.apply(this, arguments)
70
+ } else {
71
+ const promise = fn.apply(this, arguments)
72
+
73
+ if (promise && typeof promise.catch === 'function') {
74
+ return promise.catch(err => publishError(err, requestResource))
72
75
  }
73
- } catch (e) {
74
- errorChannel.publish(e)
75
- throw e
76
+
77
+ return promise
76
78
  }
77
- })
79
+ } catch (e) {
80
+ throw publishError(e, requestResource)
81
+ }
78
82
  })
79
83
 
80
84
  return addHook.apply(this, arguments)
@@ -86,11 +90,14 @@ function onRequest (request, reply, next) {
86
90
 
87
91
  const req = getReq(request)
88
92
  const res = getRes(reply)
93
+ const requestResource = new AsyncResource('bound-anonymous-fn')
89
94
 
90
- requestResources.set(req, new AsyncResource('bound-anonymous-fn'))
91
- handleChannel.publish({ req, res })
95
+ requestResources.set(req, requestResource)
92
96
 
93
- return next()
97
+ return requestResource.runInAsyncScope(() => {
98
+ handleChannel.publish({ req, res })
99
+ return next()
100
+ })
94
101
  }
95
102
 
96
103
  function preHandler (request, reply, next) {
@@ -98,61 +105,39 @@ function preHandler (request, reply, next) {
98
105
  if (!reply || typeof reply.send !== 'function') return next()
99
106
 
100
107
  const req = getReq(request)
108
+ const requestResource = requestResources.get(req)
101
109
 
102
- reply.send = requestResources.get(req).bind(wrapSend(reply.send))
110
+ reply.send = wrapSend(reply.send, requestResource)
103
111
 
104
112
  next()
105
113
  }
106
114
 
107
- function wrapSend (send) {
108
- return function sendWithTrace (payload) {
109
- if (payload instanceof Error) {
110
- errorChannel.publish(payload)
111
- }
112
-
113
- return send.apply(this, arguments)
114
- }
115
- }
116
-
117
- function wrapRoute (route) {
118
- if (typeof route !== 'function') return route
115
+ function preValidation (request, reply, next) {
116
+ const req = getReq(request)
117
+ const parsingResource = parsingResources.get(req)
119
118
 
120
- return function routeWithTrace (opts) {
121
- opts.handler = wrapHandler(opts.handler)
119
+ if (!parsingResource) return next()
122
120
 
123
- return route.apply(this, arguments)
124
- }
121
+ parsingResource.runInAsyncScope(() => next())
125
122
  }
126
123
 
127
- function wrapMethod (method) {
128
- if (typeof method !== 'function') return method
129
-
130
- return function methodWithTrace (url, opts, handler) {
131
- const lastIndex = arguments.length - 1
132
-
133
- handler = arguments[lastIndex]
134
-
135
- if (typeof handler === 'function') {
136
- arguments[lastIndex] = wrapHandler(handler)
137
- } else if (handler) {
138
- arguments[lastIndex].handler = wrapHandler(handler.handler)
139
- }
124
+ function preParsing (request, reply, next) {
125
+ const req = getReq(request)
126
+ const parsingResource = new AsyncResource('bound-anonymous-fn')
140
127
 
141
- return method.apply(this, arguments)
142
- }
128
+ parsingResources.set(req, parsingResource)
129
+ parsingResource.runInAsyncScope(() => next())
143
130
  }
144
131
 
145
- function wrapHandler (handler) {
146
- if (!handler || typeof handler !== 'function' || handler.name === 'handlerWithTrace') {
147
- return handler
148
- }
149
-
150
- return function handlerWithTrace (request, reply) {
151
- const req = getReq(request)
132
+ function wrapSend (send, resource) {
133
+ return function sendWithTrace (payload) {
134
+ if (payload instanceof Error) {
135
+ resource.runInAsyncScope(() => {
136
+ errorChannel.publish(payload)
137
+ })
138
+ }
152
139
 
153
- return requestResources.get(req).runInAsyncScope(() => {
154
- return handler.apply(this, arguments)
155
- })
140
+ return send.apply(this, arguments)
156
141
  }
157
142
  }
158
143
 
@@ -164,16 +149,15 @@ function getRes (reply) {
164
149
  return reply && (reply.raw || reply.res || reply)
165
150
  }
166
151
 
167
- addHook({ name: 'fastify', versions: ['>=3.25.2'] }, fastify => {
168
- const wrapped = shimmer.wrap(fastify, wrapFastify(fastify, false))
169
-
170
- wrapped.fastify = wrapped
171
- wrapped.default = wrapped
152
+ function publishError (error, resource) {
153
+ resource.runInAsyncScope(() => {
154
+ errorChannel.publish(error)
155
+ })
172
156
 
173
- return wrapped
174
- })
157
+ return error
158
+ }
175
159
 
176
- addHook({ name: 'fastify', versions: ['3 - 3.25.1'] }, fastify => {
160
+ addHook({ name: 'fastify', versions: ['>=3'] }, fastify => {
177
161
  const wrapped = shimmer.wrap(fastify, wrapFastify(fastify, true))
178
162
 
179
163
  wrapped.fastify = wrapped
@@ -182,6 +166,10 @@ addHook({ name: 'fastify', versions: ['3 - 3.25.1'] }, fastify => {
182
166
  return wrapped
183
167
  })
184
168
 
185
- addHook({ name: 'fastify', versions: ['1 - 2'] }, fastify => {
169
+ addHook({ name: 'fastify', versions: ['2'] }, fastify => {
186
170
  return shimmer.wrap(fastify, wrapFastify(fastify, true))
187
171
  })
172
+
173
+ addHook({ name: 'fastify', versions: ['1'] }, fastify => {
174
+ return shimmer.wrap(fastify, wrapFastify(fastify, false))
175
+ })