dd-trace 5.83.0 → 5.84.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 +0 -1
- package/index.d.ts +61 -1
- package/package.json +3 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +6 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +73 -16
- package/packages/datadog-instrumentations/src/jest.js +89 -50
- package/packages/datadog-instrumentations/src/playwright.js +12 -8
- package/packages/datadog-plugin-cucumber/src/index.js +33 -32
- package/packages/datadog-plugin-playwright/src/index.js +23 -23
- package/packages/datadog-shimmer/src/shimmer.js +2 -5
- package/packages/dd-trace/src/agent/info.js +57 -0
- package/packages/dd-trace/src/agent/url.js +28 -0
- package/packages/dd-trace/src/appsec/index.js +47 -7
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +3 -4
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +3 -3
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +2 -9
- package/packages/dd-trace/src/ci-visibility/telemetry.js +6 -2
- package/packages/dd-trace/src/config/index.js +15 -1
- package/packages/dd-trace/src/config/remote_config.js +1 -0
- package/packages/dd-trace/src/config/supported-configurations.json +1 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +2 -5
- package/packages/dd-trace/src/datastreams/writer.js +2 -8
- package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -7
- package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +10 -11
- package/packages/dd-trace/src/dogstatsd.js +3 -9
- package/packages/dd-trace/src/exporters/agent/index.js +4 -8
- package/packages/dd-trace/src/exporters/agent/writer.js +3 -2
- package/packages/dd-trace/src/exporters/common/{agent-info-exporter.js → buffering-exporter.js} +10 -37
- package/packages/dd-trace/src/exporters/span-stats/index.js +3 -10
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -8
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -9
- package/packages/dd-trace/src/log/index.js +45 -30
- package/packages/dd-trace/src/log/writer.js +13 -78
- package/packages/dd-trace/src/openfeature/writers/base.js +2 -8
- package/packages/dd-trace/src/openfeature/writers/util.js +3 -8
- package/packages/dd-trace/src/profiling/config.js +3 -6
- package/packages/dd-trace/src/remote_config/capabilities.js +1 -0
- package/packages/dd-trace/src/remote_config/index.js +2 -7
- package/packages/dd-trace/src/startup-log.js +2 -2
- package/vendor/dist/@isaacs/ttlcache/index.js +1 -1
- package/vendor/dist/esquery/index.js +1 -1
- package/vendor/dist/meriyah/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
|
@@ -6,45 +6,45 @@ const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
|
6
6
|
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
|
-
TEST_STATUS,
|
|
10
9
|
finishAllTraceSpans,
|
|
11
|
-
getTestSuitePath,
|
|
12
10
|
getTestSuiteCommonTags,
|
|
13
|
-
|
|
11
|
+
getTestSuitePath,
|
|
12
|
+
isModifiedTest,
|
|
13
|
+
TEST_BROWSER_NAME,
|
|
14
|
+
TEST_BROWSER_VERSION,
|
|
14
15
|
TEST_CODE_OWNERS,
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
TEST_COMMAND,
|
|
17
|
+
TEST_EARLY_FLAKE_ABORT_REASON,
|
|
18
|
+
TEST_EARLY_FLAKE_ENABLED,
|
|
19
|
+
TEST_HAS_FAILED_ALL_RETRIES,
|
|
20
|
+
TEST_IS_MODIFIED,
|
|
17
21
|
TEST_IS_NEW,
|
|
18
22
|
TEST_IS_RETRY,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
TELEMETRY_TEST_SESSION,
|
|
22
|
-
TEST_RETRY_REASON,
|
|
23
|
-
TEST_MANAGEMENT_IS_QUARANTINED,
|
|
23
|
+
TEST_IS_RUM_ACTIVE,
|
|
24
|
+
TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED,
|
|
24
25
|
TEST_MANAGEMENT_ENABLED,
|
|
25
|
-
TEST_BROWSER_NAME,
|
|
26
|
-
TEST_MANAGEMENT_IS_DISABLED,
|
|
27
26
|
TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
TEST_SESSION_ID,
|
|
27
|
+
TEST_MANAGEMENT_IS_DISABLED,
|
|
28
|
+
TEST_MANAGEMENT_IS_QUARANTINED,
|
|
31
29
|
TEST_MODULE_ID,
|
|
32
|
-
TEST_COMMAND,
|
|
33
30
|
TEST_MODULE,
|
|
34
|
-
TEST_SUITE,
|
|
35
|
-
TEST_SUITE_ID,
|
|
36
31
|
TEST_NAME,
|
|
37
|
-
|
|
38
|
-
TEST_BROWSER_VERSION,
|
|
32
|
+
TEST_PARAMETERS,
|
|
39
33
|
TEST_RETRY_REASON_TYPES,
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
TEST_RETRY_REASON,
|
|
35
|
+
TEST_SESSION_ID,
|
|
36
|
+
TEST_SOURCE_FILE,
|
|
37
|
+
TEST_SOURCE_START,
|
|
38
|
+
TEST_STATUS,
|
|
39
|
+
TEST_SUITE_ID,
|
|
40
|
+
TEST_SUITE,
|
|
42
41
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
43
42
|
const { RESOURCE_NAME } = require('../../../ext/tags')
|
|
44
43
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
45
44
|
const {
|
|
46
45
|
TELEMETRY_EVENT_CREATED,
|
|
47
|
-
TELEMETRY_EVENT_FINISHED
|
|
46
|
+
TELEMETRY_EVENT_FINISHED,
|
|
47
|
+
TELEMETRY_TEST_SESSION,
|
|
48
48
|
} = require('../../dd-trace/src/ci-visibility/telemetry')
|
|
49
49
|
const { appClosing: appClosingTelemetry } = require('../../dd-trace/src/telemetry')
|
|
50
50
|
const log = require('../../dd-trace/src/log')
|
|
@@ -76,11 +76,8 @@ function wrapFunction (original, wrapper) {
|
|
|
76
76
|
if (typeof original !== 'function') return original
|
|
77
77
|
|
|
78
78
|
const wrapped = wrapper(original)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
assertNotClass(original)
|
|
82
|
-
copyProperties(original, wrapped)
|
|
83
|
-
}
|
|
79
|
+
assertNotClass(original)
|
|
80
|
+
copyProperties(original, wrapped)
|
|
84
81
|
|
|
85
82
|
return wrapped
|
|
86
83
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const request = require('../exporters/common/request')
|
|
4
|
+
|
|
5
|
+
const CACHE_TTL_MS = 60_000 // 1 minute
|
|
6
|
+
|
|
7
|
+
let cachedUrl = null
|
|
8
|
+
let cachedData = null
|
|
9
|
+
let cachedTimestamp = 0
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
fetchAgentInfo,
|
|
13
|
+
clearCache // For testing purposes only
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Fetches agent information from the /info endpoint
|
|
18
|
+
* @param {URL} url - The agent URL
|
|
19
|
+
* @param {Function} callback - Callback function with signature (err, agentInfo)
|
|
20
|
+
*/
|
|
21
|
+
function fetchAgentInfo (url, callback) {
|
|
22
|
+
const urlKey = url.href
|
|
23
|
+
|
|
24
|
+
if (cachedUrl !== null && cachedUrl !== urlKey) {
|
|
25
|
+
// Clear cache if URL changes
|
|
26
|
+
clearCache()
|
|
27
|
+
} else if (cachedData !== null && (Date.now() - cachedTimestamp) < CACHE_TTL_MS) {
|
|
28
|
+
// Return cached result if still valid
|
|
29
|
+
return process.nextTick(callback, null, cachedData)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
request('', {
|
|
33
|
+
path: '/info',
|
|
34
|
+
url
|
|
35
|
+
}, (err, res) => {
|
|
36
|
+
if (err) {
|
|
37
|
+
return callback(err)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
cachedData = JSON.parse(res)
|
|
42
|
+
} catch (e) {
|
|
43
|
+
return callback(e)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
cachedUrl = urlKey
|
|
47
|
+
cachedTimestamp = Date.now()
|
|
48
|
+
|
|
49
|
+
callback(null, cachedData)
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function clearCache () {
|
|
54
|
+
cachedUrl = null
|
|
55
|
+
cachedData = null
|
|
56
|
+
cachedTimestamp = 0
|
|
57
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { URL, format } = require('url')
|
|
4
|
+
const defaults = require('../config/defaults')
|
|
5
|
+
|
|
6
|
+
module.exports = { getAgentUrl }
|
|
7
|
+
|
|
8
|
+
// TODO: Investigate merging with the getAgentUrl function in config/index.js which has
|
|
9
|
+
// additional logic for unix socket auto-detection on Linux. The config version is only used
|
|
10
|
+
// during config initialization, while this one is used throughout the codebase. Consider if
|
|
11
|
+
// the unix socket detection should be part of this general helper or remain config-specific.
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Gets the agent URL from config, constructing it from hostname/port if needed
|
|
15
|
+
* @param {ReturnType<import('../config')>} config - Tracer configuration object
|
|
16
|
+
* @returns {URL} The agent URL
|
|
17
|
+
*/
|
|
18
|
+
function getAgentUrl (config) {
|
|
19
|
+
const { url, hostname, port } = config
|
|
20
|
+
if (url) {
|
|
21
|
+
return url instanceof URL ? url : new URL(url)
|
|
22
|
+
}
|
|
23
|
+
return new URL(format({
|
|
24
|
+
protocol: 'http:',
|
|
25
|
+
hostname: hostname || defaults.hostname,
|
|
26
|
+
port: port || defaults.port
|
|
27
|
+
}))
|
|
28
|
+
}
|
|
@@ -104,6 +104,8 @@ function enable (_config) {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
const analyzedBodies = new WeakSet()
|
|
108
|
+
|
|
107
109
|
function onRequestBodyParsed ({ req, res, body, abortController }) {
|
|
108
110
|
if (body === undefined || body === null) return
|
|
109
111
|
|
|
@@ -120,6 +122,12 @@ function onRequestBodyParsed ({ req, res, body, abortController }) {
|
|
|
120
122
|
storedBodies.set(req, body)
|
|
121
123
|
}
|
|
122
124
|
|
|
125
|
+
// eslint-disable-next-line eslint-rules/eslint-safe-typeof-object
|
|
126
|
+
if (typeof body === 'object') {
|
|
127
|
+
if (isEmptyObject(body)) return
|
|
128
|
+
analyzedBodies.add(body)
|
|
129
|
+
}
|
|
130
|
+
|
|
123
131
|
const results = waf.run({
|
|
124
132
|
persistent: {
|
|
125
133
|
[addresses.HTTP_INCOMING_BODY]: body
|
|
@@ -129,12 +137,17 @@ function onRequestBodyParsed ({ req, res, body, abortController }) {
|
|
|
129
137
|
handleResults(results?.actions, req, res, rootSpan, abortController)
|
|
130
138
|
}
|
|
131
139
|
|
|
140
|
+
const analyzedCookies = new WeakSet()
|
|
141
|
+
|
|
132
142
|
function onRequestCookieParser ({ req, res, abortController, cookies }) {
|
|
133
143
|
if (!cookies || typeof cookies !== 'object') return
|
|
134
144
|
|
|
135
145
|
const rootSpan = web.root(req)
|
|
136
146
|
if (!rootSpan) return
|
|
137
147
|
|
|
148
|
+
if (isEmptyObject(cookies)) return
|
|
149
|
+
analyzedCookies.add(cookies)
|
|
150
|
+
|
|
138
151
|
const results = waf.run({
|
|
139
152
|
persistent: {
|
|
140
153
|
[addresses.HTTP_INCOMING_COOKIES]: cookies
|
|
@@ -178,19 +191,34 @@ function incomingHttpEndTranslator ({ req, res }) {
|
|
|
178
191
|
const persistent = {}
|
|
179
192
|
|
|
180
193
|
// we need to keep this to support other body parsers
|
|
181
|
-
// TODO: no need to analyze it if it was already done by the body-parser hook
|
|
182
194
|
if (req.body !== undefined && req.body !== null) {
|
|
183
|
-
|
|
195
|
+
// eslint-disable-next-line eslint-rules/eslint-safe-typeof-object
|
|
196
|
+
if (typeof req.body === 'object') {
|
|
197
|
+
if (!isEmptyObject(req.body) && !analyzedBodies.has(req.body)) {
|
|
198
|
+
persistent[addresses.HTTP_INCOMING_BODY] = req.body
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
persistent[addresses.HTTP_INCOMING_BODY] = req.body
|
|
202
|
+
}
|
|
184
203
|
}
|
|
185
204
|
|
|
186
205
|
// we need to keep this to support other cookie parsers
|
|
187
|
-
if (
|
|
206
|
+
if (
|
|
207
|
+
req.cookies !== null &&
|
|
208
|
+
typeof req.cookies === 'object' &&
|
|
209
|
+
!isEmptyObject(req.cookies) &&
|
|
210
|
+
!analyzedCookies.has(req.cookies)
|
|
211
|
+
) {
|
|
188
212
|
persistent[addresses.HTTP_INCOMING_COOKIES] = req.cookies
|
|
189
213
|
}
|
|
190
214
|
|
|
191
215
|
// we need to keep this to support nextjs
|
|
192
216
|
const query = req.query
|
|
193
|
-
if (
|
|
217
|
+
if (
|
|
218
|
+
query !== null &&
|
|
219
|
+
typeof query === 'object' &&
|
|
220
|
+
!isEmptyObject(query)
|
|
221
|
+
) {
|
|
194
222
|
persistent[addresses.HTTP_INCOMING_QUERY] = query
|
|
195
223
|
}
|
|
196
224
|
|
|
@@ -198,7 +226,7 @@ function incomingHttpEndTranslator ({ req, res }) {
|
|
|
198
226
|
persistent[addresses.WAF_CONTEXT_PROCESSOR] = { 'extract-schema': true }
|
|
199
227
|
}
|
|
200
228
|
|
|
201
|
-
if (
|
|
229
|
+
if (!isEmptyObject(persistent)) {
|
|
202
230
|
waf.run({ persistent }, req)
|
|
203
231
|
}
|
|
204
232
|
|
|
@@ -273,6 +301,8 @@ function onRequestQueryParsed ({ req, res, query, abortController }) {
|
|
|
273
301
|
const rootSpan = web.root(req)
|
|
274
302
|
if (!rootSpan) return
|
|
275
303
|
|
|
304
|
+
if (isEmptyObject(query)) return
|
|
305
|
+
|
|
276
306
|
const results = waf.run({
|
|
277
307
|
persistent: {
|
|
278
308
|
[addresses.HTTP_INCOMING_QUERY]: query
|
|
@@ -286,7 +316,7 @@ function onRequestProcessParams ({ req, res, abortController, params }) {
|
|
|
286
316
|
const rootSpan = web.root(req)
|
|
287
317
|
if (!rootSpan) return
|
|
288
318
|
|
|
289
|
-
if (!params || typeof params !== 'object' ||
|
|
319
|
+
if (!params || typeof params !== 'object' || isEmptyObject(params)) return
|
|
290
320
|
|
|
291
321
|
const results = waf.run({
|
|
292
322
|
persistent: {
|
|
@@ -310,7 +340,7 @@ function onResponseBody ({ req, res, body }) {
|
|
|
310
340
|
}
|
|
311
341
|
|
|
312
342
|
function onResponseWriteHead ({ req, res, abortController, statusCode, responseHeaders }) {
|
|
313
|
-
if (
|
|
343
|
+
if (!isEmptyObject(responseHeaders)) {
|
|
314
344
|
storedResponseHeaders.set(req, responseHeaders)
|
|
315
345
|
}
|
|
316
346
|
|
|
@@ -401,6 +431,16 @@ function disable () {
|
|
|
401
431
|
if (responseSetHeader.hasSubscribers) responseSetHeader.unsubscribe(onResponseSetHeader)
|
|
402
432
|
}
|
|
403
433
|
|
|
434
|
+
// this is faster than Object.keys().length === 0
|
|
435
|
+
function isEmptyObject (obj) {
|
|
436
|
+
// eslint-disable-next-line no-unreachable-loop
|
|
437
|
+
for (const _ in obj) {
|
|
438
|
+
return false
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return true
|
|
442
|
+
}
|
|
443
|
+
|
|
404
444
|
module.exports = {
|
|
405
445
|
enable,
|
|
406
446
|
disable,
|
|
@@ -4,6 +4,7 @@ const AgentWriter = require('../../../exporters/agent/writer')
|
|
|
4
4
|
const AgentlessWriter = require('../agentless/writer')
|
|
5
5
|
const CoverageWriter = require('../agentless/coverage-writer')
|
|
6
6
|
const CiVisibilityExporter = require('../ci-visibility-exporter')
|
|
7
|
+
const { fetchAgentInfo } = require('../../../agent/info')
|
|
7
8
|
|
|
8
9
|
const AGENT_EVP_PROXY_PATH_PREFIX = '/evp_proxy/v'
|
|
9
10
|
const AGENT_EVP_PROXY_PATH_REGEX = /\/evp_proxy\/v(\d+)\/?/
|
|
@@ -42,11 +43,11 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
42
43
|
isTestDynamicInstrumentationEnabled
|
|
43
44
|
} = config
|
|
44
45
|
|
|
45
|
-
this.
|
|
46
|
+
fetchAgentInfo(this._url, (err, agentInfo) => {
|
|
46
47
|
this._isInitialized = true
|
|
47
48
|
let latestEvpProxyVersion = getLatestEvpProxyVersion(err, agentInfo)
|
|
48
49
|
const isEvpCompatible = latestEvpProxyVersion >= 2
|
|
49
|
-
|
|
50
|
+
this._isGzipCompatible = latestEvpProxyVersion >= 4
|
|
50
51
|
|
|
51
52
|
// v3 does not work well citestcycle, so we downgrade to v2
|
|
52
53
|
if (latestEvpProxyVersion === 3) {
|
|
@@ -72,7 +73,6 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
72
73
|
const DynamicInstrumentationLogsWriter = require('../agentless/di-logs-writer')
|
|
73
74
|
this._logsWriter = new DynamicInstrumentationLogsWriter({
|
|
74
75
|
url: this._url,
|
|
75
|
-
tags,
|
|
76
76
|
isAgentProxy: true
|
|
77
77
|
})
|
|
78
78
|
this._canForwardLogs = true
|
|
@@ -92,7 +92,6 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
92
92
|
this._resolveCanUseCiVisProtocol(isEvpCompatible)
|
|
93
93
|
this.exportUncodedTraces()
|
|
94
94
|
this.exportUncodedCoverages()
|
|
95
|
-
this._isGzipCompatible = isGzipCompatible
|
|
96
95
|
})
|
|
97
96
|
}
|
|
98
97
|
|
|
@@ -11,7 +11,8 @@ const BaseWriter = require('../../../exporters/common/writer')
|
|
|
11
11
|
// It is used to encode and send logs to both the logs intake directly and the
|
|
12
12
|
// `/debugger/v1/input` endpoint in the agent, which is a proxy to the logs intake.
|
|
13
13
|
class DynamicInstrumentationLogsWriter extends BaseWriter {
|
|
14
|
-
|
|
14
|
+
// TODO: what's a good value for timeout for the logs intake?
|
|
15
|
+
constructor ({ url, timeout = 15_000, isAgentProxy = false }) {
|
|
15
16
|
super(...arguments)
|
|
16
17
|
this._url = url
|
|
17
18
|
this._encoder = new JSONEncoder()
|
|
@@ -27,8 +28,7 @@ class DynamicInstrumentationLogsWriter extends BaseWriter {
|
|
|
27
28
|
'dd-api-key': getValueFromEnvSources('DD_API_KEY'),
|
|
28
29
|
'Content-Type': 'application/json'
|
|
29
30
|
},
|
|
30
|
-
|
|
31
|
-
timeout: this.timeout || 15_000,
|
|
31
|
+
timeout: this.timeout,
|
|
32
32
|
url: this._url
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -8,7 +8,7 @@ const { getKnownTests: getKnownTestsRequest } = require('../early-flake-detectio
|
|
|
8
8
|
const { getTestManagementTests: getTestManagementTestsRequest } =
|
|
9
9
|
require('../test-management/get-test-management-tests')
|
|
10
10
|
const log = require('../../log')
|
|
11
|
-
const
|
|
11
|
+
const BufferingExporter = require('../../exporters/common/buffering-exporter')
|
|
12
12
|
const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../../plugins/util/tags')
|
|
13
13
|
const { sendGitMetadata: sendGitMetadataRequest } = require('./git/git_metadata')
|
|
14
14
|
|
|
@@ -34,7 +34,7 @@ function getIsTestSessionTrace (trace) {
|
|
|
34
34
|
const GIT_UPLOAD_TIMEOUT = 60_000 // 60 seconds
|
|
35
35
|
const CAN_USE_CI_VIS_PROTOCOL_TIMEOUT = GIT_UPLOAD_TIMEOUT
|
|
36
36
|
|
|
37
|
-
class CiVisibilityExporter extends
|
|
37
|
+
class CiVisibilityExporter extends BufferingExporter {
|
|
38
38
|
constructor (config) {
|
|
39
39
|
super(config)
|
|
40
40
|
this._timer = undefined
|
|
@@ -103,10 +103,6 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
103
103
|
)
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
shouldRequestLibraryConfiguration () {
|
|
107
|
-
return this._config.isIntelligentTestRunnerEnabled
|
|
108
|
-
}
|
|
109
|
-
|
|
110
106
|
canReportSessionTraces () {
|
|
111
107
|
return this._canUseCiVisProtocol
|
|
112
108
|
}
|
|
@@ -163,9 +159,6 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
163
159
|
getLibraryConfiguration (testConfiguration, callback) {
|
|
164
160
|
const { repositoryUrl } = testConfiguration
|
|
165
161
|
this.sendGitMetadata(repositoryUrl)
|
|
166
|
-
if (!this.shouldRequestLibraryConfiguration()) {
|
|
167
|
-
return callback(null, {})
|
|
168
|
-
}
|
|
169
162
|
this._canUseCiVisProtocolPromise.then((canUseCiVisProtocol) => {
|
|
170
163
|
if (!canUseCiVisProtocol) {
|
|
171
164
|
return callback(null, {})
|
|
@@ -21,8 +21,12 @@ const formattedTags = {
|
|
|
21
21
|
|
|
22
22
|
// Transform tags dictionary to array of strings.
|
|
23
23
|
// If tag value is true, then only tag key is added to the array.
|
|
24
|
+
/**
|
|
25
|
+
* @param {Record<string, unknown>} tagsDictionary
|
|
26
|
+
* @returns {string[]}
|
|
27
|
+
*/
|
|
24
28
|
function formatMetricTags (tagsDictionary) {
|
|
25
|
-
return Object.keys(tagsDictionary).reduce((acc, tagKey) => {
|
|
29
|
+
return Object.keys(tagsDictionary).reduce((/** @type {string[]} */ acc, tagKey) => {
|
|
26
30
|
if (tagKey === 'statusCode') {
|
|
27
31
|
const statusCode = tagsDictionary[tagKey]
|
|
28
32
|
if (isStatusCode400(statusCode)) {
|
|
@@ -31,7 +35,7 @@ function formatMetricTags (tagsDictionary) {
|
|
|
31
35
|
acc.push(`error_type:${getErrorTypeFromStatusCode(statusCode)}`)
|
|
32
36
|
return acc
|
|
33
37
|
}
|
|
34
|
-
const formattedTagKey = formattedTags[tagKey] || tagKey
|
|
38
|
+
const formattedTagKey = /** @type {string} */(formattedTags[tagKey] || tagKey)
|
|
35
39
|
if (tagsDictionary[tagKey] === true) {
|
|
36
40
|
acc.push(formattedTagKey)
|
|
37
41
|
} else if (tagsDictionary[tagKey] !== undefined && tagsDictionary[tagKey] !== null) {
|
|
@@ -600,6 +600,7 @@ class Config {
|
|
|
600
600
|
OTEL_TRACES_SAMPLER,
|
|
601
601
|
OTEL_TRACES_SAMPLER_ARG,
|
|
602
602
|
DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED,
|
|
603
|
+
DD_EXPERIMENTAL_FLAGGING_PROVIDER_INITIALIZATION_TIMEOUT_MS,
|
|
603
604
|
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
|
|
604
605
|
OTEL_EXPORTER_OTLP_LOGS_HEADERS,
|
|
605
606
|
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL,
|
|
@@ -776,7 +777,15 @@ class Config {
|
|
|
776
777
|
maybeFloat(DD_DYNAMIC_INSTRUMENTATION_UPLOAD_INTERVAL_SECONDS)
|
|
777
778
|
unprocessedTarget['dynamicInstrumentation.uploadInterval'] = DD_DYNAMIC_INSTRUMENTATION_UPLOAD_INTERVAL_SECONDS
|
|
778
779
|
this.#setString(target, 'env', DD_ENV || tags.env)
|
|
779
|
-
this.#setBoolean(
|
|
780
|
+
this.#setBoolean(
|
|
781
|
+
target,
|
|
782
|
+
'experimental.flaggingProvider.enabled',
|
|
783
|
+
DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED
|
|
784
|
+
)
|
|
785
|
+
if (DD_EXPERIMENTAL_FLAGGING_PROVIDER_INITIALIZATION_TIMEOUT_MS != null) {
|
|
786
|
+
target['experimental.flaggingProvider.initializationTimeoutMs'] =
|
|
787
|
+
maybeInt(DD_EXPERIMENTAL_FLAGGING_PROVIDER_INITIALIZATION_TIMEOUT_MS)
|
|
788
|
+
}
|
|
780
789
|
this.#setBoolean(target, 'traceEnabled', DD_TRACE_ENABLED)
|
|
781
790
|
this.#setBoolean(target, 'experimental.aiguard.enabled', DD_AI_GUARD_ENABLED)
|
|
782
791
|
this.#setString(target, 'experimental.aiguard.endpoint', DD_AI_GUARD_ENDPOINT)
|
|
@@ -1112,6 +1121,11 @@ class Config {
|
|
|
1112
1121
|
this.#setBoolean(opts, 'experimental.enableGetRumData', options.experimental?.enableGetRumData)
|
|
1113
1122
|
this.#setString(opts, 'experimental.exporter', options.experimental?.exporter)
|
|
1114
1123
|
this.#setBoolean(opts, 'experimental.flaggingProvider.enabled', options.experimental?.flaggingProvider?.enabled)
|
|
1124
|
+
opts['experimental.flaggingProvider.initializationTimeoutMs'] = maybeInt(
|
|
1125
|
+
options.experimental?.flaggingProvider?.initializationTimeoutMs
|
|
1126
|
+
)
|
|
1127
|
+
this.#optsUnprocessed['experimental.flaggingProvider.initializationTimeoutMs'] =
|
|
1128
|
+
options.experimental?.flaggingProvider?.initializationTimeoutMs
|
|
1115
1129
|
opts.flushInterval = maybeInt(options.flushInterval)
|
|
1116
1130
|
this.#optsUnprocessed.flushInterval = options.flushInterval
|
|
1117
1131
|
opts.flushMinSpans = maybeInt(options.flushMinSpans)
|
|
@@ -169,6 +169,7 @@ function enable (rc, config, onConfigUpdated) {
|
|
|
169
169
|
|
|
170
170
|
// Debugger
|
|
171
171
|
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLE_DYNAMIC_INSTRUMENTATION, true)
|
|
172
|
+
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLE_LIVE_DEBUGGING, true)
|
|
172
173
|
|
|
173
174
|
// Code Origin
|
|
174
175
|
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLE_CODE_ORIGIN, true)
|
|
@@ -73,11 +73,11 @@
|
|
|
73
73
|
"DD_ENV": ["A"],
|
|
74
74
|
"DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED": ["A"],
|
|
75
75
|
"DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED": ["A"],
|
|
76
|
+
"DD_EXPERIMENTAL_FLAGGING_PROVIDER_INITIALIZATION_TIMEOUT_MS": ["A"],
|
|
76
77
|
"DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED": ["A"],
|
|
77
78
|
"DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED": ["A"],
|
|
78
79
|
"DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR": ["A"],
|
|
79
80
|
"DD_EXTERNAL_ENV": ["A"],
|
|
80
|
-
"DD_FLAGGING_PROVIDER_ENABLED": ["A"],
|
|
81
81
|
"DD_GIT_BRANCH": ["A"],
|
|
82
82
|
"DD_GIT_COMMIT_AUTHOR_DATE": ["A"],
|
|
83
83
|
"DD_GIT_COMMIT_AUTHOR_EMAIL": ["A"],
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { URL } = require('url')
|
|
4
|
-
|
|
5
3
|
// Load binding first to not import other modules if it throws
|
|
6
4
|
const libdatadog = require('@datadog/libdatadog')
|
|
7
5
|
const binding = libdatadog.load('crashtracker')
|
|
8
6
|
|
|
9
7
|
const log = require('../log')
|
|
10
|
-
const
|
|
8
|
+
const { getAgentUrl } = require('../agent/url')
|
|
11
9
|
const pkg = require('../../../../package.json')
|
|
12
10
|
const processTags = require('../process-tags')
|
|
13
11
|
|
|
@@ -52,8 +50,7 @@ class Crashtracker {
|
|
|
52
50
|
|
|
53
51
|
// TODO: Send only configured values when defaults are fixed.
|
|
54
52
|
#getConfig (config) {
|
|
55
|
-
const
|
|
56
|
-
const url = config.url || new URL(`http://${hostname}:${port}`)
|
|
53
|
+
const url = getAgentUrl(config)
|
|
57
54
|
|
|
58
55
|
return {
|
|
59
56
|
additional_files: [],
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { URL, format } = require('url')
|
|
4
3
|
const zlib = require('zlib')
|
|
5
4
|
const pkg = require('../../../../package.json')
|
|
6
5
|
const log = require('../log')
|
|
7
6
|
const request = require('../exporters/common/request')
|
|
8
7
|
const { MsgpackEncoder } = require('../msgpack')
|
|
9
|
-
const
|
|
8
|
+
const { getAgentUrl } = require('../agent/url')
|
|
10
9
|
|
|
11
10
|
const msgpack = new MsgpackEncoder()
|
|
12
11
|
|
|
@@ -32,12 +31,7 @@ function makeRequest (data, url, cb) {
|
|
|
32
31
|
|
|
33
32
|
class DataStreamsWriter {
|
|
34
33
|
constructor (config) {
|
|
35
|
-
|
|
36
|
-
this._url = url || new URL(format({
|
|
37
|
-
protocol: 'http:',
|
|
38
|
-
hostname,
|
|
39
|
-
port
|
|
40
|
-
}))
|
|
34
|
+
this._url = getAgentUrl(config)
|
|
41
35
|
}
|
|
42
36
|
|
|
43
37
|
flush (payload) {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { workerData: { config: parentConfig, parentThreadId, configPort } } = require('node:worker_threads')
|
|
4
|
-
const {
|
|
5
|
-
const defaults = require('../../config/defaults')
|
|
4
|
+
const { getAgentUrl } = require('../../agent/url')
|
|
6
5
|
const log = require('./log')
|
|
7
6
|
|
|
8
7
|
const config = module.exports = {
|
|
@@ -19,11 +18,7 @@ configPort.on('messageerror', (err) =>
|
|
|
19
18
|
)
|
|
20
19
|
|
|
21
20
|
function updateUrl (updates) {
|
|
22
|
-
config.url = updates
|
|
23
|
-
protocol: 'http:',
|
|
24
|
-
hostname: updates.hostname || defaults.hostname,
|
|
25
|
-
port: updates.port
|
|
26
|
-
})
|
|
21
|
+
config.url = getAgentUrl(updates)
|
|
27
22
|
|
|
28
23
|
config.dynamicInstrumentation.captureTimeoutNs = BigInt(updates.dynamicInstrumentation.captureTimeoutMs) * 1_000_000n
|
|
29
24
|
}
|
|
@@ -11,26 +11,25 @@ class JSONBuffer {
|
|
|
11
11
|
this.#maxSize = size
|
|
12
12
|
this.#timeout = timeout
|
|
13
13
|
this.#onFlush = onFlush
|
|
14
|
-
this.#reset()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
#reset () {
|
|
18
|
-
clearTimeout(this.#timer)
|
|
19
|
-
this.#timer = undefined
|
|
20
|
-
this.#partialJson = undefined
|
|
21
14
|
}
|
|
22
15
|
|
|
23
16
|
#flush () {
|
|
24
17
|
const json = `${this.#partialJson}]`
|
|
25
|
-
this.#
|
|
18
|
+
this.#partialJson = undefined
|
|
26
19
|
this.#onFlush(json)
|
|
27
20
|
}
|
|
28
21
|
|
|
29
22
|
write (str, size = Buffer.byteLength(str)) {
|
|
30
|
-
if (this.#
|
|
23
|
+
if (this.#partialJson === undefined) {
|
|
31
24
|
this.#partialJson = `[${str}`
|
|
32
|
-
this.#timer
|
|
33
|
-
|
|
25
|
+
if (this.#timer === undefined) {
|
|
26
|
+
this.#timer = setTimeout(() => this.#flush(), this.#timeout)
|
|
27
|
+
} else {
|
|
28
|
+
this.#timer.refresh()
|
|
29
|
+
}
|
|
30
|
+
} else if (Buffer.byteLength(this.#partialJson) + size + 2 > this.#maxSize) {
|
|
31
|
+
clearTimeout(this.#timer)
|
|
32
|
+
this.#timer = undefined
|
|
34
33
|
this.#flush()
|
|
35
34
|
this.write(str, size)
|
|
36
35
|
} else {
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
const lookup = require('dns').lookup // cache to avoid instrumentation
|
|
4
4
|
const dgram = require('dgram')
|
|
5
5
|
const isIP = require('net').isIP
|
|
6
|
-
const { URL, format } = require('url')
|
|
7
6
|
|
|
8
7
|
const request = require('./exporters/common/request')
|
|
9
8
|
const log = require('./log')
|
|
10
9
|
const Histogram = require('./histogram')
|
|
11
10
|
const defaults = require('./config/defaults')
|
|
11
|
+
const { getAgentUrl } = require('./agent/url')
|
|
12
12
|
|
|
13
13
|
const MAX_BUFFER_SIZE = 1024 // limit from the agent
|
|
14
14
|
|
|
@@ -179,14 +179,8 @@ class DogStatsDClient {
|
|
|
179
179
|
tags
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
if (config.url) {
|
|
183
|
-
clientConfig.metricsProxyUrl = config
|
|
184
|
-
} else if (config.port) {
|
|
185
|
-
clientConfig.metricsProxyUrl = new URL(format({
|
|
186
|
-
protocol: 'http:',
|
|
187
|
-
hostname: config.hostname || defaults.hostname,
|
|
188
|
-
port: config.port
|
|
189
|
-
}))
|
|
182
|
+
if (config.url || config.port) {
|
|
183
|
+
clientConfig.metricsProxyUrl = getAgentUrl(config)
|
|
190
184
|
}
|
|
191
185
|
|
|
192
186
|
return clientConfig
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { URL
|
|
3
|
+
const { URL } = require('url')
|
|
4
4
|
const log = require('../../log')
|
|
5
|
-
const
|
|
5
|
+
const { getAgentUrl } = require('../../agent/url')
|
|
6
6
|
const Writer = require('./writer')
|
|
7
7
|
|
|
8
8
|
class AgentExporter {
|
|
@@ -10,12 +10,8 @@ class AgentExporter {
|
|
|
10
10
|
|
|
11
11
|
constructor (config, prioritySampler) {
|
|
12
12
|
this._config = config
|
|
13
|
-
const {
|
|
14
|
-
this._url =
|
|
15
|
-
protocol: 'http:',
|
|
16
|
-
hostname,
|
|
17
|
-
port
|
|
18
|
-
}))
|
|
13
|
+
const { lookup, protocolVersion, stats = {}, apmTracingEnabled } = config
|
|
14
|
+
this._url = getAgentUrl(config)
|
|
19
15
|
|
|
20
16
|
const headers = {}
|
|
21
17
|
if (stats.enabled || apmTracingEnabled === false) {
|
|
@@ -12,8 +12,9 @@ const BaseWriter = require('../common/writer')
|
|
|
12
12
|
const METRIC_PREFIX = 'datadog.tracer.node.exporter.agent'
|
|
13
13
|
|
|
14
14
|
class AgentWriter extends BaseWriter {
|
|
15
|
-
constructor (
|
|
16
|
-
super(...
|
|
15
|
+
constructor (...args) {
|
|
16
|
+
super(...args)
|
|
17
|
+
const { prioritySampler, lookup, protocolVersion, headers, config = {} } = args[0]
|
|
17
18
|
const AgentEncoder = getEncoder(protocolVersion)
|
|
18
19
|
|
|
19
20
|
this._prioritySampler = prioritySampler
|