dd-trace 2.9.1 → 2.12.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 (59) hide show
  1. package/LICENSE-3rdparty.csv +0 -1
  2. package/index.d.ts +3 -3
  3. package/package.json +7 -8
  4. package/packages/datadog-core/src/storage/async_hooks.js +4 -4
  5. package/packages/datadog-core/src/storage/async_resource.js +14 -4
  6. package/packages/datadog-instrumentations/index.js +5 -0
  7. package/packages/datadog-instrumentations/src/connect.js +3 -0
  8. package/packages/datadog-instrumentations/src/couchbase.js +166 -61
  9. package/packages/datadog-instrumentations/src/fastify.js +5 -3
  10. package/packages/datadog-instrumentations/src/graphql.js +366 -0
  11. package/packages/datadog-instrumentations/src/grpc/client.js +250 -0
  12. package/packages/datadog-instrumentations/src/grpc/server.js +144 -0
  13. package/packages/{datadog-plugin-grpc/src/kinds.js → datadog-instrumentations/src/grpc/types.js} +0 -0
  14. package/packages/datadog-instrumentations/src/grpc.js +4 -0
  15. package/packages/datadog-instrumentations/src/http/client.js +1 -1
  16. package/packages/datadog-instrumentations/src/http2/client.js +67 -0
  17. package/packages/datadog-instrumentations/src/http2/server.js +3 -0
  18. package/packages/datadog-instrumentations/src/http2.js +4 -0
  19. package/packages/datadog-instrumentations/src/jest.js +14 -14
  20. package/packages/datadog-instrumentations/src/koa.js +12 -3
  21. package/packages/datadog-instrumentations/src/microgateway-core.js +66 -0
  22. package/packages/datadog-instrumentations/src/mocha.js +198 -62
  23. package/packages/datadog-instrumentations/src/next.js +140 -0
  24. package/packages/datadog-instrumentations/src/restify.js +4 -8
  25. package/packages/datadog-instrumentations/src/router.js +3 -0
  26. package/packages/datadog-instrumentations/src/tedious.js +1 -1
  27. package/packages/datadog-plugin-couchbase/src/index.js +8 -10
  28. package/packages/datadog-plugin-graphql/src/index.js +123 -412
  29. package/packages/datadog-plugin-graphql/src/resolve.js +122 -0
  30. package/packages/datadog-plugin-grpc/src/client.js +54 -283
  31. package/packages/datadog-plugin-grpc/src/index.js +31 -3
  32. package/packages/datadog-plugin-grpc/src/server.js +50 -145
  33. package/packages/datadog-plugin-http/src/client.js +10 -7
  34. package/packages/datadog-plugin-http/src/server.js +3 -8
  35. package/packages/datadog-plugin-http2/src/client.js +72 -120
  36. package/packages/datadog-plugin-http2/src/index.js +32 -3
  37. package/packages/datadog-plugin-http2/src/server.js +6 -214
  38. package/packages/datadog-plugin-jest/src/util.js +13 -1
  39. package/packages/datadog-plugin-microgateway-core/src/index.js +14 -145
  40. package/packages/datadog-plugin-mocha/src/index.js +88 -39
  41. package/packages/datadog-plugin-next/src/index.js +56 -168
  42. package/packages/datadog-plugin-router/src/index.js +41 -13
  43. package/packages/dd-trace/src/config.js +3 -2
  44. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +111 -15
  45. package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
  46. package/packages/dd-trace/src/opentracing/span.js +6 -3
  47. package/packages/dd-trace/src/plugin_manager.js +59 -22
  48. package/packages/dd-trace/src/plugins/plugin.js +3 -1
  49. package/packages/dd-trace/src/plugins/util/test.js +35 -1
  50. package/packages/dd-trace/src/plugins/util/web.js +22 -24
  51. package/packages/dd-trace/src/profiling/config.js +10 -2
  52. package/packages/dd-trace/src/profiling/exporters/agent.js +2 -3
  53. package/packages/dd-trace/src/profiling/exporters/form-data.js +53 -0
  54. package/packages/dd-trace/src/profiling/index.js +2 -0
  55. package/packages/dd-trace/src/profiling/profiler.js +6 -1
  56. package/packages/dd-trace/src/profiling/profilers/cpu.js +126 -0
  57. package/packages/dd-trace/src/startup-log.js +1 -1
  58. package/packages/dd-trace/src/telemetry.js +1 -1
  59. package/packages/dd-trace/lib/version.js +0 -1
@@ -6,7 +6,6 @@ require,@datadog/sketches-js,Apache license 2.0,Copyright 2020 Datadog Inc.
6
6
  require,@types/node,MIT,Copyright Authors
