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
@@ -17,7 +17,6 @@ require,lodash.sortby,MIT,Copyright JS Foundation and other contributors
17
17
  require,lodash.uniq,MIT,Copyright JS Foundation and other contributors
18
18
  require,methods,MIT,Copyright 2013-2014 TJ Holowaychuk
19
19
  require,module-details-from-path,MIT,Copyright 2016 Thomas Watson Steen
20
- require,multer,MIT,Copyright 2014 Hage Yaapa
21
20
  require,opentracing,MIT,Copyright 2016 Resonance Labs Inc
22
21
  require,path-to-regexp,MIT,Copyright 2014 Blake Embrey
23
22
  require,performance-now,MIT,Copyright 2013 Braveg1rl
@@ -31,7 +30,6 @@ dev,chai,MIT,Copyright 2017 Chai.js Assertion Library
31
30
  dev,chalk,MIT,Copyright Sindre Sorhus
32
31
  dev,checksum,MIT,Copyright Daniel D. Shaw
33
32
  dev,cli-table3,MIT,Copyright 2014 James Talmage
34
- dev,codecov,MIT,Copyright 2014 Gregg Caines
35
33
  dev,dotenv,BSD-2-Clause,Copyright 2015 Scott Motte
36
34
  dev,eslint,MIT,Copyright JS Foundation and other contributors https://js.foundation
37
35
  dev,eslint-config-standard,MIT,Copyright Feross Aboukhadijeh
@@ -47,6 +45,7 @@ dev,int64-buffer,MIT,Copyright 2015-2016 Yusuke Kawasaki
47
45
  dev,jszip,MIT,Copyright 2015-2016 Stuart Knightley and contributors
48
46
  dev,mkdirp,MIT,Copyright 2010 James Halliday
49
47
  dev,mocha,MIT,Copyright 2011-2018 JS Foundation and contributors https://js.foundation
48
+ dev,multer,MIT,Copyright 2014 Hage Yaapa
50
49
  dev,msgpack-lite,MIT,Copyright 2015 Yusuke Kawasaki
51
50
  dev,nock,MIT,Copyright 2017 Pedro Teixeira and other contributors
52
51
  dev,nyc,ISC,Copyright 2015 Contributors
package/ci/init.js CHANGED
@@ -1,3 +1,5 @@
1
+ /* eslint-disable no-console */
2
+
1
3
  const path = require('path')
2
4
  const tracer = require('../packages/dd-trace')
3
5
  const { ORIGIN_KEY } = require('../packages/dd-trace/src/constants')
@@ -11,9 +13,22 @@ const options = {
11
13
  }
12
14
  }
13
15
 
