dd-trace 2.5.0 → 2.7.1

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 (84) hide show
  1. package/LICENSE-3rdparty.csv +0 -2
  2. package/index.d.ts +17 -8
  3. package/package.json +19 -23
  4. package/packages/datadog-instrumentations/index.js +15 -0
  5. package/packages/datadog-instrumentations/src/aws-sdk.js +104 -0
  6. package/packages/datadog-instrumentations/src/connect.js +111 -0
  7. package/packages/datadog-instrumentations/src/express.js +27 -0
  8. package/packages/datadog-instrumentations/src/fastify.js +187 -0
  9. package/packages/datadog-instrumentations/src/find-my-way.js +30 -0
  10. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +100 -0
  11. package/packages/datadog-instrumentations/src/http/server.js +1 -1
  12. package/packages/datadog-instrumentations/src/jest.js +175 -0
  13. package/packages/datadog-instrumentations/src/kafkajs.js +112 -0
  14. package/packages/datadog-instrumentations/src/knex.js +20 -0
  15. package/packages/datadog-instrumentations/src/koa.js +159 -0
  16. package/packages/datadog-instrumentations/src/limitd-client.js +21 -0
  17. package/packages/datadog-instrumentations/src/oracledb.js +128 -0
  18. package/packages/datadog-instrumentations/src/paperplane.js +77 -0
  19. package/packages/datadog-instrumentations/src/pg.js +2 -2
  20. package/packages/datadog-instrumentations/src/restify.js +58 -0
  21. package/packages/datadog-instrumentations/src/rhea.js +1 -1
  22. package/packages/datadog-instrumentations/src/router.js +177 -0
  23. package/packages/datadog-plugin-aws-sdk/src/base.js +146 -0
  24. package/packages/datadog-plugin-aws-sdk/src/index.js +16 -106
  25. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +4 -2
  26. package/packages/datadog-plugin-aws-sdk/src/services/default.js +7 -0
  27. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +3 -1
  28. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +5 -4
  29. package/packages/datadog-plugin-aws-sdk/src/services/index.js +12 -0
  30. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -3
  31. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +4 -3
  32. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -1
  33. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -1
  34. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +4 -3
  35. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +45 -6
  36. package/packages/datadog-plugin-connect/src/index.js +10 -114
  37. package/packages/datadog-plugin-cucumber/src/index.js +9 -21
  38. package/packages/datadog-plugin-cypress/src/plugin.js +6 -17
  39. package/packages/datadog-plugin-dns/src/index.js +12 -1
  40. package/packages/datadog-plugin-express/src/index.js +11 -25
  41. package/packages/datadog-plugin-fastify/src/index.js +17 -4
  42. package/packages/datadog-plugin-find-my-way/src/index.js +20 -0
  43. package/packages/datadog-plugin-fs/src/index.js +2 -0
  44. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +56 -111
  45. package/packages/datadog-plugin-http/src/server.js +2 -10
  46. package/packages/datadog-plugin-jest/src/index.js +101 -3
  47. package/packages/datadog-plugin-jest/src/util.js +1 -29
  48. package/packages/datadog-plugin-kafkajs/src/index.js +64 -90
  49. package/packages/datadog-plugin-koa/src/index.js +12 -164
  50. package/packages/datadog-plugin-mocha/src/index.js +5 -15
  51. package/packages/datadog-plugin-oracledb/src/index.js +34 -100
  52. package/packages/datadog-plugin-paperplane/src/index.js +14 -100
  53. package/packages/datadog-plugin-paperplane/src/logger.js +11 -0
  54. package/packages/datadog-plugin-paperplane/src/server.js +24 -0
  55. package/packages/datadog-plugin-restify/src/index.js +13 -75
  56. package/packages/datadog-plugin-router/src/index.js +67 -164
  57. package/packages/datadog-plugin-web/src/index.js +20 -0
  58. package/packages/dd-trace/lib/version.js +1 -1
  59. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +31 -11
  60. package/packages/dd-trace/src/appsec/index.js +7 -3
  61. package/packages/dd-trace/src/appsec/reporter.js +33 -3
  62. package/packages/dd-trace/src/appsec/rule_manager.js +2 -2
  63. package/packages/dd-trace/src/config.js +25 -3
  64. package/packages/dd-trace/src/format.js +9 -5
  65. package/packages/dd-trace/src/plugin_manager.js +13 -7
  66. package/packages/dd-trace/src/plugins/index.js +1 -2
  67. package/packages/dd-trace/src/plugins/log_plugin.js +8 -4
  68. package/packages/dd-trace/src/plugins/plugin.js +8 -0
  69. package/packages/dd-trace/src/plugins/util/test.js +20 -1
  70. package/packages/dd-trace/src/plugins/util/web.js +41 -12
  71. package/packages/dd-trace/src/profiling/config.js +8 -8
  72. package/packages/dd-trace/src/profiling/index.js +4 -4
  73. package/packages/dd-trace/src/profiling/profilers/{heap.js → space.js} +2 -2
  74. package/packages/dd-trace/src/profiling/profilers/{cpu.js → wall.js} +3 -3
  75. package/packages/dd-trace/src/span_processor.js +4 -1
  76. package/scripts/install_plugin_modules.js +1 -0
  77. package/packages/datadog-plugin-aws-sdk/src/helpers.js +0 -103
  78. package/packages/datadog-plugin-fastify/src/fastify.js +0 -198
  79. package/packages/datadog-plugin-fastify/src/find-my-way.js +0 -37
  80. package/packages/datadog-plugin-jest/src/jest-environment.js +0 -272
  81. package/packages/datadog-plugin-jest/src/jest-jasmine2.js +0 -185
  82. package/packages/datadog-plugin-knex/src/index.js +0 -23
  83. package/packages/datadog-plugin-limitd-client/src/index.js +0 -30
  84. package/scripts/postpublish.js +0 -24