7
7
  require,crypto-randomuuid,MIT,Copyright 2021 Node.js Foundation and contributors
8
8
  require,diagnostics_channel,MIT,Copyright 2021 Simon D.
9
- require,form-data,MIT,Copyright 2012 Felix Geisendörfer and contributors
10
9
  require,ignore,MIT,Copyright 2013 Kael Zhang and contributors
11
10
  require,import-in-the-middle,Apache license 2.0,Copyright 2021 Datadog Inc.
12
11
  require,koalas,MIT,Copyright 2013-2017 Brian Woodward
package/index.d.ts CHANGED
@@ -313,10 +313,10 @@ export declare interface TracerOptions {
313
313
  };
314
314
 
315
315
  /**
316
- * Experimental features can be enabled all at once by using true or individually using key / value pairs.
316
+ * Experimental features can be enabled individually using key / value pairs.
317
317
  * @default {}
318
318
  */
319
- experimental?: boolean | {
319
+ experimental?: {
320
320
  b3?: boolean
321
321
  traceparent?: boolean
322
322
 
@@ -1216,7 +1216,7 @@ declare namespace plugins {
1216
1216
 
1217
1217
  /**
1218
1218
  * This plugin automatically instruments the
1219
- * [mysql2](https://github.com/brianmario/mysql2) module.
1219
+ * [mysql2](https://github.com/sidorares/node-mysql2) module.
1220
1220
  */
1221
1221
  interface mysql2 extends mysql {}
1222
1222
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "2.9.1",
3
+ "version": "2.12.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -58,16 +58,15 @@
58
58
  "node": ">=12"
59
59
  },
60
60
  "dependencies": {
61
- "@datadog/native-appsec": "^1.2.0",
62
- "@datadog/native-metrics": "^1.2.0",
63
- "@datadog/pprof": "^0.4.0",
64
- "@datadog/sketches-js": "^1.0.4",
61
+ "@datadog/native-appsec": "^1.2.1",
62
+ "@datadog/native-metrics": "^1.4.1",
63
+ "@datadog/pprof": "^1.0.0",
64
+ "@datadog/sketches-js": "^1.0.5",
65
65
  "@types/node": ">=12",
66
66
  "crypto-randomuuid": "^1.0.0",
67
67
  "diagnostics_channel": "^1.1.0",
68
- "form-data": "^3.0.0",
69
68
  "ignore": "^5.2.0",
70
- "import-in-the-middle": "^1.2.1",
69
+ "import-in-the-middle": "^1.3.0",
71
70
  "koalas": "^1.0.2",
72
71
  "limiter": "^1.1.4",
73
72
  "lodash.kebabcase": "^4.1.1",
@@ -106,8 +105,8 @@
106
105
  "jszip": "^3.5.0",
107
106
  "mkdirp": "^0.5.1",
108
107
  "mocha": "8",
109
- "multer": "^1.4.2",
110
108
  "msgpack-lite": "^0.1.26",
109
+ "multer": "^1.4.5-lts.1",
111
110
  "nock": "^11.3.3",
112
111
  "nyc": "^15.1.0",
113
112
  "proxyquire": "^1.8.0",
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { createHook, executionAsyncId } = require('async_hooks')
3
+ const { executionAsyncId } = require('async_hooks')
4
4
  const AsyncResourceStorage = require('./async_resource')
5
5
 
6
6
  class AsyncHooksStorage extends AsyncResourceStorage {
@@ -17,10 +17,10 @@ class AsyncHooksStorage extends AsyncResourceStorage {
17
17
  }
18
18
 
19
19
  _createHook () {
20
- return createHook({
21
- init: this._init.bind(this),
20
+ return {
21
+ ...super._createHook(),
22
22
  destroy: this._destroy.bind(this)
23
- })
23
+ }
24
24
  }
25
25
 
26
26
  _init (asyncId, type, triggerAsyncId, resource) {
@@ -1,12 +1,16 @@
1
1
  'use strict'
2
2
 
3
3
  const { createHook, executionAsyncResource } = require('async_hooks')
4
+ const { channel } = require('diagnostics_channel')
5
+
6
+ const beforeCh = channel('dd-trace:storage:before')
7
+ const afterCh = channel('dd-trace:storage:after')
4
8
 
5
9
  class AsyncResourceStorage {
6
10
  constructor () {
7
11
  this._ddResourceStore = Symbol('ddResourceStore')
8
12
  this._enabled = false
9
- this._hook = this._createHook()
13
+ this._hook = createHook(this._createHook())
10
14
  }
11
15
 
12
16
  disable () {
@@ -48,9 +52,15 @@ class AsyncResourceStorage {
48
52
  }
49
53
 
50
54
  _createHook () {
51
- return createHook({
52
- init: this._init.bind(this)
53
- })
55
+ return {
56
+ init: this._init.bind(this),
57
+ before () {
58
+ beforeCh.publish()
59
+ },
60
+ after () {
61
+ afterCh.publish()
62
+ }
63
+ }
54
64
  }
55
65
 
56
66
  _enable () {
@@ -16,14 +16,18 @@ require('./src/fastify')
16
16
  require('./src/find-my-way')
17
17
  require('./src/generic-pool')
18
18
  require('./src/google-cloud-pubsub')
19
+ require('./src/graphql')
20
+ require('./src/grpc')
19
21
  require('./src/hapi')
20
22
  require('./src/http')
23
+ require('./src/http2')
21
24
  require('./src/ioredis')
22
25
  require('./src/jest')
23
26
  require('./src/kafkajs')
24
27
  require('./src/knex')
25
28
  require('./src/koa')
26
29
  require('./src/memcached')
30
+ require('./src/microgateway-core')
27
31
  require('./src/moleculer')
28
32
  require('./src/mongodb-core')
29
33
  require('./src/mongoose')
@@ -31,6 +35,7 @@ require('./src/mysql')
31
35
  require('./src/mysql2')
32
36
  require('./src/mocha')
33
37
  require('./src/net')
38
+ require('./src/next')
34
39
  require('./src/oracledb')
35
40
  require('./src/paperplane')
36
41
  require('./src/pino')
@@ -4,6 +4,7 @@ const shimmer = require('../../datadog-shimmer')
4
4
  const { addHook, channel, AsyncResource } = require('./helpers/instrument')
5
5
 
6
6
  const enterChannel = channel('apm:connect:middleware:enter')
7
+ const exitChannel = channel('apm:connect:middleware:exit')
7
8
  const errorChannel = channel('apm:connect:middleware:error')
8
9
  const nextChannel = channel('apm:connect:middleware:next')
9
10
  const handleChannel = channel('apm:connect:request:handle')
@@ -80,6 +81,7 @@ function wrapLayerHandle (layer) {
80
81
  } catch (e) {
81
82
  errorChannel.publish(e)
82
83
  nextChannel.publish({ req })
84
+ exitChannel.publish({ req })
83
85
 
84
86
  throw e
85
87
  }
@@ -94,6 +96,7 @@ function wrapNext (req, next) {
94
96
  }
95
97
 
96
98
  nextChannel.publish({ req })
99
+ exitChannel.publish({ req })
97
100
 
98
101
  next.apply(null, arguments)
99
102
  }
@@ -7,70 +7,23 @@ const {
7
7
  } = require('./helpers/instrument')
8
8
  const shimmer = require('../../datadog-shimmer')
9
9
 
10
- addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.5'] }, Bucket => {
11
- const startCh = channel('apm:couchbase:query:start')
12
- const finishCh = channel('apm:couchbase:query:finish')
13
- const errorCh = channel('apm:couchbase:query:error')
14
-
15
- Bucket.prototype._maybeInvoke = wrapMaybeInvoke(Bucket.prototype._maybeInvoke)
16
- Bucket.prototype.query = wrapQuery(Bucket.prototype.query)
17
-
18
- shimmer.wrap(Bucket.prototype, '_n1qlReq', _n1qlReq => function (host, q, adhoc, emitter) {
19
- if (!startCh.hasSubscribers) {
20
- return _n1qlReq.apply(this, arguments)
21
- }
22
-
23
- if (!emitter || !emitter.once) return _n1qlReq.apply(this, arguments)
24
-
25
- const n1qlQuery = q && q.statement
26
-
27
- const asyncResource = new AsyncResource('bound-anonymous-fn')
28
- return asyncResource.runInAsyncScope(() => {
29
- startCh.publish({ resource: n1qlQuery, bucket: this })
30
-
31
- emitter.once('rows', asyncResource.bind(() => {
32
- finishCh.publish(undefined)
33
- }))
34
-
35
- emitter.once('error', asyncResource.bind((error) => {
36
- errorCh.publish(error)
37
- finishCh.publish(undefined)
38
- }))
39
-
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)
45
-
46
- throw err
47
- }
48
- })
49
- })
50
-
51
- Bucket.prototype.upsert = wrap('apm:couchbase:upsert', Bucket.prototype.upsert)
52
- Bucket.prototype.insert = wrap('apm:couchbase:insert', Bucket.prototype.insert)
53
- Bucket.prototype.replace = wrap('apm:couchbase:replace', Bucket.prototype.replace)
54
- Bucket.prototype.append = wrap('apm:couchbase:append', Bucket.prototype.append)
55
- Bucket.prototype.prepend = wrap('apm:couchbase:prepend', Bucket.prototype.prepend)
56
-
57
- return Bucket
58
- })
59
-
60
- addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.5'] }, Cluster => {
61
- Cluster.prototype._maybeInvoke = wrapMaybeInvoke(Cluster.prototype._maybeInvoke)
62
- Cluster.prototype.query = wrapQuery(Cluster.prototype.query)
63
-
64
- return Cluster
65
- })
66
-
67
- function findCallbackIndex (args) {
68
- for (let i = args.length - 1; i >= 2; i--) {
10
+ function findCallbackIndex (args, lowerbound = 2) {
11
+ for (let i = args.length - 1; i >= lowerbound; i--) {
69
12
  if (typeof args[i] === 'function') return i
70
13
  }
71
14
  return -1
72
15
  }
73
16
 
17
+ // handles n1ql and string queries
18
+ function getQueryResource (q) {
19
+ return q && (typeof q === 'string' ? q : q.statement)
20
+ }
21
+
22
+ function wrapAllNames (names, action) {
23
+ names.forEach(name => action(name))
24
+ }
25
+
26
+ // semver >=2 <3
74
27
  function wrapMaybeInvoke (_maybeInvoke) {
75
28
  const wrapped = function (fn, args) {
76
29
  if (!Array.isArray(args)) return _maybeInvoke.apply(this, arguments)
@@ -106,7 +59,7 @@ function wrap (prefix, fn) {
106
59
  const finishCh = channel(prefix + ':finish')
107
60
  const errorCh = channel(prefix + ':error')
108
61
 
109
- const wrapped = function (key, value, options, callback) {
62
+ const wrapped = function () {
110
63
  if (!startCh.hasSubscribers) {
111
64
  return fn.apply(this, arguments)
112
65
  }
@@ -121,7 +74,7 @@ function wrap (prefix, fn) {
121
74
  return asyncResource.runInAsyncScope(() => {
122
75
  const cb = callbackResource.bind(arguments[callbackIndex])
123
76
 
124
- startCh.publish({ bucket: this })
77
+ startCh.publish({ bucket: { name: this.name || this._name } })
125
78
 
126
79
  arguments[callbackIndex] = asyncResource.bind(function (error, result) {
127
80
  if (error) {
@@ -143,3 +96,155 @@ function wrap (prefix, fn) {
143
96
  }
144
97
  return shimmer.wrap(fn, wrapped)
145
98
  }
99
+
100
+ // semver >=3
101
+
102
+ function wrapCBandPromise (fn, name, startData, thisArg, args) {
103
+ const startCh = channel(`apm:couchbase:${name}:start`)
104
+ const finishCh = channel(`apm:couchbase:${name}:finish`)
105
+ const errorCh = channel(`apm:couchbase:${name}:error`)
106
+
107
+ if (!startCh.hasSubscribers) return fn.apply(thisArg, args)
108
+
109
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
110
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
111
+
112
+ return asyncResource.runInAsyncScope(() => {
113
+ startCh.publish(startData)
114
+
115
+ try {
116
+ const cbIndex = findCallbackIndex(args, 1)
117
+ if (cbIndex >= 0) {
118
+ // v3 offers callback or promises event handling
119
+ // NOTE: this does not work with v3.2.0-3.2.1 cluster.query, as there is a bug in the couchbase source code
120
+ const cb = callbackResource.bind(args[cbIndex])
121
+ args[cbIndex] = asyncResource.bind(function (error, result) {
122
+ if (error) {
123
+ errorCh.publish(error)
124
+ }
125
+ finishCh.publish({ result })
126
+ return cb.apply(thisArg, arguments)
127
+ })
128
+ }
129
+ const res = fn.apply(thisArg, args)
130
+
131
+ // semver >=3 will always return promise by default
132
+ res.then(
133
+ asyncResource.bind((result) => finishCh.publish({ result })),
134
+ asyncResource.bind((err) => errorCh.publish(err)))
135
+ return res
136
+ } catch (e) {
137
+ e.stack
138
+ errorCh.publish(e)
139
+ throw e
140
+ }
141
+ })
142
+ }
143
+
144
+ function wrapWithName (name) {
145
+ return function (operation) {
146
+ return function () { // no arguments used by us
147
+ return wrapCBandPromise(operation, name, {
148
+ collection: { name: this._name || '_default' },
149
+ bucket: { name: this._scope._bucket._name }
150
+ }, this, arguments)
151
+ }
152
+ }
153
+ }
154
+
155
+ function wrapV3Query (query) {
156
+ return function (q) {
157
+ const resource = getQueryResource(q)
158
+ return wrapCBandPromise(query, 'query', { resource }, this, arguments)
159
+ }
160
+ }
161
+
162
+ // semver >=2 <3
163
+ addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.5'] }, Bucket => {
164
+ const startCh = channel('apm:couchbase:query:start')
165
+ const finishCh = channel('apm:couchbase:query:finish')
166
+ const errorCh = channel('apm:couchbase:query:error')
167
+
168
+ Bucket.prototype._maybeInvoke = wrapMaybeInvoke(Bucket.prototype._maybeInvoke)
169
+ Bucket.prototype.query = wrapQuery(Bucket.prototype.query)
170
+
171
+ shimmer.wrap(Bucket.prototype, '_n1qlReq', _n1qlReq => function (host, q, adhoc, emitter) {
172
+ if (!startCh.hasSubscribers) {
173
+ return _n1qlReq.apply(this, arguments)
174
+ }
175
+
176
+ if (!emitter || !emitter.once) return _n1qlReq.apply(this, arguments)
177
+
178
+ const n1qlQuery = getQueryResource(q)
179
+
180
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
181
+ return asyncResource.runInAsyncScope(() => {
182
+ startCh.publish({ resource: n1qlQuery, bucket: { name: this.name || this._name } })
183
+
184
+ emitter.once('rows', asyncResource.bind(() => {
185
+ finishCh.publish(undefined)
186
+ }))
187
+
188
+ emitter.once('error', asyncResource.bind((error) => {
189
+ errorCh.publish(error)
190
+ finishCh.publish(undefined)
191
+ }))
192
+
193
+ try {
194
+ return _n1qlReq.apply(this, arguments)
195
+ } catch (err) {
196
+ err.stack // trigger getting the stack at the original throwing point
197
+ errorCh.publish(err)
198
+
199
+ throw err
200
+ }
201
+ })
202
+ })
203
+
204
+ wrapAllNames(['upsert', 'insert', 'replace', 'append', 'prepend'], name => {
205
+ Bucket.prototype[name] = wrap(`apm:couchbase:${name}`, Bucket.prototype[name])
206
+ })
207
+
208
+ return Bucket
209
+ })
210
+
211
+ addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.5'] }, Cluster => {
212
+ Cluster.prototype._maybeInvoke = wrapMaybeInvoke(Cluster.prototype._maybeInvoke)
213
+ Cluster.prototype.query = wrapQuery(Cluster.prototype.query)
214
+
215
+ return Cluster
216
+ })
217
+
218
+ // semver >=3 <3.2.0
219
+
220
+ addHook({ name: 'couchbase', file: 'lib/collection.js', versions: ['>=3.0.0 <3.2.0'] }, Collection => {
221
+ wrapAllNames(['upsert', 'insert', 'replace'], name => {
222
+ shimmer.wrap(Collection.prototype, name, wrapWithName(name))
223
+ })
224
+
225
+ return Collection
226
+ })
227
+
228
+ addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['>=3.0.0 <3.2.0'] }, Cluster => {
229
+ shimmer.wrap(Cluster.prototype, 'query', wrapV3Query)
230
+ return Cluster
231
+ })
232
+
233
+ // semver >=3.2.0
234
+
235
+ addHook({ name: 'couchbase', file: 'dist/collection.js', versions: ['>=3.2.0'] }, collection => {
236
+ const Collection = collection.Collection
237
+
238
+ wrapAllNames(['upsert', 'insert', 'replace'], name => {
239
+ shimmer.wrap(Collection.prototype, name, wrapWithName(name))
240
+ })
241
+
242
+ return collection
243
+ })
244
+
245
+ addHook({ name: 'couchbase', file: 'dist/cluster.js', versions: ['3.2.0 - 3.2.1', '>=3.2.2'] }, cluster => {
246
+ const Cluster = cluster.Cluster
247
+
248
+ shimmer.wrap(Cluster.prototype, 'query', wrapV3Query)
249
+ return cluster
250
+ })
@@ -154,9 +154,11 @@ function getRes (reply) {
154
154
  }
155
155
 
156
156
  function publishError (error, resource) {
157
- resource.runInAsyncScope(() => {
158
- errorChannel.publish(error)
159
- })
157
+ if (error) {
158
+ resource.runInAsyncScope(() => {
159
+ errorChannel.publish(error)
160
+ })
161
+ }
160
162
 
161
163
  return error
162
164
  }