dd-trace 2.6.0 → 2.8.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 (118) hide show
  1. package/LICENSE-3rdparty.csv +1 -4
  2. package/index.d.ts +0 -7
  3. package/package.json +18 -24
  4. package/packages/datadog-instrumentations/index.js +16 -0
  5. package/packages/datadog-instrumentations/src/amqp10.js +33 -32
  6. package/packages/datadog-instrumentations/src/amqplib.js +16 -11
  7. package/packages/datadog-instrumentations/src/aws-sdk.js +104 -0
  8. package/packages/datadog-instrumentations/src/cassandra-driver.js +53 -51
  9. package/packages/datadog-instrumentations/src/connect.js +111 -0
  10. package/packages/datadog-instrumentations/src/couchbase.js +41 -39
  11. package/packages/datadog-instrumentations/src/cucumber.js +38 -38
  12. package/packages/datadog-instrumentations/src/dns.js +20 -19
  13. package/packages/datadog-instrumentations/src/elasticsearch.js +30 -32
  14. package/packages/datadog-instrumentations/src/express.js +27 -0
  15. package/packages/datadog-instrumentations/src/fastify.js +187 -0
  16. package/packages/datadog-instrumentations/src/find-my-way.js +30 -0
  17. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +100 -0
  18. package/packages/datadog-instrumentations/src/hapi.js +210 -0
  19. package/packages/datadog-instrumentations/src/http/client.js +44 -44
  20. package/packages/datadog-instrumentations/src/http/server.js +15 -13
  21. package/packages/datadog-instrumentations/src/ioredis.js +16 -17
  22. package/packages/datadog-instrumentations/src/jest.js +22 -17
  23. package/packages/datadog-instrumentations/src/kafkajs.js +112 -0
  24. package/packages/datadog-instrumentations/src/knex.js +20 -0
  25. package/packages/datadog-instrumentations/src/koa.js +159 -0
  26. package/packages/datadog-instrumentations/src/limitd-client.js +21 -0
  27. package/packages/datadog-instrumentations/src/memcached.js +14 -12
  28. package/packages/datadog-instrumentations/src/mocha.js +37 -39
  29. package/packages/datadog-instrumentations/src/moleculer/client.js +46 -0
  30. package/packages/datadog-instrumentations/src/moleculer/server.js +59 -0
  31. package/packages/datadog-instrumentations/src/moleculer.js +4 -0
  32. package/packages/datadog-instrumentations/src/mongodb-core.js +29 -33
  33. package/packages/datadog-instrumentations/src/mysql.js +30 -29
  34. package/packages/datadog-instrumentations/src/mysql2.js +8 -9
  35. package/packages/datadog-instrumentations/src/net.js +23 -24
  36. package/packages/datadog-instrumentations/src/oracledb.js +128 -0
  37. package/packages/datadog-instrumentations/src/paperplane.js +77 -0
  38. package/packages/datadog-instrumentations/src/pg.js +32 -32
  39. package/packages/datadog-instrumentations/src/redis.js +49 -47
  40. package/packages/datadog-instrumentations/src/restify.js +58 -0
  41. package/packages/datadog-instrumentations/src/rhea.js +52 -50
  42. package/packages/datadog-instrumentations/src/router.js +177 -0
  43. package/packages/datadog-instrumentations/src/sharedb.js +20 -20
  44. package/packages/datadog-instrumentations/src/tedious.js +19 -19
  45. package/packages/datadog-plugin-amqp10/src/index.js +2 -7
  46. package/packages/datadog-plugin-amqplib/src/index.js +1 -2
  47. package/packages/datadog-plugin-aws-sdk/src/base.js +146 -0
  48. package/packages/datadog-plugin-aws-sdk/src/index.js +16 -106
  49. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +4 -2
  50. package/packages/datadog-plugin-aws-sdk/src/services/default.js +7 -0
  51. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +3 -1
  52. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +5 -4
  53. package/packages/datadog-plugin-aws-sdk/src/services/index.js +12 -0
  54. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -3
  55. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +4 -3
  56. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -1
  57. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -1
  58. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +4 -3
  59. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +45 -6
  60. package/packages/datadog-plugin-cassandra-driver/src/index.js +1 -5
  61. package/packages/datadog-plugin-connect/src/index.js +10 -114
  62. package/packages/datadog-plugin-couchbase/src/index.js +3 -4
  63. package/packages/datadog-plugin-cucumber/src/index.js +1 -9
  64. package/packages/datadog-plugin-dns/src/index.js +15 -5
  65. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -5
  66. package/packages/datadog-plugin-express/src/index.js +11 -25
  67. package/packages/datadog-plugin-fastify/src/index.js +17 -4
  68. package/packages/datadog-plugin-find-my-way/src/index.js +20 -0
  69. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +56 -111
  70. package/packages/datadog-plugin-hapi/src/index.js +34 -3
  71. package/packages/datadog-plugin-http/src/client.js +1 -3
  72. package/packages/datadog-plugin-http/src/server.js +2 -6
  73. package/packages/datadog-plugin-jest/src/index.js +2 -3
  74. package/packages/datadog-plugin-kafkajs/src/index.js +61 -91
  75. package/packages/datadog-plugin-koa/src/index.js +12 -164
  76. package/packages/datadog-plugin-memcached/src/index.js +1 -5
  77. package/packages/datadog-plugin-mocha/src/index.js +3 -7
  78. package/packages/datadog-plugin-moleculer/src/client.js +34 -44
  79. package/packages/datadog-plugin-moleculer/src/index.js +32 -3
  80. package/packages/datadog-plugin-moleculer/src/server.js +28 -50
  81. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -5
  82. package/packages/datadog-plugin-mysql/src/index.js +1 -5
  83. package/packages/datadog-plugin-net/src/index.js +3 -7
  84. package/packages/datadog-plugin-oracledb/src/index.js +34 -100
  85. package/packages/datadog-plugin-paperplane/src/index.js +14 -100
  86. package/packages/datadog-plugin-paperplane/src/logger.js +11 -0
  87. package/packages/datadog-plugin-paperplane/src/server.js +24 -0
  88. package/packages/datadog-plugin-pg/src/index.js +1 -5
  89. package/packages/datadog-plugin-redis/src/index.js +1 -5
  90. package/packages/datadog-plugin-restify/src/index.js +13 -75
  91. package/packages/datadog-plugin-rhea/src/index.js +1 -5
  92. package/packages/datadog-plugin-router/src/index.js +67 -164
  93. package/packages/datadog-plugin-sharedb/src/index.js +1 -5
  94. package/packages/datadog-plugin-tedious/src/index.js +1 -5
  95. package/packages/datadog-plugin-web/src/index.js +20 -0
  96. package/packages/dd-trace/lib/version.js +1 -1
  97. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +8 -2
  98. package/packages/dd-trace/src/appsec/reporter.js +4 -0
  99. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +3 -1
  100. package/packages/dd-trace/src/plugin_manager.js +13 -7
  101. package/packages/dd-trace/src/plugins/index.js +1 -2
  102. package/packages/dd-trace/src/plugins/log_plugin.js +8 -4
  103. package/packages/dd-trace/src/plugins/plugin.js +8 -8
  104. package/packages/dd-trace/src/plugins/util/test.js +5 -1
  105. package/packages/dd-trace/src/plugins/util/web.js +40 -12
  106. package/packages/dd-trace/src/profiling/config.js +8 -8
  107. package/packages/dd-trace/src/profiling/index.js +4 -4
  108. package/packages/dd-trace/src/profiling/profilers/{heap.js → space.js} +2 -2
  109. package/packages/dd-trace/src/profiling/profilers/{cpu.js → wall.js} +2 -2
  110. package/scripts/install_plugin_modules.js +23 -11
  111. package/packages/datadog-plugin-aws-sdk/src/helpers.js +0 -103
  112. package/packages/datadog-plugin-fastify/src/fastify.js +0 -198
  113. package/packages/datadog-plugin-fastify/src/find-my-way.js +0 -37
  114. package/packages/datadog-plugin-hapi/src/route.js +0 -75
  115. package/packages/datadog-plugin-hapi/src/server.js +0 -204
  116. package/packages/datadog-plugin-knex/src/index.js +0 -23
  117. package/packages/datadog-plugin-limitd-client/src/index.js +0 -30
  118. package/scripts/postpublish.js +0 -24
