dd-trace 3.0.0-pre.2 → 3.0.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 (51) hide show
  1. package/LICENSE-3rdparty.csv +1 -2
  2. package/MIGRATING.md +119 -0
  3. package/ci/init.js +0 -1
  4. package/ext/formats.js +3 -5
  5. package/index.d.ts +1 -11
  6. package/package.json +6 -7
  7. package/packages/datadog-core/src/storage/index.js +1 -1
  8. package/packages/datadog-instrumentations/index.js +1 -52
  9. package/packages/datadog-instrumentations/src/connect.js +1 -1
  10. package/packages/datadog-instrumentations/src/grpc/client.js +2 -2
  11. package/packages/datadog-instrumentations/src/grpc/server.js +1 -1
  12. package/packages/datadog-instrumentations/src/hapi.js +3 -31
  13. package/packages/datadog-instrumentations/src/helpers/hooks.js +68 -0
  14. package/packages/datadog-instrumentations/src/helpers/instrument.js +5 -34
  15. package/packages/datadog-instrumentations/src/helpers/instrumentations.js +3 -0
  16. package/packages/datadog-instrumentations/src/helpers/register.js +59 -0
  17. package/packages/datadog-instrumentations/src/koa.js +1 -1
  18. package/packages/datadog-instrumentations/src/mocha.js +4 -1
  19. package/packages/datadog-instrumentations/src/pg.js +2 -2
  20. package/packages/datadog-instrumentations/src/restify.js +27 -5
  21. package/packages/datadog-instrumentations/src/router.js +1 -1
  22. package/packages/datadog-plugin-aws-sdk/src/base.js +1 -2
  23. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
  24. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  25. package/packages/datadog-plugin-restify/src/index.js +7 -0
  26. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +220 -0
  27. package/packages/dd-trace/src/config.js +6 -0
  28. package/packages/dd-trace/src/{profiling/exporters → exporters/common}/form-data.js +0 -0
  29. package/packages/dd-trace/src/id.js +16 -13
  30. package/packages/dd-trace/src/iitm.js +1 -1
  31. package/packages/dd-trace/src/noop/scope.js +2 -6
  32. package/packages/dd-trace/src/noop/span.js +12 -12
  33. package/packages/dd-trace/src/noop/tracer.js +8 -5
  34. package/packages/dd-trace/src/opentracing/propagation/text_map.js +6 -6
  35. package/packages/dd-trace/src/opentracing/span.js +63 -49
  36. package/packages/dd-trace/src/opentracing/span_context.js +1 -5
  37. package/packages/dd-trace/src/opentracing/tracer.js +31 -36
  38. package/packages/dd-trace/src/plugin_manager.js +99 -68
  39. package/packages/dd-trace/src/plugins/index.js +57 -44
  40. package/packages/dd-trace/src/plugins/util/ci.js +34 -9
  41. package/packages/dd-trace/src/plugins/util/git.js +52 -2
  42. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  43. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  44. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  45. package/packages/dd-trace/src/profiling/profilers/cpu.js +3 -3
  46. package/packages/dd-trace/src/proxy.js +16 -12
  47. package/packages/dd-trace/src/scope.js +1 -58
  48. package/packages/dd-trace/src/startup-log.js +8 -19
  49. package/packages/dd-trace/src/telemetry.js +1 -14
  50. package/scripts/install_plugin_modules.js +17 -26
  51. package/ci/jest/env.js +0 -38
@@ -3,7 +3,6 @@ require,@datadog/native-appsec,Apache license 2.0,Copyright 2018 Datadog Inc.
3
3
  require,@datadog/native-metrics,Apache license 2.0,Copyright 2018 Datadog Inc.
4
4
  require,@datadog/pprof,Apache license 2.0,Copyright 2019 Google Inc.
5
5
  require,@datadog/sketches-js,Apache license 2.0,Copyright 2020 Datadog Inc.
6
- require,@types/node,MIT,Copyright Authors
7
6
  require,crypto-randomuuid,MIT,Copyright 2021 Node.js Foundation and contributors