@@ -39,8 +39,6 @@ dev,eslint-plugin-import,MIT,Copyright 2015 Ben Mosher
39
39
  dev,eslint-plugin-node,MIT,Copyright 2015 Toru Nagashima
40
40
  dev,eslint-plugin-promise,ISC,jden and other contributors
41
41
  dev,eslint-plugin-standard,MIT,Copyright 2015 Jamund Ferguson
42
- dev,mocha-junit-reporter,MIT,Copyright 2015 Michael Allen
43
- dev,mocha-multi-reporters,MIT,Copyright 2015 Stanley Ng 2019 Yousaf Nabi
44
42
  dev,express,MIT,Copyright 2009-2014 TJ Holowaychuk 2013-2014 Roman Shtylman 2014-2015 Douglas Christopher Wilson
45
43
  dev,get-port,MIT,Copyright Sindre Sorhus
46
44
  dev,glob,ISC,Copyright Isaac Z. Schlueter and Contributors
package/index.d.ts CHANGED
@@ -428,7 +428,23 @@ export declare interface TracerOptions {
428
428
  * Controls the maximum amount of traces sampled by AppSec attacks, per second.
429
429
  * @default 100
430
430
  */
431
- rateLimit?: number
431
+ rateLimit?: number,
432
+
433
+ /**
434
+ * Controls the maximum amount of time in microseconds the WAF is allowed to run synchronously for.
435
+ * @default 5000
436
+ */
437
+ wafTimeout?: number,
438
+
439
+ /**
440
+ * Specifies a regex that will redact sensitive data by its key in attack reports.
441
+ */
442
+ obfuscatorKeyRegex?: string,
443
+
444
+ /**
445
+ * Specifies a regex that will redact sensitive data by its value in attack reports.
446
+ */
447
+ obfuscatorValueRegex?: string
432
448
  };
433
449
  }
434
450
 
