dd-trace 3.0.0-pre.1 → 3.1.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 (71) hide show
  1. package/LICENSE-3rdparty.csv +2 -2
  2. package/MIGRATING.md +119 -0
  3. package/ci/init.js +0 -1
  4. package/ext/formats.js +3 -5
  5. package/index.d.ts +1 -11
  6. package/package.json +7 -7
  7. package/packages/datadog-core/src/storage/async_resource.js +19 -1
  8. package/packages/datadog-core/src/storage/index.js +1 -1
  9. package/packages/datadog-instrumentations/index.js +1 -52
  10. package/packages/datadog-instrumentations/src/connect.js +1 -1
  11. package/packages/datadog-instrumentations/src/cucumber.js +15 -0
  12. package/packages/datadog-instrumentations/src/grpc/client.js +2 -2
  13. package/packages/datadog-instrumentations/src/grpc/server.js +1 -1
  14. package/packages/datadog-instrumentations/src/hapi.js +3 -31
  15. package/packages/datadog-instrumentations/src/helpers/hooks.js +68 -0
  16. package/packages/datadog-instrumentations/src/helpers/instrument.js +5 -34
  17. package/packages/datadog-instrumentations/src/helpers/instrumentations.js +7 -0
  18. package/packages/datadog-instrumentations/src/helpers/register.js +59 -0
  19. package/packages/datadog-instrumentations/src/jest.js +33 -11
  20. package/packages/datadog-instrumentations/src/koa.js +1 -1
  21. package/packages/datadog-instrumentations/src/mocha.js +4 -1
  22. package/packages/datadog-instrumentations/src/pg.js +2 -2
  23. package/packages/datadog-instrumentations/src/restify.js +27 -5
  24. package/packages/datadog-instrumentations/src/router.js +1 -1
  25. package/packages/datadog-plugin-aws-sdk/src/base.js +1 -2
  26. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
  27. package/packages/datadog-plugin-cucumber/src/index.js +4 -0
  28. package/packages/datadog-plugin-jest/src/index.js +25 -4
  29. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  30. package/packages/datadog-plugin-mongodb-core/src/index.js +21 -6
  31. package/packages/datadog-plugin-oracledb/src/index.js +12 -4
  32. package/packages/datadog-plugin-restify/src/index.js +7 -0
  33. package/packages/dd-trace/index.js +1 -1
  34. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +50 -0
  35. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +53 -8
  36. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +23 -24
  37. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +220 -0
  38. package/packages/dd-trace/src/config.js +13 -0
  39. package/packages/dd-trace/src/encode/0.4.js +51 -58
  40. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +13 -34
  41. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +84 -0
  42. package/packages/dd-trace/src/exporters/agent/index.js +13 -7
  43. package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
  44. package/packages/dd-trace/src/{profiling/exporters → exporters/common}/form-data.js +0 -0
  45. package/packages/dd-trace/src/exporters/common/request.js +23 -11
  46. package/packages/dd-trace/src/exporters/common/writer.js +9 -6
  47. package/packages/dd-trace/src/id.js +16 -13
  48. package/packages/dd-trace/src/iitm.js +1 -1
  49. package/packages/dd-trace/src/index.js +10 -0
  50. package/packages/dd-trace/src/noop/proxy.js +77 -0
  51. package/packages/dd-trace/src/noop/scope.js +2 -6
  52. package/packages/dd-trace/src/noop/span.js +12 -12
  53. package/packages/dd-trace/src/noop/tracer.js +8 -5
  54. package/packages/dd-trace/src/opentracing/propagation/text_map.js +6 -6
  55. package/packages/dd-trace/src/opentracing/span.js +63 -49
  56. package/packages/dd-trace/src/opentracing/span_context.js +1 -5
  57. package/packages/dd-trace/src/opentracing/tracer.js +31 -36
  58. package/packages/dd-trace/src/plugin_manager.js +101 -68
  59. package/packages/dd-trace/src/plugins/index.js +57 -44
  60. package/packages/dd-trace/src/plugins/util/ci.js +34 -9
  61. package/packages/dd-trace/src/plugins/util/git.js +52 -2
  62. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  63. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  64. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  65. package/packages/dd-trace/src/profiling/profilers/cpu.js +3 -3
  66. package/packages/dd-trace/src/proxy.js +18 -71
  67. package/packages/dd-trace/src/scope.js +1 -58
  68. package/packages/dd-trace/src/startup-log.js +8 -19
  69. package/packages/dd-trace/src/telemetry.js +2 -15
  70. package/scripts/install_plugin_modules.js +17 -26
  71. package/ci/jest/env.js +0 -38
