dd-trace 2.7.1 → 2.8.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 (66) hide show
  1. package/LICENSE-3rdparty.csv +1 -2
  2. package/package.json +3 -5
  3. package/packages/datadog-instrumentations/index.js +2 -0
  4. package/packages/datadog-instrumentations/src/amqp10.js +33 -32
  5. package/packages/datadog-instrumentations/src/amqplib.js +16 -11
  6. package/packages/datadog-instrumentations/src/cassandra-driver.js +53 -51
  7. package/packages/datadog-instrumentations/src/connect.js +5 -5
  8. package/packages/datadog-instrumentations/src/couchbase.js +41 -39
  9. package/packages/datadog-instrumentations/src/cucumber.js +38 -38
  10. package/packages/datadog-instrumentations/src/dns.js +20 -19
  11. package/packages/datadog-instrumentations/src/elasticsearch.js +30 -32
  12. package/packages/datadog-instrumentations/src/hapi.js +210 -0
  13. package/packages/datadog-instrumentations/src/http/client.js +44 -44
  14. package/packages/datadog-instrumentations/src/http/server.js +15 -13
  15. package/packages/datadog-instrumentations/src/ioredis.js +16 -17
  16. package/packages/datadog-instrumentations/src/jest.js +5 -5
  17. package/packages/datadog-instrumentations/src/koa.js +8 -8
  18. package/packages/datadog-instrumentations/src/memcached.js +14 -12
  19. package/packages/datadog-instrumentations/src/mocha.js +37 -39
  20. package/packages/datadog-instrumentations/src/moleculer/client.js +46 -0
  21. package/packages/datadog-instrumentations/src/moleculer/server.js +59 -0
  22. package/packages/datadog-instrumentations/src/moleculer.js +4 -0
  23. package/packages/datadog-instrumentations/src/mongodb-core.js +29 -33
  24. package/packages/datadog-instrumentations/src/mysql.js +30 -29
  25. package/packages/datadog-instrumentations/src/mysql2.js +8 -9
  26. package/packages/datadog-instrumentations/src/net.js +23 -24
  27. package/packages/datadog-instrumentations/src/pg.js +30 -30
  28. package/packages/datadog-instrumentations/src/redis.js +49 -47
  29. package/packages/datadog-instrumentations/src/rhea.js +51 -49
  30. package/packages/datadog-instrumentations/src/router.js +5 -5
  31. package/packages/datadog-instrumentations/src/sharedb.js +20 -20
  32. package/packages/datadog-instrumentations/src/tedious.js +19 -19
  33. package/packages/datadog-plugin-amqp10/src/index.js +2 -7
  34. package/packages/datadog-plugin-amqplib/src/index.js +1 -2
  35. package/packages/datadog-plugin-cassandra-driver/src/index.js +1 -5
  36. package/packages/datadog-plugin-couchbase/src/index.js +3 -4
  37. package/packages/datadog-plugin-cucumber/src/index.js +1 -9
  38. package/packages/datadog-plugin-dns/src/index.js +3 -4
  39. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -5
  40. package/packages/datadog-plugin-hapi/src/index.js +34 -3
  41. package/packages/datadog-plugin-http/src/client.js +1 -3
  42. package/packages/datadog-plugin-http/src/server.js +0 -4
  43. package/packages/datadog-plugin-jest/src/index.js +2 -3
  44. package/packages/datadog-plugin-kafkajs/src/index.js +0 -4
  45. package/packages/datadog-plugin-memcached/src/index.js +1 -5
  46. package/packages/datadog-plugin-mocha/src/index.js +3 -7
  47. package/packages/datadog-plugin-moleculer/src/client.js +34 -44
  48. package/packages/datadog-plugin-moleculer/src/index.js +32 -3
  49. package/packages/datadog-plugin-moleculer/src/server.js +28 -50
  50. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -5
  51. package/packages/datadog-plugin-mysql/src/index.js +1 -5
  52. package/packages/datadog-plugin-net/src/index.js +3 -7
  53. package/packages/datadog-plugin-pg/src/index.js +1 -5
  54. package/packages/datadog-plugin-redis/src/index.js +1 -5
  55. package/packages/datadog-plugin-rhea/src/index.js +1 -5
  56. package/packages/datadog-plugin-router/src/index.js +1 -1
  57. package/packages/datadog-plugin-sharedb/src/index.js +1 -5
  58. package/packages/datadog-plugin-tedious/src/index.js +1 -5
  59. package/packages/dd-trace/lib/version.js +1 -1
  60. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +2 -1
  61. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +3 -1
  62. package/packages/dd-trace/src/plugins/plugin.js +0 -8
  63. package/packages/dd-trace/src/plugins/util/test.js +5 -1
  64. package/scripts/install_plugin_modules.js +23 -11
  65. package/packages/datadog-plugin-hapi/src/route.js +0 -75
  66. package/packages/datadog-plugin-hapi/src/server.js +0 -204
