dd-trace 4.29.0 → 4.30.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/README.md +7 -0
- package/ci/cypress/after-spec.js +1 -0
- package/index.d.ts +1499 -1486
- package/package.json +3 -3
- package/packages/datadog-core/src/utils/src/get.js +11 -0
- package/packages/datadog-core/src/utils/src/has.js +14 -0
- package/packages/datadog-core/src/utils/src/set.js +16 -0
- package/packages/datadog-instrumentations/src/amqplib.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +2 -1
- package/packages/datadog-instrumentations/src/grpc/server.js +3 -1
- package/packages/datadog-instrumentations/src/jest.js +11 -5
- package/packages/datadog-instrumentations/src/mocha.js +4 -1
- package/packages/datadog-instrumentations/src/mongodb-core.js +34 -3
- package/packages/datadog-instrumentations/src/playwright.js +78 -16
- package/packages/datadog-plugin-amqplib/src/consumer.js +5 -4
- package/packages/datadog-plugin-amqplib/src/producer.js +3 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -11
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -6
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +5 -7
- package/packages/datadog-plugin-cypress/src/after-spec.js +3 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +123 -58
- package/packages/datadog-plugin-cypress/src/support.js +50 -3
- package/packages/datadog-plugin-graphql/src/index.js +1 -1
- package/packages/datadog-plugin-graphql/src/resolve.js +10 -8
- package/packages/datadog-plugin-grpc/src/util.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +11 -2
- package/packages/datadog-plugin-kafkajs/src/consumer.js +4 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -5
- package/packages/datadog-plugin-playwright/src/index.js +34 -3
- package/packages/datadog-plugin-rhea/src/consumer.js +5 -3
- package/packages/datadog-plugin-rhea/src/producer.js +3 -4
- package/packages/dd-trace/src/appsec/iast/index.js +10 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +18 -5
- package/packages/dd-trace/src/appsec/recommended.json +67 -27
- package/packages/dd-trace/src/appsec/remote_config/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -3
- package/packages/dd-trace/src/config.js +451 -460
- package/packages/dd-trace/src/data_streams_context.js +1 -1
- package/packages/dd-trace/src/datastreams/pathway.js +58 -1
- package/packages/dd-trace/src/datastreams/processor.js +3 -5
- package/packages/dd-trace/src/format.js +0 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -1
- package/packages/dd-trace/src/plugins/util/test.js +2 -0
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +38 -2
- package/packages/dd-trace/src/telemetry/index.js +22 -34
- package/packages/dd-trace/src/tracer.js +3 -3
- package/register.js +4 -0
- /package/packages/{utils → datadog-core/src/utils}/src/kebabcase.js +0 -0
- /package/packages/{utils → datadog-core/src/utils}/src/pick.js +0 -0
- /package/packages/{utils → datadog-core/src/utils}/src/uniq.js +0 -0
|
@@ -6,7 +6,7 @@ function getDataStreamsContext () {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
function setDataStreamsContext (dataStreamsContext) {
|
|
9
|
-
storage.enterWith({ ...(storage.getStore()), dataStreamsContext })
|
|
9
|
+
if (dataStreamsContext) storage.enterWith({ ...(storage.getStore()), dataStreamsContext })
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
module.exports = {
|
|
@@ -8,6 +8,9 @@ const LRUCache = require('lru-cache')
|
|
|
8
8
|
const options = { max: 500 }
|
|
9
9
|
const cache = new LRUCache(options)
|
|
10
10
|
|
|
11
|
+
const CONTEXT_PROPAGATION_KEY = 'dd-pathway-ctx'
|
|
12
|
+
const CONTEXT_PROPAGATION_KEY_BASE64 = 'dd-pathway-ctx-base64'
|
|
13
|
+
|
|
11
14
|
function shaHash (checkpointString) {
|
|
12
15
|
const hash = crypto.createHash('md5').update(checkpointString).digest('hex').slice(0, 16)
|
|
13
16
|
return Buffer.from(hash, 'hex')
|
|
@@ -33,6 +36,11 @@ function encodePathwayContext (dataStreamsContext) {
|
|
|
33
36
|
], 20)
|
|
34
37
|
}
|
|
35
38
|
|
|
39
|
+
function encodePathwayContextBase64 (dataStreamsContext) {
|
|
40
|
+
const encodedPathway = encodePathwayContext(dataStreamsContext)
|
|
41
|
+
return encodedPathway.toString('base64')
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
function decodePathwayContext (pathwayContext) {
|
|
37
45
|
if (pathwayContext == null || pathwayContext.length < 8) {
|
|
38
46
|
return null
|
|
@@ -51,8 +59,57 @@ function decodePathwayContext (pathwayContext) {
|
|
|
51
59
|
return { hash: pathwayHash, pathwayStartNs: pathwayStartMs * 1e6, edgeStartNs: edgeStartMs * 1e6 }
|
|
52
60
|
}
|
|
53
61
|
|
|
62
|
+
function decodePathwayContextBase64 (pathwayContext) {
|
|
63
|
+
if (pathwayContext == null || pathwayContext.length < 8) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
if (Buffer.isBuffer(pathwayContext)) {
|
|
67
|
+
pathwayContext = pathwayContext.toString()
|
|
68
|
+
}
|
|
69
|
+
const encodedPathway = Buffer.from(pathwayContext, 'base64')
|
|
70
|
+
return decodePathwayContext(encodedPathway)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
class DsmPathwayCodec {
|
|
74
|
+
// we use a class for encoding / decoding in case we update our encoding/decoding. A class will make updates easier
|
|
75
|
+
// instead of using individual functions.
|
|
76
|
+
static encode (dataStreamsContext, carrier) {
|
|
77
|
+
if (!dataStreamsContext || !dataStreamsContext.hash) {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
carrier[CONTEXT_PROPAGATION_KEY_BASE64] = encodePathwayContextBase64(dataStreamsContext)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static decode (carrier) {
|
|
84
|
+
if (carrier == null) return
|
|
85
|
+
|
|
86
|
+
let ctx
|
|
87
|
+
if (CONTEXT_PROPAGATION_KEY_BASE64 in carrier) {
|
|
88
|
+
// decode v2 encoding of base64
|
|
89
|
+
ctx = decodePathwayContextBase64(carrier[CONTEXT_PROPAGATION_KEY_BASE64])
|
|
90
|
+
} else if (CONTEXT_PROPAGATION_KEY in carrier) {
|
|
91
|
+
try {
|
|
92
|
+
// decode v1 encoding
|
|
93
|
+
ctx = decodePathwayContext(carrier[CONTEXT_PROPAGATION_KEY])
|
|
94
|
+
} catch {
|
|
95
|
+
// pass
|
|
96
|
+
}
|
|
97
|
+
// cover case where base64 context was received under wrong key
|
|
98
|
+
if (!ctx) ctx = decodePathwayContextBase64(carrier[CONTEXT_PROPAGATION_KEY])
|
|
99
|
+
}
|
|
100
|
+
return ctx
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static contextExists (carrier) {
|
|
104
|
+
return CONTEXT_PROPAGATION_KEY_BASE64 in carrier || CONTEXT_PROPAGATION_KEY in carrier
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
54
108
|
module.exports = {
|
|
55
109
|
computePathwayHash: computeHash,
|
|
56
110
|
encodePathwayContext,
|
|
57
|
-
decodePathwayContext
|
|
111
|
+
decodePathwayContext,
|
|
112
|
+
encodePathwayContextBase64,
|
|
113
|
+
decodePathwayContextBase64,
|
|
114
|
+
DsmPathwayCodec
|
|
58
115
|
}
|
|
@@ -4,7 +4,7 @@ const pkg = require('../../../../package.json')
|
|
|
4
4
|
const Uint64 = require('int64-buffer').Uint64BE
|
|
5
5
|
|
|
6
6
|
const { LogCollapsingLowestDenseDDSketch } = require('@datadog/sketches-js')
|
|
7
|
-
const {
|
|
7
|
+
const { DsmPathwayCodec } = require('./pathway')
|
|
8
8
|
const { DataStreamsWriter } = require('./writer')
|
|
9
9
|
const { computePathwayHash } = require('./pathway')
|
|
10
10
|
const { types } = require('util')
|
|
@@ -13,7 +13,6 @@ const { PATHWAY_HASH } = require('../../../../ext/tags')
|
|
|
13
13
|
const ENTRY_PARENT_HASH = Buffer.from('0000000000000000', 'hex')
|
|
14
14
|
|
|
15
15
|
const HIGH_ACCURACY_DISTRIBUTION = 0.0075
|
|
16
|
-
const CONTEXT_PROPAGATION_KEY = 'dd-pathway-ctx'
|
|
17
16
|
|
|
18
17
|
class StatsPoint {
|
|
19
18
|
constructor (hash, parentHash, edgeTags) {
|
|
@@ -285,7 +284,7 @@ class DataStreamsProcessor {
|
|
|
285
284
|
// Add the header for this now, as the callee doesn't have access to context when producing
|
|
286
285
|
// - 1 to account for extra byte for {
|
|
287
286
|
const ddInfoContinued = {}
|
|
288
|
-
|
|
287
|
+
DsmPathwayCodec.encode(dataStreamsContext, ddInfoContinued)
|
|
289
288
|
payloadSize += getSizeOrZero(JSON.stringify(ddInfoContinued)) - 1
|
|
290
289
|
}
|
|
291
290
|
const checkpoint = {
|
|
@@ -364,6 +363,5 @@ module.exports = {
|
|
|
364
363
|
getHeadersSize,
|
|
365
364
|
getSizeOrZero,
|
|
366
365
|
getAmqpMessageSize,
|
|
367
|
-
ENTRY_PARENT_HASH
|
|
368
|
-
CONTEXT_PROPAGATION_KEY
|
|
366
|
+
ENTRY_PARENT_HASH
|
|
369
367
|
}
|
|
@@ -58,6 +58,7 @@ const TEST_EARLY_FLAKE_IS_ENABLED = 'test.early_flake.is_enabled'
|
|
|
58
58
|
const CI_APP_ORIGIN = 'ciapp-test'
|
|
59
59
|
|
|
60
60
|
const JEST_TEST_RUNNER = 'test.jest.test_runner'
|
|
61
|
+
const JEST_DISPLAY_NAME = 'test.jest.display_name'
|
|
61
62
|
|
|
62
63
|
const TEST_ITR_TESTS_SKIPPED = '_dd.ci.itr.tests_skipped'
|
|
63
64
|
const TEST_ITR_SKIPPING_ENABLED = 'test.itr.tests_skipping.enabled'
|
|
@@ -83,6 +84,7 @@ module.exports = {
|
|
|
83
84
|
TEST_FRAMEWORK,
|
|
84
85
|
TEST_FRAMEWORK_VERSION,
|
|
85
86
|
JEST_TEST_RUNNER,
|
|
87
|
+
JEST_DISPLAY_NAME,
|
|
86
88
|
TEST_TYPE,
|
|
87
89
|
TEST_NAME,
|
|
88
90
|
TEST_SUITE,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const uniq = require('../../../../utils/src/uniq')
|
|
3
|
+
const uniq = require('../../../../datadog-core/src/utils/src/uniq')
|
|
4
4
|
const analyticsSampler = require('../../analytics_sampler')
|
|
5
5
|
const FORMAT_HTTP_HEADERS = 'http_headers'
|
|
6
6
|
const log = require('../../log')
|
|
@@ -9,6 +9,8 @@ const docker = require('../../exporters/common/docker')
|
|
|
9
9
|
const FormData = require('../../exporters/common/form-data')
|
|
10
10
|
const { storage } = require('../../../../datadog-core')
|
|
11
11
|
const version = require('../../../../../package.json').version
|
|
12
|
+
const os = require('os')
|
|
13
|
+
const perf = require('perf_hooks').performance
|
|
12
14
|
|
|
13
15
|
const containerId = docker.id()
|
|
14
16
|
|
|
@@ -50,7 +52,7 @@ function computeRetries (uploadTimeout) {
|
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
class AgentExporter {
|
|
53
|
-
constructor ({ url, logger, uploadTimeout } = {}) {
|
|
55
|
+
constructor ({ url, logger, uploadTimeout, env, host, service, version } = {}) {
|
|
54
56
|
this._url = url
|
|
55
57
|
this._logger = logger
|
|
56
58
|
|
|
@@ -58,6 +60,10 @@ class AgentExporter {
|
|
|
58
60
|
|
|
59
61
|
this._backoffTime = backoffTime
|
|
60
62
|
this._backoffTries = backoffTries
|
|
63
|
+
this._env = env
|
|
64
|
+
this._host = host
|
|
65
|
+
this._service = service
|
|
66
|
+
this._appVersion = version
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
export ({ profiles, start, end, tags }) {
|
|
@@ -83,7 +89,37 @@ class AgentExporter {
|
|
|
83
89
|
`profiler_version:${version}`,
|
|
84
90
|
'format:pprof',
|
|
85
91
|
...Object.entries(tags).map(([key, value]) => `${key}:${value}`)
|
|
86
|
-
].join(',')
|
|
92
|
+
].join(','),
|
|
93
|
+
info: {
|
|
94
|
+
application: {
|
|
95
|
+
env: this._env,
|
|
96
|
+
service: this._service,
|
|
97
|
+
start_time: new Date(perf.nodeTiming.nodeStart + perf.timeOrigin).toISOString(),
|
|
98
|
+
version: this._appVersion
|
|
99
|
+
},
|
|
100
|
+
platform: {
|
|
101
|
+
hostname: this._host,
|
|
102
|
+
kernel_name: os.type(),
|
|
103
|
+
kernel_release: os.release(),
|
|
104
|
+
kernel_version: os.version()
|
|
105
|
+
},
|
|
106
|
+
profiler: {
|
|
107
|
+
version
|
|
108
|
+
},
|
|
109
|
+
runtime: {
|
|
110
|
+
// Using `nodejs` for consistency with the existing `runtime` tag.
|
|
111
|
+
// Note that the event `family` property uses `node`, as that's what's
|
|
112
|
+
// proscribed by the Intake API, but that's an internal enum and is
|
|
113
|
+
// not customer visible.
|
|
114
|
+
engine: 'nodejs',
|
|
115
|
+
// strip off leading 'v'. This makes the format consistent with other
|
|
116
|
+
// runtimes (e.g. Ruby) but not with the existing `runtime_version` tag.
|
|
117
|
+
// We'll keep it like this as we want cross-engine consistency. We
|
|
118
|
+
// also aren't changing the format of the existing tag as we don't want
|
|
119
|
+
// to break it.
|
|
120
|
+
version: process.version.substring(1)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
87
123
|
})
|
|
88
124
|
|
|
89
125
|
fields.push(['event', event, {
|
|
@@ -20,6 +20,7 @@ let heartbeatTimeout
|
|
|
20
20
|
let heartbeatInterval
|
|
21
21
|
let extendedInterval
|
|
22
22
|
let integrations
|
|
23
|
+
let configWithOrigin = []
|
|
23
24
|
let retryData = null
|
|
24
25
|
const extendedHeartbeatPayload = {}
|
|
25
26
|
|
|
@@ -96,23 +97,6 @@ function getProducts (config) {
|
|
|
96
97
|
return products
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
function flatten (input, result = [], prefix = [], traversedObjects = null) {
|
|
100
|
-
traversedObjects = traversedObjects || new WeakSet()
|
|
101
|
-
if (traversedObjects.has(input)) {
|
|
102
|
-
return
|
|
103
|
-
}
|
|
104
|
-
traversedObjects.add(input)
|
|
105
|
-
for (const [key, value] of Object.entries(input)) {
|
|
106
|
-
if (typeof value === 'object' && value !== null) {
|
|
107
|
-
flatten(value, result, [...prefix, key], traversedObjects)
|
|
108
|
-
} else {
|
|
109
|
-
// TODO: add correct origin value
|
|
110
|
-
result.push({ name: [...prefix, key].join('.'), value, origin: 'unknown' })
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return result
|
|
114
|
-
}
|
|
115
|
-
|
|
116
100
|
function getInstallSignature (config) {
|
|
117
101
|
const { installSignature: sig } = config
|
|
118
102
|
if (sig && (sig.id || sig.time || sig.type)) {
|
|
@@ -127,7 +111,7 @@ function getInstallSignature (config) {
|
|
|
127
111
|
function appStarted (config) {
|
|
128
112
|
const app = {
|
|
129
113
|
products: getProducts(config),
|
|
130
|
-
configuration:
|
|
114
|
+
configuration: configWithOrigin
|
|
131
115
|
}
|
|
132
116
|
const installSignature = getInstallSignature(config)
|
|
133
117
|
if (installSignature) {
|
|
@@ -305,13 +289,18 @@ function updateIntegrations () {
|
|
|
305
289
|
sendData(config, application, host, reqType, payload, updateRetryData)
|
|
306
290
|
}
|
|
307
291
|
|
|
292
|
+
function formatMapForTelemetry (map) {
|
|
293
|
+
// format from an object to a string map in order for
|
|
294
|
+
// telemetry intake to accept the configuration
|
|
295
|
+
return map
|
|
296
|
+
? Object.entries(map).map(([key, value]) => `${key}:${value}`).join(',')
|
|
297
|
+
: ''
|
|
298
|
+
}
|
|
299
|
+
|
|
308
300
|
function updateConfig (changes, config) {
|
|
309
301
|
if (!config.telemetry.enabled) return
|
|
310
302
|
if (changes.length === 0) return
|
|
311
303
|
|
|
312
|
-
// Hack to make system tests happy until we ship telemetry v2
|
|
313
|
-
if (process.env.DD_INTERNAL_TELEMETRY_V2_ENABLED !== '1') return
|
|
314
|
-
|
|
315
304
|
const application = createAppObject(config)
|
|
316
305
|
const host = createHostObject()
|
|
317
306
|
|
|
@@ -325,24 +314,23 @@ function updateConfig (changes, config) {
|
|
|
325
314
|
const configuration = []
|
|
326
315
|
|
|
327
316
|
for (const change of changes) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const name = names[change.name]
|
|
317
|
+
const name = names[change.name] || change.name
|
|
331
318
|
const { origin, value } = change
|
|
332
|
-
const entry = { name,
|
|
319
|
+
const entry = { name, value, origin }
|
|
333
320
|
|
|
334
|
-
if (Array.isArray(value))
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
321
|
+
if (Array.isArray(value)) entry.value = value.join(',')
|
|
322
|
+
if (entry.name === 'DD_TAGS') entry.value = formatMapForTelemetry(entry.value)
|
|
323
|
+
if (entry.name === 'url' && entry.value) entry.value = entry.value.toString()
|
|
324
|
+
if (entry.name === 'peerServiceMapping' || entry.name === 'tags') entry.value = formatMapForTelemetry(entry.value)
|
|
339
325
|
|
|
340
326
|
configuration.push(entry)
|
|
341
327
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
328
|
+
if (!configWithOrigin.length) {
|
|
329
|
+
configWithOrigin = configuration
|
|
330
|
+
} else {
|
|
331
|
+
const { reqType, payload } = createPayload('app-client-configuration-change', { configuration })
|
|
332
|
+
sendData(config, application, host, reqType, payload, updateRetryData)
|
|
333
|
+
}
|
|
346
334
|
}
|
|
347
335
|
|
|
348
336
|
module.exports = {
|
|
@@ -8,7 +8,7 @@ const { isError } = require('./util')
|
|
|
8
8
|
const { setStartupLogConfig } = require('./startup-log')
|
|
9
9
|
const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
|
|
10
10
|
const { DataStreamsProcessor } = require('./datastreams/processor')
|
|
11
|
-
const {
|
|
11
|
+
const { DsmPathwayCodec } = require('./datastreams/pathway')
|
|
12
12
|
const { DD_MAJOR } = require('../../../version')
|
|
13
13
|
const DataStreamsContext = require('./data_streams_context')
|
|
14
14
|
|
|
@@ -39,8 +39,8 @@ class DatadogTracer extends Tracer {
|
|
|
39
39
|
return ctx
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
decodeDataStreamsContext (
|
|
43
|
-
const ctx =
|
|
42
|
+
decodeDataStreamsContext (carrier) {
|
|
43
|
+
const ctx = DsmPathwayCodec.decode(carrier)
|
|
44
44
|
// we erase the previous context everytime we decode a new one
|
|
45
45
|
DataStreamsContext.setDataStreamsContext(ctx)
|
|
46
46
|
return ctx
|
package/register.js
ADDED
|
File without changes
|
|
File without changes
|
|
File without changes
|