8
7
  require,diagnostics_channel,MIT,Copyright 2021 Simon D.
9
8
  require,ignore,MIT,Copyright 2013 Kael Zhang and contributors
@@ -18,9 +17,9 @@ require,methods,MIT,Copyright 2013-2014 TJ Holowaychuk
18
17
  require,module-details-from-path,MIT,Copyright 2016 Thomas Watson Steen
19
18
  require,opentracing,MIT,Copyright 2016 Resonance Labs Inc
20
19
  require,path-to-regexp,MIT,Copyright 2014 Blake Embrey
21
- require,performance-now,MIT,Copyright 2013 Braveg1rl
22
20
  require,retry,MIT,Copyright 2011 Tim Koschützki Felix Geisendörfer
23
21
  require,semver,ISC,Copyright Isaac Z. Schlueter and Contributors
22
+ dev,@types/node,MIT,Copyright Authors
24
23
  dev,autocannon,MIT,Copyright 2016 Matteo Collina
25
24
  dev,axios,MIT,Copyright 2014-present Matt Zabriskie
26
25
  dev,benchmark,MIT,Copyright 2010-2016 Mathias Bynens Robert Kieffer John-David Dalton
package/MIGRATING.md CHANGED
@@ -4,6 +4,125 @@ This guide describes the steps to upgrade dd-trace from a major version to the
4
4
  next. If you are having any issues related to migrating, please feel free to
