dd-trace 2.12.2 → 2.15.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 (76) hide show
  1. package/LICENSE-3rdparty.csv +2 -0
  2. package/ext/tags.d.ts +2 -1
  3. package/ext/tags.js +2 -1
  4. package/index.d.ts +43 -20
  5. package/package.json +5 -3
  6. package/packages/datadog-core/src/storage/async_resource.js +19 -1
  7. package/packages/datadog-instrumentations/index.js +1 -52
  8. package/packages/datadog-instrumentations/src/crypto.js +30 -0
  9. package/packages/datadog-instrumentations/src/cucumber.js +15 -0
  10. package/packages/datadog-instrumentations/src/fs.js +11 -0
  11. package/packages/datadog-instrumentations/src/helpers/hooks.js +70 -0
  12. package/packages/datadog-instrumentations/src/helpers/instrument.js +5 -34
  13. package/packages/datadog-instrumentations/src/helpers/instrumentations.js +7 -0
  14. package/packages/datadog-instrumentations/src/helpers/register.js +59 -0
  15. package/packages/datadog-instrumentations/src/http/server.js +1 -1
  16. package/packages/datadog-instrumentations/src/jest.js +33 -11
  17. package/packages/datadog-instrumentations/src/net.js +13 -0
  18. package/packages/datadog-plugin-cucumber/src/index.js +4 -0
  19. package/packages/datadog-plugin-fs/src/index.js +72 -38
  20. package/packages/datadog-plugin-jest/src/index.js +25 -4
  21. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  22. package/packages/datadog-plugin-mongodb-core/src/index.js +32 -8
  23. package/packages/datadog-plugin-oracledb/src/index.js +12 -4
  24. package/packages/dd-trace/index.js +1 -1
  25. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +3 -0
  26. package/packages/dd-trace/src/appsec/iast/analyzers/index.js +20 -0
  27. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +48 -0
  28. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +24 -0
  29. package/packages/dd-trace/src/appsec/iast/iast-context.js +50 -0
  30. package/packages/dd-trace/src/appsec/iast/index.js +59 -0
  31. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +94 -0
  32. package/packages/dd-trace/src/appsec/iast/path-line.js +70 -0
  33. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +113 -0
  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 +89 -10
  39. package/packages/dd-trace/src/constants.js +9 -1
  40. package/packages/dd-trace/src/encode/0.4.js +51 -58
  41. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +13 -34
  42. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +84 -0
  43. package/packages/dd-trace/src/encode/span-stats.js +155 -0
  44. package/packages/dd-trace/src/exporters/agent/index.js +25 -7
  45. package/packages/dd-trace/src/exporters/agent/writer.js +7 -4
  46. package/packages/dd-trace/src/{profiling/exporters → exporters/common}/form-data.js +0 -0
  47. package/packages/dd-trace/src/exporters/common/request.js +25 -10
  48. package/packages/dd-trace/src/exporters/common/writer.js +9 -6
  49. package/packages/dd-trace/src/exporters/span-stats/index.js +20 -0
  50. package/packages/dd-trace/src/exporters/span-stats/writer.js +54 -0
  51. package/packages/dd-trace/src/format.js +2 -0
  52. package/packages/dd-trace/src/id.js +16 -13
  53. package/packages/dd-trace/src/iitm.js +11 -0
  54. package/packages/dd-trace/src/index.js +10 -0
  55. package/packages/dd-trace/src/noop/proxy.js +87 -0
  56. package/packages/dd-trace/src/opentracing/propagation/text_map.js +77 -6
  57. package/packages/dd-trace/src/opentracing/tracer.js +1 -1
  58. package/packages/dd-trace/src/plugin_manager.js +107 -65
  59. package/packages/dd-trace/src/plugins/index.js +58 -45
  60. package/packages/dd-trace/src/plugins/log_plugin.js +16 -9
  61. package/packages/dd-trace/src/plugins/util/ci.js +34 -9
  62. package/packages/dd-trace/src/plugins/util/git.js +52 -2
  63. package/packages/dd-trace/src/plugins/util/ip_blocklist.js +25 -0
  64. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  65. package/packages/dd-trace/src/plugins/util/web.js +99 -2
  66. package/packages/dd-trace/src/priority_sampler.js +36 -1
  67. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  68. package/packages/dd-trace/src/proxy.js +23 -89
  69. package/packages/dd-trace/src/ritm.js +10 -1
  70. package/packages/dd-trace/src/span_processor.js +7 -1
  71. package/packages/dd-trace/src/span_stats.js +210 -0
  72. package/packages/dd-trace/src/startup-log.js +8 -19
  73. package/packages/dd-trace/src/telemetry/dependencies.js +83 -0
  74. package/packages/dd-trace/src/{telemetry.js → telemetry/index.js} +11 -79
  75. package/packages/dd-trace/src/telemetry/send-data.js +35 -0
  76. package/scripts/install_plugin_modules.js +17 -26