@@ -10,8 +10,7 @@ const shimmer = require('../../datadog-shimmer')
10
10
  addHook({ name: 'memcached', versions: ['>=2.2'] }, Memcached => {
11
11
  const startCh = channel('apm:memcached:command:start')
12
12
  const startWithArgsCh = channel('apm:memcached:command:start:with-args')
13
- const asyncEndCh = channel('apm:memcached:command:async-end')
14
- const endCh = channel('apm:memcached:command:end')
13
+ const finishCh = channel('apm:memcached:command:finish')
15
14
  const errorCh = channel('apm:memcached:command:error')
16
15
 
17
16
  shimmer.wrap(Memcached.prototype, 'command', command => function (queryCompiler, server) {
@@ -19,34 +18,37 @@ addHook({ name: 'memcached', versions: ['>=2.2'] }, Memcached => {
19
18
  return command.apply(this, arguments)
20
19
  }
21
20
 
21
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
22
22
  const asyncResource = new AsyncResource('bound-anonymous-fn')
23
23
 
24
24
  const client = this
25
25
 
26
- const wrappedQueryCompiler = function () {
26
+ const wrappedQueryCompiler = asyncResource.bind(function () {
27
27
  const query = queryCompiler.apply(this, arguments)
28
- const callback = asyncResource.bind(query.callback)
28
+ const callback = callbackResource.bind(query.callback)
29
29
 
30
- query.callback = AsyncResource.bind(function (err) {
30
+ query.callback = asyncResource.bind(function (err) {
31
31
  if (err) {
32
32
  errorCh.publish(err)
33
33
  }
34
- asyncEndCh.publish(undefined)
34
+ finishCh.publish()
35
35
 
36
36
  return callback.apply(this, arguments)
37
37
  })
38
38
  startWithArgsCh.publish({ client, server, query })
39
39
 
40
40
  return query
41
- }
41
+ })
42
+
43
+ return asyncResource.runInAsyncScope(() => {
44
+ startCh.publish()
42
45
 
43
- startCh.publish(undefined)
46
+ arguments[0] = wrappedQueryCompiler
44
47
 
45
- arguments[0] = wrappedQueryCompiler
48
+ const result = command.apply(this, arguments)
46
49
 
47
- const result = command.apply(this, arguments)
48
- endCh.publish(undefined)
49
- return result
50
+ return result
51
+ })
50
52
  })
51
53
 
52
54
  return Memcached
@@ -4,12 +4,11 @@ const shimmer = require('../../datadog-shimmer')
4
4
  const testStartCh = channel('ci:mocha:test:start')
5
5
  const errorCh = channel('ci:mocha:test:error')
6
6
  const skipCh = channel('ci:mocha:test:skip')
7
- const testEndCh = channel('ci:mocha:test:end')
8
- const testAsyncEndCh = channel('ci:mocha:test:async-end')
9
- const suiteEndCh = channel('ci:mocha:suite:end')
7
+ const testFinishCh = channel('ci:mocha:test:finish')
8
+ const suiteFinishCh = channel('ci:mocha:suite:finish')
10
9
  const hookErrorCh = channel('ci:mocha:hook:error')
11
10
  const parameterizedTestCh = channel('ci:mocha:test:parameterize')
12
- const testRunEndCh = channel('ci:mocha:run:end')
11
+ const testRunFinishCh = channel('ci:mocha:run:finish')
13
12
 
14
13
  // TODO: remove when root hooks and fixtures are implemented
15
14
  const patched = new WeakSet()
@@ -38,59 +37,58 @@ function mochaHook (Runner) {
38
37
  patched.add(Runner)
39
38
 
40
39
  shimmer.wrap(Runner.prototype, 'runTest', runTest => function () {
41
- if (!testStartCh.hasSubscribers) {
40
+ if (!testStartCh.hasSubscribers || isRetry(this.test)) {
42
41
  return runTest.apply(this, arguments)
43
42
  }
44
43
 
45
- if (!isRetry(this.test)) {
44
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
45
+ return asyncResource.runInAsyncScope(() => {
46
46
  testStartCh.publish(this.test)
47
- }
48
-
49
- this.once('test end', AsyncResource.bind(() => {
50
- let status
51
47
 
52
- if (this.test.pending) {
53
- status = 'skipped'
54
- } else if (this.test.state !== 'failed' && !this.test.timedOut) {
55
- status = 'pass'
56
- } else {
57
- status = 'fail'
48
+ this.once('test end', AsyncResource.bind(() => {
49
+ let status
50
+
51
+ if (this.test.pending) {
52
+ status = 'skipped'
53
+ } else if (this.test.state !== 'failed' && !this.test.timedOut) {
54
+ status = 'pass'
55
+ } else {
56
+ status = 'fail'
57
+ }
58
+
59
+ testFinishCh.publish(status)
60
+ }))
61
+
62
+ this.once('fail', AsyncResource.bind((test, err) => {
63
+ errorCh.publish(err)
64
+ }))
65
+
66
+ this.once('pending', AsyncResource.bind((test) => {
67
+ skipCh.publish(test)
68
+ }))
69
+
70
+ try {
71
+ return runTest.apply(this, arguments)
72
+ } catch (err) {
73
+ errorCh.publish(err)
74
+ throw err
58
75
  }
59
-
60
- testAsyncEndCh.publish(status)
61
- }))
62
-
63
- this.once('fail', AsyncResource.bind((test, err) => {
64
- errorCh.publish(err)
65
- }))
66
-
67
- this.once('pending', AsyncResource.bind((test) => {
68
- skipCh.publish(test)
69
- }))
70
-
71
- try {
72
- return runTest.apply(this, arguments)
73
- } catch (err) {
74
- errorCh.publish(err)
75
- throw err
76
- } finally {
77
- testEndCh.publish(undefined)
78
- }
76
+ })
79
77
  })
80
78
 
81
79
  shimmer.wrap(Runner.prototype, 'runTests', runTests => function () {
82
- if (!suiteEndCh.hasSubscribers) {
80
+ if (!suiteFinishCh.hasSubscribers) {
83
81
  return runTests.apply(this, arguments)
84
82
  }
85
83
  this.once('end', AsyncResource.bind(() => {
86
- testRunEndCh.publish(undefined)
84
+ testRunFinishCh.publish()
87
85
  }))
88
86
  runTests.apply(this, arguments)
89
87
  const suite = arguments[0]
90
88
  // We call `getAllTestsInSuite` with the root suite so every skipped test
91
89
  // should already have an associated test span.
92
90
  const tests = getAllTestsInSuite(suite)
93
- suiteEndCh.publish(tests)
91
+ suiteFinishCh.publish(tests)
94
92
  })
95
93
 
96
94
  shimmer.wrap(Runner.prototype, 'fail', fail => function (hook, error) {
@@ -0,0 +1,46 @@
1
+ 'use strict'
2
+
3
+ const { channel, addHook, AsyncResource } = require('../helpers/instrument')
4
+ const shimmer = require('../../../datadog-shimmer')
5
+
6
+ const startChannel = channel('apm:moleculer:call:start')
7
+ const finishChannel = channel('apm:moleculer:call:finish')
8
+ const errorChannel = channel('apm:moleculer:call:error')
9
+
10
+ function wrapCall (call) {
11
+ return function (actionName, params, opts) {
12
+ const callResource = new AsyncResource('bound-anonymous-fn')
13
+
14
+ opts = arguments[2] = opts || {}
15
+ opts.meta = opts.meta || {}
16
+
17
+ arguments.length = Math.max(3, arguments.length)
18
+
19
+ return callResource.runInAsyncScope(() => {
20
+ startChannel.publish({ actionName, params, opts })
21
+
22
+ const promise = call.apply(this, arguments)
23
+ const broker = this
24
+ const ctx = promise.ctx
25
+
26
+ return promise
27
+ .then(
28
+ result => {
29
+ finishChannel.publish({ broker, ctx })
30
+ return result
31
+ },
32
+ error => {
33
+ errorChannel.publish(error)
34
+ finishChannel.publish({ broker, ctx })
35
+ throw error
36
+ }
37
+ )
38
+ })
39
+ }
40
+ }
41
+
42
+ addHook({ name: 'moleculer', versions: ['>=0.14'] }, moleculer => {
43
+ shimmer.wrap(moleculer.ServiceBroker.prototype, 'call', wrapCall)
44
+
45
+ return moleculer
46
+ })
@@ -0,0 +1,59 @@
1
+ 'use strict'
2
+
3
+ const { channel, addHook, AsyncResource } = require('../helpers/instrument')
4
+ const shimmer = require('../../../datadog-shimmer')
5
+
6
+ const startChannel = channel('apm:moleculer:action:start')
7
+ const finishChannel = channel('apm:moleculer:action:finish')
8
+ const errorChannel = channel('apm:moleculer:action:error')
9
+
10
+ function wrapRegisterMiddlewares (registerMiddlewares) {
11
+ return function (userMiddlewares) {
12
+ if (this.middlewares && this.middlewares.add) {
13
+ this.middlewares.add(createMiddleware())
14
+ }
15
+
16
+ return registerMiddlewares.apply(this, arguments)
17
+ }
18
+ }
19
+
20
+ function createMiddleware () {
21
+ return {
22
+ name: 'Datadog',
23
+
24
+ localAction (next, action) {
25
+ const broker = this
26
+
27
+ return function datadogMiddleware (ctx) {
28
+ const actionResource = new AsyncResource('bound-anonymous-fn')
29
+
30
+ return actionResource.runInAsyncScope(() => {
31
+ startChannel.publish({ action, ctx, broker })
32
+
33
+ try {
34
+ return next(ctx).then(
35
+ result => {
36
+ finishChannel.publish()
37
+ return result
38
+ },
39
+ error => {
40
+ errorChannel.publish(error)
41
+ finishChannel.publish()
42
+ throw error
43
+ }
44
+ )
45
+ } catch (e) {
46
+ errorChannel.publish(e)
47
+ finishChannel.publish()
48
+ }
49
+ })
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ addHook({ name: 'moleculer', versions: ['>=0.14'] }, moleculer => {
56
+ shimmer.wrap(moleculer.ServiceBroker.prototype, 'registerMiddlewares', wrapRegisterMiddlewares)
57
+
58
+ return moleculer
59
+ })
@@ -0,0 +1,4 @@
1
+ 'use strict'
2
+
3
+ require('./moleculer/client')
4
+ require('./moleculer/server')
@@ -8,8 +8,7 @@ const {
8
8
  const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  const startCh = channel(`apm:mongodb:query:start`)
11
- const endCh = channel(`apm:mongodb:query:end`)
12
- const asyncEndCh = channel(`apm:mongodb:query:async-end`)
11
+ const finishCh = channel(`apm:mongodb:query:finish`)
13
12
  const errorCh = channel(`apm:mongodb:query:error`)
14
13
 
15
14
  addHook({ name: 'mongodb-core', versions: ['2 - 3.1.9'] }, Server => {
@@ -79,8 +78,7 @@ function wrapUnifiedCommand (command, operation, name) {
79
78
  if (!startCh.hasSubscribers) {
80
79
  return command.apply(this, arguments)
81
80
  }
82
- const asyncResource = new AsyncResource('bound-anonymous-fn')
83
- return instrument(asyncResource, operation, command, this, arguments, server, ns, ops, { name })
81
+ return instrument(operation, command, this, arguments, server, ns, ops, { name })
84
82
  }
85
83
  return shimmer.wrap(command, wrapped)
86
84
  }
@@ -90,7 +88,6 @@ function wrapConnectionCommand (command, operation, name) {
90
88
  if (!startCh.hasSubscribers) {
91
89
  return command.apply(this, arguments)
92
90
  }
93
- const asyncResource = new AsyncResource('bound-anonymous-fn')
94
91
  const hostParts = typeof this.address === 'string' ? this.address.split(':') : ''
95
92
  const options = hostParts.length === 2
96
93
  ? { host: hostParts[0], port: hostParts[1] }
@@ -98,7 +95,7 @@ function wrapConnectionCommand (command, operation, name) {
98
95
  const topology = { s: { options } }
99
96
 
100
97
  ns = `${ns.db}.${ns.collection}`
101
- return instrument(asyncResource, operation, command, this, arguments, topology, ns, ops, { name })
98
+ return instrument(operation, command, this, arguments, topology, ns, ops, { name })
102
99
  }
103
100
  return shimmer.wrap(command, wrapped)
104
101
  }
@@ -108,11 +105,10 @@ function wrapQuery (query, operation, name) {
108
105
  if (!startCh.hasSubscribers) {
109
106
  return query.apply(this, arguments)
110
107
  }
111
- const asyncResource = new AsyncResource('bound-anonymous-fn')
112
108
  const pool = this.server.s.pool
113
109
  const ns = this.ns
114
110
  const ops = this.cmd
115
- return instrument(asyncResource, operation, query, this, arguments, pool, ns, ops)
111
+ return instrument(operation, query, this, arguments, pool, ns, ops)
116
112
  }
117
113
 
118
114
  return shimmer.wrap(query, wrapped)
@@ -123,10 +119,9 @@ function wrapCursor (cursor, operation, name) {
123
119
  if (!startCh.hasSubscribers) {
124
120
  return cursor.apply(this, arguments)
125
121
  }
126
- const asyncResource = new AsyncResource('bound-anonymous-fn')
127
122
  const pool = this.server.s.pool
128
123
  const ns = this.ns
129
- return instrument(asyncResource, operation, cursor, this, arguments, pool, ns, {}, { name })
124
+ return instrument(operation, cursor, this, arguments, pool, ns, {}, { name })
130
125
  }
131
126
  return shimmer.wrap(cursor, wrapped)
132
127
  }
@@ -136,44 +131,45 @@ function wrapCommand (command, operation, name) {
136
131
  if (!startCh.hasSubscribers) {
137
132
  return command.apply(this, arguments)
138
133
  }
139
- const asyncResource = new AsyncResource('bound-anonymous-fn')
140
- return instrument(asyncResource, operation, command, this, arguments, this, ns, ops, { name })
134
+ return instrument(operation, command, this, arguments, this, ns, ops, { name })
141
135
  }
142
136
  return shimmer.wrap(command, wrapped)
143
137
  }
144
138
 
145
- function instrument (ar, operation, command, ctx, args, server, ns, ops, options = {}) {
139
+ function instrument (operation, command, ctx, args, server, ns, ops, options = {}) {
146
140
  const name = options.name || (ops && Object.keys(ops)[0])
147
141
  const index = args.length - 1
148
142
  let callback = args[index]
149
143
 
150
144
  if (typeof callback !== 'function') return command.apply(ctx, args)
151
145
 
152
- callback = ar.bind(callback)
153
-
154
146
  const serverInfo = server && server.s && server.s.options
147
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
148
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
155
149
 
156
- startCh.publish({ ns, ops, options: serverInfo, name })
150
+ callback = callbackResource.bind(callback)
157
151
 
158
- args[index] = AsyncResource.bind(function (err, res) {
159
- if (err) {
160
- errorCh.publish(err)
161
- }
152
+ return asyncResource.runInAsyncScope(() => {
153
+ startCh.publish({ ns, ops, options: serverInfo, name })
162
154
 
163
- asyncEndCh.publish(undefined)
155
+ args[index] = asyncResource.bind(function (err, res) {
156
+ if (err) {
157
+ errorCh.publish(err)
158
+ }
164
159
 
165
- if (callback) {
166
- return callback.apply(this, arguments)
167
- }
168
- })
160
+ finishCh.publish()
169
161
 
170
- try {
171
- return command.apply(ctx, args)
172
- } catch (err) {
173
- errorCh.publish(err)
162
+ if (callback) {
163
+ return callback.apply(this, arguments)
164
+ }
165
+ })
174
166
 
175
- throw err
176
- } finally {
177
- endCh.publish(undefined)
178
- }
167
+ try {
168
+ return command.apply(ctx, args)
169
+ } catch (err) {
170
+ errorCh.publish(err)
171
+
172
+ throw err
173
+ }
174
+ })
179
175
  }
@@ -9,12 +9,10 @@ const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connection => {
11
11
  const startCh = channel('apm:mysql:query:start')
12
- const asyncEndCh = channel('apm:mysql:query:async-end')
13
- const endCh = channel('apm:mysql:query:end')
12
+ const finishCh = channel('apm:mysql:query:finish')
14
13
  const errorCh = channel('apm:mysql:query:error')
15
14
 
16
15
  shimmer.wrap(Connection.prototype, 'query', query => function () {
17
- const asyncResource = new AsyncResource('bound-anonymous-fn')
18
16
  if (!startCh.hasSubscribers) {
19
17
  return query.apply(this, arguments)
20
18
  }
@@ -22,37 +20,40 @@ addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connect
22
20
  const sql = arguments[0].sql ? arguments[0].sql : arguments[0]
23
21
  const conf = this.config
24
22
 
25
- startCh.publish({ sql, conf })
23
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
24
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
26
25
 
27
- try {
28
- const res = query.apply(this, arguments)
26
+ return asyncResource.runInAsyncScope(() => {
27
+ startCh.publish({ sql, conf })
29
28
 
30
- if (res._callback) {
31
- const cb = asyncResource.bind(res._callback)
32
- res._callback = AsyncResource.bind(function (error, result) {
33
- if (error) {
34
- errorCh.publish(error)
35
- }
36
- asyncEndCh.publish(result)
29
+ try {
30
+ const res = query.apply(this, arguments)
37
31
 
38
- return cb.apply(this, arguments)
39
- })
40
- } else {
41
- const cb = AsyncResource.bind(function () {
42
- asyncEndCh.publish(undefined)
43
- })
44
- res.on('end', cb)
45
- }
32
+ if (res._callback) {
33
+ const cb = callbackResource.bind(res._callback)
34
+ res._callback = asyncResource.bind(function (error, result) {
35
+ if (error) {
36
+ errorCh.publish(error)
37
+ }
38
+ finishCh.publish(result)
46
39
 
47
- return res
48
- } catch (err) {
49
- err.stack // trigger getting the stack at the original throwing point
50
- errorCh.publish(err)
40
+ return cb.apply(this, arguments)
41
+ })
42
+ } else {
43
+ const cb = asyncResource.bind(function () {
44
+ finishCh.publish(undefined)
45
+ })
46
+ res.on('end', cb)
47
+ }
51
48
 
52
- throw err
53
- } finally {
54
- endCh.publish(undefined)
55
- }
49
+ return res
50
+ } catch (err) {
51
+ err.stack // trigger getting the stack at the original throwing point
52
+ errorCh.publish(err)
53
+
54
+ throw err
55
+ }
56
+ })
56
57
  })
57
58
 
58
59
  return Connection
@@ -9,8 +9,7 @@ const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connection => {
11
11
  const startCh = channel('apm:mysql2:query:start')
12
- const asyncEndCh = channel('apm:mysql2:query:async-end')
13
- const endCh = channel('apm:mysql2:query:end')
12
+ const finishCh = channel('apm:mysql2:query:finish')
14
13
  const errorCh = channel('apm:mysql2:query:error')
15
14
 
16
15
  shimmer.wrap(Connection.prototype, 'addCommand', addCommand => function (cmd) {
@@ -42,24 +41,26 @@ addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connec
42
41
  }
43
42
 
44
43
  function wrapExecute (cmd, execute, asyncResource, config) {
44
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
45
+
45
46
  return asyncResource.bind(function executeWithTrace (packet, connection) {
46
47
  const sql = cmd.statement ? cmd.statement.query : cmd.sql
47
48
 
48
49
  startCh.publish({ sql, conf: config })
49
50
 
50
51
  if (this.onResult) {
51
- const onResult = asyncResource.bind(this.onResult)
52
+ const onResult = callbackResource.bind(this.onResult)
52
53
 
53
- this.onResult = AsyncResource.bind(function (error) {
54
+ this.onResult = asyncResource.bind(function (error) {
54
55
  if (error) {
55
56
  errorCh.publish(error)
56
57
  }
57
- asyncEndCh.publish(undefined)
58
+ finishCh.publish(undefined)
58
59
  onResult.apply(this, arguments)
59
60
  }, 'bound-anonymous-fn', this)
60
61
  } else {
61
- this.on('error', AsyncResource.bind(error => errorCh.publish(error)))
62
- this.on('end', AsyncResource.bind(() => asyncEndCh.publish(undefined)))
62
+ this.on('error', asyncResource.bind(error => errorCh.publish(error)))
63
+ this.on('end', asyncResource.bind(() => finishCh.publish(undefined)))
63
64
  }
64
65
 
65
66
  this.execute = execute
@@ -68,8 +69,6 @@ addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connec
68
69
  return execute.apply(this, arguments)
69
70
  } catch (err) {
70
71
  errorCh.publish(err)
71
- } finally {
72
- endCh.publish(undefined)
73
72
  }
74
73
  }, cmd)
75
74
  }
@@ -8,13 +8,11 @@ const {
8
8
  const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  const startICPCh = channel('apm:net:ipc:start')
11
- const asyncICPEndCh = channel('apm:net:ipc:async-end')
12
- const endICPCh = channel('apm:net:ipc:end')
11
+ const finishICPCh = channel('apm:net:ipc:finish')
13
12
  const errorICPCh = channel('apm:net:ipc:error')
14
13
 
15
14
  const startTCPCh = channel('apm:net:tcp:start')
16
- const asyncTCPEndCh = channel('apm:net:tcp:async-end')
17
- const endTCPCh = channel('apm:net:tcp:end')
15
+ const finishTCPCh = channel('apm:net:tcp:finish')
18
16
  const errorTCPCh = channel('apm:net:tcp:error')
19
17
 
20
18
  const connectionCh = channel(`apm:net:tcp:connection`)
@@ -33,31 +31,32 @@ addHook({ name: 'net' }, net => {
33
31
 
34
32
  if (!options) return connect.apply(this, arguments)
35
33
 
34
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
36
35
  const asyncResource = new AsyncResource('bound-anonymous-fn')
37
36
 
38
37
  if (typeof callback === 'function') {
39
- arguments[lastIndex] = asyncResource.bind(callback)
38
+ arguments[lastIndex] = callbackResource.bind(callback)
40
39
  }
41
40
 
42
41
  const protocol = options.path ? 'ipc' : 'tcp'
43
42
 
44
- if (protocol === 'ipc') {
45
- startICPCh.publish({ options })
46
- setupListeners(this, 'ipc', asyncResource)
47
- } else {
48
- startTCPCh.publish({ options })
49
- setupListeners(this, 'tcp', asyncResource)
50
- }
43
+ return asyncResource.runInAsyncScope(() => {
44
+ if (protocol === 'ipc') {
45
+ startICPCh.publish({ options })
46
+ setupListeners(this, 'ipc', asyncResource)
47
+ } else {
48
+ startTCPCh.publish({ options })
49
+ setupListeners(this, 'tcp', asyncResource)
50
+ }
51
51
 
52
- try {
53
- return connect.apply(this, arguments)
54
- } catch (err) {
55
- protocol === 'ipc' ? errorICPCh.publish(err) : errorTCPCh.publish(err)
52
+ try {
53
+ return connect.apply(this, arguments)
54
+ } catch (err) {
55
+ protocol === 'ipc' ? errorICPCh.publish(err) : errorTCPCh.publish(err)
56
56
 
57
- throw err
58
- } finally {
59
- protocol === 'ipc' ? endICPCh.publish(undefined) : endTCPCh.publish(undefined)
60
- }
57
+ throw err
58
+ }
59
+ })
61
60
  })
62
61
 
63
62
  return net
@@ -84,17 +83,17 @@ function getOptions (args) {
84
83
  }
85
84
  }
86
85
 
87
- function setupListeners (socket, protocol, ar) {
86
+ function setupListeners (socket, protocol, asyncResource) {
88
87
  const events = ['connect', 'error', 'close', 'timeout']
89
88
 
90
- const wrapListener = AsyncResource.bind(function (error) {
89
+ const wrapListener = asyncResource.bind(function (error) {
91
90
  if (error) {
92
91
  protocol === 'ipc' ? errorICPCh.publish(error) : errorTCPCh.publish(error)
93
92
  }
94
- protocol === 'ipc' ? asyncICPEndCh.publish(undefined) : asyncTCPEndCh.publish(undefined)
93
+ protocol === 'ipc' ? finishICPCh.publish(undefined) : finishTCPCh.publish(undefined)
95
94
  })
96
95
 
97
- const localListener = AsyncResource.bind(function () {
96
+ const localListener = asyncResource.bind(function () {
98
97
  connectionCh.publish({ socket })
99
98
  })
100
99