@@ -3,39 +3,44 @@
3
3
  // TODO: Add test with slow or unresponsive agent.
4
4
  // TODO: Add telemetry for things like dropped requests, errors, etc.
5
5
 
6
+ const { Readable } = require('stream')
6
7
  const http = require('http')
7
8
  const https = require('https')
8
9
  const docker = require('./docker')
9
10
  const { storage } = require('../../../../datadog-core')
11
+ const log = require('../../log')
10
12
 
11
13
  const keepAlive = true
12
- const maxTotalSockets = 8
14
+ const maxTotalSockets = 1
15
+ const maxActiveRequests = 8
13
16
  const httpAgent = new http.Agent({ keepAlive, maxTotalSockets })
14
17
  const httpsAgent = new https.Agent({ keepAlive, maxTotalSockets })
15
18
  const containerId = docker.id()
16
19
 
17
20
  let activeRequests = 0
18
21
 
19
- function request (data, options, keepAlive, callback) {
22
+ function request (data, options, callback) {
20
23
  if (!options.headers) {
21
24
  options.headers = {}
22
25
  }
23
26
 
27
+ const isReadable = data instanceof Readable
28
+
24
29
  // The timeout should be kept low to avoid excessive queueing.
25
30
  const timeout = options.timeout || 2000
26
31
  const isSecure = options.protocol === 'https:'
27
32
  const client = isSecure ? https : http
28
33
  const dataArray = [].concat(data)
29
34
 
30
- options.headers['Content-Length'] = byteLength(dataArray)
35
+ if (!isReadable) {
36
+ options.headers['Content-Length'] = byteLength(dataArray)
37
+ }
31
38
 
32
39
  if (containerId) {
33
40
  options.headers['Datadog-Container-ID'] = containerId
34
41
  }
35
42
 
36
- if (keepAlive) {
37
- options.agent = isSecure ? httpsAgent : httpAgent
38
- }
43
+ options.agent = isSecure ? httpsAgent : httpAgent
39
44
 
40
45
  const onResponse = res => {
41
46
  let responseData = ''
@@ -58,7 +63,10 @@ function request (data, options, keepAlive, callback) {
58
63
  }
59
64
 
60
65
  const makeRequest = onError => {
61
- if (!request.writable) return callback(null)
66
+ if (!request.writable) {
67
+ log.debug('Maximum number of active requests reached: payload is discarded.')
68
+ return callback(null)
69
+ }
62
70
 
63
71
  activeRequests++
64
72
 
@@ -73,10 +81,14 @@ function request (data, options, keepAlive, callback) {
73
81
  onError(err)
74
82
  })
75
83
 
76
- dataArray.forEach(buffer => req.write(buffer))
77
-
78
84
  req.setTimeout(timeout, req.abort)
79
- req.end()
85
+
86
+ if (isReadable) {
87
+ data.pipe(req)
88
+ } else {
89
+ dataArray.forEach(buffer => req.write(buffer))
90
+ req.end()
91
+ }
80
92
 
81
93
  storage.enterWith(store)
82
94
  }
@@ -90,7 +102,7 @@ function byteLength (data) {
90
102
 
91
103
  Object.defineProperty(request, 'writable', {
92
104
  get () {
93
- return activeRequests < maxTotalSockets
105
+ return activeRequests < maxActiveRequests
94
106
  }
95
107
  })
96
108
 
@@ -23,16 +23,19 @@ class Writer {
23
23
  }
24
24
  }
25
25
 
26
- append (spans) {
27
- if (!request.writable) return
26
+ append (payload) {
27
+ if (!request.writable) {
28
+ log.debug(() => `Maximum number of active requests reached. Payload discarded: ${JSON.stringify(payload)}`)
29
+ return
30
+ }
28
31
 
29
- log.debug(() => `Encoding trace: ${JSON.stringify(spans)}`)
32
+ log.debug(() => `Encoding payload: ${JSON.stringify(payload)}`)
30
33
 
31
- this._encode(spans)
34
+ this._encode(payload)
32
35
  }
33
36
 
34
- _encode (trace) {
35
- this._encoder.encode(trace)
37
+ _encode (payload) {
38
+ this._encoder.encode(payload)
36
39
  }
37
40
 
38
41
  setUrl (url) {
@@ -14,17 +14,17 @@ let batch = 0
14
14
 
15
15
  // Internal representation of a trace or span ID.
16
16
  class Identifier {
17
- constructor (value, radix) {
17
+ constructor (value, radix = 16) {
18
18
  this._isUint64BE = true // msgpack-lite compatibility
19
- this._buffer = typeof radix === 'number'
20
- ? fromString(value, radix)
21
- : createBuffer(value)
19
+ this._buffer = radix === 16
20
+ ? createBuffer(value)
21
+ : fromString(value, radix)
22
22
  }
23
23
 
24
- toString (radix) {
25
- return typeof radix === 'number'
26
- ? toNumberString(this._buffer, radix)
27
- : toHexString(this._buffer)
24
+ toString (radix = 16) {
25
+ return radix === 16
26
+ ? toHexString(this._buffer)
27
+ : toNumberString(this._buffer, radix)
28
28
  }
29
29
 
30
30
  toBuffer () {
@@ -49,10 +49,13 @@ function createBuffer (value) {
49
49
  if (value === '0') return zeroId
50
50
  if (!value) return pseudoRandom()
51
51
 
52
- const size = Math.ceil(value.length / 2)
53
- const buffer = new Array(size)
52
+ const size = Math.ceil(value.length / 16) * 16
53
+ const bytes = size / 2
54
+ const buffer = new Array(bytes)
54
55
 
55
- for (let i = 0; i < size; i++) {
56
+ value = value.padStart(size, '0')
57
+
58
+ for (let i = 0; i < bytes; i++) {
56
59
  buffer[i] = parseInt(value.substring(i * 2, i * 2 + 2), 16)
57
60
  }
58
61
 
@@ -100,8 +103,8 @@ function fromString (str, raddix) {
100
103
 
101
104
  // Convert a buffer to a numerical string.
102
105
  function toNumberString (buffer, radix) {
103
- let high = readInt32(buffer, 0)
104
- let low = readInt32(buffer, 4)
106
+ let high = readInt32(buffer, buffer.length - 8)
107
+ let low = readInt32(buffer, buffer.length - 4)
105
108
  let str = ''
106
109
 
107
110
  radix = radix || 10
@@ -3,7 +3,7 @@
3
3
  const semver = require('semver')
4
4
  const logger = require('./log')
5
5
 
6
- if (semver.satisfies(process.versions.node, '^12.20.0 || >=14.13.1')) {
6
+ if (semver.satisfies(process.versions.node, '>=14.13.1')) {
7
7
  module.exports = require('import-in-the-middle')
8
8
  } else {
9
9
  logger.warn('ESM is not fully supported by this version of Node.js, ' +
@@ -0,0 +1,10 @@
1
+ 'use strict'
2
+
3
+ const { isFalse } = require('./util')
4
+
5
+ // Global `jest` is only present in Jest workers.
6
+ const inJestWorker = typeof jest !== 'undefined'
7
+
8
+ module.exports = isFalse(process.env.DD_TRACE_ENABLED) || inJestWorker
9
+ ? require('./noop/proxy')
10
+ : require('./proxy')
@@ -0,0 +1,77 @@
1
+ 'use strict'
2
+
3
+ const NoopTracer = require('./tracer')
4
+
5
+ const noop = new NoopTracer()
6
+
7
+ class Tracer {
8
+ constructor () {
9
+ this._tracer = noop
10
+ }
11
+
12
+ init () {
13
+ return this
14
+ }
15
+
16
+ use () {
17
+ return this
18
+ }
19
+
20
+ trace (name, options, fn) {
21
+ if (!fn) {
22
+ fn = options
23
+ options = {}
24
+ }
25
+
26
+ if (typeof fn !== 'function') return
27
+
28
+ options = options || {}
29
+
30
+ return this._tracer.trace(name, options, fn)
31
+ }
32
+
33
+ wrap (name, options, fn) {
34
+ if (!fn) {
35
+ fn = options
36
+ options = {}
37
+ }
38
+
39
+ if (typeof fn !== 'function') return fn
40
+
41
+ options = options || {}
42
+
43
+ return this._tracer.wrap(name, options, fn)
44
+ }
45
+
46
+ setUrl () {
47
+ this._tracer.setUrl.apply(this._tracer, arguments)
48
+ return this
49
+ }
50
+
51
+ startSpan () {
52
+ return this._tracer.startSpan.apply(this._tracer, arguments)
53
+ }
54
+
55
+ inject () {
56
+ return this._tracer.inject.apply(this._tracer, arguments)
57
+ }
58
+
59
+ extract () {
60
+ return this._tracer.extract.apply(this._tracer, arguments)
61
+ }
62
+
63
+ scope () {
64
+ return this._tracer.scope.apply(this._tracer, arguments)
65
+ }
66
+
67
+ getRumData () {
68
+ return this._tracer.getRumData.apply(this._tracer, arguments)
69
+ }
70
+
71
+ setUser () {
72
+ this._tracer.setUser.apply(this._tracer, arguments)
73
+ return this
74
+ }
75
+ }
76
+
77
+ module.exports = Tracer
@@ -11,12 +11,8 @@ class Scope {
11
11
  return callback()
12
12
  }
13
13
 
14
- bind (target, span) {
15
- return target
16
- }
17
-
18
- unbind (target) {
19
- return target
14
+ bind (fn, span) {
15
+ return fn
20
16
  }
21
17
  }
22
18
 
@@ -1,26 +1,26 @@
1
1
  'use strict'
2
2
 
3
- const Span = require('opentracing').Span
4
- const NoopSpanContext = require('../noop/span_context')
3
+ const NoopSpanContext = require('./span_context')
5
4
  const id = require('../id')
6
5
  const { storage } = require('../../../datadog-core') // TODO: noop storage?
7
6
 
8
- class NoopSpan extends Span {
7
+ class NoopSpan {
9
8
  constructor (tracer, parent) {
10
- super()
11
-
12
9
  this._store = storage.getStore()
13
10
  this._noopTracer = tracer
14
11
  this._noopContext = this._createContext(parent)
15
12
  }
16
13
 
17
- _context () {
18
- return this._noopContext
19
- }
20
-
21
- _tracer () {
22
- return this._noopTracer
23
- }
14
+ context () { return this._noopContext }
15
+ tracer () { return this._noopTracer }
16
+ setOperationName (name) { return this }
17
+ setBaggageItem (key, value) { return this }
18
+ getBaggageItem (key) {}
19
+ setTag (key, value) { return this }
20
+ addTags (keyValueMap) { return this }
21
+ log () { return this }
22
+ logEvent () {}
23
+ finish (finishTime) {}
24
24
 
25
25
  _createContext (parent) {
26
26
  const spanId = id()
@@ -1,13 +1,10 @@
1
1
  'use strict'
2
2
 
3
- const Tracer = require('opentracing').Tracer
4
3
  const Scope = require('../noop/scope')
5
4
  const Span = require('./span')
6
5
 
7
- class NoopTracer extends Tracer {
6
+ class NoopTracer {
8
7
  constructor (config) {
9
- super(config)
10
-
11
8
  this._scope = new Scope()
12
9
  this._span = new Span(this)
13
10
  }
@@ -31,10 +28,16 @@ class NoopTracer extends Tracer {
31
28
  setUrl () {
32
29
  }
33
30
 
34
- _startSpan (name, options) {
31
+ startSpan (name, options) {
35
32
  return this._span
36
33
  }
37
34
 
35
+ inject (spanContext, format, carrier) {}
36
+
37
+ extract (format, carrier) {
38
+ return this._span.context()
39
+ }
40
+
38
41
  setUser () {
39
42
  return this
40
43
  }
@@ -82,8 +82,8 @@ class TextMapPropagator {
82
82
  _injectB3 (spanContext, carrier) {
83
83
  if (!this._config.experimental.b3) return
84
84
 
85
- carrier[b3TraceKey] = spanContext._traceId.toString('hex')
86
- carrier[b3SpanKey] = spanContext._spanId.toString('hex')
85
+ carrier[b3TraceKey] = spanContext._traceId.toString(16)
86
+ carrier[b3SpanKey] = spanContext._spanId.toString(16)
87
87
  carrier[b3SampledKey] = spanContext._sampling.priority >= AUTO_KEEP ? '1' : '0'
88
88
 
89
89
  if (spanContext._sampling.priority > AUTO_KEEP) {
@@ -91,7 +91,7 @@ class TextMapPropagator {
91
91
  }
92
92
 
93
93
  if (spanContext._parentId) {
94
- carrier[b3ParentKey] = spanContext._parentId.toString('hex')
94
+ carrier[b3ParentKey] = spanContext._parentId.toString(16)
95
95
  }
96
96
  }
97
97
 
@@ -99,8 +99,8 @@ class TextMapPropagator {
99
99
  if (!this._config.experimental.traceparent) return
100
100
 
101
101
  const sampling = spanContext._sampling.priority >= AUTO_KEEP ? '01' : '00'
102
- const traceId = spanContext._traceId.toString('hex').padStart(32, '0')
103
- const spanId = spanContext._spanId.toString('hex').padStart(16, '0')
102
+ const traceId = spanContext._traceId.toString(16).padStart(32, '0')
103
+ const spanId = spanContext._spanId.toString(16).padStart(16, '0')
104
104
  carrier[traceparentKey] = `01-${traceId}-${spanId}-${sampling}`
105
105
  }
106
106
 
@@ -129,7 +129,7 @@ class TextMapPropagator {
129
129
  const b3 = this._extractB3Headers(carrier)
130
130
  const debug = b3[b3FlagsKey] === '1'
131
131
  const priority = this._getPriority(b3[b3SampledKey], debug)
132
- const spanContext = this._extractGenericContext(b3, b3TraceKey, b3SpanKey)
132
+ const spanContext = this._extractGenericContext(b3, b3TraceKey, b3SpanKey, 16)
133
133
 
134
134
  if (priority !== undefined) {
135
135
  if (!spanContext) {
@@ -1,11 +1,9 @@
1
1
  'use strict'
2
2
 
3
3
  // TODO (new internal tracer): use DC events for lifecycle metrics and test them
4
-
5
- const opentracing = require('opentracing')
6
- const now = require('performance-now')
4
+ const now = require('perf_hooks').performance.now
5
+ const dateNow = Date.now
7
6
  const semver = require('semver')
8
- const Span = opentracing.Span
9
7
  const SpanContext = require('./span_context')
10
8
  const id = require('../id')
11
9
  const tagger = require('../tagger')
@@ -21,10 +19,8 @@ const {
21
19
  const unfinishedRegistry = createRegistry('unfinished')
22
20
  const finishedRegistry = createRegistry('finished')
23
21
 
24
- class DatadogSpan extends Span {
22
+ class DatadogSpan {
25
23
  constructor (tracer, processor, prioritySampler, fields, debug) {
26
- super()
27
-
28
24
  const operationName = fields.operationName
29
25
  const parent = fields.parent || null
30
26
  const tags = Object.assign({}, fields.tags)
@@ -70,66 +66,45 @@ class DatadogSpan extends Span {
70
66
  return `Span${json}`
71
67
  }
72
68
 
73
- _createContext (parent) {
74
- let spanContext
75
-
76
- if (parent) {
77
- spanContext = new SpanContext({
78
- traceId: parent._traceId,
79
- spanId: id(),
80
- parentId: parent._spanId,
81
- sampling: parent._sampling,
82
- baggageItems: Object.assign({}, parent._baggageItems),
83
- trace: parent._trace
84
- })
85
- } else {
86
- const spanId = id()
87
- spanContext = new SpanContext({
88
- traceId: spanId,
89
- spanId
90
- })
91
- }
92
-
93
- spanContext._trace.started.push(this)
94
- spanContext._trace.startTime = spanContext._trace.startTime || Date.now()
95
- spanContext._trace.ticks = spanContext._trace.ticks || now()
96
-
97
- return spanContext
98
- }
99
-
100
- _getTime () {
101
- const { startTime, ticks } = this._spanContext._trace
102
-
103
- return startTime + now() - ticks
104
- }
105
-
106
- _context () {
69
+ context () {
107
70
  return this._spanContext
108
71
  }
109
72
 
110
- _tracer () {
73
+ tracer () {
111
74
  return this._parentTracer
112
75
  }
113
76
 
114
- _setOperationName (name) {
77
+ setOperationName (name) {
115
78
  this._spanContext._name = name
79
+ return this
116
80
  }
117
81
 
118
- _setBaggageItem (key, value) {
82
+ setBaggageItem (key, value) {
119
83
  this._spanContext._baggageItems[key] = value
84
+ return this
120
85
  }
121
86
 
122
- _getBaggageItem (key) {
87
+ getBaggageItem (key) {
123
88
  return this._spanContext._baggageItems[key]
124
89
  }
125
90
 
126
- _addTags (keyValuePairs) {
127
- tagger.add(this._spanContext._tags, keyValuePairs)
91
+ setTag (key, value) {
92
+ this._addTags({ [key]: value })
93
+ return this
94
+ }
128
95
 
129
- this._prioritySampler.sample(this, false)
96
+ addTags (keyValueMap) {
97
+ this._addTags(keyValueMap)
98
+ return this
99
+ }
100
+
101
+ log () {
102
+ return this
130
103
  }
131
104
 
132
- _finish (finishTime) {
105
+ logEvent () {}
106
+
107
+ finish (finishTime) {
133
108
  if (this._duration !== undefined) {
134
109
  return
135
110
  }
@@ -157,6 +132,45 @@ class DatadogSpan extends Span {
157
132
  this._spanContext._isFinished = true
158
133
  this._processor.process(this)
159
134
  }
135
+
136
+ _createContext (parent) {
137
+ let spanContext
138
+
139
+ if (parent) {
140
+ spanContext = new SpanContext({
141
+ traceId: parent._traceId,
142
+ spanId: id(),
143
+ parentId: parent._spanId,
144
+ sampling: parent._sampling,
145
+ baggageItems: Object.assign({}, parent._baggageItems),
146
+ trace: parent._trace
147
+ })
148
+ } else {
149
+ const spanId = id()
150
+ spanContext = new SpanContext({
151
+ traceId: spanId,
152
+ spanId
153
+ })
154
+ }
155
+
156
+ spanContext._trace.started.push(this)
157
+ spanContext._trace.startTime = spanContext._trace.startTime || dateNow()
158
+ spanContext._trace.ticks = spanContext._trace.ticks || now()
159
+
160
+ return spanContext
161
+ }
162
+
163
+ _getTime () {
164
+ const { startTime, ticks } = this._spanContext._trace
165
+
166
+ return startTime + now() - ticks
167
+ }
168
+
169
+ _addTags (keyValuePairs) {
170
+ tagger.add(this._spanContext._tags, keyValuePairs)
171
+
172
+ this._prioritySampler.sample(this, false)
173
+ }
160
174
  }
161
175
 
162
176
  function createRegistry (type) {
@@ -1,11 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const SpanContext = require('opentracing').SpanContext
4
-
5
- class DatadogSpanContext extends SpanContext {
3
+ class DatadogSpanContext {
6
4
  constructor (props) {
7
- super()
8
-
9
5
  props = props || {}
10
6
 
11
7
  this._traceId = props.traceId