5
5
  open an issue or contact our [support](https://www.datadoghq.com/support/) team.
6
6
 
7
+ ## 2.0 to 3.0
8
+
9
+ ### Node 12 is no longer supported
10
+
11
+ Node.js 12 has been EOL since April 2022 and is no longer supported. Generally
12
+ speaking, we highly recommend always keeping Node.js up to date regardless of our
13
+ support policy.
14
+
15
+ ### HTTP query string reported by default
16
+
17
+ HTTP query strings are now reported by default as part of the `http.url` tag.
18
+ This change is considered breaking only because there might be sensitive data
19
+ in the query string. A default regular expression based obfuscator is provided
20
+ for common use cases like API keys, but if your use case is not covered, the
21
+ [DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP](https://datadoghq.dev/dd-trace-js/#tracer-settings)
22
+ environment variable can be used to control what is obfuscated, and a value of
23
+ `.*` would redact the query string entirely.
24
+
25
+ ### HTTP operation name change
26
+
27
+ The HTTP integration now uses `web.request` for incoming requests and continues
28
+ to use `http.request` for outgoing requests. When using a supported web
29
+ framework like Express, this change will have no effect because the root span
30
+ would already have an operation name override like `express.request`.
31
+ Any [monitor](https://docs.datadoghq.com/monitors/create/types/apm/?tab=apmmetrics)
32
+ on `http.request` for incoming requests should be updated to `web.request`.
33
+
34
+ With this change, both operation names also appear under the main service name
35
+ and are no longer split between the server service name and a separate client
36
+ service name suffixed with `-http-client`.
37
+
38
+ ### gRPC operation name change
39
+
40
+ The gRPC integration now uses `grpc.server` for incoming requests and
41
+ `grpc.client` for outgoing requests. Any
42
+ [monitor](https://docs.datadoghq.com/monitors/create/types/apm/?tab=apmmetrics)
43
+ on `grpc.request` should be updated to one of these.
44
+
45
+ With this change, both operation names also appear under the main service name
46
+ and are no longer split between the server service name and a separate client
47
+ service name suffixed with `-http-client`.
48
+
49
+ ### Removal of `fs` integration
50
+
51
+ The `fs` integration was removed as it was originally added without an actual
52
+ use case, and it's been problematic ever since. It's noisy, the output is
53
+ confusing when using streams, errors that are handled higher in the stack end up
54
+ being captured, etc.
55
+
56
+ If you had any use for file system instrumentation, please let us know so we can
57
+ provide an alternative.
58
+
59
+ ### Scope binding for promises and event emitters
60
+
61
+ It's no longer possible to bind promises using `tracer.scope().bind(promise)` or
62
+ event emitters using `tracer.scope().bind(emitter)`. These were historically
63
+ added mostly for internal use, and changes to context propagation over the years
64
+ made them unnecessary, both internally and externaly. If one of these is used
65
+ anywhere, the call will simply be ignored and no binding will occur.
66
+
67
+ To bind the `then` handler of a promise, bind the function directly directly:
68
+
69
+ ```js
70
+ promise.then(tracer.scope().bind(handler))
71
+ ```
72
+
73
+ To bind all listeners for an event, wrap the call to `emit` directly instead:
74
+
75
+ ```js
76
+ tracer.scope().activate(span, () => {
77
+ emitter.emit('event')
78
+ })
79
+ ```
80
+
81
+ To bind individual listeners, bind the listener function directly instead:
82
+
83
+ ```js
84
+ emitter.on('event', tracer.scope().bind(listener, span))
85
+ ```
86
+
87
+ ### Removed APIs
88
+
89
+ The following APIs have been deprecated for a long time and have now been
90
+ completely removed:
91
+
92
+ - `tracer.currentSpan()`
93
+ - `tracer.bindEmitter()`
94
+
95
+ Since these have not been recommended nor publicly documented for years at this
96
+ point, there should be no impact as no application is expected to be using them.
97
+
98
+ ### CI Visibility new entrypoints
99
+
100
+ #### Cypress
101
+
102
+ `dd-trace/cypress/plugin` and `dd-trace/cypress/support` are removed, so you won't
103
+ be able to use them for your `cypress` instrumentation. Use `dd-trace/ci/cypress/plugin`
104
+ and `dd-trace/ci/cypress/support` instead for your plugin and support configuration
105
+ respectively.
106
+
107
+ #### Jest
108
+
109
+ The use of `'dd-trace/ci/jest/env'` in [`testEnvironment`](https://jestjs.io/docs/configuration#testenvironment-string)
110
+ is no longer supported.
111
+ The way to instrument your `jest` tests now is by passing the `NODE_OPTIONS='-r dd-trace/ci/init'`
112
+ environment variable to the process running the tests.
113
+
114
+ #### Mocha
115
+
116
+ The use of `--require dd-trace/ci/init` as a `mocha` flag is no longer supported.
117
+ The way to instrument your `mocha` tests now is by passing the `NODE_OPTIONS='-r dd-trace/ci/init'`
118
+ environment variable to the process running the tests.
119
+
120
+ #### Cucumber
121
+
122
+ The use of `--require-module dd-trace/ci/init` as a `cucumber-js` flag is no longer supported.
123
+ The way to instrument your `cucumber-js` tests now is by passing the `NODE_OPTIONS='-r dd-trace/ci/init'`
124
+ environment variable to the process running the tests.
125
+
7
126
  ## 1.0 to 2.0
8
127
 
9
128
  ### Configuration
package/ci/init.js CHANGED
@@ -29,7 +29,6 @@ so dd-trace will not be initialized.`)
29
29
 
30
30
  if (shouldInit) {
31
31
  tracer.init(options)
32
- tracer.use('fs', false)
33
32
  }
34
33
 
35
34
  module.exports = tracer
package/ext/formats.js CHANGED
@@ -1,10 +1,8 @@
1
1
  'use strict'
2
2
 
3
- const opentracing = require('opentracing')
4
-
5
3
  module.exports = {
6
- TEXT_MAP: opentracing.FORMAT_TEXT_MAP,
7
- HTTP_HEADERS: opentracing.FORMAT_HTTP_HEADERS,
8
- BINARY: opentracing.FORMAT_BINARY,
4
+ TEXT_MAP: 'text_map',
5
+ HTTP_HEADERS: 'http_headers',
6
+ BINARY: 'binary',
9
7
  LOG: 'log'
10
8
  }
package/index.d.ts CHANGED
@@ -491,15 +491,6 @@ export declare interface TracerOptions {
491
491
  [key: string]: string | undefined
492
492
  }
493
493
 
494
- /** @hidden */
495
- interface EventEmitter {
496
- emit(eventName: string | symbol, ...args: any[]): any;
497
- on?(eventName: string | symbol, listener: (...args: any[]) => any): any;
498
- off?(eventName: string | symbol, listener: (...args: any[]) => any): any;
499
- addListener?(eventName: string | symbol, listener: (...args: any[]) => any): any;
500
- removeListener?(eventName: string | symbol, listener: (...args: any[]) => any): any;
501
- }
502
-
503
494
  /** @hidden */
504
495
  declare type anyObject = {
505
496
  [key: string]: any;
@@ -537,14 +528,13 @@ export declare interface Scope {
537
528
  /**
538
529
  * Binds a target to the provided span, or the active span if omitted.
539
530
  *
540
- * @param {Function|Promise|EventEmitter} target Target that will have the span activated on its scope.
531
+ * @param {Function|Promise} target Target that will have the span activated on its scope.
541
532
  * @param {Span} [span=scope.active()] The span to activate.
542
533
  * @returns The bound target.
543
534
  */
544
535
  bind<T extends (...args: any[]) => void>(fn: T, span?: Span | null): T;
545
536
  bind<V, T extends (...args: any[]) => V>(fn: T, span?: Span | null): T;
546
537
  bind<T>(fn: Promise<T>, span?: Span | null): Promise<T>;
547
- bind(emitter: EventEmitter, span?: Span | null): EventEmitter;
548
538
  }
549
539
 
550
540
  /** @hidden */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "3.0.0-pre.2",
3
+ "version": "3.0.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -55,14 +55,13 @@
55
55
  },
56
56
  "homepage": "https://github.com/DataDog/dd-trace-js#readme",
57
57
  "engines": {
58
- "node": ">=12"
58
+ "node": ">=14"
59
59
  },
60
60
  "dependencies": {
61
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
- "@types/node": ">=12",
62
+ "@datadog/native-metrics": "^1.4.2",
63
+ "@datadog/pprof": "^1.0.2",
64
+ "@datadog/sketches-js": "^2.0.0",
66
65
  "crypto-randomuuid": "^1.0.0",
67
66
  "diagnostics_channel": "^1.1.0",
68
67
  "ignore": "^5.2.0",
@@ -77,11 +76,11 @@
77
76
  "module-details-from-path": "^1.0.3",
78
77
  "opentracing": ">=0.12.1",
79
78
  "path-to-regexp": "^0.1.2",
80
- "performance-now": "^2.1.0",
81
79
  "retry": "^0.10.1",
82
80
  "semver": "^5.5.0"
83
81
  },
84
82
  "devDependencies": {
83
+ "@types/node": ">=14",
85
84
  "autocannon": "^4.5.2",
86
85
  "axios": "^0.21.2",
87
86
  "benchmark": "^2.1.4",
@@ -5,7 +5,7 @@
5
5
  const semver = require('semver')
6
6
 
7
7
  // https://github.com/nodejs/node/pull/33801
8
- const hasJavaScriptAsyncHooks = semver.satisfies(process.versions.node, '>=14.5 || ^12.19.0')
8
+ const hasJavaScriptAsyncHooks = semver.satisfies(process.versions.node, '>=14.5')
9
9
 
10
10
  if (hasJavaScriptAsyncHooks) {
11
11
  module.exports = require('./async_resource')
@@ -1,54 +1,3 @@
1
1
  'use strict'
2
2
 
3
- require('./src/amqplib')
4
- require('./src/amqp10')
5
- require('./src/aws-sdk')
6
- require('./src/bluebird')
7
- require('./src/bunyan')
8
- require('./src/cassandra-driver')
9
- require('./src/connect')
10
- require('./src/couchbase')
11
- require('./src/cucumber')
12
- require('./src/dns')
13
- require('./src/elasticsearch')
14
- require('./src/express')
15
- require('./src/fastify')
16
- require('./src/find-my-way')
17
- require('./src/generic-pool')
18
- require('./src/google-cloud-pubsub')
19
- require('./src/graphql')
20
- require('./src/grpc')
21
- require('./src/hapi')
22
- require('./src/http')
23
- require('./src/http2')
24
- require('./src/ioredis')
25
- require('./src/jest')
26
- require('./src/kafkajs')
27
- require('./src/knex')
28
- require('./src/koa')
29
- require('./src/memcached')
30
- require('./src/microgateway-core')
31
- require('./src/moleculer')
32
- require('./src/mongodb-core')
33
- require('./src/mongoose')
34
- require('./src/mysql')
35
- require('./src/mysql2')
36
- require('./src/mocha')
37
- require('./src/net')
38
- require('./src/next')
39
- require('./src/oracledb')
40
- require('./src/paperplane')
41
- require('./src/pino')
42
- require('./src/pg')
43
- require('./src/promise')
44
- require('./src/promise-js')
45
- require('./src/q')
46
- require('./src/redis')
47
- require('./src/restify')
48
- require('./src/router')
49
- require('./src/rhea')
50
- require('./src/sharedb')
51
- require('./src/tedious')
52
- require('./src/when')
53
- require('./src/winston')
54
- require('./src/limitd-client')
3
+ require('./src/helpers/register')
@@ -98,7 +98,7 @@ function wrapNext (req, next) {
98
98
  nextChannel.publish({ req })
99
99
  exitChannel.publish({ req })
100
100
 
101
- next.apply(null, arguments)
101
+ next.apply(this, arguments)
102
102
  }
103
103
  }
104
104
 
@@ -232,9 +232,9 @@ function patch (grpc) {
232
232
  return grpc
233
233
  }
234
234
 
235
- addHook({ name: 'grpc', versions: ['>=1.20.2'] }, patch)
235
+ addHook({ name: 'grpc', versions: ['>=1.24.3'] }, patch)
236
236
 
237
- addHook({ name: 'grpc', versions: ['>=1.20.2'], file: 'src/client.js' }, client => {
237
+ addHook({ name: 'grpc', versions: ['>=1.24.3'], file: 'src/client.js' }, client => {
238
238
  shimmer.wrap(client, 'makeClientConstructor', createWrapMakeClientConstructor())
239
239
 
240
240
  return client
@@ -131,7 +131,7 @@ function isEmitter (obj) {
131
131
  return typeof obj.emit === 'function' && typeof obj.once === 'function'
132
132
  }
133
133
 
134
- addHook({ name: 'grpc', versions: ['>=1.20.2'], file: 'src/server.js' }, server => {
134
+ addHook({ name: 'grpc', versions: ['>=1.24.3'], file: 'src/server.js' }, server => {
135
135
  shimmer.wrap(server.Server.prototype, 'register', wrapRegister)
136
136
 
137
137
  return server
@@ -62,16 +62,6 @@ function wrapDispatch (dispatch) {
62
62
  }
63
63
  }
64
64
 
65
- function wrapLifecycle (lifecycle) {
66
- return function () {
67
- const result = lifecycle.apply(this, arguments)
68
-
69
- if (Array.isArray(result)) return result.map(wrapHandler)
70
-
71
- return result
72
- }
73
- }
74
-
75
65
  function wrapRebuild (rebuild) {
76
66
  return function (event) {
77
67
  const result = rebuild.apply(this, arguments)
@@ -166,20 +156,14 @@ addHook({ name: 'hapi', versions: ['>=17'] }, hapi => {
166
156
  return hapi
167
157
  })
168
158
 
169
- addHook({ name: 'hapi', versions: ['2 - 7.1', '8 - 16'] }, hapi => {
159
+ addHook({ name: 'hapi', versions: ['16'] }, hapi => {
170
160
  shimmer.wrap(hapi.Server.prototype, 'start', wrapStart)
171
161
  shimmer.wrap(hapi.Server.prototype, 'ext', wrapExt)
172
162
 
173
163
  return hapi
174
164
  })
175
165
 
176
- addHook({ name: 'hapi', versions: ['^7.2'] }, hapi => {
177
- shimmer.wrap(hapi, 'createServer', wrapServer)
178
-
179
- return hapi
180
- })
181
-
182
- addHook({ name: 'hapi', versions: ['7.2 - 16'], file: 'lib/connection.js' }, Connection => {
166
+ addHook({ name: 'hapi', versions: ['16'], file: 'lib/connection.js' }, Connection => {
183
167
  shimmer.wrap(Connection.prototype, '_dispatch', wrapDispatch)
184
168
 
185
169
  return Connection
@@ -191,20 +175,8 @@ addHook({ name: 'hapi', versions: ['>=17'], file: 'lib/core.js' }, Core => {
191
175
  return Core
192
176
  })
193
177
 
194
- addHook({ name: 'hapi', versions: ['2 - 7.1'], file: 'lib/server.js' }, Server => {
195
- shimmer.wrap(Server.prototype, '_dispatch', wrapDispatch)
196
-
197
- return Server
198
- })
199
-
200
- addHook({ name: 'hapi', versions: ['>=10.4'], file: 'lib/route.js' }, Route => {
178
+ addHook({ name: 'hapi', versions: ['>=16'], file: 'lib/route.js' }, Route => {
201
179
  shimmer.wrap(Route.prototype, 'rebuild', wrapRebuild)
202
180
 
203
181
  return Route
204
182
  })
205
-
206
- addHook({ name: 'hapi', versions: ['2 - 10.3'], file: 'lib/route.js' }, Route => {
207
- shimmer.wrap(Route.prototype, 'lifecycle', wrapLifecycle)
208
-
209
- return Route
210
- })
@@ -0,0 +1,68 @@
1
+ 'use strict'
2
+
3
+ module.exports = {
4
+ '@cucumber/cucumber': () => require('../cucumber'),
5
+ '@elastic/elasticsearch': () => require('../elasticsearch'),
6
+ '@elastic/transport': () => require('../elasticsearch'),
7
+ '@google-cloud/pubsub': () => require('../google-cloud-pubsub'),
8
+ '@grpc/grpc-js': () => require('../grpc'),
9
+ '@hapi/hapi': () => require('../hapi'),
10
+ '@koa/router': () => require('../koa'),
11
+ '@node-redis/client': () => require('../redis'),
12
+ 'amqp10': () => require('../amqp10'),
13
+ 'amqplib': () => require('../amqplib'),
14
+ 'aws-sdk': () => require('../aws-sdk'),
15
+ 'bluebird': () => require('../bluebird'),
16
+ 'bunyan': () => require('../bunyan'),
17
+ 'cassandra-driver': () => require('../cassandra-driver'),
18
+ 'connect': () => require('../connect'),
19
+ 'couchbase': () => require('../couchbase'),
20
+ 'cypress': () => require('../cypress'),
21
+ 'dns': () => require('../dns'),
22
+ 'elasticsearch': () => require('../elasticsearch'),
23
+ 'express': () => require('../express'),
24
+ 'fastify': () => require('../fastify'),
25
+ 'find-my-way': () => require('../find-my-way'),
26
+ 'graphql': () => require('../graphql'),
27
+ 'grpc': () => require('../grpc'),
28
+ 'hapi': () => require('../hapi'),
29
+ 'http': () => require('../http'),
30
+ 'http2': () => require('../http2'),
31
+ 'https': () => require('../http'),
32
+ 'ioredis': () => require('../ioredis'),
33
+ 'jest-environment-node': () => require('../jest'),
34
+ 'jest-environment-jsdom': () => require('../jest'),
35
+ 'jest-jasmine2': () => require('../jest'),
36
+ 'koa': () => require('../koa'),
37
+ 'koa-router': () => require('../koa'),
38
+ 'kafkajs': () => require('../kafkajs'),
39
+ 'limitd-client': () => require('../limitd-client'),
40
+ 'memcached': () => require('../memcached'),
41
+ 'microgateway-core': () => require('../microgateway-core'),
42
+ 'mocha': () => require('../mocha'),
43
+ 'mocha-each': () => require('../mocha'),
44
+ 'moleculer': () => require('../moleculer'),
45
+ 'mongodb': () => require('../mongodb-core'),
46
+ 'mongodb-core': () => require('../mongodb-core'),
47
+ 'mongoose': () => require('../mongoose'),
48
+ 'mysql': () => require('../mysql'),
49
+ 'mysql2': () => require('../mysql2'),
50
+ 'net': () => require('../net'),
51
+ 'next': () => require('../next'),
52
+ 'oracledb': () => require('../oracledb'),
53
+ 'paperplane': () => require('../paperplane'),
54
+ 'pg': () => require('../pg'),
55
+ 'pino': () => require('../pino'),
56
+ 'pino-pretty': () => require('../pino'),
57
+ 'promise-js': () => require('../promise-js'),
58
+ 'promise': () => require('../promise'),
59
+ 'q': () => require('../q'),
60
+ 'redis': () => require('../redis'),
61
+ 'restify': () => require('../restify'),
62
+ 'rhea': () => require('../rhea'),
63
+ 'router': () => require('../router'),
64
+ 'sharedb': () => require('../sharedb'),
65
+ 'tedious': () => require('../tedious'),
66
+ 'when': () => require('../when'),
67
+ 'winston': () => require('../winston')
68
+ }
@@ -1,16 +1,12 @@
1
1
  'use strict'
2
2
 
3
3
  const dc = require('diagnostics_channel')
4
- const path = require('path')
5
4
  const semver = require('semver')
6
- const Hook = require('./hook')
7
- const requirePackageJson = require('../../../dd-trace/src/require-package-json')
5
+ const instrumentations = require('./instrumentations')
8
6
  const { AsyncResource } = require('async_hooks')
9
- const log = require('../../../dd-trace/src/log')
10
7
 
11
- const pathSepExpr = new RegExp(`\\${path.sep}`, 'g')
12
8
  const channelMap = {}
13
- exports.channel = function channel (name) {
9
+ exports.channel = function (name) {
14
10
  const maybe = channelMap[name]
15
11
  if (maybe) return maybe
16
12
  const ch = dc.channel(name)
@@ -19,36 +15,11 @@ exports.channel = function channel (name) {
19
15
  }
20
16
 
21
17
  exports.addHook = function addHook ({ name, versions, file }, hook) {
22
- const fullFilename = filename(name, file)
23
-
24
- Hook([name], (moduleExports, moduleName, moduleBaseDir) => {
25
- moduleName = moduleName.replace(pathSepExpr, '/')
26
-
27
- if (moduleName !== fullFilename || !matchVersion(getVersion(moduleBaseDir), versions)) {
28
- return moduleExports
29
- }
30
-
31
- try {
32
- return hook(moduleExports)
33
- } catch (e) {
34
- log.error(e)
35
- return moduleExports
36
- }
37
- })
38
- }
39
-
40
- function matchVersion (version, ranges) {
41
- return !version || (ranges && ranges.some(range => semver.satisfies(semver.coerce(version), range)))
42
- }
43
-
44
- function getVersion (moduleBaseDir) {
45
- if (moduleBaseDir) {
46
- return requirePackageJson(moduleBaseDir, module).version
18
+ if (!instrumentations[name]) {
19
+ instrumentations[name] = []
47
20
  }
48
- }
49
21
 
50
- function filename (name, file) {
51
- return [name, file].filter(val => val).join('/')
22
+ instrumentations[name].push({ name, versions, file, hook })
52
23
  }
53
24
 
54
25
  // AsyncResource.bind exists and binds `this` properly only from 17.8.0 and up.
@@ -0,0 +1,3 @@
1
+ 'use strict'
2
+
3
+ module.exports = {}
@@ -0,0 +1,59 @@
1
+ 'use strict'
2
+
3
+ const { channel } = require('diagnostics_channel')
4
+ const path = require('path')
5
+ const semver = require('semver')
6
+ const Hook = require('./hook')
7
+ const requirePackageJson = require('../../../dd-trace/src/require-package-json')
8
+ const log = require('../../../dd-trace/src/log')
9
+
10
+ const hooks = require('./hooks')
11
+ const instrumentations = require('./instrumentations')
12
+ const names = Object.keys(hooks)
13
+ const pathSepExpr = new RegExp(`\\${path.sep}`, 'g')
14
+
15
+ const loadChannel = channel('dd-trace:instrumentation:load')
16
+
17
+ // TODO: make this more efficient
18
+
19
+ for (const packageName of names) {
20
+ Hook([packageName], (moduleExports, moduleName, moduleBaseDir) => {
21
+ moduleName = moduleName.replace(pathSepExpr, '/')
22
+
23
+ hooks[packageName]()
24
+
25
+ for (const { name, file, versions, hook } of instrumentations[packageName]) {
26
+ const fullFilename = filename(name, file)
27
+
28
+ if (moduleName === fullFilename) {
29
+ const version = getVersion(moduleBaseDir)
30
+
31
+ if (matchVersion(version, versions)) {
32
+ try {
33
+ loadChannel.publish({ name, version, file })
34
+
35
+ moduleExports = hook(moduleExports)
36
+ } catch (e) {
37
+ log.error(e)
38
+ }
39
+ }
40
+ }
41
+ }
42
+
43
+ return moduleExports
44
+ })
45
+ }
46
+
47
+ function matchVersion (version, ranges) {
48
+ return !version || (ranges && ranges.some(range => semver.satisfies(semver.coerce(version), range)))
49
+ }
50
+
51
+ function getVersion (moduleBaseDir) {
52
+ if (moduleBaseDir) {
53
+ return requirePackageJson(moduleBaseDir, module).version
54
+ }
55
+ }
56
+
57
+ function filename (name, file) {
58
+ return [name, file].filter(val => val).join('/')
59
+ }
@@ -145,7 +145,7 @@ function wrapNext (req, next) {
145
145
  return function () {
146
146
  nextChannel.publish({ req })
147
147
 
148
- return next.apply(null, arguments)
148
+ return next.apply(this, arguments)
149
149
  }
150
150
  }
151
151
 
@@ -153,7 +153,10 @@ function mochaHook (Runner) {
153
153
  if (isHook && testOrHook.ctx) {
154
154
  test = testOrHook.ctx.currentTest
155
155
  }
156
- const asyncResource = getTestAsyncResource(test)
156
+ let asyncResource
157
+ if (test) {
158
+ asyncResource = getTestAsyncResource(test)
159
+ }
157
160
  if (asyncResource) {
158
161
  asyncResource.runInAsyncScope(() => {
159
162
  if (isHook) {
@@ -11,12 +11,12 @@ const startCh = channel('apm:pg:query:start')
11
11
  const finishCh = channel('apm:pg:query:finish')
12
12
  const errorCh = channel('apm:pg:query:error')
13
13
 
14
- addHook({ name: 'pg', versions: ['>=4.5.5'] }, pg => {
14
+ addHook({ name: 'pg', versions: ['>=8.0.3'] }, pg => {
15
15
  shimmer.wrap(pg.Client.prototype, 'query', query => wrapQuery(query))
16
16
  return pg
17
17
  })
18
18
 
19
- addHook({ name: 'pg', file: 'lib/native/index.js', versions: ['>=4.5.5'] }, Client => {
19
+ addHook({ name: 'pg', file: 'lib/native/index.js', versions: ['>=8.0.3'] }, Client => {
20
20
  shimmer.wrap(Client.prototype, 'query', query => wrapQuery(query))
21
21
  return Client
22
22
  })