@@ -0,0 +1,155 @@
1
+ 'use strict'
2
+
3
+ const { AgentEncoder } = require('./0.4')
4
+
5
+ const {
6
+ MAX_NAME_LENGTH,
7
+ MAX_SERVICE_LENGTH,
8
+ MAX_RESOURCE_NAME_LENGTH,
9
+ MAX_TYPE_LENGTH,
10
+ DEFAULT_SPAN_NAME,
11
+ DEFAULT_SERVICE_NAME
12
+ } = require('./tags-processors')
13
+
14
+ function truncate (value, maxLength, suffix = '') {
15
+ if (!value) {
16
+ return value
17
+ }
18
+ if (value.length > maxLength) {
19
+ return `${value.slice(0, maxLength)}${suffix}`
20
+ }
21
+ return value
22
+ }
23
+
24
+ class SpanStatsEncoder extends AgentEncoder {
25
+ _encodeBool (bytes, value) {
26
+ this._encodeByte(bytes, value ? 0xc3 : 0xc2)
27
+ }
28
+
29
+ makePayload () {
30
+ const traceSize = this._traceBytes.length
31
+ const buffer = Buffer.allocUnsafe(traceSize)
32
+ this._traceBytes.copy(buffer, 0, traceSize)
33
+ this._reset()
34
+ return buffer
35
+ }
36
+
37
+ _encodeMapPrefix (bytes, length) {
38
+ const offset = bytes.length
39
+
40
+ bytes.reserve(1)
41
+ bytes.length += 1
42
+
43
+ bytes.buffer[offset] = 0x80 + length
44
+ }
45
+
46
+ _encodeBuffer (bytes, buffer) {
47
+ const length = buffer.length
48
+ const offset = bytes.length
49
+
50
+ bytes.reserve(5)
51
+ bytes.length += 5
52
+
53
+ bytes.buffer[offset] = 0xc6
54
+ bytes.buffer[offset + 1] = length >> 24
55
+ bytes.buffer[offset + 2] = length >> 16
56
+ bytes.buffer[offset + 3] = length >> 8
57
+ bytes.buffer[offset + 4] = length
58
+
59
+ buffer.copy(bytes.buffer, offset + 5)
60
+ bytes.length += length
61
+ }
62
+
63
+ _encodeStat (bytes, stat) {
64
+ this._encodeMapPrefix(bytes, 12)
65
+
66
+ this._encodeString(bytes, 'Service')
67
+ const service = stat.Service || DEFAULT_SERVICE_NAME
68
+ this._encodeString(bytes, truncate(service, MAX_SERVICE_LENGTH))
69
+
70
+ this._encodeString(bytes, 'Name')
71
+ const name = stat.Name || DEFAULT_SPAN_NAME
72
+ this._encodeString(bytes, truncate(name, MAX_NAME_LENGTH))
73
+
74
+ this._encodeString(bytes, 'Resource')
75
+ this._encodeString(bytes, truncate(stat.Resource, MAX_RESOURCE_NAME_LENGTH, '...'))
76
+
77
+ this._encodeString(bytes, 'HTTPStatusCode')
78
+ this._encodeInteger(bytes, stat.HTTPStatusCode)
79
+
80
+ this._encodeString(bytes, 'Type')
81
+ this._encodeString(bytes, truncate(stat.Type, MAX_TYPE_LENGTH))
82
+
83
+ this._encodeString(bytes, 'Hits')
84
+ this._encodeLong(bytes, stat.Hits)
85
+
86
+ this._encodeString(bytes, 'Errors')
87
+ this._encodeLong(bytes, stat.Errors)
88
+
89
+ this._encodeString(bytes, 'Duration')
90
+ this._encodeLong(bytes, stat.Duration)
91
+
92
+ this._encodeString(bytes, 'OkSummary')
93
+ this._encodeBuffer(bytes, stat.OkSummary)
94
+
95
+ this._encodeString(bytes, 'ErrorSummary')
96
+ this._encodeBuffer(bytes, stat.ErrorSummary)
97
+
98
+ this._encodeString(bytes, 'Synthetics')
99
+ this._encodeBool(bytes, stat.Synthetics)
100
+
101
+ this._encodeString(bytes, 'TopLevelHits')
102
+ this._encodeLong(bytes, stat.TopLevelHits)
103
+ }
104
+
105
+ _encodeBucket (bytes, bucket) {
106
+ this._encodeMapPrefix(bytes, 3)
107
+
108
+ this._encodeString(bytes, 'Start')
109
+ this._encodeLong(bytes, bucket.Start)
110
+
111
+ this._encodeString(bytes, 'Duration')
112
+ this._encodeLong(bytes, bucket.Duration)
113
+
114
+ this._encodeString(bytes, 'Stats')
115
+ this._encodeArrayPrefix(bytes, bucket.Stats)
116
+ for (const stat of bucket.Stats) {
117
+ this._encodeStat(bytes, stat)
118
+ }
119
+ }
120
+
121
+ _encode (bytes, stats) {
122
+ this._encodeMapPrefix(bytes, 8)
123
+
124
+ this._encodeString(bytes, 'Hostname')
125
+ this._encodeString(bytes, stats.Hostname)
126
+
127
+ this._encodeString(bytes, 'Env')
128
+ this._encodeString(bytes, stats.Env)
129
+
130
+ this._encodeString(bytes, 'Version')
131
+ this._encodeString(bytes, stats.Version)
132
+
133
+ this._encodeString(bytes, 'Stats')
134
+ this._encodeArrayPrefix(bytes, stats.Stats)
135
+ for (const bucket of stats.Stats) {
136
+ this._encodeBucket(bytes, bucket)
137
+ }
138
+
139
+ this._encodeString(bytes, 'Lang')
140
+ this._encodeString(bytes, stats.Lang)
141
+
142
+ this._encodeString(bytes, 'TracerVersion')
143
+ this._encodeString(bytes, stats.TracerVersion)
144
+
145
+ this._encodeString(bytes, 'RuntimeID')
146
+ this._encodeString(bytes, stats.RuntimeID)
147
+
148
+ this._encodeString(bytes, 'Sequence')
149
+ this._encodeLong(bytes, stats.Sequence)
150
+ }
151
+ }
152
+
153
+ module.exports = {
154
+ SpanStatsEncoder
155
+ }
@@ -3,17 +3,28 @@
3
3
  const URL = require('url').URL
