dd-trace 3.0.0 → 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.
- package/LICENSE-3rdparty.csv +1 -0
- package/MIGRATING.md +6 -6
- package/package.json +2 -1
- package/packages/datadog-core/src/storage/async_resource.js +19 -1
- package/packages/datadog-instrumentations/src/cucumber.js +15 -0
- package/packages/datadog-instrumentations/src/helpers/instrumentations.js +5 -1
- package/packages/datadog-instrumentations/src/jest.js +33 -11
- package/packages/datadog-plugin-cucumber/src/index.js +4 -0
- package/packages/datadog-plugin-jest/src/index.js +25 -4
- package/packages/datadog-plugin-mongodb-core/src/index.js +21 -6
- package/packages/datadog-plugin-oracledb/src/index.js +12 -4
- package/packages/dd-trace/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +50 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +53 -8
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +23 -24
- package/packages/dd-trace/src/config.js +7 -0
- package/packages/dd-trace/src/encode/0.4.js +51 -58
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +13 -34
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +84 -0
- package/packages/dd-trace/src/exporters/agent/index.js +13 -7
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
- package/packages/dd-trace/src/exporters/common/request.js +20 -9
- package/packages/dd-trace/src/exporters/common/writer.js +9 -6
- package/packages/dd-trace/src/index.js +10 -0
- package/packages/dd-trace/src/noop/proxy.js +77 -0
- package/packages/dd-trace/src/plugin_manager.js +6 -4
- package/packages/dd-trace/src/proxy.js +5 -62
- package/packages/dd-trace/src/telemetry.js +1 -1
|
@@ -13,7 +13,8 @@ float64Array[0] = -1
|
|
|
13
13
|
const bigEndian = uInt8Float64Array[7] === 0
|
|
14
14
|
|
|
15
15
|
class AgentEncoder {
|
|
16
|
-
constructor (writer) {
|
|
16
|
+
constructor (writer, limit = SOFT_LIMIT) {
|
|
17
|
+
this._limit = limit
|
|
17
18
|
this._traceBytes = new Chunk()
|
|
18
19
|
this._stringBytes = new Chunk()
|
|
19
20
|
this._writer = writer
|
|
@@ -41,7 +42,8 @@ class AgentEncoder {
|
|
|
41
42
|
})
|
|
42
43
|
|
|
43
44
|
// we can go over the soft limit since the agent has a 50MB hard limit
|
|
44
|
-
if (this._traceBytes.length >
|
|
45
|
+
if (this._traceBytes.length > this._limit || this._stringBytes.length > this._limit) {
|
|
46
|
+
log.debug('Buffer went over soft limit, flushing')
|
|
45
47
|
this._writer.flush()
|
|
46
48
|
}
|
|
47
49
|
}
|
|
@@ -113,29 +115,37 @@ class AgentEncoder {
|
|
|
113
115
|
|
|
114
116
|
_encodeArrayPrefix (bytes, value) {
|
|
115
117
|
const length = value.length
|
|
116
|
-
const buffer = bytes.buffer
|
|
117
118
|
const offset = bytes.length
|
|
118
119
|
|
|
119
120
|
bytes.reserve(5)
|
|
120
121
|
bytes.length += 5
|
|
121
122
|
|
|
122
|
-
buffer[offset] = 0xdd
|
|
123
|
-
buffer[offset + 1] = length >> 24
|
|
124
|
-
buffer[offset + 2] = length >> 16
|
|
125
|
-
buffer[offset + 3] = length >> 8
|
|
126
|
-
buffer[offset + 4] = length
|
|
123
|
+
bytes.buffer[offset] = 0xdd
|
|
124
|
+
bytes.buffer[offset + 1] = length >> 24
|
|
125
|
+
bytes.buffer[offset + 2] = length >> 16
|
|
126
|
+
bytes.buffer[offset + 3] = length >> 8
|
|
127
|
+
bytes.buffer[offset + 4] = length
|
|
127
128
|
}
|
|
128
129
|
|
|
129
|
-
|
|
130
|
-
const
|
|
130
|
+
_encodeMapPrefix (bytes, keysLength) {
|
|
131
|
+
const offset = bytes.length
|
|
131
132
|
|
|
133
|
+
bytes.reserve(5)
|
|
134
|
+
bytes.length += 5
|
|
135
|
+
bytes.buffer[offset] = 0xdf
|
|
136
|
+
bytes.buffer[offset + 1] = keysLength >> 24
|
|
137
|
+
bytes.buffer[offset + 2] = keysLength >> 16
|
|
138
|
+
bytes.buffer[offset + 3] = keysLength >> 8
|
|
139
|
+
bytes.buffer[offset + 4] = keysLength
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
_encodeByte (bytes, value) {
|
|
132
143
|
bytes.reserve(1)
|
|
133
144
|
|
|
134
|
-
buffer[bytes.length++] = value
|
|
145
|
+
bytes.buffer[bytes.length++] = value
|
|
135
146
|
}
|
|
136
147
|
|
|
137
148
|
_encodeId (bytes, id) {
|
|
138
|
-
const buffer = bytes.buffer
|
|
139
149
|
const offset = bytes.length
|
|
140
150
|
|
|
141
151
|
bytes.reserve(9)
|
|
@@ -143,33 +153,31 @@ class AgentEncoder {
|
|
|
143
153
|
|
|
144
154
|
id = id.toArray()
|
|
145
155
|
|
|
146
|
-
buffer[offset] = 0xcf
|
|
147
|
-
buffer[offset + 1] = id[0]
|
|
148
|
-
buffer[offset + 2] = id[1]
|
|
149
|
-
buffer[offset + 3] = id[2]
|
|
150
|
-
buffer[offset + 4] = id[3]
|
|
151
|
-
buffer[offset + 5] = id[4]
|
|
152
|
-
buffer[offset + 6] = id[5]
|
|
153
|
-
buffer[offset + 7] = id[6]
|
|
154
|
-
buffer[offset + 8] = id[7]
|
|
156
|
+
bytes.buffer[offset] = 0xcf
|
|
157
|
+
bytes.buffer[offset + 1] = id[0]
|
|
158
|
+
bytes.buffer[offset + 2] = id[1]
|
|
159
|
+
bytes.buffer[offset + 3] = id[2]
|
|
160
|
+
bytes.buffer[offset + 4] = id[3]
|
|
161
|
+
bytes.buffer[offset + 5] = id[4]
|
|
162
|
+
bytes.buffer[offset + 6] = id[5]
|
|
163
|
+
bytes.buffer[offset + 7] = id[6]
|
|
164
|
+
bytes.buffer[offset + 8] = id[7]
|
|
155
165
|
}
|
|
156
166
|
|
|
157
167
|
_encodeInteger (bytes, value) {
|
|
158
|
-
const buffer = bytes.buffer
|
|
159
168
|
const offset = bytes.length
|
|
160
169
|
|
|
161
170
|
bytes.reserve(5)
|
|
162
171
|
bytes.length += 5
|
|
163
172
|
|
|
164
|
-
buffer[offset] = 0xce
|
|
165
|
-
buffer[offset + 1] = value >> 24
|
|
166
|
-
buffer[offset + 2] = value >> 16
|
|
167
|
-
buffer[offset + 3] = value >> 8
|
|
168
|
-
buffer[offset + 4] = value
|
|
173
|
+
bytes.buffer[offset] = 0xce
|
|
174
|
+
bytes.buffer[offset + 1] = value >> 24
|
|
175
|
+
bytes.buffer[offset + 2] = value >> 16
|
|
176
|
+
bytes.buffer[offset + 3] = value >> 8
|
|
177
|
+
bytes.buffer[offset + 4] = value
|
|
169
178
|
}
|
|
170
179
|
|
|
171
180
|
_encodeLong (bytes, value) {
|
|
172
|
-
const buffer = bytes.buffer
|
|
173
181
|
const offset = bytes.length
|
|
174
182
|
const hi = (value / Math.pow(2, 32)) >> 0
|
|
175
183
|
const lo = value >>> 0
|
|
@@ -177,40 +185,27 @@ class AgentEncoder {
|
|
|
177
185
|
bytes.reserve(9)
|
|
178
186
|
bytes.length += 9
|
|
179
187
|
|
|
180
|
-
buffer[offset] = 0xcf
|
|
181
|
-
buffer[offset + 1] = hi >> 24
|
|
182
|
-
buffer[offset + 2] = hi >> 16
|
|
183
|
-
buffer[offset + 3] = hi >> 8
|
|
184
|
-
buffer[offset + 4] = hi
|
|
185
|
-
buffer[offset + 5] = lo >> 24
|
|
186
|
-
buffer[offset + 6] = lo >> 16
|
|
187
|
-
buffer[offset + 7] = lo >> 8
|
|
188
|
-
buffer[offset + 8] = lo
|
|
188
|
+
bytes.buffer[offset] = 0xcf
|
|
189
|
+
bytes.buffer[offset + 1] = hi >> 24
|
|
190
|
+
bytes.buffer[offset + 2] = hi >> 16
|
|
191
|
+
bytes.buffer[offset + 3] = hi >> 8
|
|
192
|
+
bytes.buffer[offset + 4] = hi
|
|
193
|
+
bytes.buffer[offset + 5] = lo >> 24
|
|
194
|
+
bytes.buffer[offset + 6] = lo >> 16
|
|
195
|
+
bytes.buffer[offset + 7] = lo >> 8
|
|
196
|
+
bytes.buffer[offset + 8] = lo
|
|
189
197
|
}
|
|
190
198
|
|
|
191
199
|
_encodeMap (bytes, value) {
|
|
192
200
|
const keys = Object.keys(value)
|
|
193
|
-
const
|
|
194
|
-
const offset = bytes.length
|
|
195
|
-
|
|
196
|
-
bytes.reserve(5)
|
|
197
|
-
bytes.length += 5
|
|
201
|
+
const validKeys = keys.filter(key => typeof value[key] === 'string' || typeof value[key] === 'number')
|
|
198
202
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
for (const key of keys) {
|
|
202
|
-
if (typeof value[key] !== 'string' && typeof value[key] !== 'number') return
|
|
203
|
-
length++
|
|
203
|
+
this._encodeMapPrefix(bytes, validKeys.length)
|
|
204
204
|
|
|
205
|
+
for (const key of validKeys) {
|
|
205
206
|
this._encodeString(bytes, key)
|
|
206
207
|
this._encodeValue(bytes, value[key])
|
|
207
208
|
}
|
|
208
|
-
|
|
209
|
-
buffer[offset] = 0xdf
|
|
210
|
-
buffer[offset + 1] = length >> 24
|
|
211
|
-
buffer[offset + 2] = length >> 16
|
|
212
|
-
buffer[offset + 3] = length >> 8
|
|
213
|
-
buffer[offset + 4] = length
|
|
214
209
|
}
|
|
215
210
|
|
|
216
211
|
_encodeValue (bytes, value) {
|
|
@@ -237,21 +232,19 @@ class AgentEncoder {
|
|
|
237
232
|
_encodeFloat (bytes, value) {
|
|
238
233
|
float64Array[0] = value
|
|
239
234
|
|
|
240
|
-
const buffer = bytes.buffer
|
|
241
235
|
const offset = bytes.length
|
|
242
|
-
|
|
243
236
|
bytes.reserve(9)
|
|
244
237
|
bytes.length += 9
|
|
245
238
|
|
|
246
|
-
buffer[offset] = 0xcb
|
|
239
|
+
bytes.buffer[offset] = 0xcb
|
|
247
240
|
|
|
248
241
|
if (bigEndian) {
|
|
249
242
|
for (let i = 0; i <= 7; i++) {
|
|
250
|
-
buffer[offset + i + 1] = uInt8Float64Array[i]
|
|
243
|
+
bytes.buffer[offset + i + 1] = uInt8Float64Array[i]
|
|
251
244
|
}
|
|
252
245
|
} else {
|
|
253
246
|
for (let i = 7; i >= 0; i--) {
|
|
254
|
-
buffer[bytes.length - i - 1] = uInt8Float64Array[i]
|
|
247
|
+
bytes.buffer[bytes.length - i - 1] = uInt8Float64Array[i]
|
|
255
248
|
}
|
|
256
249
|
}
|
|
257
250
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const { truncateSpan, normalizeSpan } = require('./tags-processors')
|
|
3
|
-
const Chunk = require('./chunk')
|
|
4
3
|
const { AgentEncoder } = require('./0.4')
|
|
5
4
|
const { version: ddTraceVersion } = require('../../../../package.json')
|
|
6
5
|
const id = require('../../../dd-trace/src/id')
|
|
7
|
-
|
|
8
6
|
const ENCODING_VERSION = 1
|
|
9
7
|
|
|
10
8
|
const ALLOWED_CONTENT_TYPES = ['test_session_end', 'test_suite_end', 'test']
|
|
@@ -12,7 +10,7 @@ const ALLOWED_CONTENT_TYPES = ['test_session_end', 'test_suite_end', 'test']
|
|
|
12
10
|
const TEST_SUITE_KEYS_LENGTH = 11
|
|
13
11
|
const TEST_SESSION_KEYS_LENGTH = 10
|
|
14
12
|
|
|
15
|
-
const
|
|
13
|
+
const INTAKE_SOFT_LIMIT = 2 * 1024 * 1024 // 2MB
|
|
16
14
|
|
|
17
15
|
function formatSpan (span) {
|
|
18
16
|
let encodingVersion = ENCODING_VERSION
|
|
@@ -27,16 +25,11 @@ function formatSpan (span) {
|
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
30
|
-
constructor ({ runtimeId, service, env }) {
|
|
31
|
-
super(
|
|
32
|
-
this._events = []
|
|
28
|
+
constructor (writer, { runtimeId, service, env }) {
|
|
29
|
+
super(writer, INTAKE_SOFT_LIMIT)
|
|
33
30
|
this.runtimeId = runtimeId
|
|
34
31
|
this.service = service
|
|
35
32
|
this.env = env
|
|
36
|
-
this._traceBytes = new Chunk(CHUNK_SIZE)
|
|
37
|
-
this._stringBytes = new Chunk(CHUNK_SIZE)
|
|
38
|
-
this._stringCount = 0
|
|
39
|
-
this._stringMap = {}
|
|
40
33
|
|
|
41
34
|
// Used to keep track of the number of encoded events to update the
|
|
42
35
|
// length of `payload.events` when calling `makePayload`
|
|
@@ -186,35 +179,21 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
186
179
|
const lo = value >>> 0
|
|
187
180
|
const flag = isPositive ? 0xcf : 0xd3
|
|
188
181
|
|
|
189
|
-
const buffer = bytes.buffer
|
|
190
182
|
const offset = bytes.length
|
|
191
183
|
|
|
192
184
|
// int 64
|
|
193
185
|
bytes.reserve(9)
|
|
194
186
|
bytes.length += 9
|
|
195
187
|
|
|
196
|
-
buffer[offset] = flag
|
|
197
|
-
buffer[offset + 1] = hi >> 24
|
|
198
|
-
buffer[offset + 2] = hi >> 16
|
|
199
|
-
buffer[offset + 3] = hi >> 8
|
|
200
|
-
buffer[offset + 4] = hi
|
|
201
|
-
buffer[offset + 5] = lo >> 24
|
|
202
|
-
buffer[offset + 6] = lo >> 16
|
|
203
|
-
buffer[offset + 7] = lo >> 8
|
|
204
|
-
buffer[offset + 8] = lo
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
_encodeMapPrefix (bytes, keysLength) {
|
|
208
|
-
const buffer = bytes.buffer
|
|
209
|
-
const offset = bytes.length
|
|
210
|
-
|
|
211
|
-
bytes.reserve(5)
|
|
212
|
-
bytes.length += 5
|
|
213
|
-
buffer[offset] = 0xdf
|
|
214
|
-
buffer[offset + 1] = keysLength >> 24
|
|
215
|
-
buffer[offset + 2] = keysLength >> 16
|
|
216
|
-
buffer[offset + 3] = keysLength >> 8
|
|
217
|
-
buffer[offset + 4] = keysLength
|
|
188
|
+
bytes.buffer[offset] = flag
|
|
189
|
+
bytes.buffer[offset + 1] = hi >> 24
|
|
190
|
+
bytes.buffer[offset + 2] = hi >> 16
|
|
191
|
+
bytes.buffer[offset + 3] = hi >> 8
|
|
192
|
+
bytes.buffer[offset + 4] = hi
|
|
193
|
+
bytes.buffer[offset + 5] = lo >> 24
|
|
194
|
+
bytes.buffer[offset + 6] = lo >> 16
|
|
195
|
+
bytes.buffer[offset + 7] = lo >> 8
|
|
196
|
+
bytes.buffer[offset + 8] = lo
|
|
218
197
|
}
|
|
219
198
|
|
|
220
199
|
_encode (bytes, trace) {
|
|
@@ -240,7 +219,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
240
219
|
const traceSize = bytes.length
|
|
241
220
|
const buffer = Buffer.allocUnsafe(traceSize)
|
|
242
221
|
|
|
243
|
-
bytes.buffer.copy(buffer, 0, 0,
|
|
222
|
+
bytes.buffer.copy(buffer, 0, 0, traceSize)
|
|
244
223
|
|
|
245
224
|
this.reset()
|
|
246
225
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const { AgentEncoder } = require('./0.4')
|
|
3
|
+
const Chunk = require('./chunk')
|
|
4
|
+
|
|
5
|
+
const FormData = require('../exporters/common/form-data')
|
|
6
|
+
|
|
7
|
+
const COVERAGE_PAYLOAD_VERSION = 1
|
|
8
|
+
const COVERAGE_KEYS_LENGTH = 4
|
|
9
|
+
const MAXIMUM_NUM_COVERAGE_FILES = 100
|
|
10
|
+
|
|
11
|
+
class CoverageCIVisibilityEncoder extends AgentEncoder {
|
|
12
|
+
constructor () {
|
|
13
|
+
super(...arguments)
|
|
14
|
+
this.codeCoverageBuffers = []
|
|
15
|
+
this._coverageBytes = new Chunk()
|
|
16
|
+
this.reset()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
count () {
|
|
20
|
+
return this.codeCoverageBuffers.length
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
encode (coverage) {
|
|
24
|
+
const bytes = this._coverageBytes
|
|
25
|
+
const coverageBuffer = this.encodeCodeCoverage(bytes, coverage)
|
|
26
|
+
this.codeCoverageBuffers.push(coverageBuffer)
|
|
27
|
+
this.reset()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
encodeCodeCoverage (bytes, coverage) {
|
|
31
|
+
this._encodeMapPrefix(bytes, COVERAGE_KEYS_LENGTH)
|
|
32
|
+
this._encodeString(bytes, 'version')
|
|
33
|
+
this._encodeInteger(bytes, COVERAGE_PAYLOAD_VERSION)
|
|
34
|
+
this._encodeString(bytes, 'trace_id')
|
|
35
|
+
this._encodeId(bytes, coverage.traceId)
|
|
36
|
+
this._encodeString(bytes, 'span_id')
|
|
37
|
+
this._encodeId(bytes, coverage.spanId)
|
|
38
|
+
this._encodeString(bytes, 'files')
|
|
39
|
+
this._encodeArrayPrefix(bytes, coverage.files)
|
|
40
|
+
for (const filename of coverage.files) {
|
|
41
|
+
this._encodeMapPrefix(bytes, 1)
|
|
42
|
+
this._encodeString(bytes, 'filename')
|
|
43
|
+
this._encodeString(bytes, filename)
|
|
44
|
+
}
|
|
45
|
+
const traceSize = bytes.length
|
|
46
|
+
const buffer = Buffer.allocUnsafe(traceSize)
|
|
47
|
+
|
|
48
|
+
bytes.buffer.copy(buffer, 0, 0, bytes.length)
|
|
49
|
+
|
|
50
|
+
return buffer
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
reset () {
|
|
54
|
+
this._reset()
|
|
55
|
+
if (this._coverageBytes) {
|
|
56
|
+
this._coverageBytes.length = 0
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
makePayload () {
|
|
61
|
+
const form = new FormData()
|
|
62
|
+
|
|
63
|
+
let coverageFileIndex = 1
|
|
64
|
+
|
|
65
|
+
for (const coverageBuffer of this.codeCoverageBuffers.slice(0, MAXIMUM_NUM_COVERAGE_FILES)) {
|
|
66
|
+
const coverageFilename = `coverage${coverageFileIndex++}`
|
|
67
|
+
form.append(
|
|
68
|
+
coverageFilename,
|
|
69
|
+
coverageBuffer,
|
|
70
|
+
{
|
|
71
|
+
filename: `${coverageFilename}.msgpack`,
|
|
72
|
+
contentType: 'application/msgpack'
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
// 'event' is a backend requirement
|
|
77
|
+
form.append('event', JSON.stringify({}), { filename: 'event.json', contentType: 'application/json' })
|
|
78
|
+
this.codeCoverageBuffers = this.codeCoverageBuffers.slice(MAXIMUM_NUM_COVERAGE_FILES)
|
|
79
|
+
|
|
80
|
+
return form
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = { CoverageCIVisibilityEncoder }
|
|
@@ -3,17 +3,16 @@
|
|
|
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 (
|
|
8
|
+
constructor (config, prioritySampler) {
|
|
9
|
+
this._config = config
|
|
10
|
+
const { url, hostname, port, lookup, protocolVersion } = config
|
|
10
11
|
this._url = url || new URL(`http://${hostname || 'localhost'}:${port}`)
|
|
11
12
|
this._writer = new Writer({ url: this._url, prioritySampler, lookup, protocolVersion })
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
this._scheduler && this._scheduler.start()
|
|
14
|
+
this._timer = undefined
|
|
15
|
+
process.once('beforeExit', () => this._writer.flush())
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
setUrl (url) {
|
|
@@ -29,8 +28,15 @@ class AgentExporter {
|
|
|
29
28
|
export (spans) {
|
|
30
29
|
this._writer.append(spans)
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
const { flushInterval } = this._config
|
|
32
|
+
|
|
33
|
+
if (flushInterval === 0) {
|
|
33
34
|
this._writer.flush()
|
|
35
|
+
} else if (flushInterval > 0 && !this._timer) {
|
|
36
|
+
this._timer = setTimeout(() => {
|
|
37
|
+
this._writer.flush()
|
|
38
|
+
this._timer = clearTimeout(this._timer)
|
|
39
|
+
}, flushInterval).unref()
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
42
|
}
|
|
@@ -99,7 +99,7 @@ function makeRequest (version, data, count, url, lookup, needsStartupLog, cb) {
|
|
|
99
99
|
|
|
100
100
|
log.debug(() => `Request to the agent: ${JSON.stringify(options)}`)
|
|
101
101
|
|
|
102
|
-
request(data, options,
|
|
102
|
+
request(data, options, (err, res, status) => {
|
|
103
103
|
if (needsStartupLog) {
|
|
104
104
|
// Note that logging will only happen once, regardless of how many times this is called.
|
|
105
105
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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,10 +81,14 @@ 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
|
-
|
|
85
|
+
|
|
86
|
+
if (isReadable) {
|
|
87
|
+
data.pipe(req)
|
|
88
|
+
} else {
|
|
89
|
+
dataArray.forEach(buffer => req.write(buffer))
|
|
90
|
+
req.end()
|
|
91
|
+
}
|
|
81
92
|
|
|
82
93
|
storage.enterWith(store)
|
|
83
94
|
}
|
|
@@ -23,16 +23,19 @@ class Writer {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
append (
|
|
27
|
-
if (!request.writable)
|
|
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
|
|
32
|
+
log.debug(() => `Encoding payload: ${JSON.stringify(payload)}`)
|
|
30
33
|
|
|
31
|
-
this._encode(
|
|
34
|
+
this._encode(payload)
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
_encode (
|
|
35
|
-
this._encoder.encode(
|
|
37
|
+
_encode (payload) {
|
|
38
|
+
this._encoder.encode(payload)
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
setUrl (url) {
|
|
@@ -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
|
|
@@ -120,7 +120,8 @@ module.exports = class PluginManager {
|
|
|
120
120
|
logInjection,
|
|
121
121
|
serviceMapping,
|
|
122
122
|
experimental,
|
|
123
|
-
queryStringObfuscation
|
|
123
|
+
queryStringObfuscation,
|
|
124
|
+
isIntelligentTestRunnerEnabled
|
|
124
125
|
} = this._tracerConfig
|
|
125
126
|
|
|
126
127
|
const sharedConfig = {}
|
|
@@ -133,11 +134,12 @@ module.exports = class PluginManager {
|
|
|
133
134
|
sharedConfig.queryStringObfuscation = queryStringObfuscation
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
sharedConfig.isAgentlessEnabled = experimental && experimental.exporter === 'datadog'
|
|
137
|
+
if (experimental) {
|
|
138
|
+
sharedConfig.isAgentlessEnabled = experimental.exporter === 'datadog'
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
sharedConfig.isIntelligentTestRunnerEnabled = isIntelligentTestRunnerEnabled
|
|
142
|
+
|
|
141
143
|
if (serviceMapping && serviceMapping[name]) {
|
|
142
144
|
sharedConfig.service = serviceMapping[name]
|
|
143
145
|
}
|