14
- if (process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED && (process.env.DATADOG_API_KEY || process.env.DD_API_KEY)) {
15
- options.experimental = {
16
- exporter: 'datadog'
16
+ let shouldInit = true
17
+
18
+ const isAgentlessEnabled = process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED &&
19
+ process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED !== 'false' &&
20
+ process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED !== '0'
21
+
22
+ if (isAgentlessEnabled) {
23
+ if (process.env.DATADOG_API_KEY || process.env.DD_API_KEY) {
24
+ options.experimental = {
25
+ exporter: 'datadog'
26
+ }
27
+ } else {
28
+ console.error(`DD_CIVISIBILITY_AGENTLESS_ENABLED is set, \
29
+ but neither DD_API_KEY nor DATADOG_API_KEY are set in your environment, \
30
+ so dd-trace will not be initialized.`)
31
+ shouldInit = false
17
32
  }
18
33
  }
19
34
 
@@ -36,8 +51,9 @@ try {
36
51
  // ignore error and let the tracer initialize anyway
37
52
  }
38
53
 
39
- tracer.init(options)
40
-
41
- tracer.use('fs', false)
54
+ if (shouldInit) {
55
+ tracer.init(options)
56
+ tracer.use('fs', false)
57
+ }
42
58
 
43
59
  module.exports = tracer
package/ci/jest/env.js CHANGED
@@ -1,3 +1,5 @@
1
+ /* eslint-disable no-console */
2
+
1
3
  const tracer = require('../../packages/dd-trace')
2
4
  const { ORIGIN_KEY } = require('../../packages/dd-trace/src/constants')
3
5
 
@@ -8,13 +10,23 @@ const options = {
8
10
  }
9
11
  }
10
12
 
11
- if (process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED && (process.env.DATADOG_API_KEY || process.env.DD_API_KEY)) {
12
- tracer.init({
13
- ...options,
14
- experimental: {
15
- exporter: 'datadog'
16
- }
17
- })
13
+ const isAgentlessEnabled = process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED &&
14
+ process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED !== 'false' &&
15
+ process.env.DD_CIVISIBILITY_AGENTLESS_ENABLED !== '0'
16
+
17
+ if (isAgentlessEnabled) {
18
+ if (process.env.DATADOG_API_KEY || process.env.DD_API_KEY) {
19
+ tracer.init({
20
+ ...options,
21
+ experimental: {
22
+ exporter: 'datadog'
23
+ }
24
+ })
25
+ } else {
26
+ console.error(`DD_CIVISIBILITY_AGENTLESS_ENABLED is set, \
27
+ but neither DD_API_KEY nor DATADOG_API_KEY are set in your environment, \
28
+ so dd-trace will not be initialized.`)
29
+ }
18
30
  } else {
19
31
  tracer.init({
20
32
  ...options,
package/ext/tags.d.ts CHANGED
@@ -15,6 +15,7 @@ declare const tags: {
15
15
  HTTP_ROUTE: 'http.route'
16
16
  HTTP_REQUEST_HEADERS: 'http.request.headers'
17
17
  HTTP_RESPONSE_HEADERS: 'http.response.headers'
18
+ HTTP_USERAGENT: 'http.useragent'
18
19
  }
19
20
 
20
21
  export = tags
package/ext/tags.js CHANGED
@@ -19,7 +19,8 @@ const tags = {
19
19
  HTTP_STATUS_CODE: 'http.status_code',
20
20
  HTTP_ROUTE: 'http.route',
21
21
  HTTP_REQUEST_HEADERS: 'http.request.headers',
22
- HTTP_RESPONSE_HEADERS: 'http.response.headers'
22
+ HTTP_RESPONSE_HEADERS: 'http.response.headers',
23
+ HTTP_USERAGENT: 'http.useragent'
23
24
  }
24
25
 
25
26
  // Deprecated
package/index.d.ts CHANGED
@@ -1210,13 +1210,15 @@ declare namespace plugins {
1210
1210
  * This plugin automatically instruments the
1211
1211
  * [mysql](https://github.com/mysqljs/mysql) module.
1212
1212
  */
1213
- interface mysql extends Instrumentation {}
1213
+ interface mysql extends Instrumentation {
1214
+ service?: string | ((params: any) => string);
1215
+ }
1214
1216
 
1215
1217
  /**
1216
1218
  * This plugin automatically instruments the
1217
1219
  * [mysql2](https://github.com/brianmario/mysql2) module.
1218
1220
  */
1219
- interface mysql2 extends Instrumentation {}
1221
+ interface mysql2 extends mysql {}
1220
1222
 
1221
1223
  /**
1222
1224
  * This plugin automatically instruments the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "2.7.0",
3
+ "version": "2.9.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -32,7 +32,6 @@
32
32
  "test:shimmer:ci": "nyc --no-clean --include 'packages/datadog-shimmer/src/**/*.js' -- npm run test:shimmer",
33
33
  "leak:core": "node ./scripts/install_plugin_modules && (cd packages/memwatch && yarn) && NODE_PATH=./packages/memwatch/node_modules node --no-warnings ./node_modules/.bin/tape 'packages/dd-trace/test/leak/**/*.js'",
34
34
  "leak:plugins": "yarn services && (cd packages/memwatch && yarn) && NODE_PATH=./packages/memwatch/node_modules node --no-warnings ./node_modules/.bin/tape \"packages/datadog-plugin-@($(echo $PLUGINS))/test/leak.js\"",
35
- "codecov": "codecov",
36
35
  "junit:upload": "node ./scripts/junit_report.js"
37
36
  },
38
37
  "repository": {
@@ -59,7 +58,7 @@
59
58
  "node": ">=12"
60
59
  },
61
60
  "dependencies": {
62
- "@datadog/native-appsec": "^1.1.1",
61
+ "@datadog/native-appsec": "^1.2.0",
63
62
  "@datadog/native-metrics": "^1.2.0",
64
63
  "@datadog/pprof": "^0.4.0",
65
64
  "@datadog/sketches-js": "^1.0.4",
@@ -77,7 +76,6 @@
77
76
  "lodash.uniq": "^4.5.0",
78
77
  "methods": "^1.1.2",
79
78
  "module-details-from-path": "^1.0.3",
80
- "multer": "^1.4.2",
81
79
  "opentracing": ">=0.12.1",
82
80
  "path-to-regexp": "^0.1.2",
83
81
  "performance-now": "^2.1.0",
@@ -93,7 +91,6 @@
93
91
  "chalk": "^3.0.0",
94
92
  "checksum": "^0.1.1",
95
93
  "cli-table3": "^0.5.1",
96
- "codecov": "3.8.1",
97
94
  "dotenv": "8.2.0",
98
95
  "eslint": "^7.32.0",
99
96
  "eslint-config-standard": "^11.0.0-beta.0",
@@ -109,6 +106,7 @@
109
106
  "jszip": "^3.5.0",
110
107
  "mkdirp": "^0.5.1",
111
108
  "mocha": "8",
109
+ "multer": "^1.4.2",
112
110
  "msgpack-lite": "^0.1.26",
113
111
  "nock": "^11.3.3",
114
112
  "nyc": "^15.1.0",
@@ -69,7 +69,7 @@ class AsyncResourceStorage {
69
69
  }
70
70
 
71
71
  _executionAsyncResource () {
72
- return executionAsyncResource()
72
+ return executionAsyncResource() || {}
73
73
  }
74
74
  }
75
75
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require('./src/amqplib')
4
4
  require('./src/amqp10')
5
+ require('./src/aws-sdk')
5
6
  require('./src/bluebird')
6
7
  require('./src/bunyan')
7
8
  require('./src/cassandra-driver')
@@ -15,6 +16,7 @@ require('./src/fastify')
15
16
  require('./src/find-my-way')
16
17
  require('./src/generic-pool')
17
18
  require('./src/google-cloud-pubsub')
19
+ require('./src/hapi')
18
20
  require('./src/http')
19
21
  require('./src/ioredis')
20
22
  require('./src/jest')
@@ -22,6 +24,7 @@ require('./src/kafkajs')
22
24
  require('./src/knex')
23
25
  require('./src/koa')
24
26
  require('./src/memcached')
27
+ require('./src/moleculer')
25
28
  require('./src/mongodb-core')
26
29
  require('./src/mongoose')
27
30
  require('./src/mysql')
@@ -9,62 +9,63 @@ const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  addHook({ name: 'amqp10', file: 'lib/sender_link.js', versions: ['>=3'] }, SenderLink => {
11
11
  const startCh = channel('apm:amqp10:send:start')
12
- const asyncEndCh = channel('apm:amqp10:send:async-end')
13
- const endCh = channel('apm:amqp10:send:end')
12
+ const finishCh = channel('apm:amqp10:send:finish')
14
13
  const errorCh = channel('apm:amqp10:send:error')
15
14
  shimmer.wrap(SenderLink.prototype, 'send', send => function (msg, options) {
16
15
  if (!startCh.hasSubscribers) {
17
16
  return send.apply(this, arguments)
18
17
  }
19
- startCh.publish({ link: this })
20
- try {
21
- const promise = send.apply(this, arguments)
18
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
19
+ return asyncResource.runInAsyncScope(() => {
20
+ startCh.publish({ link: this })
21
+ try {
22
+ const promise = send.apply(this, arguments)
22
23
 
23
- if (!promise) {
24
- finish(asyncEndCh, errorCh)
25
- return promise
26
- }
27
-
28
- const asyncResource = new AsyncResource('bound-anonymous-fn')
24
+ if (!promise) {
25
+ finish(finishCh, errorCh)
26
+ return promise
27
+ }
29
28
 
30
- promise.then(asyncResource.bind(() => finish(asyncEndCh, errorCh)),
31
- asyncResource.bind(e => finish(asyncEndCh, errorCh, e)))
29
+ promise.then(asyncResource.bind(() => finish(finishCh, errorCh)),
30
+ asyncResource.bind(e => finish(finishCh, errorCh, e)))
32
31
 
33
- return promise
34
- } catch (err) {
35
- finish(asyncEndCh, errorCh, err)
36
- throw err
37
- } finally {
38
- endCh.publish(undefined)
39
- }
32
+ return promise
33
+ } catch (err) {
34
+ finish(finishCh, errorCh, err)
35
+ throw err
36
+ }
37
+ })
40
38
  })
41
39
  return SenderLink
42
40
  })
43
41
 
44
42
  addHook({ name: 'amqp10', file: 'lib/receiver_link.js', versions: ['>=3'] }, ReceiverLink => {
45
43
  const startCh = channel('apm:amqp10:receive:start')
46
- const endCh = channel('apm:amqp10:receive:end')
44
+ const finishCh = channel('apm:amqp10:receive:finish')
47
45
  const errorCh = channel('apm:amqp10:receive:error')
48
46
  shimmer.wrap(ReceiverLink.prototype, '_messageReceived', messageReceived => function (transferFrame) {
49
47
  if (!transferFrame || transferFrame.aborted || transferFrame.more) {
50
48
  return messageReceived.apply(this, arguments)
51
49
  }
52
- startCh.publish({ link: this })
53
- try {
54
- return messageReceived.apply(this, arguments)
55
- } catch (err) {
56
- errorCh.publish(err)
57
- throw err
58
- } finally {
59
- endCh.publish(undefined)
60
- }
50
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
51
+ return asyncResource.runInAsyncScope(() => {
52
+ startCh.publish({ link: this })
53
+ try {
54
+ return messageReceived.apply(this, arguments)
55
+ } catch (err) {
56
+ errorCh.publish(err)
57
+ throw err
58
+ } finally {
59
+ finishCh.publish()
60
+ }
61
+ })
61
62
  })
62
63
  return ReceiverLink
63
64
  })
64
65
 
65
- function finish (asyncEndCh, errorCh, error) {
66
+ function finish (finishCh, errorCh, error) {
66
67
  if (error) {
67
68
  errorCh.publish(error)
68
69
  }
69
- asyncEndCh.publish(undefined)
70
+ finishCh.publish()
70
71
  }
@@ -2,13 +2,14 @@
2
2
 
3
3
  const {
4
4
  channel,
5
- addHook
5
+ addHook,
6
+ AsyncResource
6
7
  } = require('./helpers/instrument')
7
8
  const kebabCase = require('lodash.kebabcase')
8
9
  const shimmer = require('../../datadog-shimmer')
9
10
 
10
11
  const startCh = channel('apm:amqplib:command:start')
11
- const endCh = channel('apm:amqplib:command:end')
12
+ const finishCh = channel('apm:amqplib:command:finish')
12
13
  const errorCh = channel('apm:amqplib:command:error')
13
14
 
14
15
  let methods = {}
@@ -40,17 +41,21 @@ function instrument (send, channel, args, method, fields, message) {
40
41
  if (!startCh.hasSubscribers) {
41
42
  return send.apply(channel, args)
42
43
  }
43
- startCh.publish({ channel, method, fields, message })
44
44
 
45
- try {
46
- return send.apply(channel, args)
47
- } catch (err) {
48
- errorCh.publish(err)
45
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
46
+ return asyncResource.runInAsyncScope(() => {
47
+ startCh.publish({ channel, method, fields, message })
49
48
 
50
- throw err
51
- } finally {
52
- endCh.publish(undefined)
53
- }
49
+ try {
50
+ return send.apply(channel, args)
51
+ } catch (err) {
52
+ errorCh.publish(err)
53
+
54
+ throw err
55
+ } finally {
56
+ finishCh.publish()
57
+ }
58
+ })
54
59
  }
55
60
 
56
61
  function isCamelCase (str) {
@@ -0,0 +1,105 @@
1
+ 'use strict'
2
+
3
+ const {
4
+ channel,
5
+ addHook,
6
+ AsyncResource
7
+ } = require('./helpers/instrument')
8
+ const shimmer = require('../../datadog-shimmer')
9
+
10
+ function wrapRequest (send) {
11
+ return function wrappedRequest (cb) {
12
+ if (!this.service) return send.apply(this, arguments)
13
+
14
+ const serviceIdentifier = this.service.serviceIdentifier
15
+ const channelSuffix = getChannelSuffix(serviceIdentifier)
16
+ const startCh = channel(`apm:aws:request:start:${channelSuffix}`)
17
+ if (!startCh.hasSubscribers) return send.apply(this, arguments)
18
+ const innerAr = new AsyncResource('apm:aws:request:inner')
19
+ const outerAr = new AsyncResource('apm:aws:request:outer')
20
+
21
+ return innerAr.runInAsyncScope(() => {
22
+ this.on('complete', innerAr.bind(response => {
23
+ channel(`apm:aws:request:complete:${channelSuffix}`).publish({ response })
24
+ }))
25
+
26
+ startCh.publish({
27
+ serviceIdentifier,
28
+ operation: this.operation,
29
+ awsRegion: this.service.config && this.service.config.region,
30
+ awsService: this.service.api && this.service.api.className,
31
+ request: this
32
+ })
33
+
34
+ if (typeof cb === 'function') {
35
+ arguments[0] = wrapCb(cb, channelSuffix, this, outerAr)
36
+ }
37
+ return send.apply(this, arguments)
38
+ })
39
+ }
40
+ }
41
+
42
+ function wrapCb (cb, serviceName, request, ar) {
43
+ return function wrappedCb (err, response) {
44
+ const obj = { request, response }
45
+ return ar.runInAsyncScope(() => {
46
+ channel(`apm:aws:response:start:${serviceName}`).publish(obj)
47
+ // TODO(bengl) make this work without needing a needsFinish property added to the object
48
+ if (!obj.needsFinish) {
49
+ return cb.apply(this, arguments)
50
+ }
51
+ const finishChannel = channel(`apm:aws:response:finish:${serviceName}`)
52
+ try {
53
+ let result = cb.apply(this, arguments)
54
+ if (result && result.then) {
55
+ result = result.then(x => {
56
+ finishChannel.publish()
57
+ return x
58
+ }, e => {
59
+ finishChannel.publish(e)
60
+ throw e
61
+ })
62
+ } else {
63
+ finishChannel.publish()
64
+ }
65
+ return result
66
+ } catch (e) {
67
+ finishChannel.publish(e)
68
+ throw e
69
+ }
70
+ })
71
+ }
72
+ }
73
+
74
+ function getChannelSuffix (name) {
75
+ return [
76
+ 'cloudwatchlogs',
77
+ 'dynamodb',
78
+ 'eventbridge',
79
+ 'kinesis',
80
+ 'lambda',
81
+ 'redshift',
82
+ 's3',
83
+ 'sns',
84
+ 'sqs'
85
+ ].includes(name) ? name : 'default'
86
+ }
87
+
88
+ addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
89
+ shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
90
+ shimmer.wrap(AWS.config, 'setPromisesDependency', setPromisesDependency => {
91
+ return function wrappedSetPromisesDependency (dep) {
92
+ const result = setPromisesDependency.apply(this, arguments)
93
+ shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
94
+ return result
95
+ }
96
+ })
97
+ return AWS
98
+ })
99
+
100
+ // <2.1.35 has breaking changes for instrumentation
101
+ // https://github.com/aws/aws-sdk-js/pull/629
102
+ addHook({ name: 'aws-sdk', versions: ['>=2.1.35'] }, AWS => {
103
+ shimmer.wrap(AWS.Request.prototype, 'send', wrapRequest)
104
+ return AWS
105
+ })
@@ -8,8 +8,7 @@ const {
8
8
  const shimmer = require('../../datadog-shimmer')
9
9
 
10
10
  const startCh = channel('apm:cassandra:query:start')
11
- const asyncEndCh = channel('apm:cassandra:query:async-end')
12
- const endCh = channel('apm:cassandra:query:end')
11
+ const finishCh = channel('apm:cassandra:query:finish')
13
12
  const errorCh = channel('apm:cassandra:query:error')
14
13
  const addConnectionCh = channel(`apm:cassandra:query:addConnection`)
15
14
 
@@ -18,34 +17,34 @@ addHook({ name: 'cassandra-driver', versions: ['>=3.0.0'] }, cassandra => {
18
17
  if (!startCh.hasSubscribers) {
19
18
  return batch.apply(this, arguments)
20
19
  }
20
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
21
21
  const asyncResource = new AsyncResource('bound-anonymous-fn')
22
- startCh.publish({ keyspace: this.keyspace, query: queries })
23
-
24
22
  const lastIndex = arguments.length - 1
25
23
  let cb = arguments[lastIndex]
26
24
 
27
25
  if (typeof cb === 'function') {
28
- cb = asyncResource.bind(cb)
29
- arguments[lastIndex] = wrapCallback(asyncEndCh, errorCh, cb)
26
+ cb = callbackResource.bind(cb)
27
+ arguments[lastIndex] = wrapCallback(finishCh, errorCh, asyncResource, cb)
30
28
  }
31
29
 
32
- try {
33
- const res = batch.apply(this, arguments)
34
- if (typeof res === 'function' || !res) {
35
- return wrapCallback(asyncEndCh, errorCh, res)
36
- } else {
37
- const promiseAsyncResource = new AsyncResource('bound-anonymous-fn')
38
- return res.then(
39
- promiseAsyncResource.bind(() => finish(asyncEndCh, errorCh)),
40
- promiseAsyncResource.bind(err => finish(asyncEndCh, errorCh, err))
41
- )
30
+ return asyncResource.runInAsyncScope(() => {
31
+ startCh.publish({ keyspace: this.keyspace, query: queries })
32
+ try {
33
+ const res = batch.apply(this, arguments)
34
+ if (typeof res === 'function' || !res) {
35
+ return wrapCallback(finishCh, errorCh, asyncResource, res)
36
+ } else {
37
+ const promiseAsyncResource = new AsyncResource('bound-anonymous-fn')
38
+ return res.then(
39
+ promiseAsyncResource.bind(() => finish(finishCh, errorCh)),
40
+ promiseAsyncResource.bind(err => finish(finishCh, errorCh, err))
41
+ )
42
+ }
43
+ } catch (e) {
44
+ finish(finishCh, errorCh, e)
45
+ throw e
42
46
  }
43
- } catch (e) {
44
- finish(asyncEndCh, errorCh, e)
45
- throw e
46
- } finally {
47
- endCh.publish(undefined)
48
- }
47
+ })
49
48
  })
50
49
  return cassandra
51
50
  })
@@ -55,17 +54,19 @@ addHook({ name: 'cassandra-driver', versions: ['>=4.4'] }, cassandra => {
55
54
  if (!startCh.hasSubscribers) {
56
55
  return _execute.apply(this, arguments)
57
56
  }
58
- startCh.publish({ keyspace: this.keyspace, query })
59
- const promise = _execute.apply(this, arguments)
57
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
58
+ return asyncResource.runInAsyncScope(() => {
59
+ startCh.publish({ keyspace: this.keyspace, query })
60
+ const promise = _execute.apply(this, arguments)
60
61
 
61
- const promiseAsyncResource = new AsyncResource('bound-anonymous-fn')
62
+ const promiseAsyncResource = new AsyncResource('bound-anonymous-fn')
62
63
 
63
- promise.then(
64
- promiseAsyncResource.bind(() => finish(asyncEndCh, errorCh)),
65
- promiseAsyncResource.bind(err => finish(asyncEndCh, errorCh, err))
66
- )
67
- endCh.publish(undefined)
68
- return promise
64
+ promise.then(
65
+ promiseAsyncResource.bind(() => finish(finishCh, errorCh)),
66
+ promiseAsyncResource.bind(err => finish(finishCh, errorCh, err))
67
+ )
68
+ return promise
69
+ })
69
70
  })
70
71
  return cassandra
71
72
  })
@@ -76,6 +77,7 @@ addHook({ name: 'cassandra-driver', versions: ['3 - 4.3'] }, cassandra => {
76
77
  if (!startCh.hasSubscribers) {
77
78
  return _innerExecute.apply(this, arguments)
78
79
  }
80
+ const callbackResource = new AsyncResource('bound-anonymous-fn')
79
81
  const asyncResource = new AsyncResource('bound-anonymous-fn')
80
82
  const isValid = (args) => {
81
83
  return args.length === 4 || typeof args[3] === 'function'
@@ -85,24 +87,24 @@ addHook({ name: 'cassandra-driver', versions: ['3 - 4.3'] }, cassandra => {
85
87
  return _innerExecute.apply(this, arguments)
86
88
  }
87
89
 
88
- startCh.publish({ keyspace: this.keyspace, query })
90
+ return asyncResource.runInAsyncScope(() => {
91
+ startCh.publish({ keyspace: this.keyspace, query })
89
92
 
90
- const lastIndex = arguments.length - 1
91
- let cb = arguments[lastIndex]
93
+ const lastIndex = arguments.length - 1
94
+ let cb = arguments[lastIndex]
92
95
 
93
- if (typeof cb === 'function') {
94
- cb = asyncResource.bind(cb)
95
- arguments[lastIndex] = wrapCallback(asyncEndCh, errorCh, cb)
96
- }
96
+ if (typeof cb === 'function') {
97
+ cb = callbackResource.bind(cb)
98
+ arguments[lastIndex] = wrapCallback(finishCh, errorCh, asyncResource, cb)
99
+ }
97
100
 
98
- try {
99
- return _innerExecute.apply(this, arguments)
100
- } catch (e) {
101
- finish(asyncEndCh, errorCh, e)
102
- throw e
103
- } finally {
104
- endCh.publish(undefined)
105
- }
101
+ try {
102
+ return _innerExecute.apply(this, arguments)
103
+ } catch (e) {
104
+ finish(finishCh, errorCh, e)
105
+ throw e
106
+ }
107
+ })
106
108
  }
107
109
  )
108
110
  return cassandra
@@ -167,16 +169,16 @@ addHook({ name: 'cassandra-driver', versions: ['3 - 3.2'], file: 'lib/request-ha
167
169
  return RequestHandler
168
170
  })
169
171
 
170
- function finish (asyncEndCh, errorCh, error) {
172
+ function finish (finishCh, errorCh, error) {
171
173
  if (error) {
172
174
  errorCh.publish(error)
173
175
  }
174
- asyncEndCh.publish(undefined)
176
+ finishCh.publish(undefined)
175
177
  }
176
178
 
177
- function wrapCallback (asyncEndCh, errorCh, callback) {
178
- return AsyncResource.bind(function (err) {
179
- finish(asyncEndCh, errorCh, err)
179
+ function wrapCallback (finishCh, errorCh, asyncResource, callback) {
180
+ return asyncResource.bind(function (err) {
181
+ finish(finishCh, errorCh, err)
180
182
  if (callback) {
181
183
  return callback.apply(this, arguments)
182
184
  }