dd-trace 2.2.0 → 2.3.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 (55) hide show
  1. package/LICENSE-3rdparty.csv +0 -2
  2. package/index.d.ts +6 -12
  3. package/package.json +3 -5
  4. package/packages/datadog-instrumentations/index.js +9 -0
  5. package/packages/datadog-instrumentations/src/bunyan.js +22 -0
  6. package/packages/datadog-instrumentations/src/cucumber.js +116 -0
  7. package/packages/datadog-instrumentations/src/elasticsearch.js +15 -5
  8. package/packages/datadog-instrumentations/src/generic-pool.js +48 -0
  9. package/packages/datadog-instrumentations/src/ioredis.js +52 -0
  10. package/packages/datadog-instrumentations/src/mongoose.js +30 -0
  11. package/packages/datadog-instrumentations/src/pino.js +105 -0
  12. package/packages/datadog-instrumentations/src/redis.js +118 -0
  13. package/packages/datadog-instrumentations/src/sharedb.js +78 -0
  14. package/packages/datadog-instrumentations/src/winston.js +57 -0
  15. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -2
  16. package/packages/datadog-plugin-bunyan/src/index.js +5 -22
  17. package/packages/datadog-plugin-cucumber/src/index.js +83 -128
  18. package/packages/datadog-plugin-fastify/src/find-my-way.js +0 -1
  19. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +8 -6
  20. package/packages/datadog-plugin-graphql/src/index.js +34 -28
  21. package/packages/datadog-plugin-grpc/src/client.js +20 -6
  22. package/packages/datadog-plugin-http2/src/server.js +2 -0
  23. package/packages/datadog-plugin-ioredis/src/index.js +5 -35
  24. package/packages/datadog-plugin-jest/src/jest-environment.js +26 -30
  25. package/packages/datadog-plugin-koa/src/index.js +6 -2
  26. package/packages/datadog-plugin-microgateway-core/src/index.js +1 -3
  27. package/packages/datadog-plugin-mocha/src/index.js +5 -3
  28. package/packages/datadog-plugin-mongodb-core/src/util.js +31 -7
  29. package/packages/datadog-plugin-next/src/index.js +9 -4
  30. package/packages/datadog-plugin-oracledb/src/index.js +10 -7
  31. package/packages/datadog-plugin-pino/src/index.js +5 -158
  32. package/packages/datadog-plugin-redis/src/index.js +96 -80
  33. package/packages/datadog-plugin-restify/src/index.js +18 -3
  34. package/packages/datadog-plugin-rhea/src/index.js +8 -5
  35. package/packages/datadog-plugin-router/src/index.js +23 -14
  36. package/packages/datadog-plugin-sharedb/src/index.js +47 -87
  37. package/packages/datadog-plugin-winston/src/index.js +5 -113
  38. package/packages/datadog-shimmer/src/shimmer.js +1 -1
  39. package/packages/dd-trace/lib/version.js +1 -1
  40. package/packages/dd-trace/src/appsec/index.js +2 -1
  41. package/packages/dd-trace/src/appsec/reporter.js +3 -2
  42. package/packages/dd-trace/src/config.js +7 -1
  43. package/packages/dd-trace/src/constants.js +1 -6
  44. package/packages/dd-trace/src/opentracing/propagation/text_map.js +0 -34
  45. package/packages/dd-trace/src/opentracing/tracer.js +1 -1
  46. package/packages/dd-trace/src/plugins/index.js +0 -2
  47. package/packages/dd-trace/src/plugins/log_plugin.js +49 -0
  48. package/packages/dd-trace/src/plugins/plugin.js +7 -0
  49. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  50. package/packages/dd-trace/src/plugins/util/web.js +102 -84
  51. package/packages/dd-trace/src/priority_sampler.js +1 -49
  52. package/packages/dd-trace/src/scope.js +47 -23
  53. package/packages/dd-trace/src/span_processor.js +22 -7
  54. package/packages/datadog-plugin-generic-pool/src/index.js +0 -52
  55. package/packages/datadog-plugin-mongoose/src/index.js +0 -51
@@ -1,20 +1,14 @@
1
1
  'use strict'
2
2
 
3
- const coalesce = require('koalas')
4
3
  const RateLimiter = require('./rate_limiter')