4
4
  const log = require('../../log')
5
5
  const Writer = require('./writer')
6
- const Scheduler = require('../scheduler')
7
6
 
8
7
  class AgentExporter {
9
- constructor ({ url, hostname, port, flushInterval, lookup, protocolVersion }, prioritySampler) {
8
+ constructor (config, prioritySampler) {
9
+ this._config = config
10
+ const { url, hostname, port, lookup, protocolVersion, stats = {} } = config
10
11
  this._url = url || new URL(`http://${hostname || 'localhost'}:${port}`)
11
- this._writer = new Writer({ url: this._url, prioritySampler, lookup, protocolVersion })
12
12
 
13
- if (flushInterval > 0) {
14
- this._scheduler = new Scheduler(() => this._writer.flush(), flushInterval)
13
+ const headers = {}
14
+ if (stats.enabled) {
15
+ headers['Datadog-Client-Computed-Stats'] = 'yes'
15
16
  }
16
- this._scheduler && this._scheduler.start()
17
+
18
+ this._writer = new Writer({
19
+ url: this._url,
20
+ prioritySampler,
21
+ lookup,
22
+ protocolVersion,
23
+ headers
24
+ })
25
+
26
+ this._timer = undefined
27
+ process.once('beforeExit', () => this._writer.flush())
17
28
  }
18
29
 
19
30
  setUrl (url) {
@@ -29,8 +40,15 @@ class AgentExporter {
29
40
  export (spans) {
30
41
  this._writer.append(spans)
31
42
 
32
- if (!this._scheduler) {
43
+ const { flushInterval } = this._config
44
+
45
+ if (flushInterval === 0) {
33
46
  this._writer.flush()
47
+ } else if (flushInterval > 0 && !this._timer) {
48
+ this._timer = setTimeout(() => {
49
+ this._writer.flush()
50
+ this._timer = clearTimeout(this._timer)
51
+ }, flushInterval).unref()
34
52
  }
35
53
  }
36
54
  }
@@ -10,7 +10,7 @@ const BaseWriter = require('../common/writer')
10
10
  const METRIC_PREFIX = 'datadog.tracer.node.exporter.agent'
11
11
 
12
12
  class Writer extends BaseWriter {
13
- constructor ({ prioritySampler, lookup, protocolVersion }) {
13
+ constructor ({ prioritySampler, lookup, protocolVersion, headers }) {
14
14
  super(...arguments)
15
15
  const AgentEncoder = getEncoder(protocolVersion)
16
16
 
@@ -18,12 +18,14 @@ class Writer extends BaseWriter {
18
18
  this._lookup = lookup
19
19
  this._protocolVersion = protocolVersion
20
20
  this._encoder = new AgentEncoder(this)
21
+ this._headers = headers
21
22
  }
22
23
 
23
24
  _sendPayload (data, count, done) {
24
25
  metrics.increment(`${METRIC_PREFIX}.requests`, true)
25
26
 
26
- makeRequest(this._protocolVersion, data, count, this._url, this._lookup, true, (err, res, status) => {
27
+ const { _headers, _lookup, _protocolVersion, _url } = this
28
+ makeRequest(_protocolVersion, data, count, _url, _headers, _lookup, true, (err, res, status) => {
27
29
  if (status) {
28
30
  metrics.increment(`${METRIC_PREFIX}.responses`, true)
29
31
  metrics.increment(`${METRIC_PREFIX}.responses.by.status`, `status:${status}`, true)
@@ -73,11 +75,12 @@ function getEncoder (protocolVersion) {
73
75
  }
74
76
  }
75
77
 
76
- function makeRequest (version, data, count, url, lookup, needsStartupLog, cb) {
78
+ function makeRequest (version, data, count, url, headers, lookup, needsStartupLog, cb) {
77
79
  const options = {
78
80
  path: `/v${version}/traces`,
79
81
  method: 'PUT',
80
82
  headers: {
83
+ ...headers,
81
84
  'Content-Type': 'application/msgpack',
82
85
  'Datadog-Meta-Tracer-Version': tracerVersion,
83
86
  'X-Datadog-Trace-Count': String(count)
@@ -99,7 +102,7 @@ function makeRequest (version, data, count, url, lookup, needsStartupLog, cb) {
99
102
 
100
103
  log.debug(() => `Request to the agent: ${JSON.stringify(options)}`)
101
104
 
102
- request(data, options, true, (err, res, status) => {
105
+ request(data, options, (err, res, status) => {
103
106
  if (needsStartupLog) {
104
107
  // Note that logging will only happen once, regardless of how many times this is called.
105
108
  startupLog({
@@ -3,10 +3,12 @@
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
14
  const maxTotalSockets = 1
@@ -17,26 +19,28 @@ const containerId = docker.id()
17
19
 
18
20
  let activeRequests = 0
19
21
 
20
- function request (data, options, keepAlive, callback) {
22
+ function request (data, options, callback) {
21
23
  if (!options.headers) {
22
24
  options.headers = {}
23
25
  }
24
26
 
27
+ const isReadable = data instanceof Readable
28
+
25
29
  // The timeout should be kept low to avoid excessive queueing.
26
30
  const timeout = options.timeout || 2000
27
31
  const isSecure = options.protocol === 'https:'
28
32
  const client = isSecure ? https : http
29
33
  const dataArray = [].concat(data)
30
34
 
31
- options.headers['Content-Length'] = byteLength(dataArray)
35
+ if (!isReadable) {
36
+ options.headers['Content-Length'] = byteLength(dataArray)
37
+ }
32
38
 
33
39
  if (containerId) {
34
40
  options.headers['Datadog-Container-ID'] = containerId
35
41
  }
36
42
 
37
- if (keepAlive) {
38
- options.agent = isSecure ? httpsAgent : httpAgent
39
- }
43
+ options.agent = isSecure ? httpsAgent : httpAgent
40
44
 
41
45
  const onResponse = res => {
42
46
  let responseData = ''
@@ -59,7 +63,10 @@ function request (data, options, keepAlive, callback) {
59
63
  }
60
64
 
61
65
  const makeRequest = onError => {
62
- 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
+ }
63
70
 
64
71
  activeRequests++
65
72
 
@@ -74,15 +81,23 @@ function request (data, options, keepAlive, callback) {
74
81
  onError(err)
75
82
  })
76
83
 
77
- dataArray.forEach(buffer => req.write(buffer))
78
-
79
84
  req.setTimeout(timeout, req.abort)
80
- req.end()
85
+
86
+ if (isReadable) {
87
+ data.pipe(req) // TODO: Validate whether this is actually retriable.
88
+ } else {
89
+ dataArray.forEach(buffer => req.write(buffer))
90
+ req.end()
91
+ }
81
92
 
82
93
  storage.enterWith(store)
83
94
  }
84
95
 
85
- makeRequest(() => makeRequest(callback))
96
+ // TODO: Figure out why setTimeout is needed to avoid losing the async context
97
+ // in the retry request before socket.connect() is called.
98
+ // TODO: Test that this doesn't trace itself on retry when the diagnostics
99
+ // channel events are available in the agent exporter.
100
+ makeRequest(() => setTimeout(() => makeRequest(callback)))
86
101
  }
87
102
 
88
103
  function byteLength (data) {
@@ -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) {
@@ -0,0 +1,20 @@
1
+ const { URL } = require('url')
2
+
3
+ const { Writer } = require('./writer')
4
+
5
+ class SpanStatsExporter {
6
+ constructor (config) {
7
+ const { hostname = '127.0.0.1', port = 8126, tags, url } = config
8
+ this._url = url || new URL(`http://${hostname || 'localhost'}:${port}`)
9
+ this._writer = new Writer({ url: this._url, tags })
10
+ }
11
+
12
+ export (payload) {
13
+ this._writer.append(payload)
14
+ this._writer.flush()
15
+ }
16
+ }
17
+
18
+ module.exports = {
19
+ SpanStatsExporter
20
+ }
@@ -0,0 +1,54 @@
1
+
2
+ const { SpanStatsEncoder } = require('../../encode/span-stats')
3
+
4
+ const pkg = require('../../../../../package.json')
5
+
6
+ const BaseWriter = require('../common/writer')
7
+ const request = require('../common/request')
8
+ const log = require('../../log')
9
+
10
+ class Writer extends BaseWriter {
11
+ constructor ({ url }) {
12
+ super(...arguments)
13
+ this._url = url
14
+ this._encoder = new SpanStatsEncoder(this)
15
+ }
16
+
17
+ _sendPayload (data, _, done) {
18
+ makeRequest(data, this._url, (err, res) => {
19
+ if (err) {
20
+ log.error(err)
21
+ done()
22
+ return
23
+ }
24
+ log.debug(`Response from the intake: ${res}`)
25
+ done()
26
+ })
27
+ }
28
+ }
29
+
30
+ function makeRequest (data, url, cb) {
31
+ const options = {
32
+ path: '/v0.6/stats',
33
+ method: 'PUT',
34
+ headers: {
35
+ 'Datadog-Meta-Lang': 'javascript',
36
+ 'Datadog-Meta-Tracer-Version': pkg.version,
37
+ 'Content-Type': 'application/msgpack'
38
+ }
39
+ }
40
+
41
+ options.protocol = url.protocol
42
+ options.hostname = url.hostname
43
+ options.port = url.port
44
+
45
+ log.debug(() => `Request to the intake: ${JSON.stringify(options)}`)
46
+
47
+ request(data, options, (err, res) => {
48
+ cb(err, res)
49
+ })
50
+ }
51
+
52
+ module.exports = {
53
+ Writer
54
+ }
@@ -12,6 +12,7 @@ const SAMPLING_AGENT_DECISION = constants.SAMPLING_AGENT_DECISION
12
12
  const MEASURED = tags.MEASURED
13
13
  const ORIGIN_KEY = constants.ORIGIN_KEY
14
14
  const HOSTNAME_KEY = constants.HOSTNAME_KEY
15
+ const TOP_LEVEL_KEY = constants.TOP_LEVEL_KEY
15
16
 
16
17
  const map = {
17
18
  'service.name': 'service',
@@ -110,6 +111,7 @@ function extractRootTags (trace, span) {
110
111
  addTag({}, trace.metrics, SAMPLING_RULE_DECISION, context._trace[SAMPLING_RULE_DECISION])
111
112
  addTag({}, trace.metrics, SAMPLING_LIMIT_DECISION, context._trace[SAMPLING_LIMIT_DECISION])
112
113
  addTag({}, trace.metrics, SAMPLING_AGENT_DECISION, context._trace[SAMPLING_AGENT_DECISION])
114
+ addTag({}, trace.metrics, TOP_LEVEL_KEY, 1)
113
115
  }
114
116
 
115
117
  function extractChunkTags (trace, span) {
@@ -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
@@ -2,8 +2,19 @@
2
2
 
3
3
  const semver = require('semver')
4
4
  const logger = require('./log')
5
+ const { addHook } = require('import-in-the-middle')
6
+ const dc = require('diagnostics_channel')
5
7
 
6
8
  if (semver.satisfies(process.versions.node, '^12.20.0 || >=14.13.1')) {
9
+ const moduleLoadStartChannel = dc.channel('dd-trace:moduleLoadStart')
10
+ addHook((name, namespace) => {
11
+ if (moduleLoadStartChannel.hasSubscribers) {
12
+ moduleLoadStartChannel.publish({
13
+ filename: name,
14
+ module: namespace
15
+ })
16
+ }
17
+ })
7
18
  module.exports = require('import-in-the-middle')
8
19
  } else {
9
20
  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,87 @@
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
+ currentSpan () {
68
+ return this._tracer.currentSpan.apply(this._tracer, arguments)
69
+ }
70
+
71
+ bind (callback) {
72
+ return callback
73
+ }
74
+
75
+ bindEmitter () {}
76
+
77
+ getRumData () {
78
+ return this._tracer.getRumData.apply(this._tracer, arguments)
79
+ }
80
+
81
+ setUser () {
82
+ this._tracer.setUser.apply(this._tracer, arguments)
83
+ return this
84
+ }
85
+ }
86
+
87
+ module.exports = Tracer