dd-trace 4.40.0 → 4.42.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/ext/exporters.d.ts +1 -1
- package/index.d.ts +54 -1
- package/init.js +40 -1
- package/initialize.mjs +8 -5
- package/package.json +24 -20
- package/packages/datadog-core/src/storage/index.js +1 -10
- package/packages/datadog-esbuild/index.js +5 -1
- package/packages/datadog-instrumentations/src/aws-sdk.js +2 -1
- package/packages/datadog-instrumentations/src/cucumber.js +76 -34
- package/packages/datadog-instrumentations/src/helpers/hook.js +8 -3
- package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +4 -3
- package/packages/datadog-instrumentations/src/helpers/register.js +56 -5
- package/packages/datadog-instrumentations/src/http/server.js +98 -0
- package/packages/datadog-instrumentations/src/mocha/main.js +12 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +58 -14
- package/packages/datadog-instrumentations/src/mocha/worker.js +1 -0
- package/packages/datadog-instrumentations/src/playwright.js +1 -1
- package/packages/datadog-instrumentations/src/undici.js +18 -0
- package/packages/datadog-instrumentations/src/vitest.js +303 -0
- package/packages/datadog-plugin-aws-sdk/src/base.js +8 -1
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +6 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +23 -5
- package/packages/datadog-plugin-child_process/src/index.js +1 -1
- package/packages/datadog-plugin-cucumber/src/index.js +24 -1
- package/packages/datadog-plugin-mocha/src/index.js +25 -4
- package/packages/datadog-plugin-openai/src/index.js +52 -30
- package/packages/datadog-plugin-openai/src/token-estimator.js +20 -0
- package/packages/datadog-plugin-undici/src/index.js +12 -0
- package/packages/datadog-plugin-vitest/src/index.js +156 -0
- package/packages/dd-trace/src/appsec/blocking.js +4 -0
- package/packages/dd-trace/src/appsec/channels.js +1 -0
- package/packages/dd-trace/src/appsec/iast/path-line.js +2 -19
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -0
- package/packages/dd-trace/src/appsec/index.js +45 -11
- package/packages/dd-trace/src/appsec/rasp.js +32 -5
- package/packages/dd-trace/src/appsec/recommended.json +208 -3
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +1 -0
- package/packages/dd-trace/src/appsec/remote_config/index.js +2 -0
- package/packages/dd-trace/src/appsec/reporter.js +64 -20
- package/packages/dd-trace/src/appsec/sdk/track_event.js +3 -0
- package/packages/dd-trace/src/appsec/stack_trace.js +90 -0
- package/packages/dd-trace/src/appsec/standalone.js +130 -0
- package/packages/dd-trace/src/appsec/telemetry.js +33 -1
- package/packages/dd-trace/src/appsec/waf/index.js +2 -2
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -2
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -2
- package/packages/dd-trace/src/config.js +110 -40
- package/packages/dd-trace/src/constants.js +3 -1
- package/packages/dd-trace/src/datastreams/processor.js +2 -1
- package/packages/dd-trace/src/exporters/agent/index.js +2 -2
- package/packages/dd-trace/src/format.js +22 -2
- package/packages/dd-trace/src/opentelemetry/span.js +33 -7
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +12 -0
- package/packages/dd-trace/src/opentracing/span.js +42 -1
- package/packages/dd-trace/src/opentracing/tracer.js +2 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +7 -0
- package/packages/dd-trace/src/plugins/index.js +3 -0
- package/packages/dd-trace/src/plugins/util/test.js +5 -1
- package/packages/dd-trace/src/priority_sampler.js +2 -5
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/proxy.js +3 -1
- package/packages/dd-trace/src/rate_limiter.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
- package/packages/dd-trace/src/span_stats.js +4 -3
- package/packages/dd-trace/src/tagger.js +10 -1
- package/packages/dd-trace/src/telemetry/init-telemetry.js +75 -0
- package/packages/dd-trace/src/tracer.js +2 -2
- package/packages/dd-trace/src/util.js +6 -1
- package/packages/datadog-core/src/storage/async_hooks.js +0 -49
|
@@ -18,6 +18,7 @@ module.exports = {
|
|
|
18
18
|
get '@opensearch-project/opensearch' () { return require('../../../datadog-plugin-opensearch/src') },
|
|
19
19
|
get '@redis/client' () { return require('../../../datadog-plugin-redis/src') },
|
|
20
20
|
get '@smithy/smithy-client' () { return require('../../../datadog-plugin-aws-sdk/src') },
|
|
21
|
+
get '@vitest/runner' () { return require('../../../datadog-plugin-vitest/src') },
|
|
21
22
|
get aerospike () { return require('../../../datadog-plugin-aerospike/src') },
|
|
22
23
|
get amqp10 () { return require('../../../datadog-plugin-amqp10/src') },
|
|
23
24
|
get amqplib () { return require('../../../datadog-plugin-amqplib/src') },
|
|
@@ -54,6 +55,7 @@ module.exports = {
|
|
|
54
55
|
get 'microgateway-core' () { return require('../../../datadog-plugin-microgateway-core/src') },
|
|
55
56
|
get mocha () { return require('../../../datadog-plugin-mocha/src') },
|
|
56
57
|
get 'mocha-each' () { return require('../../../datadog-plugin-mocha/src') },
|
|
58
|
+
get vitest () { return require('../../../datadog-plugin-vitest/src') },
|
|
57
59
|
get workerpool () { return require('../../../datadog-plugin-mocha/src') },
|
|
58
60
|
get moleculer () { return require('../../../datadog-plugin-moleculer/src') },
|
|
59
61
|
get mongodb () { return require('../../../datadog-plugin-mongodb-core/src') },
|
|
@@ -81,5 +83,6 @@ module.exports = {
|
|
|
81
83
|
get 'selenium-webdriver' () { return require('../../../datadog-plugin-selenium/src') },
|
|
82
84
|
get sharedb () { return require('../../../datadog-plugin-sharedb/src') },
|
|
83
85
|
get tedious () { return require('../../../datadog-plugin-tedious/src') },
|
|
86
|
+
get undici () { return require('../../../datadog-plugin-undici/src') },
|
|
84
87
|
get winston () { return require('../../../datadog-plugin-winston/src') }
|
|
85
88
|
}
|
|
@@ -95,6 +95,9 @@ const MOCHA_WORKER_TRACE_PAYLOAD_CODE = 80
|
|
|
95
95
|
const EFD_STRING = "Retried by Datadog's Early Flake Detection"
|
|
96
96
|
const EFD_TEST_NAME_REGEX = new RegExp(EFD_STRING + ' \\(#\\d+\\): ', 'g')
|
|
97
97
|
|
|
98
|
+
// Flaky test retries
|
|
99
|
+
const NUM_FAILED_TEST_RETRIES = 5
|
|
100
|
+
|
|
98
101
|
module.exports = {
|
|
99
102
|
TEST_CODE_OWNERS,
|
|
100
103
|
TEST_FRAMEWORK,
|
|
@@ -167,7 +170,8 @@ module.exports = {
|
|
|
167
170
|
TEST_BROWSER_DRIVER,
|
|
168
171
|
TEST_BROWSER_DRIVER_VERSION,
|
|
169
172
|
TEST_BROWSER_NAME,
|
|
170
|
-
TEST_BROWSER_VERSION
|
|
173
|
+
TEST_BROWSER_VERSION,
|
|
174
|
+
NUM_FAILED_TEST_RETRIES
|
|
171
175
|
}
|
|
172
176
|
|
|
173
177
|
// Returns pkg manager and its version, separated by '-', e.g. npm-8.15.0 or yarn-1.22.19
|
|
@@ -4,6 +4,7 @@ const RateLimiter = require('./rate_limiter')
|
|
|
4
4
|
const Sampler = require('./sampler')
|
|
5
5
|
const { setSamplingRules } = require('./startup-log')
|
|
6
6
|
const SamplingRule = require('./sampling_rule')
|
|
7
|
+
const { hasOwn } = require('./util')
|
|
7
8
|
|
|
8
9
|
const {
|
|
9
10
|
SAMPLING_MECHANISM_DEFAULT,
|
|
@@ -66,7 +67,7 @@ class PrioritySampler {
|
|
|
66
67
|
if (context._sampling.priority !== undefined) return
|
|
67
68
|
if (!root) return // noop span
|
|
68
69
|
|
|
69
|
-
const tag = this._getPriorityFromTags(context._tags)
|
|
70
|
+
const tag = this._getPriorityFromTags(context._tags, context)
|
|
70
71
|
|
|
71
72
|
if (this.validate(tag)) {
|
|
72
73
|
context._sampling.priority = tag
|
|
@@ -202,8 +203,4 @@ class PrioritySampler {
|
|
|
202
203
|
}
|
|
203
204
|
}
|
|
204
205
|
|
|
205
|
-
function hasOwn (object, prop) {
|
|
206
|
-
return Object.prototype.hasOwnProperty.call(object, prop)
|
|
207
|
-
}
|
|
208
|
-
|
|
209
206
|
module.exports = PrioritySampler
|
|
@@ -69,7 +69,7 @@ class Profiler extends EventEmitter {
|
|
|
69
69
|
setLogger(config.logger)
|
|
70
70
|
|
|
71
71
|
mapper = await maybeSourceMap(config.sourceMap, SourceMapper, config.debugSourceMaps)
|
|
72
|
-
if (config.
|
|
72
|
+
if (config.sourceMap && config.debugSourceMaps) {
|
|
73
73
|
this._logger.debug(() => {
|
|
74
74
|
return mapper.infoMap.size === 0
|
|
75
75
|
? 'Found no source maps'
|
|
@@ -15,6 +15,7 @@ const NoopDogStatsDClient = require('./noop/dogstatsd')
|
|
|
15
15
|
const spanleak = require('./spanleak')
|
|
16
16
|
const { SSIHeuristics } = require('./profiling/ssi-heuristics')
|
|
17
17
|
const telemetryLog = require('dc-polyfill').channel('datadog:telemetry:log')
|
|
18
|
+
const appsecStandalone = require('./appsec/standalone')
|
|
18
19
|
|
|
19
20
|
class LazyModule {
|
|
20
21
|
constructor (provider) {
|
|
@@ -178,7 +179,8 @@ class Tracer extends NoopProxy {
|
|
|
178
179
|
this._modules.appsec.enable(config)
|
|
179
180
|
}
|
|
180
181
|
if (!this._tracingInitialized) {
|
|
181
|
-
|
|
182
|
+
const prioritySampler = appsecStandalone.configure(config)
|
|
183
|
+
this._tracer = new DatadogTracer(config, prioritySampler)
|
|
182
184
|
this.appsec = new AppsecSdk(this._tracer, config)
|
|
183
185
|
this._tracingInitialized = true
|
|
184
186
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
const limiter = require('limiter')
|
|
4
4
|
|
|
5
5
|
class RateLimiter {
|
|
6
|
-
constructor (rateLimit) {
|
|
6
|
+
constructor (rateLimit, interval = 'second') {
|
|
7
7
|
this._rateLimit = parseInt(rateLimit)
|
|
8
|
-
this._limiter = new limiter.RateLimiter(this._rateLimit,
|
|
8
|
+
this._limiter = new limiter.RateLimiter(this._rateLimit, interval)
|
|
9
9
|
this._tokensRequested = 0
|
|
10
10
|
this._prevIntervalTokens = 0
|
|
11
11
|
this._prevTokensRequested = 0
|
|
@@ -126,7 +126,8 @@ class SpanStatsProcessor {
|
|
|
126
126
|
port,
|
|
127
127
|
url,
|
|
128
128
|
env,
|
|
129
|
-
tags
|
|
129
|
+
tags,
|
|
130
|
+
appsec
|
|
130
131
|
} = {}) {
|
|
131
132
|
this.exporter = new SpanStatsExporter({
|
|
132
133
|
hostname,
|
|
@@ -138,12 +139,12 @@ class SpanStatsProcessor {
|
|
|
138
139
|
this.bucketSizeNs = interval * 1e9
|
|
139
140
|
this.buckets = new TimeBuckets()
|
|
140
141
|
this.hostname = os.hostname()
|
|
141
|
-
this.enabled = enabled
|
|
142
|
+
this.enabled = enabled && !appsec?.standalone?.enabled
|
|
142
143
|
this.env = env
|
|
143
144
|
this.tags = tags || {}
|
|
144
145
|
this.sequence = 0
|
|
145
146
|
|
|
146
|
-
if (enabled) {
|
|
147
|
+
if (this.enabled) {
|
|
147
148
|
this.timer = setInterval(this.onInterval.bind(this), interval * 1e3)
|
|
148
149
|
this.timer.unref()
|
|
149
150
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const constants = require('./constants')
|
|
3
4
|
const log = require('./log')
|
|
5
|
+
const ERROR_MESSAGE = constants.ERROR_MESSAGE
|
|
6
|
+
const ERROR_STACK = constants.ERROR_STACK
|
|
7
|
+
const ERROR_TYPE = constants.ERROR_TYPE
|
|
4
8
|
|
|
5
9
|
const otelTagMap = {
|
|
6
10
|
'deployment.environment': 'env',
|
|
@@ -14,7 +18,6 @@ function add (carrier, keyValuePairs, parseOtelTags = false) {
|
|
|
14
18
|
if (Array.isArray(keyValuePairs)) {
|
|
15
19
|
return keyValuePairs.forEach(tags => add(carrier, tags))
|
|
16
20
|
}
|
|
17
|
-
|
|
18
21
|
try {
|
|
19
22
|
if (typeof keyValuePairs === 'string') {
|
|
20
23
|
const segments = keyValuePairs.split(',')
|
|
@@ -32,6 +35,12 @@ function add (carrier, keyValuePairs, parseOtelTags = false) {
|
|
|
32
35
|
carrier[key.trim()] = value.trim()
|
|
33
36
|
}
|
|
34
37
|
} else {
|
|
38
|
+
// HACK: to ensure otel.recordException does not influence trace.error
|
|
39
|
+
if (ERROR_MESSAGE in keyValuePairs || ERROR_STACK in keyValuePairs || ERROR_TYPE in keyValuePairs) {
|
|
40
|
+
if (!('doNotSetTraceError' in keyValuePairs)) {
|
|
41
|
+
carrier.setTraceError = true
|
|
42
|
+
}
|
|
43
|
+
}
|
|
35
44
|
Object.assign(carrier, keyValuePairs)
|
|
36
45
|
}
|
|
37
46
|
} catch (e) {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const { spawn } = require('child_process')
|
|
5
|
+
const tracerVersion = require('../../../../package.json').version
|
|
6
|
+
const log = require('../log')
|
|
7
|
+
|
|
8
|
+
module.exports = sendTelemetry
|
|
9
|
+
|
|
10
|
+
if (!process.env.DD_INJECTION_ENABLED) {
|
|
11
|
+
module.exports = () => {}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (!process.env.DD_TELEMETRY_FORWARDER_PATH) {
|
|
15
|
+
module.exports = () => {}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (!fs.existsSync(process.env.DD_TELEMETRY_FORWARDER_PATH)) {
|
|
19
|
+
module.exports = () => {}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const metadata = {
|
|
23
|
+
language_name: 'nodejs',
|
|
24
|
+
language_version: process.versions.node,
|
|
25
|
+
runtime_name: 'nodejs',
|
|
26
|
+
runtime_version: process.versions.node,
|
|
27
|
+
tracer_version: tracerVersion,
|
|
28
|
+
pid: process.pid
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const seen = []
|
|
32
|
+
function hasSeen (point) {
|
|
33
|
+
if (point.name === 'abort') {
|
|
34
|
+
// This one can only be sent once, regardless of tags
|
|
35
|
+
return seen.includes('abort')
|
|
36
|
+
}
|
|
37
|
+
if (point.name === 'abort.integration') {
|
|
38
|
+
// For now, this is the only other one we want to dedupe
|
|
39
|
+
const compiledPoint = point.name + point.tags.join('')
|
|
40
|
+
return seen.includes(compiledPoint)
|
|
41
|
+
}
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function sendTelemetry (name, tags = []) {
|
|
46
|
+
let points = name
|
|
47
|
+
if (typeof name === 'string') {
|
|
48
|
+
points = [{ name, tags }]
|
|
49
|
+
}
|
|
50
|
+
if (['1', 'true', 'True'].includes(process.env.DD_INJECT_FORCE)) {
|
|
51
|
+
points = points.filter(p => ['error', 'complete'].includes(p.name))
|
|
52
|
+
}
|
|
53
|
+
points = points.filter(p => !hasSeen(p))
|
|
54
|
+
points.forEach(p => {
|
|
55
|
+
p.name = `library_entrypoint.${p.name}`
|
|
56
|
+
})
|
|
57
|
+
if (points.length === 0) {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
const proc = spawn(process.env.DD_TELEMETRY_FORWARDER_PATH, ['library_entrypoint'], {
|
|
61
|
+
stdio: 'pipe'
|
|
62
|
+
})
|
|
63
|
+
proc.on('error', () => {
|
|
64
|
+
log.error('Failed to spawn telemetry forwarder')
|
|
65
|
+
})
|
|
66
|
+
proc.on('exit', (code) => {
|
|
67
|
+
if (code !== 0) {
|
|
68
|
+
log.error(`Telemetry forwarder exited with code ${code}`)
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
proc.stdin.on('error', () => {
|
|
72
|
+
log.error('Failed to write telemetry data to telemetry forwarder')
|
|
73
|
+
})
|
|
74
|
+
proc.stdin.end(JSON.stringify({ metadata, points }))
|
|
75
|
+
}
|
|
@@ -20,8 +20,8 @@ const SERVICE_NAME = tags.SERVICE_NAME
|
|
|
20
20
|
const MEASURED = tags.MEASURED
|
|
21
21
|
|
|
22
22
|
class DatadogTracer extends Tracer {
|
|
23
|
-
constructor (config) {
|
|
24
|
-
super(config)
|
|
23
|
+
constructor (config, prioritySampler) {
|
|
24
|
+
super(config, prioritySampler)
|
|
25
25
|
this._dataStreamsProcessor = new DataStreamsProcessor(config)
|
|
26
26
|
this._scope = new Scope()
|
|
27
27
|
setStartupLogConfig(config)
|
|
@@ -69,10 +69,15 @@ function calculateDDBasePath (dirname) {
|
|
|
69
69
|
return dirSteps.slice(0, packagesIndex + 1).join(path.sep) + path.sep
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
function hasOwn (object, prop) {
|
|
73
|
+
return Object.prototype.hasOwnProperty.call(object, prop)
|
|
74
|
+
}
|
|
75
|
+
|
|
72
76
|
module.exports = {
|
|
73
77
|
isTrue,
|
|
74
78
|
isFalse,
|
|
75
79
|
isError,
|
|
76
80
|
globMatch,
|
|
77
|
-
calculateDDBasePath
|
|
81
|
+
calculateDDBasePath,
|
|
82
|
+
hasOwn
|
|
78
83
|
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { executionAsyncId } = require('async_hooks')
|
|
4
|
-
const AsyncResourceStorage = require('./async_resource')
|
|
5
|
-
|
|
6
|
-
class AsyncHooksStorage extends AsyncResourceStorage {
|
|
7
|
-
constructor () {
|
|
8
|
-
super()
|
|
9
|
-
|
|
10
|
-
this._resources = new Map()
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
disable () {
|
|
14
|
-
super.disable()
|
|
15
|
-
|
|
16
|
-
this._resources.clear()
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
_createHook () {
|
|
20
|
-
return {
|
|
21
|
-
...super._createHook(),
|
|
22
|
-
destroy: this._destroy.bind(this)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
_init (asyncId, type, triggerAsyncId, resource) {
|
|
27
|
-
super._init.apply(this, arguments)
|
|
28
|
-
|
|
29
|
-
this._resources.set(asyncId, resource)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
_destroy (asyncId) {
|
|
33
|
-
this._resources.delete(asyncId)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
_executionAsyncResource () {
|
|
37
|
-
const asyncId = executionAsyncId()
|
|
38
|
-
|
|
39
|
-
let resource = this._resources.get(asyncId)
|
|
40
|
-
|
|
41
|
-
if (!resource) {
|
|
42
|
-
this._resources.set(asyncId, resource = {})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return resource
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
module.exports = AsyncHooksStorage
|