5
4
  const Sampler = require('./sampler')
6
5
  const ext = require('../../../ext')
7
6
  const { setSamplingRules } = require('./startup-log')
8
7
 
9
8
  const {
10
- SAMPLING_MECHANISM_DEFAULT,
11
- SAMPLING_MECHANISM_AGENT,
12
- SAMPLING_MECHANISM_RULE,
13
- SAMPLING_MECHANISM_MANUAL,
14
9
  SAMPLING_RULE_DECISION,
15
10
  SAMPLING_LIMIT_DECISION,
16
- SAMPLING_AGENT_DECISION,
17
- UPSTREAM_SERVICES_KEY
11
+ SAMPLING_AGENT_DECISION
18
12
  } = require('./constants')
19
13
 
20
14
  const SERVICE_NAME = ext.tags.SERVICE_NAME
@@ -28,7 +22,6 @@ const USER_KEEP = ext.priority.USER_KEEP
28
22
  const DEFAULT_KEY = 'service:,env:'
29
23
 
30
24
  const defaultSampler = new Sampler(AUTO_KEEP)
31
- const serviceNames = new Map()
32
25
 
33
26
  class PrioritySampler {
34
27
  constructor (env, { sampleRate, rateLimit = 100, rules = [] } = {}) {
@@ -59,14 +52,9 @@ class PrioritySampler {
59
52
 
60
53
  if (this.validate(tag)) {
61
54
  context._sampling.priority = tag
62
- context._sampling.mechanism = SAMPLING_MECHANISM_MANUAL
63
55
  } else if (auto) {
64
56
  context._sampling.priority = this._getPriorityFromAuto(root)
65
- } else {
66
- return
67
57
  }
68
-
69
- this._addUpstreamService(root)
70
58
  }
71
59
 
72
60
  update (rates) {
@@ -127,7 +115,6 @@ class PrioritySampler {
127
115
 
128
116
  _getPriorityByRule (context, rule) {
129
117
  context._trace[SAMPLING_RULE_DECISION] = rule.sampleRate
130
- context._sampling.mechanism = SAMPLING_MECHANISM_RULE
131
118
 
132
119
  return rule.sampler.isSampled(context) && this._isSampledByRateLimit(context) ? USER_KEEP : USER_REJECT
133
120
  }
@@ -146,44 +133,9 @@ class PrioritySampler {
146
133
 
147
134
  context._trace[SAMPLING_AGENT_DECISION] = sampler.rate()
148
135
 
149
- if (sampler === defaultSampler) {
150
- context._sampling.mechanism = SAMPLING_MECHANISM_DEFAULT
151
- } else {
152
- context._sampling.mechanism = SAMPLING_MECHANISM_AGENT
153
- }
154
-
155
136
  return sampler.isSampled(context) ? AUTO_KEEP : AUTO_REJECT
156
137
  }
157
138
 
158
- _addUpstreamService (span) {
159
- const context = span.context()
160
- const trace = context._trace
161
- const service = this._toBase64(context._tags['service.name'])
162
- const priority = context._sampling.priority
163
- const mechanism = context._sampling.mechanism
164
- const rate = Math.ceil(coalesce(
165
- context._trace[SAMPLING_RULE_DECISION],
166
- context._trace[SAMPLING_AGENT_DECISION]
167
- ) * 10000) / 10000
168
- const group = `${service}|${priority}|${mechanism}|${rate}`
169
- const groups = trace.tags[UPSTREAM_SERVICES_KEY]
170
- ? `${trace.tags[UPSTREAM_SERVICES_KEY]};${group}`
171
- : group
172
-
173
- trace.tags[UPSTREAM_SERVICES_KEY] = groups
174
- }
175
-
176
- _toBase64 (serviceName) {
177
- let encoded = serviceNames.get(serviceName)
178
-
179
- if (!encoded) {
180
- encoded = Buffer.from(serviceName).toString('base64')
181
- serviceNames.set(serviceName, encoded)
182
- }
183
-
184
- return encoded
185
- }
186
-
187
139
  _normalizeRules (rules, sampleRate) {
188
140
  return rules
189
141
  .concat({ sampleRate })
@@ -2,6 +2,14 @@
2
2
 
3
3
  const { storage } = require('../../datadog-core')
4
4
 
5
+ // TODO: deprecate binding event emitters in 3.0
6
+
7
+ const originals = new WeakMap()
8
+ const listenerMaps = new WeakMap()
9
+ const emitterSpans = new WeakMap()
10
+ const emitterScopes = new WeakMap()
11
+ const emitters = new WeakSet()
12
+
5
13
  class Scope {
6
14
  active () {
7
15
  const store = storage.getStore()
@@ -58,7 +66,7 @@ class Scope {
58
66
  })
59
67
  }
60
68
 
61
- bound._datadog_unbound = fn
69
+ originals.set(bound, fn)
62
70
 
63
71
  return bound
64
72
  }
@@ -66,16 +74,16 @@ class Scope {
66
74
  _unbindFn (fn) {
67
75
  if (typeof fn !== 'function') return fn
68
76
 
69
- return fn._datadog_unbound || fn
77
+ return originals.get(fn) || fn
70
78
  }
71
79
 
72
80
  _bindEmitter (emitter, span) {
73
81
  if (!this._isEmitter(emitter)) return emitter
74
- if (!emitter.__is_dd_emitter) {
82
+ if (!emitters.has(emitter)) {
75
83
  Scope._wrapEmitter(emitter)
76
84
  }
77
- emitter.__dd_span = span
78
- emitter.__dd_scope = this
85
+ emitterSpans.set(emitter, span)
86
+ emitterScopes.set(emitter, this)
79
87
  return emitter
80
88
  }
81
89
 
@@ -90,13 +98,13 @@ class Scope {
90
98
  wrapMethod(emitter, 'removeListener', wrapRemoveListener)
91
99
  wrapMethod(emitter, 'off', wrapRemoveListener)
92
100
  wrapMethod(emitter, 'removeAllListeners', wrapRemoveAllListeners)
93
- emitter.__is_dd_emitter = true
101
+ emitters.add(emitter)
94
102
  }
95
103
 
96
104
  _unbindEmitter (emitter) {
97
105
  if (!this._isEmitter(emitter)) return emitter
98
- delete emitter.__dd_scope
99
- delete emitter.__dd_span
106
+ emitterScopes.delete(emitter)
107
+ emitterSpans.delete(emitter)
100
108
  return emitter
101
109
  }
102
110
 
@@ -111,7 +119,7 @@ class Scope {
111
119
  _unbindPromise (promise) {
112
120
  if (!this._isPromise(promise)) return promise
113
121
 
114
- promise.then = promise.then._datadog_unbound || promise.then
122
+ promise.then = originals.get(promise.then) || promise.then
115
123
 
116
124
  return promise
117
125
  }
@@ -133,6 +141,18 @@ class Scope {
133
141
  }
134
142
  }
135
143
 
144
+ function getScope (emitter) {
145
+ return emitterScopes.get(emitter) || emitterScopes.get(emitter.constructor.prototype)
146
+ }
147
+
148
+ function getSpan (emitter) {
149
+ return emitterSpans.get(emitter) || emitterSpans.get(emitter.constructor.prototype)
150
+ }
151
+
152
+ function hasScope (emitter) {
153
+ return emitterScopes.has(emitter) || emitterScopes.has(emitter.constructor.prototype)
154
+ }
155
+
136
156
  function wrapThen (then, scope, span) {
137
157
  return function thenWithTrace (onFulfilled, onRejected) {
138
158
  const args = new Array(arguments.length)
@@ -147,21 +167,22 @@ function wrapThen (then, scope, span) {
147
167
 
148
168
  function wrapAddListener (addListener) {
149
169
  return function addListenerWithTrace (eventName, listener) {
150
- if (!this.__dd_scope || !listener || listener._datadog_unbound || listener.listener) {
170
+ const scope = getScope(this)
171
+ if (!scope || !listener || originals.has(listener) || listener.listener) {
151
172
  return addListener.apply(this, arguments)
152
173
  }
153
- const scope = this.__dd_scope
154
- const span = this.__dd_span
174
+ const span = getSpan(this)
155
175
 
156
176
  const bound = scope.bind(listener, scope._spanOrActive(span))
177
+ const listenerMap = listenerMaps.get(this) || {}
157
178
 
158
- this._datadog_events = this._datadog_events || {}
179
+ listenerMaps.set(this, listenerMap)
159
180
 
160
- if (!this._datadog_events[eventName]) {
161
- this._datadog_events[eventName] = new WeakMap()
181
+ if (!listenerMap[eventName]) {
182
+ listenerMap[eventName] = new WeakMap()
162
183
  }
163
184
 
164
- const events = this._datadog_events[eventName]
185
+ const events = listenerMap[eventName]
165
186
 
166
187
  if (!events.has(listener)) {
167
188
  events.set(listener, [])
@@ -175,11 +196,12 @@ function wrapAddListener (addListener) {
175
196
 
176
197
  function wrapRemoveListener (removeListener) {
177
198
  return function removeListenerWithTrace (eventName, listener) {
178
- if (!this.__dd_scope) {
199
+ if (!hasScope(this)) {
179
200
  return removeListener.apply(this, arguments)
180
201
  }
181
202
 
182
- const listeners = this._datadog_events && this._datadog_events[eventName]
203
+ const listenerMap = listenerMaps.get(this)
204
+ const listeners = listenerMap && listenerMap[eventName]
183
205
 
184
206
  if (!listener || !listeners || !listeners.has(listener)) {
185
207
  return removeListener.apply(this, arguments)
@@ -197,11 +219,13 @@ function wrapRemoveListener (removeListener) {
197
219
 
198
220
  function wrapRemoveAllListeners (removeAllListeners) {
199
221
  return function removeAllListenersWithTrace (eventName) {
200
- if (this.__dd_scope && this._datadog_events) {
222
+ const listenerMap = listenerMaps.get(this)
223
+
224
+ if (hasScope(this) && listenerMap) {
201
225
  if (eventName) {
202
- delete this._datadog_events[eventName]
226
+ delete listenerMap[eventName]
203
227
  } else {
204
- delete this._datadog_events
228
+ listenerMaps.delete(this)
205
229
  }
206
230
  }
207
231
 
@@ -210,12 +234,12 @@ function wrapRemoveAllListeners (removeAllListeners) {
210
234
  }
211
235
 
212
236
  function wrapMethod (target, name, wrapper, ...args) {
213
- if (!target[name] || target[name]._datadog_unbound) return
237
+ if (!target[name] || originals.has(target[name])) return
214
238
 
215
239
  const original = target[name]
216
240
 
217
241
  target[name] = wrapper(target[name], ...args)
218
- target[name]._datadog_unbound = original
242
+ originals.set(target[name], original)
219
243
  }
220
244
 
221
245
  module.exports = Scope
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const log = require('./log')
2
4
  const format = require('./format')
3
5
 
@@ -5,24 +7,37 @@ const startedSpans = new WeakSet()
5
7
  const finishedSpans = new WeakSet()
6
8
 
7
9
  class SpanProcessor {
8
- constructor (exporter, prioritySampler) {
10
+ constructor (exporter, prioritySampler, config) {
9
11
  this._exporter = exporter
10
12
  this._prioritySampler = prioritySampler
13
+ this._config = config
11
14
  }
12
15
 
13
16
  process (span) {
14
17
  const spanContext = span.context()
18
+ const active = []
19
+ const formatted = []
15
20
  const trace = spanContext._trace
21
+ const { flushMinSpans } = this._config
22
+ const { started, finished } = trace
16
23
 
17
- if (trace.started.length === trace.finished.length) {
24
+ if (started.length === finished.length || finished.length >= flushMinSpans) {
18
25
  this._prioritySampler.sample(spanContext)
19
- const formattedSpans = trace.finished.map(format)
20
- this._exporter.export(formattedSpans)
21
- this._erase(trace)
26
+
27
+ for (const span of started) {
28
+ if (span._duration !== undefined) {
29
+ formatted.push(format(span))
30
+ } else {
31
+ active.push(span)
32
+ }
33
+ }
34
+
35
+ this._exporter.export(formatted)
36
+ this._erase(trace, active)
22
37
  }
23
38
  }
24
39
 
25
- _erase (trace) {
40
+ _erase (trace, active) {
26
41
  if (process.env.DD_TRACE_EXPERIMENTAL_STATE_TRACKING === 'true') {
27
42
  const started = new Set()
28
43
  const startedIds = new Set()
@@ -98,7 +113,7 @@ class SpanProcessor {
98
113
  span.context()._tags = {}
99
114
  }
100
115
 
101
- trace.started = []
116
+ trace.started = active
102
117
  trace.finished = []
103
118
  }
104
119
  }
@@ -1,52 +0,0 @@
1
- 'use strict'
2
-
3
- function createWrapAcquire (tracer, config) {
4
- return function wrapAcquire (acquire) {
5
- return function acquireWithTrace (callback, priority) {
6
- if (typeof callback === 'function') {
7
- arguments[0] = tracer.scope().bind(callback)
8
- }
9
-
10
- return acquire.apply(this, arguments)
11
- }
12
- }
13
- }
14
-
15
- function createWrapPool (tracer, config, instrumenter) {
16
- return function wrapPool (Pool) {
17
- if (typeof Pool !== 'function') return Pool
18
-
19
- return function PoolWithTrace (factory) {
20
- const pool = Pool.apply(this, arguments)
21
-
22
- if (pool && typeof pool.acquire === 'function') {
23
- instrumenter.wrap(pool, 'acquire', createWrapAcquire(tracer, config))
24
- }
25
-
26
- return pool
27
- }
28
- }
29
- }
30
-
31
- module.exports = [
32
- {
33
- name: 'generic-pool',
34
- versions: ['^2.4'],
35
- patch (genericPool, tracer, config) {
36
- this.wrap(genericPool.Pool.prototype, 'acquire', createWrapAcquire(tracer, config))
37
- },
38
- unpatch (genericPool) {
39
- this.unwrap(genericPool.Pool.prototype, 'acquire')
40
- }
41
- },
42
- {
43
- name: 'generic-pool',
44
- versions: ['2 - 2.3'],
45
- patch (genericPool, tracer, config) {
46
- this.wrap(genericPool, 'Pool', createWrapPool(tracer, config, this))
47
- },
48
- unpatch (genericPool) {
49
- this.unwrap(genericPool, 'Pool')
50
- }
51
- }
52
- ]
@@ -1,51 +0,0 @@
1
- 'use strict'
2
-
3
- const { wrapThen } = require('../../datadog-instrumentations/src/helpers/promise')
4
-
5
- function createWrapCollectionAddQueue (tracer, config) {
6
- return function wrapAddQueue (addQueue) {
7
- return function addQueueWithTrace (name) {
8
- const scope = tracer.scope()
9
-
10
- if (typeof name === 'function') {
11
- arguments[0] = scope.bind(name)
12
- } else if (typeof this[name] === 'function') {
13
- arguments[0] = scope.bind((...args) => this[name](...args))
14
- }
15
-
16
- return addQueue.apply(this, arguments)
17
- }
18
- }
19
- }
20
-
21
- function createWrapWrapCallback (tracer, config) {
22
- return function wrapWrapCallback ($wrapCallback) {
23
- return function $wrapCallbackWithTrace (cb) {
24
- arguments[0] = tracer.scope().bind(cb)
25
- return $wrapCallback.apply(this, arguments)
26
- }
27
- }
28
- }
29
-
30
- module.exports = [
31
- {
32
- name: 'mongoose',
33
- versions: ['>=4.6.4'],
34
- patch (mongoose, tracer, config) {
35
- if (mongoose.Promise !== global.Promise) {
36
- this.wrap(mongoose.Promise.prototype, 'then', wrapThen)
37
- }
38
-
39
- this.wrap(mongoose.Collection.prototype, 'addQueue', createWrapCollectionAddQueue(tracer, config))
40
- this.wrap(mongoose.Model, '$wrapCallback', createWrapWrapCallback(tracer, config))
41
- },
42
- unpatch (mongoose) {
43
- if (mongoose.Promise !== global.Promise) {
44
- this.unwrap(mongoose.Promise.prototype, 'then')
45
- }
46
-
47
- this.unwrap(mongoose.Collection.prototype, 'addQueue')
48
- this.unwrap(mongoose.Model, '$wrapCallback')
49
- }
50
- }
51
- ]