@@ -559,7 +575,6 @@ interface Plugins {
559
575
  "kafkajs": plugins.kafkajs
560
576
  "knex": plugins.knex;
561
577
  "koa": plugins.koa;
562
- "limitd-client": plugins.limitd_client;
563
578
  "memcached": plugins.memcached;
564
579
  "microgateway-core": plugins.microgateway_core;
565
580
  "mocha": plugins.mocha;
@@ -1143,12 +1158,6 @@ declare namespace plugins {
1143
1158
  */
1144
1159
  interface kafkajs extends Instrumentation {}
1145
1160
 
1146
- /**
1147
- * This plugin automatically instruments the
1148
- * [limitd-client](https://github.com/limitd/node-client) module.
1149
- */
1150
- interface limitd_client extends Integration {}
1151
-
1152
1161
  /**
1153
1162
  * This plugin automatically instruments the
1154
1163
  * [memcached](https://github.com/3rd-Eden/memcached) module.
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "2.5.0",
3
+ "version": "2.7.1",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
7
7
  "scripts": {
8
8
  "preinstall": "node scripts/preinstall.js",
9
- "postpublish": "node scripts/postpublish.js",
10
9
  "bench": "node benchmark",
11
10
  "bench:profiler": "node benchmark/profiler",
12
11
  "bench:e2e": "SERVICES=mongo yarn services && cd benchmark/e2e && node benchmark-run.js --duration=30",
@@ -16,24 +15,23 @@
16
15
  "lint": "node scripts/check_licenses.js && eslint . && yarn audit --groups dependencies",
17
16
  "services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
18
17
  "tdd": "node scripts/tdd.js",
19
- "test": "SERVICES=* yarn services && mocha --exit --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
20
- "test:trace:core": "mocha --exit --expose-gc --file packages/dd-trace/test/setup/core.js \"packages/dd-trace/test/**/*.spec.js\"",
21
- "test:trace:core:ci": "nyc --include \"packages/dd-trace/src/**/*.js\" -- npm run test:trace:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
22
- "test:instrumentations": "mocha --file 'packages/dd-trace/test/setup/core.js' 'packages/datadog-instrumentations/test/**/*.spec.js'",
23
- "test:instrumentations:ci": "nyc --include 'packages/datadog-instrumentations/src/**/*.js' -- npm run test:instrumentations -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
24
- "test:core": "mocha --file packages/datadog-core/test/setup.js 'packages/datadog-core/test/**/*.spec.js'",
25
- "test:core:ci": "nyc --include 'packages/datadog-core/src/**/*.js' -- npm run test:core -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
26
- "test:plugins": "mocha --exit --file \"packages/dd-trace/test/setup/core.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/*.spec.js\"",
27
- "test:plugins:ci": "yarn services && nyc --include \"packages/datadog-plugin-@($(echo $PLUGINS))/src/**/*.js\" -- npm run test:plugins -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
18
+ "test": "SERVICES=* yarn services && mocha --colors --exit --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
19
+ "test:trace:core": "mocha --colors --exit --expose-gc --file packages/dd-trace/test/setup/core.js --exclude \"packages/dd-trace/test/profiling/**/*.spec.js\" \"packages/dd-trace/test/**/*.spec.js\"",
20
+ "test:trace:core:ci": "nyc --no-clean --include \"packages/dd-trace/src/**/*.js\" --exclude \"packages/dd-trace/src/profiling/**/*.js\" -- npm run test:trace:core",
21
+ "test:instrumentations": "mocha --colors --file 'packages/dd-trace/test/setup/core.js' 'packages/datadog-instrumentations/test/**/*.spec.js'",
22
+ "test:instrumentations:ci": "nyc --no-clean --include 'packages/datadog-instrumentations/src/**/*.js' -- npm run test:instrumentations",
23
+ "test:core": "mocha --colors --file packages/datadog-core/test/setup.js 'packages/datadog-core/test/**/*.spec.js'",
24
+ "test:core:ci": "nyc --no-clean --include 'packages/datadog-core/src/**/*.js' -- npm run test:core",
25
+ "test:plugins": "mocha --colors --exit --file \"packages/dd-trace/test/setup/core.js\" \"packages/datadog-instrumentations/test/@($(echo $PLUGINS)).spec.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/*.spec.js\"",
26
+ "test:plugins:ci": "yarn services && nyc --no-clean --include \"packages/datadog-instrumentations/src/@($(echo $PLUGINS)).js\" --include \"packages/datadog-instrumentations/src/@($(echo $PLUGINS))/**/*.js\" --include \"packages/datadog-plugin-@($(echo $PLUGINS))/src/**/*.js\" -- npm run test:plugins",
28
27
  "test:plugins:upstream": "node ./packages/dd-trace/test/plugins/suite.js",
29
- "test:profiler": "mocha --exit --file \"packages/dd-trace/test/setup/core.js\" \"packages/dd-trace/test/profiling/**/*.spec.js\"",
30
- "test:integration": "mocha --timeout 30000 \"integration-tests/**/*.spec.js\"",
31
- "test:shimmer": "mocha 'packages/datadog-shimmer/test/**/*.spec.js'",
32
- "test:shimmer:ci": "nyc --include 'packages/datadog-shimmer/src/**/*.js' -- npm run test:shimmer -- --reporter mocha-multi-reporters --reporter-options configFile=mocha-reporter-config.json",
28
+ "test:profiler": "mocha --colors --exit --file \"packages/dd-trace/test/setup/core.js\" \"packages/dd-trace/test/profiling/**/*.spec.js\"",
29
+ "test:profiler:ci": "nyc --no-clean --include \"packages/dd-trace/src/profiling/**/*.js\" -- npm run test:profiler",
30
+ "test:integration": "mocha --colors --timeout 30000 \"integration-tests/**/*.spec.js\"",
31
+ "test:shimmer": "mocha --colors 'packages/datadog-shimmer/test/**/*.spec.js'",
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
- "cover:merge": "nyc merge ./.nyc_output ./.nyc_merge/$CIRCLE_JOB.json",
36
- "cover:report": "nyc report -t ./.nyc_merge -n 'packages/**/*.js'",
37
35
  "codecov": "codecov",
38
36
  "junit:upload": "node ./scripts/junit_report.js"
39
37
  },
@@ -61,9 +59,9 @@
61
59
  "node": ">=12"
62
60
  },
