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
@@ -1,118 +1,28 @@
1
1
  'use strict'
2
2
 
3
- const Tags = require('opentracing').Tags
4
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
5
- const awsHelpers = require('./helpers')
3
+ const Plugin = require('../../dd-trace/src/plugins/plugin')
6
4
 
7
- function createWrapRequest (tracer, config) {
8
- config = normalizeConfig(config)
9
- return function wrapRequest (send) {
10
- return function requestWithTrace (cb) {
11
- if (!this.service) return send.apply(this, arguments)
5
+ const services = require('./services')
12
6
 
13
- const serviceIdentifier = this.service.serviceIdentifier
14
-
15
- if (!awsHelpers.isEnabled(serviceIdentifier, config[serviceIdentifier], this)) {
16
- return send.apply(this, arguments)
17
- }
18
-
19
- const serviceName = getServiceName(serviceIdentifier, tracer, config)
20
- const childOf = tracer.scope().active()
21
- const tags = {
22
- [Tags.SPAN_KIND]: 'client',
23
- 'service.name': serviceName,
24
- 'aws.operation': this.operation,
25
- 'aws.region': this.service.config && this.service.config.region,
26
- 'aws.service': this.service.api && this.service.api.className,
27
- 'component': 'aws-sdk'
28
- }
29
-
30
- const span = tracer.startSpan('aws.request', {
31
- childOf,
32
- tags
33
- })
34
-
35
- this.on('complete', response => {
36
- if (!span) return
37
-
38
- awsHelpers.addResponseTags(span, response, serviceIdentifier, config, tracer)
39
- awsHelpers.finish(config, span, response, response.error)
40
- })
41
-
42
- analyticsSampler.sample(span, config.measured)
43
-
44
- awsHelpers.requestInject(span, this, serviceIdentifier, tracer)
45
-
46
- const request = this
7
+ class AwsSdkPlugin extends Plugin {
8
+ static get name () {
9
+ return 'aws-sdk'
10
+ }
47
11
 
48
- return tracer.scope().activate(span, () => {
49
- if (typeof cb === 'function') {
50
- arguments[0] = awsHelpers.wrapCb(cb, serviceIdentifier, tags, request, tracer, childOf)
51
- }
52
- return send.apply(this, arguments)
53
- })
12
+ constructor (...args) {
13
+ super(...args)
14
+ this.services = {}
15
+ for (const name in services) {
16
+ const ServicePlugin = services[name]
17
+ this.services[name] = new ServicePlugin(...args)
54
18
  }
55
19
  }
56
- }
57
-
58
- function createWrapSetPromisesDependency (tracer, config, instrumenter, AWS) {
59
- return function wrapSetPromisesDependency (setPromisesDependency) {
60
- return function setPromisesDependencyWithTrace (dep) {
61
- const result = setPromisesDependency.apply(this, arguments)
62
-
63
- instrumenter.wrap(AWS.Request.prototype, 'promise', createWrapRequest(tracer, config))
64
20
 
65
- return result
21
+ configure (config) {
22
+ for (const service of Object.values(this.services)) {
23
+ service.configure(config)
66
24
  }
67
25
  }
68
26
  }
69
27
 
70
- function normalizeConfig (config) {
71
- const hooks = getHooks(config)
72
-
73
- return Object.assign({}, config, {
74
- splitByAwsService: config.splitByAwsService !== false,
75
- hooks
76
- })
77
- }
78
-
79
- function getHooks (config) {
80
- const noop = () => {}
81
- const request = (config.hooks && config.hooks.request) || noop
82
-
83
- return { request }
84
- }
85
-
86
- // TODO: test splitByAwsService when the test suite is fixed
87
- function getServiceName (serviceIdentifier, tracer, config) {
88
- return config.service
89
- ? config.service
90
- : `${tracer._service}-aws-${serviceIdentifier}`
91
- }
92
-
93
- // <2.1.35 has breaking changes for instrumentation
94
- // https://github.com/aws/aws-sdk-js/pull/629
95
- module.exports = [
96
- {
97
- name: 'aws-sdk',
98
- versions: ['>=2.3.0'],
99
- patch (AWS, tracer, config) {
100
- this.wrap(AWS.Request.prototype, 'promise', createWrapRequest(tracer, config))
101
- this.wrap(AWS.config, 'setPromisesDependency', createWrapSetPromisesDependency(tracer, config, this, AWS))
102
- },
103
- unpatch (AWS) {
104
- this.unwrap(AWS.Request.prototype, 'promise')
105
- this.unwrap(AWS.config, 'setPromisesDependency')
106
- }
107
- },
108
- {
109
- name: 'aws-sdk',
110
- versions: ['>=2.1.35'],
111
- patch (AWS, tracer, config) {
112
- this.wrap(AWS.Request.prototype, 'send', createWrapRequest(tracer, config))
113
- },
114
- unpatch (AWS) {
115
- this.unwrap(AWS.Request.prototype, 'send')
116
- }
117
- }
118
- ]
28
+ module.exports = AwsSdkPlugin
@@ -1,7 +1,9 @@
1
1
  'use strict'
2
2
 
3
- class CloudwatchLogs {
4
- generateTags (params, operation, response) {
3
+ const BaseAwsSdkPlugin = require('../base')
4
+
5
+ class CloudwatchLogs extends BaseAwsSdkPlugin {
6
+ generateTags (params, operation) {
5
7
  const tags = {}
6
8
 
7
9
  if (!params || !params.logGroupName) return tags
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+
3
+ const BaseAwsSdkPlugin = require('../base')
4
+
5
+ class Default extends BaseAwsSdkPlugin {}
6
+
7
+ module.exports = Default
@@ -1,6 +1,8 @@
1
1
  'use strict'
2
2
 
3
- class DynamoDb {
3
+ const BaseAwsSdkPlugin = require('../base')
4
+
5
+ class DynamoDb extends BaseAwsSdkPlugin {
4
6
  generateTags (params, operation, response) {
5
7
  const tags = {}
6
8
 
@@ -1,6 +1,8 @@
1
1
  'use strict'
2
2
  const log = require('../../../dd-trace/src/log')
3
- class EventBridge {
3
+ const BaseAwsSdkPlugin = require('../base')
4
+
5
+ class EventBridge extends BaseAwsSdkPlugin {
4
6
  generateTags (params, operation, response) {
5
7
  if (!params || !params.source) return {}
6
8
 
@@ -14,14 +16,13 @@ class EventBridge {
14
16
  * requestInject
15
17
  * @param {*} span
16
18
  * @param {*} request
17
- * @param {*} tracer
18
19
  *
19
20
  * Docs: https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEventsRequestEntry.html
20
21
  * We cannot use the traceHeader field as that's reserved for X-Ray.
21
22
  * Detail must be a valid JSON string
22
23
  * Max size per event is 256kb (https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevent-size.html)
23
24
  */
24
- requestInject (span, request, tracer) {
25
+ requestInject (span, request) {
25
26
  const operation = request.operation
26
27
  if (operation === 'putEvents' &&
27
28
  request.params &&
@@ -31,7 +32,7 @@ class EventBridge {
31
32
  try {
32
33
  const details = JSON.parse(request.params.Entries[0].Detail)
33
34
  details._datadog = {}
34
- tracer.inject(span, 'text_map', details._datadog)
35
+ this.tracer.inject(span, 'text_map', details._datadog)
35
36
  const finalData = JSON.stringify(details)
36
37
  const byteSize = Buffer.byteLength(finalData)
37
38
  if (byteSize >= (1024 * 256)) {
@@ -0,0 +1,12 @@
1
+ 'use strict'
2
+
3
+ exports.cloudwatchlogs = require('./cloudwatchlogs')
4
+ exports.dynamodb = require('./dynamodb')
5
+ exports.eventbridge = require('./eventbridge')
6
+ exports.kinesis = require('./kinesis')
7
+ exports.lambda = require('./lambda')
8
+ exports.redshift = require('./redshift')
9
+ exports.s3 = require('./s3')
10
+ exports.sns = require('./sns')
11
+ exports.sqs = require('./sqs')
12
+ exports.default = require('./default')
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
  const log = require('../../../dd-trace/src/log')
3
- class Kinesis {
3
+ const BaseAwsSdkPlugin = require('../base')
4
+ class Kinesis extends BaseAwsSdkPlugin {
4
5
  generateTags (params, operation, response) {
5
6
  if (!params || !params.StreamName) return {}
6
7
 
@@ -26,7 +27,7 @@ class Kinesis {
26
27
  }
27
28
  }
28
29
 
29
- requestInject (span, request, tracer) {
30
+ requestInject (span, request) {
30
31
  const operation = request.operation
31
32
  if (operation === 'putRecord' || operation === 'putRecords') {
32
33
  if (!request.params) {
@@ -34,7 +35,7 @@ class Kinesis {
34
35
  }
35
36
 
36
37
  const traceData = {}
37
- tracer.inject(span, 'text_map', traceData)
38
+ this.tracer.inject(span, 'text_map', traceData)
38
39
  let injectPath
39
40
  if (request.params.Records && request.params.Records.length > 0) {
40
41
  injectPath = request.params.Records[0]
@@ -1,8 +1,9 @@
1
1
  'use strict'
2
2
 
3
3
  const log = require('../../../dd-trace/src/log')
4
+ const BaseAwsSdkPlugin = require('../base')
4
5
 
5
- class Lambda {
6
+ class Lambda extends BaseAwsSdkPlugin {
6
7
  generateTags (params, operation, response) {
7
8
  const tags = {}
8
9
 
@@ -14,7 +15,7 @@ class Lambda {
14
15
  })
15
16
  }
16
17
 
17
- requestInject (span, request, tracer) {
18
+ requestInject (span, request) {
18
19
  const operation = request.operation
19
20
  if (operation === 'invoke') {
20
21
  if (!request.params) {
@@ -35,7 +36,7 @@ class Lambda {
35
36
  if (!clientContext.custom) {
36
37
  clientContext.custom = {}
37
38
  }
38
- tracer.inject(span, 'text_map', clientContext.custom)
39
+ this.tracer.inject(span, 'text_map', clientContext.custom)
39
40
  const newContextBase64 = Buffer.from(JSON.stringify(clientContext)).toString('base64')
40
41
  request.params.ClientContext = newContextBase64
41
42
  } catch (err) {
@@ -1,6 +1,8 @@
1
1
  'use strict'
2
2
 
3
- class Redshift {
3
+ const BaseAwsSdkPlugin = require('../base')
4
+
5
+ class Redshift extends BaseAwsSdkPlugin {
4
6
  generateTags (params, operation, response) {
5
7
  const tags = {}
6
8
 
@@ -1,6 +1,8 @@
1
1
  'use strict'
2
2
 
3
- class S3 {
3
+ const BaseAwsSdkPlugin = require('../base')
4
+
5
+ class S3 extends BaseAwsSdkPlugin {
4
6
  generateTags (params, operation, response) {
5
7
  const tags = {}
6
8
 
@@ -1,7 +1,8 @@
1
1
  'use strict'
2
2
  const log = require('../../../dd-trace/src/log')
3
+ const BaseAwsSdkPlugin = require('../base')
3
4
 
4
- class Sns {
5
+ class Sns extends BaseAwsSdkPlugin {
5
6
  generateTags (params, operation, response) {
6
7
  if (!params) return {}
7
8
 
@@ -16,7 +17,7 @@ class Sns {
16
17
  // for example if it contains a phone number?
17
18
  }
18
19
 
19
- requestInject (span, request, tracer) {
20
+ requestInject (span, request) {
20
21
  const operation = request.operation
21
22
  if (operation === 'publish' || operation === 'publishBatch') {
22
23
  if (!request.params) {
@@ -36,7 +37,7 @@ class Sns {
36
37
  return
37
38
  }
38
39
  const ddInfo = {}
39
- tracer.inject(span, 'text_map', ddInfo)
40
+ this.tracer.inject(span, 'text_map', ddInfo)
40
41
  injectPath.MessageAttributes._datadog = {
41
42
  DataType: 'Binary',
42
43
  BinaryValue: JSON.stringify(ddInfo) // BINARY types are automatically base64 encoded
@@ -1,9 +1,48 @@
1
1
  'use strict'
2
2
 
3
+ const Tags = require('opentracing').Tags
3
4
  const log = require('../../../dd-trace/src/log')
5
+ const BaseAwsSdkPlugin = require('../base')
6
+ const { storage } = require('../../../datadog-core')
4
7
 
5
- class Sqs {
6
- isEnabled (config, request) {
8
+ class Sqs extends BaseAwsSdkPlugin {
9
+ constructor (...args) {
10
+ super(...args)
11
+ //
12
+ // TODO(bengl) Find a way to create the response span tags without this WeakMap being populated
13
+ // in the base class
14
+ this.requestTags = new WeakMap()
15
+
16
+ this.addSub('apm:aws:response:start:sqs', obj => {
17
+ const { request, response } = obj
18
+ const store = storage.getStore()
19
+ const plugin = this
20
+ const maybeChildOf = this.responseExtract(request.params, request.operation, response)
21
+ if (maybeChildOf) {
22
+ obj.needsFinish = true
23
+ const options = {
24
+ childOf: maybeChildOf,
25
+ tags: Object.assign(
26
+ {},
27
+ this.requestTags.get(request) || {},
28
+ { [Tags.SPAN_KIND]: 'server' }
29
+ )
30
+ }
31
+ const span = plugin.tracer.startSpan('aws.response', options)
32
+ this.enter(span, store)
33
+ }
34
+ })
35
+
36
+ this.addSub('apm:aws:response:finish:sqs', err => {
37
+ const { span } = storage.getStore()
38
+ this.finish(span, null, err)
39
+ })
40
+ }
41
+
42
+ isEnabled (request) {
43
+ // TODO(bengl) Figure out a way to make separate plugins for consumer and producer so that
44
+ // config can be isolated to `.configure()` instead of this whole isEnabled() thing.
45
+ const config = this.config
7
46
  switch (request.operation) {
8
47
  case 'receiveMessage':
9
48
  return config.consumer !== false
@@ -39,7 +78,7 @@ class Sqs {
39
78
  return tags
40
79
  }
41
80
 
42
- responseExtract (params, operation, response, tracer) {
81
+ responseExtract (params, operation, response) {
43
82
  if (operation === 'receiveMessage') {
44
83
  if (
45
84
  (!params.MaxNumberOfMessages || params.MaxNumberOfMessages === 1) &&
@@ -52,7 +91,7 @@ class Sqs {
52
91
  ) {
53
92
  const textMap = response.Messages[0].MessageAttributes._datadog.StringValue
54
93
  try {
55
- return tracer.extract('text_map', JSON.parse(textMap))
94
+ return this.tracer.extract('text_map', JSON.parse(textMap))
56
95
  } catch (err) {
57
96
  log.error(err)
58
97
  return undefined
@@ -61,7 +100,7 @@ class Sqs {
61
100
  }
62
101
  }
63
102
 
64
- requestInject (span, request, tracer) {
103
+ requestInject (span, request) {
65
104
  const operation = request.operation
66
105
  if (operation === 'sendMessage') {
67
106
  if (!request.params) {
@@ -74,7 +113,7 @@ class Sqs {
74
113
  return
75
114
  }
76
115
  const ddInfo = {}
77
- tracer.inject(span, 'text_map', ddInfo)
116
+ this.tracer.inject(span, 'text_map', ddInfo)
78
117
  request.params.MessageAttributes._datadog = {
79
118
  DataType: 'String',
80
119
  StringValue: JSON.stringify(ddInfo)
@@ -43,15 +43,11 @@ class CassandraDriverPlugin extends Plugin {
43
43
  this.enter(span, store)
44
44
  })
45
45
 
46
- this.addSub(`apm:cassandra:query:end`, () => {
47
- this.exit()
48
- })
49
-
50
46
  this.addSub(`apm:cassandra:query:error`, err => {
51
47
  storage.getStore().span.setTag('error', err)
52
48
  })
53
49
 
54
- this.addSub(`apm:cassandra:query:async-end`, () => {
50
+ this.addSub(`apm:cassandra:query:finish`, () => {
55
51
  storage.getStore().span.finish()
56
52
  })
57
53
 
@@ -9,11 +9,10 @@ class CouchBasePlugin extends Plugin {
9
9
  return 'couchbase'
10
10
  }
11
11
 
12
- addSubs (func, start, asyncEnd = defaultAsyncEnd) {
12
+ addSubs (func, start, finish = defaultFinish) {
13
13
  this.addSub(`apm:couchbase:${func}:start`, start)
14
- this.addSub(`apm:couchbase:${func}:end`, this.exit.bind(this))
15
14
  this.addSub(`apm:couchbase:${func}:error`, errorHandler)
16
- this.addSub(`apm:couchbase:${func}:async-end`, asyncEnd)
15
+ this.addSub(`apm:couchbase:${func}:finish`, finish)
17
16
  }
18
17
 
19
18
  startSpan (operation, customTags, store, bucket) {
@@ -63,7 +62,7 @@ class CouchBasePlugin extends Plugin {
63
62
  }
64
63
  }
65
64
 
66
- function defaultAsyncEnd () {
65
+ function defaultFinish () {
67
66
  storage.getStore().span.finish()
68
67
  }
69
68
 
@@ -54,10 +54,6 @@ class CucumberPlugin extends Plugin {
54
54
  this.enter(span, store)
55
55
  })
56
56
 
57
- this.addSub('ci:cucumber:run:end', () => {
58
- this.exit()
59
- })
60
-
61
57
  this.addSub('ci:cucumber:run-step:start', ({ resource }) => {
62
58
  const store = storage.getStore()
63
59
  const childOf = store ? store.span : store
@@ -71,11 +67,7 @@ class CucumberPlugin extends Plugin {
71
67
  this.enter(span, store)
72
68
  })
73
69
 
74
- this.addSub('ci:cucumber:run-step:end', () => {
75
- this.exit()
76
- })
77
-
78
- this.addSub('ci:cucumber:run:async-end', ({ isStep, status, skipReason, errorMessage }) => {
70
+ this.addSub('ci:cucumber:run:finish', ({ isStep, status, skipReason, errorMessage }) => {
79
71
  const span = storage.getStore().span
80
72
  const statusTag = isStep ? 'step.status' : TEST_STATUS
81
73
 
@@ -9,11 +9,10 @@ class DNSPlugin extends Plugin {
9
9
  return 'dns'
10
10
  }
11
11
 
12
- addSubs (func, start, asyncEnd = defaultAsyncEnd) {
12
+ addSubs (func, start, finish = defaultFinish) {
13
13
  this.addSub(`apm:dns:${func}:start`, start)
14
- this.addSub(`apm:dns:${func}:end`, this.exit.bind(this))
15
14
  this.addSub(`apm:dns:${func}:error`, errorHandler)
16
- this.addSub(`apm:dns:${func}:async-end`, asyncEnd)
15
+ this.addSub(`apm:dns:${func}:finish`, finish)
17
16
  }
18
17
 
19
18
  startSpan (name, customTags, store) {
@@ -88,7 +87,7 @@ class DNSPlugin extends Plugin {
88
87
  }
89
88
  }
90
89
 
91
- function defaultAsyncEnd () {
90
+ function defaultFinish () {
92
91
  storage.getStore().span.finish()
93
92
  }
94
93
 
@@ -34,16 +34,12 @@ class ElasticsearchPlugin extends Plugin {
34
34
  this.enter(span, store)
35
35
  })
36
36
 
37
- this.addSub('apm:elasticsearch:query:end', () => {
38
- this.exit()
39
- })
40
-
41
37
  this.addSub('apm:elasticsearch:query:error', err => {
42
38
  const span = storage.getStore().span
43
39
  span.setTag('error', err)
44
40
  })
45
41
 
46
- this.addSub('apm:elasticsearch:query:async-end', ({ params }) => {
42
+ this.addSub('apm:elasticsearch:query:finish', ({ params }) => {
47
43
  const span = storage.getStore().span
48
44
  this.config.hooks.query(span, params)
49
45
  span.finish()
@@ -1,6 +1,37 @@
1
1
  'use strict'
2
2
 
3
- const route = require('./route')
4
- const server = require('./server')
3
+ const { storage } = require('../../datadog-core')
4
+ const RouterPlugin = require('../../datadog-plugin-router/src')
5
+ const web = require('../../dd-trace/src/plugins/util/web')
5
6
 
6
- module.exports = [].concat(route, server)
7
+ class HapiPlugin extends RouterPlugin {
8
+ static get name () {
9
+ return 'hapi'
10
+ }
11
+
12
+ constructor (...args) {
13
+ super(...args)
14
+
15
+ this._requestSpans = new WeakMap()
16
+
17
+ this.addSub('apm:hapi:request:handle', ({ req }) => {
18
+ const store = storage.getStore()
19
+ const span = store && store.span
20
+
21
+ this.setFramework(req, 'hapi', this.config)
22
+ this._requestSpans.set(req, span)
23
+ })
24
+
25
+ this.addSub('apm:hapi:request:route', ({ req, route }) => {
26
+ web.setRoute(req, route)
27
+ })
28
+
29
+ this.addSub(`apm:hapi:request:error`, this.addError)
30
+
31
+ this.addSub('apm:hapi:extension:enter', ({ req }) => {
32
+ this.enter(this._requestSpans.get(req))
33
+ })
34
+ }
35
+ }
36
+
37
+ module.exports = HapiPlugin
@@ -54,9 +54,7 @@ class HttpClientPlugin extends Plugin {
54
54
  this.enter(span, store)
55
55
  })
56
56
 
57
- this.addSub('apm:http:client:request:end', this.exit.bind(this))
58
-
59
- this.addSub('apm:http:client:request:async-end', ({ req, res }) => {
57
+ this.addSub('apm:http:client:request:finish', ({ req, res }) => {
60
58
  const span = storage.getStore().span
61
59
  if (res) {
62
60
  span.setTag(HTTP_STATUS_CODE, res.statusCode)
@@ -31,10 +31,6 @@ class HttpServerPlugin extends Plugin {
31
31
  }
32
32
  })
33
33
 
34
- this.addSub('apm:http:server:request:end', () => {
35
- this.exit()
36
- })
37
-
38
34
  this.addSub('apm:http:server:request:error', (error) => {
39
35
  const span = storage.getStore().span
40
36
  span.addTags({
@@ -22,6 +22,7 @@ const HTTP_STATUS_CODE = tags.HTTP_STATUS_CODE
22
22
  const HTTP_ROUTE = tags.HTTP_ROUTE
23
23
  const HTTP_REQUEST_HEADERS = tags.HTTP_REQUEST_HEADERS
24
24
  const HTTP_RESPONSE_HEADERS = tags.HTTP_RESPONSE_HEADERS
25
+ const HTTP_USERAGENT = tags.HTTP_USERAGENT
25
26
  const MANUAL_DROP = tags.MANUAL_DROP
26
27
 
27
28
  const HTTP_STATUS_OK = 200
@@ -141,7 +142,8 @@ function addRequestTags (stream, headers) {
141
142
  [HTTP_METHOD]: headers[HTTP2_HEADER_METHOD],
142
143
  [HTTP_URL]: url.split('?')[0],
143
144
  [SPAN_KIND]: SERVER,
144
- [SPAN_TYPE]: WEB
145
+ [SPAN_TYPE]: WEB,
146
+ [HTTP_USERAGENT]: headers['user-agent']
145
147
  })
146
148
  }
147
149
 
@@ -48,15 +48,14 @@ class JestPlugin extends Plugin {
48
48
  this.enter(span, store)
49
49
  })
50
50
 
51
- this.addSub('ci:jest:test:end', (status) => {
51
+ this.addSub('ci:jest:test:finish', (status) => {
52
52
  const span = storage.getStore().span
53
53
  span.setTag(TEST_STATUS, status)
54
54
  span.finish()
55
55
  finishAllTraceSpans(span)
56
- this.exit()
57
56
  })
58
57
 
59
- this.addSub('ci:jest:test-suite:end', () => {
58
+ this.addSub('ci:jest:test-suite:finish', () => {
60
59
  this.tracer._exporter._writer.flush()
61
60
  })
62
61
 
@@ -60,10 +60,6 @@ class KafkajsPlugin extends Plugin {
60
60
  this.enter(span, store)
61
61
  })
62
62
 
63
- this.addSub(`apm:kafkajs:end`, () => {
64
- this.exit()
65
- })
66
-
67
63
  this.addSub(`apm:kafkajs:consume:error`, errorHandler)
68
64
 
69
65
  this.addSub(`apm:kafkajs:consume:finish`, finishHandler)
@@ -28,10 +28,6 @@ class MemcachedPlugin extends Plugin {
28
28
  this.enter(span, store)
29
29
  })
30
30
 
31
- this.addSub('apm:memcached:command:end', () => {
32
- this.exit()
33
- })
34
-
35
31
  this.addSub('apm:memcached:command:start:with-args', ({ client, server, query }) => {
36
32
  const span = storage.getStore().span
37
33
  span.addTags({
@@ -54,7 +50,7 @@ class MemcachedPlugin extends Plugin {
54
50
  span.setTag('error', err)
55
51
  })
56
52
 
57
- this.addSub('apm:memcached:command:async-end', () => {
53
+ this.addSub('apm:memcached:command:finish', () => {
58
54
  const span = storage.getStore().span
59
55
  span.finish()
60
56
  })