dd-trace 4.21.0 → 4.23.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/index.d.ts +5 -0
- package/package.json +6 -6
- package/packages/datadog-instrumentations/src/apollo-server-core.js +41 -0
- package/packages/datadog-instrumentations/src/apollo-server.js +83 -0
- package/packages/datadog-instrumentations/src/child-process.js +4 -5
- package/packages/datadog-instrumentations/src/couchbase.js +5 -4
- package/packages/datadog-instrumentations/src/crypto.js +2 -1
- package/packages/datadog-instrumentations/src/dns.js +2 -1
- package/packages/datadog-instrumentations/src/graphql.js +18 -4
- package/packages/datadog-instrumentations/src/helpers/hooks.js +9 -2
- package/packages/datadog-instrumentations/src/helpers/instrument.js +8 -3
- package/packages/datadog-instrumentations/src/helpers/register.js +18 -2
- package/packages/datadog-instrumentations/src/http/client.js +4 -16
- package/packages/datadog-instrumentations/src/http/server.js +7 -4
- package/packages/datadog-instrumentations/src/http2/client.js +3 -1
- package/packages/datadog-instrumentations/src/http2/server.js +3 -1
- package/packages/datadog-instrumentations/src/jest.js +1 -1
- package/packages/datadog-instrumentations/src/net.js +10 -2
- package/packages/datadog-instrumentations/src/next.js +15 -5
- package/packages/datadog-instrumentations/src/rhea.js +15 -9
- package/packages/datadog-plugin-cucumber/src/index.js +34 -2
- package/packages/datadog-plugin-cypress/src/plugin.js +60 -8
- package/packages/datadog-plugin-graphql/src/resolve.js +26 -18
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +38 -4
- package/packages/datadog-plugin-mocha/src/index.js +32 -1
- package/packages/datadog-plugin-next/src/index.js +32 -6
- package/packages/datadog-plugin-playwright/src/index.js +17 -1
- package/packages/dd-trace/src/appsec/activation.js +29 -0
- package/packages/dd-trace/src/appsec/addresses.js +1 -0
- package/packages/dd-trace/src/appsec/api_security_sampler.js +48 -0
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -1
- package/packages/dd-trace/src/appsec/blocking.js +95 -43
- package/packages/dd-trace/src/appsec/channels.js +4 -1
- package/packages/dd-trace/src/appsec/graphql.js +146 -0
- package/packages/dd-trace/src/appsec/index.js +29 -40
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +6 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +40 -15
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +25 -13
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +30 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +30 -1
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +36 -4
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +18 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +26 -1
- package/packages/dd-trace/src/ci-visibility/telemetry.js +130 -0
- package/packages/dd-trace/src/config.js +104 -58
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +14 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +14 -0
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +4 -0
- package/packages/dd-trace/src/exporters/common/form-data.js +4 -0
- package/packages/dd-trace/src/opentracing/tracer.js +2 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +44 -8
- package/packages/dd-trace/src/plugins/index.js +5 -0
- package/packages/dd-trace/src/plugins/util/exec.js +23 -2
- package/packages/dd-trace/src/plugins/util/git.js +94 -19
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +3 -2
- package/packages/dd-trace/src/priority_sampler.js +30 -38
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -0
- package/packages/dd-trace/src/profiling/profiler.js +7 -6
- package/packages/dd-trace/src/profiling/profilers/events.js +18 -13
- package/packages/dd-trace/src/profiling/profilers/shared.js +34 -4
- package/packages/dd-trace/src/profiling/profilers/space.js +2 -1
- package/packages/dd-trace/src/profiling/profilers/wall.js +17 -12
- package/packages/dd-trace/src/proxy.js +4 -0
- package/packages/dd-trace/src/sampling_rule.js +130 -0
- package/packages/dd-trace/src/span_sampler.js +6 -64
- package/packages/dd-trace/src/telemetry/index.js +43 -5
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { globMatch } = require('../src/util')
|
|
4
|
+
const RateLimiter = require('./rate_limiter')
|
|
5
|
+
const Sampler = require('./sampler')
|
|
6
|
+
|
|
7
|
+
class AlwaysMatcher {
|
|
8
|
+
match () {
|
|
9
|
+
return true
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class GlobMatcher {
|
|
14
|
+
constructor (pattern, locator) {
|
|
15
|
+
this.pattern = pattern
|
|
16
|
+
this.locator = locator
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
match (span) {
|
|
20
|
+
const subject = this.locator(span)
|
|
21
|
+
if (!subject) return false
|
|
22
|
+
return globMatch(this.pattern, subject)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class RegExpMatcher {
|
|
27
|
+
constructor (pattern, locator) {
|
|
28
|
+
this.pattern = pattern
|
|
29
|
+
this.locator = locator
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
match (span) {
|
|
33
|
+
const subject = this.locator(span)
|
|
34
|
+
if (!subject) return false
|
|
35
|
+
return this.pattern.test(subject)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function matcher (pattern, locator) {
|
|
40
|
+
if (pattern instanceof RegExp) {
|
|
41
|
+
return new RegExpMatcher(pattern, locator)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (typeof pattern === 'string' && pattern !== '*') {
|
|
45
|
+
return new GlobMatcher(pattern, locator)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return new AlwaysMatcher()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function makeTagLocator (tag) {
|
|
52
|
+
return (span) => span.context()._tags[tag]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function nameLocator (span) {
|
|
56
|
+
return span.context()._name
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function serviceLocator (span) {
|
|
60
|
+
const { _tags: tags } = span.context()
|
|
61
|
+
return tags.service ||
|
|
62
|
+
tags['service.name'] ||
|
|
63
|
+
span.tracer()._service
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
class SamplingRule {
|
|
67
|
+
constructor ({ name, service, resource, tags, sampleRate = 1.0, maxPerSecond } = {}) {
|
|
68
|
+
this.matchers = []
|
|
69
|
+
|
|
70
|
+
if (name) {
|
|
71
|
+
this.matchers.push(matcher(name, nameLocator))
|
|
72
|
+
}
|
|
73
|
+
if (service) {
|
|
74
|
+
this.matchers.push(matcher(service, serviceLocator))
|
|
75
|
+
}
|
|
76
|
+
if (resource) {
|
|
77
|
+
this.matchers.push(matcher(resource, makeTagLocator('resource.name')))
|
|
78
|
+
}
|
|
79
|
+
for (const [key, value] of Object.entries(tags || {})) {
|
|
80
|
+
this.matchers.push(matcher(value, makeTagLocator(key)))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this._sampler = new Sampler(sampleRate)
|
|
84
|
+
this._limiter = undefined
|
|
85
|
+
|
|
86
|
+
if (Number.isFinite(maxPerSecond)) {
|
|
87
|
+
this._limiter = new RateLimiter(maxPerSecond)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static from (config) {
|
|
92
|
+
return new SamplingRule(config)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get sampleRate () {
|
|
96
|
+
return this._sampler.rate()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get effectiveRate () {
|
|
100
|
+
return this._limiter && this._limiter.effectiveRate()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
get maxPerSecond () {
|
|
104
|
+
return this._limiter && this._limiter._rateLimit
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
match (span) {
|
|
108
|
+
for (const matcher of this.matchers) {
|
|
109
|
+
if (!matcher.match(span)) {
|
|
110
|
+
return false
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return true
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
sample () {
|
|
118
|
+
if (!this._sampler.isSampled()) {
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (this._limiter) {
|
|
123
|
+
return this._limiter.isAllowed()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return true
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
module.exports = SamplingRule
|
|
@@ -1,67 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
const { globMatch } = require('../src/util')
|
|
3
|
-
const { USER_KEEP, AUTO_KEEP } = require('../../../ext').priority
|
|
4
|
-
const RateLimiter = require('./rate_limiter')
|
|
5
|
-
const Sampler = require('./sampler')
|
|
6
|
-
|
|
7
|
-
class SpanSamplingRule {
|
|
8
|
-
constructor ({ service, name, sampleRate = 1.0, maxPerSecond } = {}) {
|
|
9
|
-
this.service = service
|
|
10
|
-
this.name = name
|
|
11
|
-
|
|
12
|
-
this._sampler = new Sampler(sampleRate)
|
|
13
|
-
this._limiter = undefined
|
|
14
|
-
|
|
15
|
-
if (Number.isFinite(maxPerSecond)) {
|
|
16
|
-
this._limiter = new RateLimiter(maxPerSecond)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get sampleRate () {
|
|
21
|
-
return this._sampler.rate()
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get maxPerSecond () {
|
|
25
|
-
return this._limiter && this._limiter._rateLimit
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static from (config) {
|
|
29
|
-
return new SpanSamplingRule(config)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
match (service, name) {
|
|
33
|
-
if (this.service && !globMatch(this.service, service)) {
|
|
34
|
-
return false
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (this.name && !globMatch(this.name, name)) {
|
|
38
|
-
return false
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return true
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
sample () {
|
|
45
|
-
if (!this._sampler.isSampled()) {
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
2
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return true
|
|
54
|
-
}
|
|
55
|
-
}
|
|
3
|
+
const { USER_KEEP, AUTO_KEEP } = require('../../../ext').priority
|
|
4
|
+
const SamplingRule = require('./sampling_rule')
|
|
56
5
|
|
|
57
6
|
class SpanSampler {
|
|
58
7
|
constructor ({ spanSamplingRules = [] } = {}) {
|
|
59
|
-
this._rules = spanSamplingRules.map(
|
|
8
|
+
this._rules = spanSamplingRules.map(SamplingRule.from)
|
|
60
9
|
}
|
|
61
10
|
|
|
62
|
-
findRule (
|
|
11
|
+
findRule (context) {
|
|
63
12
|
for (const rule of this._rules) {
|
|
64
|
-
if (rule.match(
|
|
13
|
+
if (rule.match(context)) {
|
|
65
14
|
return rule
|
|
66
15
|
}
|
|
67
16
|
}
|
|
@@ -73,14 +22,7 @@ class SpanSampler {
|
|
|
73
22
|
|
|
74
23
|
const { started } = spanContext._trace
|
|
75
24
|
for (const span of started) {
|
|
76
|
-
const
|
|
77
|
-
const tags = context._tags || {}
|
|
78
|
-
const name = context._name
|
|
79
|
-
const service = tags.service ||
|
|
80
|
-
tags['service.name'] ||
|
|
81
|
-
span.tracer()._service
|
|
82
|
-
|
|
83
|
-
const rule = this.findRule(service, name)
|
|
25
|
+
const rule = this.findRule(span)
|
|
84
26
|
if (rule && rule.sample()) {
|
|
85
27
|
span.context()._spanSampling = {
|
|
86
28
|
sampleRate: rule.sampleRate,
|
|
@@ -112,11 +112,26 @@ function flatten (input, result = [], prefix = [], traversedObjects = null) {
|
|
|
112
112
|
return result
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
function getInstallSignature (config) {
|
|
116
|
+
const { installSignature: sig } = config
|
|
117
|
+
if (sig && (sig.id || sig.time || sig.type)) {
|
|
118
|
+
return {
|
|
119
|
+
install_id: sig.id,
|
|
120
|
+
install_time: sig.time,
|
|
121
|
+
install_type: sig.type
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
115
126
|
function appStarted (config) {
|
|
116
127
|
const app = {
|
|
117
128
|
products: getProducts(config),
|
|
118
129
|
configuration: flatten(config)
|
|
119
130
|
}
|
|
131
|
+
const installSignature = getInstallSignature(config)
|
|
132
|
+
if (installSignature) {
|
|
133
|
+
app.install_signature = installSignature
|
|
134
|
+
}
|
|
120
135
|
// TODO: add app.error with correct error codes
|
|
121
136
|
// if (errors.agentError) {
|
|
122
137
|
// app.error = errors.agentError
|
|
@@ -129,6 +144,10 @@ function onBeforeExit () {
|
|
|
129
144
|
process.removeListener('beforeExit', onBeforeExit)
|
|
130
145
|
const { reqType, payload } = createPayload('app-closing')
|
|
131
146
|
sendData(config, application, host, reqType, payload)
|
|
147
|
+
// we flush before shutting down. Only in CI Visibility
|
|
148
|
+
if (config.isCiVisibility) {
|
|
149
|
+
metricsManager.send(config, application, host)
|
|
150
|
+
}
|
|
132
151
|
}
|
|
133
152
|
|
|
134
153
|
function createAppObject (config) {
|
|
@@ -286,11 +305,30 @@ function updateConfig (changes, config) {
|
|
|
286
305
|
const application = createAppObject(config)
|
|
287
306
|
const host = createHostObject()
|
|
288
307
|
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
308
|
+
const names = {
|
|
309
|
+
sampleRate: 'DD_TRACE_SAMPLE_RATE',
|
|
310
|
+
logInjection: 'DD_LOG_INJECTION',
|
|
311
|
+
headerTags: 'DD_TRACE_HEADER_TAGS',
|
|
312
|
+
tags: 'DD_TAGS'
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const configuration = []
|
|
316
|
+
|
|
317
|
+
for (const change of changes) {
|
|
318
|
+
if (!names.hasOwnProperty(change.name)) continue
|
|
319
|
+
|
|
320
|
+
const name = names[change.name]
|
|
321
|
+
const { origin, value } = change
|
|
322
|
+
const entry = { name, origin, value }
|
|
323
|
+
|
|
324
|
+
if (Array.isArray(value)) {
|
|
325
|
+
entry.value = value.join(',')
|
|
326
|
+
} else if (name === 'DD_TAGS') {
|
|
327
|
+
entry.value = Object.entries(value).map(([key, value]) => `${key}:${value}`)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
configuration.push(entry)
|
|
331
|
+
}
|
|
294
332
|
|
|
295
333
|
const { reqType, payload } = createPayload('app-client-configuration-change', { configuration })
|
|
296
334
|
|