63
61
  "dependencies": {
64
- "@datadog/native-appsec": "^1.0.1",
65
- "@datadog/native-metrics": "^1.1.0",
66
- "@datadog/pprof": "^0.3.0",
62
+ "@datadog/native-appsec": "^1.1.1",
63
+ "@datadog/native-metrics": "^1.2.0",
64
+ "@datadog/pprof": "^0.4.0",
67
65
  "@datadog/sketches-js": "^1.0.4",
68
66
  "@types/node": ">=12",
69
67
  "crypto-randomuuid": "^1.0.0",
@@ -97,7 +95,7 @@
97
95
  "cli-table3": "^0.5.1",
98
96
  "codecov": "3.8.1",
99
97
  "dotenv": "8.2.0",
100
- "eslint": "^4.15.0",
98
+ "eslint": "^7.32.0",
101
99
  "eslint-config-standard": "^11.0.0-beta.0",
102
100
  "eslint-plugin-import": "^2.8.0",
103
101
  "eslint-plugin-node": "^5.2.1",
@@ -111,8 +109,6 @@
111
109
  "jszip": "^3.5.0",
112
110
  "mkdirp": "^0.5.1",
113
111
  "mocha": "8",
114
- "mocha-junit-reporter": "^2.0.0",
115
- "mocha-multi-reporters": "^1.5.1",
116
112
  "msgpack-lite": "^0.1.26",
117
113
  "nock": "^11.3.3",
118
114
  "nyc": "^15.1.0",
@@ -2,16 +2,26 @@
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')
9
+ require('./src/connect')
8
10
  require('./src/couchbase')
9
11
  require('./src/cucumber')
10
12
  require('./src/dns')
11
13
  require('./src/elasticsearch')
14
+ require('./src/express')
15
+ require('./src/fastify')
16
+ require('./src/find-my-way')
12
17
  require('./src/generic-pool')
18
+ require('./src/google-cloud-pubsub')
13
19
  require('./src/http')
14
20
  require('./src/ioredis')
21
+ require('./src/jest')
22
+ require('./src/kafkajs')
23
+ require('./src/knex')
24
+ require('./src/koa')
15
25
  require('./src/memcached')
16
26
  require('./src/mongodb-core')
17
27
  require('./src/mongoose')
@@ -19,14 +29,19 @@ require('./src/mysql')
19
29
  require('./src/mysql2')
20
30
  require('./src/mocha')
21
31
  require('./src/net')
32
+ require('./src/oracledb')
33
+ require('./src/paperplane')
22
34
  require('./src/pino')
23
35
  require('./src/pg')
24
36
  require('./src/promise')
25
37
  require('./src/promise-js')
26
38
  require('./src/q')
27
39
  require('./src/redis')
40
+ require('./src/restify')
41
+ require('./src/router')
28
42
  require('./src/rhea')
29
43
  require('./src/sharedb')
30
44
  require('./src/tedious')
31
45
  require('./src/when')
32
46
  require('./src/winston')
47
+ require('./src/limitd-client')
@@ -0,0 +1,104 @@
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 outerAr = new AsyncResource('apm:aws:request:outer')
19
+
20
+ this.on('complete', response => {
21
+ channel(`apm:aws:request:complete:${channelSuffix}`).publish({ response })
22
+ })
23
+
24
+ return new AsyncResource('apm:aws:request:inner').runInAsyncScope(() => {
25
+ startCh.publish({
26
+ serviceIdentifier,
27
+ operation: this.operation,
28
+ awsRegion: this.service.config && this.service.config.region,
29
+ awsService: this.service.api && this.service.api.className,
30
+ request: this
31
+ })
32
+
33
+ if (typeof cb === 'function') {
34
+ arguments[0] = wrapCb(cb, channelSuffix, this, outerAr)
35
+ }
36
+ return send.apply(this, arguments)
37
+ })
38
+ }
39
+ }
40
+
41
+ function wrapCb (cb, serviceName, request, ar) {
42
+ return function wrappedCb (err, response) {
43
+ const obj = { request, response }
44
+ return ar.runInAsyncScope(() => {
45
+ channel(`apm:aws:response:start:${serviceName}`).publish(obj)
46
+ // TODO(bengl) make this work without needing a needsFinish property added to the object
47
+ if (!obj.needsFinish) {
48
+ return cb.apply(this, arguments)
49
+ }
50
+ const finishChannel = channel(`apm:aws:response:finish:${serviceName}`)
51
+ try {
52
+ let result = cb.apply(this, arguments)
53
+ if (result && result.then) {
54
+ result = result.then(x => {
55
+ finishChannel.publish()
56
+ return x
57
+ }, e => {
58
+ finishChannel.publish(e)
59
+ throw e
60
+ })
61
+ } else {
62
+ finishChannel.publish()
63
+ }
64
+ return result
65
+ } catch (e) {
66
+ finishChannel.publish(e)
67
+ throw e
68
+ }
69
+ })
70
+ }
71
+ }
72
+
73
+ function getChannelSuffix (name) {
74
+ return [
75
+ 'cloudwatchlogs',
76
+ 'dynamodb',
77
+ 'eventbridge',
78
+ 'kinesis',
79
+ 'lambda',
80
+ 'redshift',
81
+ 's3',
82
+ 'sns',
83
+ 'sqs'
84
+ ].includes(name) ? name : 'default'
85
+ }
86
+
87
+ addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
88
+ shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
89
+ shimmer.wrap(AWS.config, 'setPromisesDependency', setPromisesDependency => {
90
+ return function wrappedSetPromisesDependency (dep) {
91
+ const result = setPromisesDependency.apply(this, arguments)
92
+ shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
93
+ return result
94
+ }
95
+ })
96
+ return AWS
97
+ })
98
+
99
+ // <2.1.35 has breaking changes for instrumentation
100
+ // https://github.com/aws/aws-sdk-js/pull/629
101
+ addHook({ name: 'aws-sdk', versions: ['>=2.1.35'] }, AWS => {
102
+ shimmer.wrap(AWS.Request.prototype, 'send', wrapRequest)
103
+ return AWS
104
+ })
@@ -0,0 +1,111 @@
1
+ 'use strict'
2
+
3
+ const shimmer = require('../../datadog-shimmer')
4
+ const { addHook, channel, AsyncResource } = require('./helpers/instrument')
5
+
6
+ const enterChannel = channel('apm:connect:middleware:enter')
7
+ const errorChannel = channel('apm:connect:middleware:error')
8
+ const exitChannel = channel('apm:connect:middleware:exit')
9
+ const handleChannel = channel('apm:connect:request:handle')
10
+
11
+ function wrapConnect (connect) {
12
+ if (typeof connect !== 'function') return connect
13
+
14
+ return function connectWithTrace () {
15
+ const app = connect()
16
+
17
+ if (!app) return app
18
+
19
+ shimmer.wrap(app, 'use', wrapUse)
20
+ shimmer.wrap(app, 'handle', wrapHandle)
21
+
22
+ return app
23
+ }
24
+ }
25
+
26
+ function wrapUse (use) {
27
+ if (typeof use !== 'function') return use
28
+
29
+ return function useWithTrace (route, fn) {
30
+ const result = use.apply(this, arguments)
31
+
32
+ if (!this || !Array.isArray(this.stack)) return result
33
+
34
+ const index = this.stack.length - 1
35
+ const layer = this.stack[index]
36
+
37
+ if (layer && layer.handle) {
38
+ this.stack[index].handle = wrapLayerHandle(layer)
39
+ }
40
+
41
+ return result
42
+ }
43
+ }
44
+
45
+ function wrapHandle (handle) {
46
+ return function handleWithTrace (req, res) {
47
+ if (handleChannel.hasSubscribers) {
48
+ handleChannel.publish({ req, res })
49
+ }
50
+
51
+ return handle.apply(this, arguments)
52
+ }
53
+ }
54
+
55
+ function wrapLayerHandle (layer) {
56
+ if (typeof layer.handle !== 'function') return layer.handle
57
+
58
+ const original = layer.handle
59
+
60
+ return shimmer.wrap(original, function () {
61
+ if (!enterChannel.hasSubscribers) return original.apply(this, arguments)
62
+
63
+ const middlewareResource = new AsyncResource('bound-anonymous-fn')
64
+ const lastIndex = arguments.length - 1
65
+ const name = original._name || original.name
66
+ const req = arguments[arguments.length > 3 ? 1 : 0]
67
+ const next = AsyncResource.bind(arguments[lastIndex])
68
+
69
+ if (typeof next === 'function') {
70
+ arguments[lastIndex] = wrapNext(req, middlewareResource.bind(next))
71
+ }
72
+
73
+ return middlewareResource.runInAsyncScope(() => {
74
+ const route = layer.route
75
+
76
+ enterChannel.publish({ name, req, route })
77
+
78
+ try {
79
+ return original.apply(this, arguments)
80
+ } catch (e) {
81
+ errorChannel.publish(e)
82
+ exitChannel.publish({ req })
83
+
84
+ throw e
85
+ }
86
+ })
87
+ })
88
+ }
89
+
90
+ function wrapNext (req, next) {
91
+ return function (error) {
92
+ if (error) {
93
+ errorChannel.publish(error)
94
+ }
95
+
96
+ exitChannel.publish({ req })
97
+
98
+ next.apply(null, arguments)
99
+ }
100
+ }
101
+
102
+ addHook({ name: 'connect', versions: ['>=3'] }, connect => {
103
+ return shimmer.wrap(connect, wrapConnect(connect))
104
+ })
105
+
106
+ addHook({ name: 'connect', versions: ['2.2.2'] }, connect => {
107
+ shimmer.wrap(connect.proto, 'use', wrapUse)
108
+ shimmer.wrap(connect.proto, 'handle', wrapHandle)
109
+
110
+ return connect
111
+ })
@@ -0,0 +1,27 @@
1
+ 'use strict'
2
+
3
+ const { createWrapRouterMethod } = require('./router')
4
+ const shimmer = require('../../datadog-shimmer')
5
+ const { addHook, channel } = require('./helpers/instrument')
6
+
7
+ const handleChannel = channel('apm:express:request:handle')
8
+
9
+ function wrapHandle (handle) {
10
+ return function handleWithTrace (req, res) {
11
+ if (handleChannel.hasSubscribers) {
12
+ handleChannel.publish({ req })
13
+ }
14
+
15
+ return handle.apply(this, arguments)
16
+ }
17
+ }
18
+
19
+ const wrapRouterMethod = createWrapRouterMethod('express')
20
+
21
+ addHook({ name: 'express', versions: ['>=4'] }, express => {
22
+ shimmer.wrap(express.application, 'handle', wrapHandle)
23
+ shimmer.wrap(express.Router, 'use', wrapRouterMethod)
24
+ shimmer.wrap(express.Router, 'route', wrapRouterMethod)
25
+
26
+ return express
27
+ })
@@ -0,0 +1,187 @@
1
+ 'use strict'
2
+
3
+ const methods = require('methods').concat('all')
4
+ const shimmer = require('../../datadog-shimmer')
5
+ const { addHook, channel, AsyncResource } = require('./helpers/instrument')
6
+
7
+ const errorChannel = channel('apm:fastify:middleware:error')
8
+ const handleChannel = channel('apm:fastify:request:handle')
9
+
10
+ const requestResources = new WeakMap()
11
+
12
+ function wrapFastify (fastify) {
13
+ if (typeof fastify !== 'function') return fastify
14
+
15
+ return function fastifyWithTrace () {
16
+ const app = fastify.apply(this, arguments)
17
+
18
+ if (!app) return app
19
+
20
+ if (typeof app.addHook === 'function') {
21
+ app.addHook('onRequest', onRequest)
22
+ app.addHook = wrapAddHook(app.addHook)
23
+ app.addHook('preHandler', preHandler)
24
+ }
25
+
26
+ methods.forEach(method => {
27
+ app[method] = wrapMethod(app[method])
28
+ })
29
+
30
+ app.route = wrapRoute(app.route)
31
+
32
+ return app
33
+ }
34
+ }
35
+
36
+ function wrapAddHook (addHook) {
37
+ return function addHookWithTrace (name, fn) {
38
+ fn = arguments[arguments.length - 1]
39
+
40
+ if (typeof fn !== 'function') return addHook.apply(this, arguments)
41
+
42
+ arguments[arguments.length - 1] = shimmer.wrap(fn, function (request, reply, done) {
43
+ const req = getReq(request)
44
+ const requestResource = requestResources.get(req)
45
+
46
+ if (!requestResource) return fn.apply(this, arguments)
47
+
48
+ return requestResource.runInAsyncScope(() => {
49
+ const hookResource = new AsyncResource('bound-anonymous-fn')
50
+
51
+ try {
52
+ if (typeof done === 'function') {
53
+ done = arguments[arguments.length - 1]
54
+
55
+ arguments[arguments.length - 1] = hookResource.bind(function (err) {
56
+ errorChannel.publish(err)
57
+ return done.apply(this, arguments)
58
+ })
59
+
60
+ return hookResource.bind(fn).apply(this, arguments)
61
+ } else {
62
+ const promise = hookResource.bind(fn).apply(this, arguments)
63
+
64
+ if (promise && typeof promise.catch === 'function') {
65
+ return promise.catch(err => {
66
+ errorChannel.publish(err)
67
+ throw err
68
+ })
69
+ }
70
+
71
+ return promise
72
+ }
73
+ } catch (e) {
74
+ errorChannel.publish(e)
75
+ throw e
76
+ }
77
+ })
78
+ })
79
+
80
+ return addHook.apply(this, arguments)
81
+ }
82
+ }
83
+
84
+ function onRequest (request, reply, next) {
85
+ if (typeof next !== 'function') return
86
+
87
+ const req = getReq(request)
88
+ const res = getRes(reply)
89
+
90
+ requestResources.set(req, new AsyncResource('bound-anonymous-fn'))
91
+ handleChannel.publish({ req, res })
92
+
93
+ return next()
94
+ }
95
+
96
+ function preHandler (request, reply, next) {
97
+ if (typeof next !== 'function') return
98
+ if (!reply || typeof reply.send !== 'function') return next()
99
+
100
+ const req = getReq(request)
101
+
102
+ reply.send = requestResources.get(req).bind(wrapSend(reply.send))
103
+
104
+ next()
105
+ }
106
+
107
+ function wrapSend (send) {
108
+ return function sendWithTrace (payload) {
109
+ if (payload instanceof Error) {
110
+ errorChannel.publish(payload)
111
+ }
112
+
113
+ return send.apply(this, arguments)
114
+ }
115
+ }
116
+
117
+ function wrapRoute (route) {
118
+ if (typeof route !== 'function') return route
119
+
120
+ return function routeWithTrace (opts) {
121
+ opts.handler = wrapHandler(opts.handler)
122
+
123
+ return route.apply(this, arguments)
124
+ }
125
+ }
126
+
127
+ function wrapMethod (method) {
128
+ if (typeof method !== 'function') return method
129
+
130
+ return function methodWithTrace (url, opts, handler) {
131
+ const lastIndex = arguments.length - 1
132
+
133
+ handler = arguments[lastIndex]
134
+
135
+ if (typeof handler === 'function') {
136
+ arguments[lastIndex] = wrapHandler(handler)
137
+ } else if (handler) {
138
+ arguments[lastIndex].handler = wrapHandler(handler.handler)
139
+ }
140
+
141
+ return method.apply(this, arguments)
142
+ }
143
+ }
144
+
145
+ function wrapHandler (handler) {
146
+ if (!handler || typeof handler !== 'function' || handler.name === 'handlerWithTrace') {
147
+ return handler
148
+ }
149
+
150
+ return function handlerWithTrace (request, reply) {
151
+ const req = getReq(request)
152
+
153
+ return requestResources.get(req).runInAsyncScope(() => {
154
+ return handler.apply(this, arguments)
155
+ })
156
+ }
157
+ }
158
+
159
+ function getReq (request) {
160
+ return request && (request.raw || request.req || request)
161
+ }
162
+
163
+ function getRes (reply) {
164
+ return reply && (reply.raw || reply.res || reply)
165
+ }
166
+
167
+ addHook({ name: 'fastify', versions: ['>=3.25.2'] }, fastify => {
168
+ const wrapped = shimmer.wrap(fastify, wrapFastify(fastify, false))
169
+
170
+ wrapped.fastify = wrapped
171
+ wrapped.default = wrapped
172
+
173
+ return wrapped
174
+ })
175
+
176
+ addHook({ name: 'fastify', versions: ['3 - 3.25.1'] }, fastify => {
177
+ const wrapped = shimmer.wrap(fastify, wrapFastify(fastify, true))
178
+
179
+ wrapped.fastify = wrapped
180
+ wrapped.default = wrapped
181
+
182
+ return wrapped
183
+ })
184
+
185
+ addHook({ name: 'fastify', versions: ['1 - 2'] }, fastify => {
186
+ return shimmer.wrap(fastify, wrapFastify(fastify, true))
187
+ })
@@ -0,0 +1,30 @@
1
+ 'use strict'
2
+
3
+ const shimmer = require('../../datadog-shimmer')
4
+ const { addHook, channel } = require('./helpers/instrument')
5
+
6
+ const routeChannel = channel('apm:find-my-way:request:route')
7
+
8
+ function wrapOn (on) {
9
+ return function onWithTrace (method, path, opts) {
10
+ const index = typeof opts === 'function' ? 2 : 3
11
+ const handler = arguments[index]
12
+ const wrapper = function (req) {
13
+ routeChannel.publish({ req, route: path })
14
+
15
+ return handler.apply(this, arguments)
16
+ }
17
+
18
+ if (typeof handler === 'function') {
19
+ arguments[index] = wrapper
20
+ }
21
+
22
+ return on.apply(this, arguments)
23
+ }
24
+ }
25
+
26
+ addHook({ name: 'find-my-way', versions: ['>=1'] }, Router => {
27
+ shimmer.wrap(Router.prototype, 'on', wrapOn)
28
+
29
+ return Router
30
+ })