@@ -1,204 +1,107 @@
1
1
  'use strict'
2
2
 
3
- const METHODS = require('methods').concat('all')
4
- const pathToRegExp = require('path-to-regexp')
5
- const shimmer = require('../../datadog-shimmer')
6
3
  const web = require('../../dd-trace/src/plugins/util/web')
4
+ const WebPlugin = require('../../datadog-plugin-web/src')
5
+ const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
6
+ const { storage } = require('../../datadog-core')
7
7
 
8
- // TODO: stop checking for fast star and fast slash
9
-
10
- const contexts = new WeakMap()
11
- const layerMatchers = new WeakMap()
12
- const regexpCache = Object.create(null)
13
-
14
- function createWrapHandle (tracer, config) {
15
- return function wrapHandle (handle) {
16
- return function handleWithTrace (req, res, done) {
17
- web.patch(req)
18
-
19
- if (!contexts.has(req)) {
20
- const context = {
21
- route: '',
22
- stack: []
23
- }
24
-
25
- web.beforeEnd(req, () => {
26
- web.enterRoute(req, context.route)
27
- })
28
-
29
- contexts.set(req, context)
30
- }
31
-
32
- return handle.apply(this, arguments)
33
- }
8
+ class RouterPlugin extends WebPlugin {
9
+ static get name () {
10
+ return 'router'
34
11
  }
35
- }
36
12
 
37
- function wrapRouterMethod (original) {
38
- return function methodWithTrace (fn) {
39
- const offset = this.stack ? [].concat(this.stack).length : 0
40
- const router = original.apply(this, arguments)
13
+ constructor (...args) {
14
+ super(...args)
41
15
 
42
- if (typeof this.stack === 'function') {
43
- this.stack = [{ handle: this.stack }]
44
- }
16
+ this._contexts = new WeakMap()
45
17
 
46
- wrapStack(this.stack, offset, extractMatchers(fn))
47
-
48
- return router
49
- }
50
- }
18
+ this.addSub(`apm:${this.constructor.name}:middleware:enter`, ({ req, name, route }) => {
19
+ const store = storage.getStore()
20
+ const context = this._createContext(req, route)
21
+ const span = this._getMiddlewareSpan(context, store, name)
51
22
 
52
- function wrapLayerHandle (layer, handle) {
53
- handle._name = handle._name || layer.name
23
+ this.enter(span, store)
54
24
 
55
- let wrapCallHandle
56
-
57
- if (handle.length === 4) {
58
- wrapCallHandle = shimmer.wrap(handle, function (error, req, res, next) {
59
- return callHandle(layer, handle, req, [error, req, res, wrapNext(layer, req, next)])
60
- })
61
- } else {
62
- wrapCallHandle = shimmer.wrap(handle, function (req, res, next) {
63
- return callHandle(layer, handle, req, [req, res, wrapNext(layer, req, next)])
25
+ web.patch(req)
26
+ web.setRoute(req, context.route)
64
27
  })
65
- }
66
28
 
67
- // This is a workaround for the `loopback` library so that it can find the correct express layer
68
- // that contains the real handle function
69
- wrapCallHandle._datadog_orig = handle
29
+ this.addSub(`apm:${this.constructor.name}:middleware:next`, ({ req }) => {
30
+ const context = this._contexts.get(req)
70
31
 
71
- return wrapCallHandle
72
- }
32
+ if (!context) return
73
33
 
74
- function wrapStack (stack, offset, matchers) {
75
- [].concat(stack).slice(offset).forEach(layer => {
76
- if (layer.__handle) { // express-async-errors
77
- layer.__handle = wrapLayerHandle(layer, layer.__handle)
78
- } else {
79
- layer.handle = wrapLayerHandle(layer, layer.handle)
80
- }
81
-
82
- layerMatchers.set(layer, matchers)
83
-
84
- if (layer.route) {
85
- METHODS.forEach(method => {
86
- if (typeof layer.route.stack === 'function') {
87
- layer.route.stack = [{ handle: layer.route.stack }]
88
- }
34
+ context.stack.pop()
89
35
 
90
- layer.route[method] = wrapRouterMethod(layer.route[method])
91
- })
92
- }
93
- })
94
- }
36
+ if (context.middleware.length > 0) {
37
+ context.middleware.pop().finish()
38
+ }
39
+ })
95
40
 
96
- function wrapNext (layer, req, next) {
97
- if (!next || !web.active(req)) return next
41
+ this.addSub(`apm:${this.constructor.name}:middleware:error`, this.addError)
98
42
 
99
- const originalNext = next
100
- const context = contexts.get(req)
101
- const matchers = layerMatchers.get(layer)
43
+ this.addSub(`apm:http:server:request:finish`, ({ req }) => {
44
+ const context = this._contexts.get(req)
102
45
 
103
- return function (error) {
104
- if (layer.path && !isFastStar(layer, matchers) && !isFastSlash(layer, matchers)) {
105
- context.stack.pop()
106
- }
46
+ if (!context) return
107
47
 
108
- web.finish(req, error)
48
+ let span
109
49
 
110
- originalNext.apply(null, arguments)
50
+ while ((span = context.middleware.pop())) {
51
+ span.finish()
52
+ }
53
+ })
111
54
  }
112
- }
113
-
114
- function callHandle (layer, handle, req, args) {
115
- const matchers = layerMatchers.get(layer)
116
55
 
117
- if (web.active(req) && matchers) {
118
- // Try to guess which path actually matched
119
- for (let i = 0; i < matchers.length; i++) {
120
- if (matchers[i].test(layer)) {
121
- const context = contexts.get(req)
56
+ _getMiddlewareSpan (context, store, name) {
57
+ const childOf = store && store.span
122
58
 
123
- context.stack.push(matchers[i].path)
124
-
125
- const route = context.stack.join('')
126
-
127
- // Longer route is more likely to be the actual route handler route.
128
- if (route.length > context.route.length) {
129
- context.route = route
130
- }
59
+ if (this.config.middleware === false) {
60
+ return childOf
61
+ }
131
62
 
132
- break
63
+ const span = this.tracer.startSpan(`${this.constructor.name}.middleware`, {
64
+ childOf,
65
+ tags: {
66
+ 'resource.name': name || '<anonymous>'
133
67
  }
134
- }
135
- }
68
+ })
136
69
 
137
- return web.wrapMiddleware(req, handle, 'express.middleware', () => {
138
- return handle.apply(layer, args)
139
- })
140
- }
70
+ context.middleware.push(span)
141
71
 
142
- function extractMatchers (fn) {
143
- const arg = flatten([].concat(fn))
72
+ analyticsSampler.sample(span, this.config.measured)
144
73
 
145
- if (typeof arg[0] === 'function') {
146
- return []
74
+ return span
147
75
  }
148
76
 
149
- return arg.map(pattern => ({
150
- path: pattern instanceof RegExp ? `(${pattern})` : pattern,
151
- test: layer => {
152
- const matchers = layerMatchers.get(layer)
77
+ _createContext (req, route) {
78
+ let context = this._contexts.get(req)
153
79
 
154
- return !isFastStar(layer, matchers) &&
155
- !isFastSlash(layer, matchers) &&
156
- cachedPathToRegExp(pattern).test(layer.path)
80
+ if (!route || route === '/' || route === '*') {
81
+ route = ''
157
82
  }
158
- }))
159
- }
160
83
 
161
- function isFastStar (layer, matchers) {
162
- if (layer.regexp.fast_star !== undefined) {
163
- return layer.regexp.fast_star
164
- }
84
+ if (context) {
85
+ context.stack.push(route)
165
86
 
166
- return matchers.some(matcher => matcher.path === '*')
167
- }
87
+ route = context.stack.join('')
168
88
 
169
- function isFastSlash (layer, matchers) {
170
- if (layer.regexp.fast_slash !== undefined) {
171
- return layer.regexp.fast_slash
172
- }
173
-
174
- return matchers.some(matcher => matcher.path === '/')
175
- }
89
+ // Longer route is more likely to be the actual route handler route.
90
+ if (route.length > context.route.length) {
91
+ context.route = route
92
+ }
93
+ } else {
94
+ context = {
95
+ stack: [route],
96
+ route,
97
+ middleware: []
98
+ }
176
99
 
177
- function flatten (arr) {
178
- return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), [])
179
- }
100
+ this._contexts.set(req, context)
101
+ }
180
102
 
181
- function cachedPathToRegExp (pattern) {
182
- const maybeCached = regexpCache[pattern]
183
- if (maybeCached) {
184
- return maybeCached
103
+ return context
185
104
  }
186
- const regexp = pathToRegExp(pattern)
187
- regexpCache[pattern] = regexp
188
- return regexp
189
105
  }
190
106
 
191
- module.exports = {
192
- name: 'router',
193
- versions: ['>=1'],
194
- patch (Router, tracer, config) {
195
- this.wrap(Router.prototype, 'handle', createWrapHandle(tracer, config))
196
- this.wrap(Router.prototype, 'use', wrapRouterMethod)
197
- this.wrap(Router.prototype, 'route', wrapRouterMethod)
198
- },
199
- unpatch (Router) {
200
- this.unwrap(Router.prototype, 'handle')
201
- this.unwrap(Router.prototype, 'use')
202
- this.unwrap(Router.prototype, 'route')
203
- }
204
- }
107
+ module.exports = RouterPlugin
@@ -31,16 +31,12 @@ class SharedbPlugin extends Plugin {
31
31
  this.enter(span, store)
32
32
  })
33
33
 
34
- this.addSub(`apm:sharedb:request:end`, () => {
35
- this.exit()
36
- })
37
-
38
34
  this.addSub(`apm:sharedb:request:error`, err => {
39
35
  const span = storage.getStore().span
40
36
  span.setTag('error', err)
41
37
  })
42
38
 
43
- this.addSub(`apm:sharedb:request:async-end`, ({ request, res }) => {
39
+ this.addSub(`apm:sharedb:request:finish`, ({ request, res }) => {
44
40
  const span = storage.getStore().span
45
41
  if (this.config.hooks && this.config.hooks.reply) {
46
42
  this.config.hooks.reply(span, request, res)
@@ -35,16 +35,12 @@ class TediousPlugin extends Plugin {
35
35
  this.enter(span, store)
36
36
  })
37
37
 
38
- this.addSub(`apm:tedious:request:end`, () => {
39
- this.exit()
40
- })
41
-
42
38
  this.addSub(`apm:tedious:request:error`, err => {
43
39
  const span = storage.getStore().span
44
40
  span.setTag('error', err)
45
41
  })
46
42
 
47
- this.addSub(`apm:tedious:request:async-end`, () => {
43
+ this.addSub(`apm:tedious:request:finish`, () => {
48
44
  const span = storage.getStore().span
49
45
  span.finish()
50
46
  })
@@ -0,0 +1,20 @@
1
+ 'use strict'
2
+
3
+ const Plugin = require('../../dd-trace/src/plugins/plugin')
4
+ const web = require('../../dd-trace/src/plugins/util/web')
5
+
6
+ class WebPlugin extends Plugin {
7
+ static get name () {
8
+ return 'web'
9
+ }
10
+
11
+ configure (config) {
12
+ return super.configure(web.normalizeConfig(config))
13
+ }
14
+
15
+ setFramework (req, name, config) {
16
+ web.setFramework(req, name, config)
17
+ }
18
+ }
19
+
20
+ module.exports = WebPlugin
@@ -1 +1 @@
1
- module.exports = '2.6.0'
1
+ module.exports = '2.8.0'
@@ -33,10 +33,11 @@ class WAFCallback {
33
33
 
34
34
  Reporter.metricsQueue.set('_dd.appsec.waf.version', `${version.major}.${version.minor}.${version.patch}`)
35
35
 
36
- const { loaded, failed } = this.ddwaf.rulesInfo
36
+ const { loaded, failed, errors } = this.ddwaf.rulesInfo
37
37
 
38
38
  Reporter.metricsQueue.set('_dd.appsec.event_rules.loaded', loaded)
39
39
  Reporter.metricsQueue.set('_dd.appsec.event_rules.error_count', failed)
40
+ if (failed) Reporter.metricsQueue.set('_dd.appsec.event_rules.errors', JSON.stringify(errors))
40
41
 
41
42
  Reporter.metricsQueue.set('manual.keep', true)
42
43
 
@@ -95,8 +96,12 @@ class WAFCallback {
95
96
 
96
97
  try {
97
98
  // TODO: possible optimizaion: only send params that haven't already been sent to this wafContext
99
+ const start = process.hrtime.bigint()
100
+
98
101
  const result = wafContext.run(params, this.wafTimeout)
99
102
 
103
+ result.durationExt = parseInt(process.hrtime.bigint() - start)
104
+
100
105
  return this.applyResult(result, store)
101
106
  } catch (err) {
102
107
  log.error('Error while running the AppSec WAF')
@@ -108,7 +113,8 @@ class WAFCallback {
108
113
 
109
114
  applyResult (result, store) {
110
115
  Reporter.reportMetrics({
111
- duration: result.totalRuntime,
116
+ duration: result.totalRuntime / 1e3,
117
+ durationExt: result.durationExt / 1e3,
112
118
  rulesVersion: this.ddwaf.rulesInfo.version
113
119
  }, store)
114
120
 
@@ -93,6 +93,10 @@ function reportMetrics (metrics, store) {
93
93
  topSpan.setTag('_dd.appsec.waf.duration', metrics.duration)
94
94
  }
95
95
 
96
+ if (metrics.durationExt) {
97
+ topSpan.setTag('_dd.appsec.waf.duration_ext', metrics.durationExt)
98
+ }
99
+
96
100
  if (metrics.rulesVersion) {
97
101
  topSpan.setTag('_dd.appsec.event_rules.version', metrics.rulesVersion)
98
102
  }
@@ -2,6 +2,7 @@
2
2
  const { truncateSpan, normalizeSpan } = require('./tags-processors')
3
3
  const Chunk = require('./chunk')
4
4
  const { AgentEncoder } = require('./0.4')
5
+ const { version: ddTraceVersion } = require('../../../../package.json')
5
6
 
6
7
  const ENCODING_VERSION = 1
7
8
 
@@ -156,7 +157,8 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
156
157
  version: ENCODING_VERSION,
157
158
  metadata: {
158
159
  '*': {
159
- 'language': 'javascript'
160
+ 'language': 'javascript',
161
+ 'library_version': ddTraceVersion
160
162
  }
161
163
  },
162
164
  events: []
@@ -27,9 +27,11 @@ function getConfig (name, config = {}) {
27
27
  module.exports = class PluginManager {
28
28
  constructor (tracer) {
29
29
  this._pluginsByName = {}
30
+ this._configsByName = {}
30
31
  for (const PluginClass of Object.values(plugins)) {
31
32
  if (typeof PluginClass !== 'function') continue
32
33
  this._pluginsByName[PluginClass.name] = new PluginClass(tracer)
34
+ this._configsByName[PluginClass.name] = {}
33
35
  }
34
36
  }
35
37
 
@@ -40,25 +42,29 @@ module.exports = class PluginManager {
40
42
  pluginConfig = { enabled: pluginConfig }
41
43
  }
42
44
 
43
- this._pluginsByName[name].configure(getConfig(name, pluginConfig))
45
+ const config = {
46
+ ...this._configsByName[name],
47
+ ...pluginConfig
48
+ }
49
+
50
+ this._pluginsByName[name].configure(getConfig(name, config))
44
51
  }
45
52
 
46
53
  // like instrumenter.enable()
47
54
  configure (config) {
48
- const serviceMapping = config.serviceMapping
55
+ const { logInjection, serviceMapping } = config
49
56
 
50
57
  if (config.plugins !== false) {
51
58
  for (const name in this._pluginsByName) {
52
- const pluginConfig = {}
59
+ const pluginConfig = {
60
+ ...this._configsByName[name],
61
+ logInjection
62
+ }
53
63
  if (serviceMapping && serviceMapping[name]) {
54
64
  pluginConfig.service = serviceMapping[name]
55
65
  }
56
66
  this.configurePlugin(name, pluginConfig)
57
67
  }
58
- } else {
59
- for (const name in this._pluginsByName) {
60
- this.configurePlugin(name, false)
61
- }
62
68
  }
63
69
  }
64
70
 
@@ -14,6 +14,7 @@ module.exports = {
14
14
  'elasticsearch': require('../../../datadog-plugin-elasticsearch/src'),
15
15
  'express': require('../../../datadog-plugin-express/src'),
16
16
  'fastify': require('../../../datadog-plugin-fastify/src'),
17
+ 'find-my-way': require('../../../datadog-plugin-find-my-way/src'),
17
18
  'fs': require('../../../datadog-plugin-fs/src'),
18
19
  'google-cloud-pubsub': require('../../../datadog-plugin-google-cloud-pubsub/src'),
19
20
  'graphql': require('../../../datadog-plugin-graphql/src'),
@@ -23,10 +24,8 @@ module.exports = {
23
24
  'http2': require('../../../datadog-plugin-http2/src'),
24
25
  'ioredis': require('../../../datadog-plugin-ioredis/src'),
25
26
  'jest': require('../../../datadog-plugin-jest/src'),
26
- 'knex': require('../../../datadog-plugin-knex/src'),
27
27
  'koa': require('../../../datadog-plugin-koa/src'),
28
28
  'kafkajs': require('../../../datadog-plugin-kafkajs/src'),
29
- 'limitd-client': require('../../../datadog-plugin-limitd-client/src'),
30
29
  'memcached': require('../../../datadog-plugin-memcached/src'),
31
30
  'microgateway-core': require('../../../datadog-plugin-microgateway-core/src'),
32
31
  'mocha': require('../../../datadog-plugin-mocha/src'),
@@ -31,11 +31,8 @@ function messageProxy (message, holder) {
31
31
  module.exports = class LogPlugin extends Plugin {
32
32
  constructor (...args) {
33
33
  super(...args)
34
- this.addSub(`apm:${this.constructor.name}:log`, (arg) => {
35
- // TODO rather than checking this every time, setting it ought to enable/disable any plugin
36
- // extending from this one
37
- if (!this.tracer._logInjection) return
38
34
 
35
+ this.addSub(`apm:${this.constructor.name}:log`, (arg) => {
39
36
  const store = storage.getStore()
40
37
  const span = store && store.span
41
38
 
@@ -46,4 +43,11 @@ module.exports = class LogPlugin extends Plugin {
46
43
  arg.message = messageProxy(arg.message, holder)
47
44
  })
48
45
  }
46
+
47
+ configure (config) {
48
+ return super.configure({
49
+ ...config,
50
+ enabled: config.enabled && config.logInjection
51
+ })
52
+ }
49
53
  }
@@ -27,7 +27,6 @@ module.exports = class Plugin {
27
27
  constructor (tracer) {
28
28
  this._subscriptions = []
29
29
  this._enabled = false
30
- this._storeStack = []
31
30
  this._tracer = tracer
32
31
  }
33
32
 
@@ -37,25 +36,26 @@ module.exports = class Plugin {
37
36
 
38
37
  enter (span, store) {
39
38
  store = store || storage.getStore()
40
- this._storeStack.push(store)
41
39
  storage.enterWith({ ...store, span })
42
40
  }
43
41
 
44
42
  /** Prevents creation of spans here and for all async descendants. */
45
43
  skip () {
46
- const store = storage.getStore()
47
- this._storeStack.push(store)
48
44
  storage.enterWith({ noop: true })
49
45
  }
50
46
 
51
- exit () {
52
- storage.enterWith(this._storeStack.pop())
53
- }
54
-
55
47
  addSub (channelName, handler) {
56
48
  this._subscriptions.push(new Subscription(channelName, handler))
57
49
  }
58
50
 
51
+ addError (error) {
52
+ const store = storage.getStore()
53
+
54
+ if (!store || !store.span) return
55
+
56
+ store.span.setTag('error', error)
57
+ }
58
+
59
59
  configure (config) {
60
60
  if (typeof config === 'boolean') {
61
61
  config = { enabled: config }
@@ -22,6 +22,7 @@ const id = require('../../id')
22
22
  const { SPAN_TYPE, RESOURCE_NAME, SAMPLING_PRIORITY } = require('../../../../../ext/tags')
23
23
  const { SAMPLING_RULE_DECISION } = require('../../constants')
24
24
  const { AUTO_KEEP } = require('../../../../../ext/priority')
25
+ const { version: ddTraceVersion } = require('../../../../../package.json')
25
26
 
26
27
  const TEST_FRAMEWORK = 'test.framework'
27
28
  const TEST_FRAMEWORK_VERSION = 'test.framework_version'
@@ -33,6 +34,7 @@ const TEST_PARAMETERS = 'test.parameters'
33
34
  const TEST_SKIP_REASON = 'test.skip_reason'
34
35
  const TEST_IS_RUM_ACTIVE = 'test.is_rum_active'
35
36
  const TEST_CODE_OWNERS = 'test.codeowners'
37
+ const LIBRARY_VERSION = 'library_version'
36
38
 
37
39
  const ERROR_TYPE = 'error.type'
38
40
  const ERROR_MESSAGE = 'error.msg'
@@ -58,6 +60,7 @@ module.exports = {
58
60
  ERROR_MESSAGE,
59
61
  ERROR_STACK,
60
62
  CI_APP_ORIGIN,
63
+ LIBRARY_VERSION,
61
64
  getTestEnvironmentMetadata,
62
65
  getTestParametersString,
63
66
  finishAllTraceSpans,
@@ -149,7 +152,8 @@ function getTestCommonTags (name, suite, version) {
149
152
  [TEST_NAME]: name,
150
153
  [TEST_SUITE]: suite,
151
154
  [RESOURCE_NAME]: `${suite}.${name}`,
152
- [TEST_FRAMEWORK_VERSION]: version
155
+ [TEST_FRAMEWORK_VERSION]: version,
156
+ [LIBRARY_VERSION]: ddTraceVersion
153
157
  }
154
158
  }
155
159
 
@@ -52,10 +52,38 @@ const web = {
52
52
  })
53
53
  },
54
54
 
55
- startSpan (tracer, config, req, res, name) {
55
+ setFramework (req, name, config) {
56
56
  const context = this.patch(req)
57
+ const span = context.span
58
+
59
+ if (!span) return
60
+
61
+ span.context()._name = `${name}.request`
62
+
63
+ web.setConfig(req, config)
64
+ },
65
+
66
+ setConfig (req, config) {
67
+ const context = contexts.get(req)
68
+ const span = context.span
69
+
57
70
  context.config = config
58
71
 
72
+ if (!config.filter(req.url)) {
73
+ span.setTag(MANUAL_DROP, true)
74
+ span.context()._trace.isRecording = false
75
+ }
76
+
77
+ if (config.service) {
78
+ span.setTag(SERVICE_NAME, config.service)
79
+ }
80
+
81
+ analyticsSampler.sample(span, config.measured, true)
82
+ },
83
+
84
+ startSpan (tracer, config, req, res, name) {
85
+ const context = this.patch(req)
86
+
59
87
  let span
60
88
 
61
89
  if (context.span) {
@@ -69,16 +97,7 @@ const web = {
69
97
  context.span = span
70
98
  context.res = res
71
99
 
72
- if (!config.filter(req.url)) {
73
- span.setTag(MANUAL_DROP, true)
74
- span.context()._trace.isRecording = false
75
- }
76
-
77
- if (config.service) {
78
- span.setTag(SERVICE_NAME, config.service)
79
- }
80
-
81
- analyticsSampler.sample(span, config.measured, true)
100
+ this.setConfig(req, config)
82
101
 
83
102
  return span
84
103
  },
@@ -111,6 +130,14 @@ const web = {
111
130
  }
112
131
  },
113
132
 
133
+ setRoute (req, path) {
134
+ const context = contexts.get(req)
135
+
136
+ if (!context) return
137
+
138
+ context.paths = [path]
139
+ },
140
+
114
141
  // Remove the current route segment.
115
142
  exitRoute (req) {
116
143
  contexts.get(req).paths.pop()
@@ -232,8 +259,9 @@ const web = {
232
259
  const context = contexts.get(req)
233
260
  const span = context.span
234
261
  const error = context.error
262
+ const hasMiddlewareError = span.context()._tags['error'] || span.context()._tags['error.msg']
235
263
 
236
- if (!context.config.validateStatus(statusCode)) {
264
+ if (!hasMiddlewareError && !context.config.validateStatus(statusCode)) {
237
265
  span.setTag(ERROR, error || true)
238
266
  }
239
267
  },