dd-trace 2.26.2 → 2.27.1
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/ci/init.js +2 -1
- package/index.d.ts +20 -0
- package/package.json +2 -2
- package/packages/datadog-instrumentations/src/aws-sdk.js +86 -0
- package/packages/datadog-instrumentations/src/cucumber.js +74 -15
- package/packages/datadog-instrumentations/src/cypress.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +24 -33
- package/packages/datadog-instrumentations/src/mocha.js +4 -7
- package/packages/datadog-instrumentations/src/playwright.js +2 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +12 -5
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +29 -24
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +31 -16
- package/packages/datadog-plugin-cucumber/src/index.js +42 -11
- package/packages/datadog-plugin-cypress/src/plugin.js +129 -4
- package/packages/datadog-plugin-cypress/src/support.js +5 -0
- package/packages/datadog-plugin-hapi/src/index.js +5 -1
- package/packages/datadog-plugin-jest/src/index.js +18 -67
- package/packages/datadog-plugin-mocha/src/index.js +35 -84
- package/packages/datadog-plugin-playwright/src/index.js +2 -61
- package/packages/datadog-shimmer/src/shimmer.js +28 -11
- package/packages/dd-trace/src/appsec/reporter.js +14 -14
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +1 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -5
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +32 -10
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +1 -1
- package/packages/dd-trace/src/config.js +55 -6
- package/packages/dd-trace/src/encode/0.4.js +1 -1
- package/packages/dd-trace/src/encode/0.5.js +1 -1
- package/packages/dd-trace/src/encode/tags-processors.js +3 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +188 -36
- package/packages/dd-trace/src/opentracing/propagation/tracestate.js +99 -0
- package/packages/dd-trace/src/opentracing/span.js +2 -1
- package/packages/dd-trace/src/opentracing/span_context.js +5 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +69 -12
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/telemetry/send-data.js +4 -1
|
@@ -8,17 +8,9 @@ const {
|
|
|
8
8
|
TEST_PARAMETERS,
|
|
9
9
|
finishAllTraceSpans,
|
|
10
10
|
getTestSuitePath,
|
|
11
|
-
getTestParentSpan,
|
|
12
11
|
getTestParametersString,
|
|
13
|
-
getTestSessionCommonTags,
|
|
14
|
-
getTestModuleCommonTags,
|
|
15
12
|
getTestSuiteCommonTags,
|
|
16
|
-
addIntelligentTestRunnerSpanTags
|
|
17
|
-
TEST_SUITE_ID,
|
|
18
|
-
TEST_SESSION_ID,
|
|
19
|
-
TEST_MODULE_ID,
|
|
20
|
-
TEST_BUNDLE,
|
|
21
|
-
TEST_COMMAND
|
|
13
|
+
addIntelligentTestRunnerSpanTags
|
|
22
14
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
23
15
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
24
16
|
|
|
@@ -49,36 +41,11 @@ class MochaPlugin extends CiPlugin {
|
|
|
49
41
|
})
|
|
50
42
|
})
|
|
51
43
|
|
|
52
|
-
this.addSub('ci:mocha:session:start', ({ command, frameworkVersion }) => {
|
|
53
|
-
const childOf = getTestParentSpan(this.tracer)
|
|
54
|
-
const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion)
|
|
55
|
-
|
|
56
|
-
this.command = command
|
|
57
|
-
this.testSessionSpan = this.tracer.startSpan('mocha.test_session', {
|
|
58
|
-
childOf,
|
|
59
|
-
tags: {
|
|
60
|
-
[COMPONENT]: this.constructor.name,
|
|
61
|
-
...this.testEnvironmentMetadata,
|
|
62
|
-
...testSessionSpanMetadata
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion)
|
|
67
|
-
this.testModuleSpan = this.tracer.startSpan('mocha.test_module', {
|
|
68
|
-
childOf: this.testSessionSpan,
|
|
69
|
-
tags: {
|
|
70
|
-
[COMPONENT]: this.constructor.name,
|
|
71
|
-
...this.testEnvironmentMetadata,
|
|
72
|
-
...testModuleSpanMetadata
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
})
|
|
76
|
-
|
|
77
44
|
this.addSub('ci:mocha:test-suite:start', (suite) => {
|
|
78
45
|
const store = storage.getStore()
|
|
79
46
|
const testSuiteMetadata = getTestSuiteCommonTags(
|
|
80
47
|
this.command,
|
|
81
|
-
this.
|
|
48
|
+
this.frameworkVersion,
|
|
82
49
|
getTestSuitePath(suite.file, this.sourceRoot)
|
|
83
50
|
)
|
|
84
51
|
const testSuiteSpan = this.tracer.startSpan('mocha.test_suite', {
|
|
@@ -94,18 +61,24 @@ class MochaPlugin extends CiPlugin {
|
|
|
94
61
|
})
|
|
95
62
|
|
|
96
63
|
this.addSub('ci:mocha:test-suite:finish', (status) => {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
64
|
+
const store = storage.getStore()
|
|
65
|
+
if (store && store.span) {
|
|
66
|
+
const span = storage.getStore().span
|
|
67
|
+
// the test status of the suite may have been set in ci:mocha:test-suite:error already
|
|
68
|
+
if (!span.context()._tags[TEST_STATUS]) {
|
|
69
|
+
span.setTag(TEST_STATUS, status)
|
|
70
|
+
}
|
|
71
|
+
span.finish()
|
|
101
72
|
}
|
|
102
|
-
span.finish()
|
|
103
73
|
})
|
|
104
74
|
|
|
105
75
|
this.addSub('ci:mocha:test-suite:error', (err) => {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
76
|
+
const store = storage.getStore()
|
|
77
|
+
if (store && store.span) {
|
|
78
|
+
const span = storage.getStore().span
|
|
79
|
+
span.setTag('error', err)
|
|
80
|
+
span.setTag(TEST_STATUS, 'fail')
|
|
81
|
+
}
|
|
109
82
|
})
|
|
110
83
|
|
|
111
84
|
this.addSub('ci:mocha:test:start', (test) => {
|
|
@@ -116,12 +89,16 @@ class MochaPlugin extends CiPlugin {
|
|
|
116
89
|
})
|
|
117
90
|
|
|
118
91
|
this.addSub('ci:mocha:test:finish', (status) => {
|
|
119
|
-
const
|
|
92
|
+
const store = storage.getStore()
|
|
120
93
|
|
|
121
|
-
|
|
94
|
+
if (store && store.span) {
|
|
95
|
+
const span = storage.getStore().span
|
|
96
|
+
|
|
97
|
+
span.setTag(TEST_STATUS, status)
|
|
122
98
|
|
|
123
|
-
|
|
124
|
-
|
|
99
|
+
span.finish()
|
|
100
|
+
finishAllTraceSpans(span)
|
|
101
|
+
}
|
|
125
102
|
})
|
|
126
103
|
|
|
127
104
|
this.addSub('ci:mocha:test:skip', (test) => {
|
|
@@ -135,8 +112,9 @@ class MochaPlugin extends CiPlugin {
|
|
|
135
112
|
})
|
|
136
113
|
|
|
137
114
|
this.addSub('ci:mocha:test:error', (err) => {
|
|
138
|
-
|
|
139
|
-
|
|
115
|
+
const store = storage.getStore()
|
|
116
|
+
if (err && store && store.span) {
|
|
117
|
+
const span = store.span
|
|
140
118
|
if (err.constructor.name === 'Pending' && !this.forbidPending) {
|
|
141
119
|
span.setTag(TEST_STATUS, 'skip')
|
|
142
120
|
} else {
|
|
@@ -172,46 +150,19 @@ class MochaPlugin extends CiPlugin {
|
|
|
172
150
|
}
|
|
173
151
|
|
|
174
152
|
startTestSpan (test) {
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
// the test event as the root span of its trace.
|
|
178
|
-
childOf._trace.startTime = this.testSessionSpan.context()._trace.startTime
|
|
179
|
-
childOf._trace.ticks = this.testSessionSpan.context()._trace.ticks
|
|
180
|
-
|
|
181
|
-
const testSuiteTags = {}
|
|
182
|
-
const testSuiteSpan = this._testSuites.get(test.parent.file)
|
|
183
|
-
if (testSuiteSpan) {
|
|
184
|
-
const testSuiteId = testSuiteSpan.context().toSpanId()
|
|
185
|
-
testSuiteTags[TEST_SUITE_ID] = testSuiteId
|
|
186
|
-
}
|
|
153
|
+
const testName = test.fullTitle()
|
|
154
|
+
const { file: testSuiteAbsolutePath, title } = test
|
|
187
155
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
testSuiteTags[TEST_SESSION_ID] = testSessionId
|
|
191
|
-
testSuiteTags[TEST_COMMAND] = this.command
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (this.testModuleSpan) {
|
|
195
|
-
const testModuleId = this.testModuleSpan.context().toSpanId()
|
|
196
|
-
testSuiteTags[TEST_MODULE_ID] = testModuleId
|
|
197
|
-
testSuiteTags[TEST_COMMAND] = this.command
|
|
198
|
-
testSuiteTags[TEST_BUNDLE] = this.command
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const { file: testSuiteAbsolutePath } = test
|
|
202
|
-
const fullTestName = test.fullTitle()
|
|
203
|
-
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.sourceRoot)
|
|
204
|
-
|
|
205
|
-
const extraTags = {
|
|
206
|
-
...testSuiteTags
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const testParametersString = getTestParametersString(this._testNameToParams, test.title)
|
|
156
|
+
const extraTags = {}
|
|
157
|
+
const testParametersString = getTestParametersString(this._testNameToParams, title)
|
|
210
158
|
if (testParametersString) {
|
|
211
159
|
extraTags[TEST_PARAMETERS] = testParametersString
|
|
212
160
|
}
|
|
213
161
|
|
|
214
|
-
|
|
162
|
+
const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.sourceRoot)
|
|
163
|
+
const testSuiteSpan = this._testSuites.get(testSuiteAbsolutePath)
|
|
164
|
+
|
|
165
|
+
return super.startTestSpan(testName, testSuite, testSuiteSpan, extraTags)
|
|
215
166
|
}
|
|
216
167
|
}
|
|
217
168
|
|
|
@@ -6,16 +6,8 @@ const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
|
6
6
|
const {
|
|
7
7
|
TEST_STATUS,
|
|
8
8
|
finishAllTraceSpans,
|
|
9
|
-
getTestParentSpan,
|
|
10
|
-
getTestSessionCommonTags,
|
|
11
9
|
getTestSuitePath,
|
|
12
|
-
|
|
13
|
-
TEST_COMMAND,
|
|
14
|
-
TEST_SUITE_ID,
|
|
15
|
-
getTestSuiteCommonTags,
|
|
16
|
-
getTestModuleCommonTags,
|
|
17
|
-
TEST_MODULE_ID,
|
|
18
|
-
TEST_BUNDLE
|
|
10
|
+
getTestSuiteCommonTags
|
|
19
11
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
20
12
|
const { RESOURCE_NAME } = require('../../../ext/tags')
|
|
21
13
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
@@ -30,32 +22,6 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
30
22
|
|
|
31
23
|
this._testSuites = new Map()
|
|
32
24
|
|
|
33
|
-
this.addSub('ci:playwright:session:start', ({ command, frameworkVersion, rootDir }) => {
|
|
34
|
-
const childOf = getTestParentSpan(this.tracer)
|
|
35
|
-
this.command = command
|
|
36
|
-
this.frameworkVersion = frameworkVersion
|
|
37
|
-
this.rootDir = rootDir
|
|
38
|
-
|
|
39
|
-
const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion)
|
|
40
|
-
this.testSessionSpan = this.tracer.startSpan('playwright.test_session', {
|
|
41
|
-
childOf,
|
|
42
|
-
tags: {
|
|
43
|
-
[COMPONENT]: this.constructor.name,
|
|
44
|
-
...this.testEnvironmentMetadata,
|
|
45
|
-
...testSessionSpanMetadata
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion)
|
|
49
|
-
this.testModuleSpan = this.tracer.startSpan('playwright.test_module', {
|
|
50
|
-
childOf: this.testSessionSpan,
|
|
51
|
-
tags: {
|
|
52
|
-
[COMPONENT]: this.constructor.name,
|
|
53
|
-
...this.testEnvironmentMetadata,
|
|
54
|
-
...testModuleSpanMetadata
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
|
|
59
25
|
this.addSub('ci:playwright:session:finish', ({ status, onDone }) => {
|
|
60
26
|
this.testModuleSpan.setTag(TEST_STATUS, status)
|
|
61
27
|
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
@@ -138,33 +104,8 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
138
104
|
}
|
|
139
105
|
|
|
140
106
|
startTestSpan (testName, testSuite) {
|
|
141
|
-
const childOf = getTestParentSpan(this.tracer)
|
|
142
|
-
// This is a hack to get good time resolution on test events, while keeping
|
|
143
|
-
// the test event as the root span of its trace.
|
|
144
|
-
childOf._trace.startTime = this.testSessionSpan.context()._trace.startTime
|
|
145
|
-
childOf._trace.ticks = this.testSessionSpan.context()._trace.ticks
|
|
146
|
-
|
|
147
|
-
const testSuiteTags = {}
|
|
148
107
|
const testSuiteSpan = this._testSuites.get(testSuite)
|
|
149
|
-
|
|
150
|
-
const testSuiteId = testSuiteSpan.context().toSpanId()
|
|
151
|
-
testSuiteTags[TEST_SUITE_ID] = testSuiteId
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (this.testSessionSpan) {
|
|
155
|
-
const testSessionId = this.testSessionSpan.context().toTraceId()
|
|
156
|
-
testSuiteTags[TEST_SESSION_ID] = testSessionId
|
|
157
|
-
testSuiteTags[TEST_COMMAND] = this.command
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (this.testModuleSpan) {
|
|
161
|
-
const testModuleId = this.testModuleSpan.context().toSpanId()
|
|
162
|
-
testSuiteTags[TEST_MODULE_ID] = testModuleId
|
|
163
|
-
testSuiteTags[TEST_COMMAND] = this.command
|
|
164
|
-
testSuiteTags[TEST_BUNDLE] = this.command
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return super.startTestSpan(testName, testSuite, testSuiteTags, childOf)
|
|
108
|
+
return super.startTestSpan(testName, testSuite, testSuiteSpan)
|
|
168
109
|
}
|
|
169
110
|
}
|
|
170
111
|
|
|
@@ -10,7 +10,11 @@ function copyProperties (original, wrapped) {
|
|
|
10
10
|
const keys = Reflect.ownKeys(props)
|
|
11
11
|
|
|
12
12
|
for (const key of keys) {
|
|
13
|
-
|
|
13
|
+
try {
|
|
14
|
+
Object.defineProperty(wrapped, key, props[key])
|
|
15
|
+
} catch (e) {
|
|
16
|
+
// TODO: figure out how to handle this without a try/catch
|
|
17
|
+
}
|
|
14
18
|
}
|
|
15
19
|
}
|
|
16
20
|
|
|
@@ -33,28 +37,41 @@ function wrapFn (original, delegate) {
|
|
|
33
37
|
|
|
34
38
|
function wrapMethod (target, name, wrapper) {
|
|
35
39
|
assertMethod(target, name)
|
|
36
|
-
assertNotClass(target[name]) // TODO: support constructors of native classes
|
|
37
40
|
assertFunction(wrapper)
|
|
38
41
|
|
|
39
42
|
const original = target[name]
|
|
40
43
|
const wrapped = wrapper(original)
|
|
41
44
|
const descriptor = Object.getOwnPropertyDescriptor(target, name)
|
|
42
45
|
|
|
46
|
+
const attributes = {
|
|
47
|
+
configurable: true,
|
|
48
|
+
...descriptor
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
copyProperties(original, wrapped)
|
|
52
|
+
|
|
43
53
|
if (descriptor) {
|
|
44
54
|
unwrappers.set(wrapped, () => Object.defineProperty(target, name, descriptor))
|
|
55
|
+
|
|
56
|
+
if (descriptor.get || descriptor.set) {
|
|
57
|
+
attributes.get = () => wrapped
|
|
58
|
+
} else {
|
|
59
|
+
attributes.value = wrapped
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// TODO: create a single object for multiple wrapped methods
|
|
63
|
+
if (descriptor.configurable === false) {
|
|
64
|
+
return Object.create(target, {
|
|
65
|
+
[name]: attributes
|
|
66
|
+
})
|
|
67
|
+
}
|
|
45
68
|
} else { // no descriptor means original was on the prototype
|
|
46
69
|
unwrappers.set(wrapped, () => delete target[name])
|
|
70
|
+
attributes.value = wrapped
|
|
71
|
+
attributes.writable = true
|
|
47
72
|
}
|
|
48
73
|
|
|
49
|
-
Object.defineProperty(target, name,
|
|
50
|
-
configurable: true,
|
|
51
|
-
writable: true,
|
|
52
|
-
enumerable: false,
|
|
53
|
-
...descriptor,
|
|
54
|
-
value: wrapped
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
copyProperties(original, wrapped)
|
|
74
|
+
Object.defineProperty(target, name, attributes)
|
|
58
75
|
|
|
59
76
|
return target
|
|
60
77
|
}
|
|
@@ -86,28 +86,28 @@ function formatHeaderName (name) {
|
|
|
86
86
|
|
|
87
87
|
function reportMetrics (metrics, store) {
|
|
88
88
|
const req = store && store.get('req')
|
|
89
|
-
const
|
|
90
|
-
if (!
|
|
89
|
+
const rootSpan = web.root(req)
|
|
90
|
+
if (!rootSpan) return false
|
|
91
91
|
|
|
92
92
|
if (metrics.duration) {
|
|
93
|
-
|
|
93
|
+
rootSpan.setTag('_dd.appsec.waf.duration', metrics.duration)
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
if (metrics.durationExt) {
|
|
97
|
-
|
|
97
|
+
rootSpan.setTag('_dd.appsec.waf.duration_ext', metrics.durationExt)
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
if (metrics.rulesVersion) {
|
|
101
|
-
|
|
101
|
+
rootSpan.setTag('_dd.appsec.event_rules.version', metrics.rulesVersion)
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
function reportAttack (attackData, store) {
|
|
106
106
|
const req = store && store.get('req')
|
|
107
|
-
const
|
|
108
|
-
if (!
|
|
107
|
+
const rootSpan = web.root(req)
|
|
108
|
+
if (!rootSpan) return false
|
|
109
109
|
|
|
110
|
-
const currentTags =
|
|
110
|
+
const currentTags = rootSpan.context()._tags
|
|
111
111
|
|
|
112
112
|
const newTags = {
|
|
113
113
|
'appsec.event': 'true'
|
|
@@ -146,20 +146,20 @@ function reportAttack (attackData, store) {
|
|
|
146
146
|
newTags['network.client.ip'] = resolvedRequest.remote_ip
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
rootSpan.addTags(newTags)
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
function finishRequest (req, context) {
|
|
153
|
-
const
|
|
154
|
-
if (!
|
|
153
|
+
const rootSpan = web.root(req)
|
|
154
|
+
if (!rootSpan) return false
|
|
155
155
|
|
|
156
156
|
if (metricsQueue.size) {
|
|
157
|
-
|
|
157
|
+
rootSpan.addTags(Object.fromEntries(metricsQueue))
|
|
158
158
|
|
|
159
159
|
metricsQueue.clear()
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
if (!context || !
|
|
162
|
+
if (!context || !rootSpan.context()._tags['appsec.event']) return false
|
|
163
163
|
|
|
164
164
|
const resolvedResponse = resolveHTTPResponse(context)
|
|
165
165
|
|
|
@@ -169,7 +169,7 @@ function finishRequest (req, context) {
|
|
|
169
169
|
newTags['http.endpoint'] = resolvedResponse.endpoint
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
rootSpan.addTags(newTags)
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
function setRateLimit (rateLimit) {
|
|
@@ -20,8 +20,7 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
20
20
|
prioritySampler,
|
|
21
21
|
lookup,
|
|
22
22
|
protocolVersion,
|
|
23
|
-
headers
|
|
24
|
-
isGitUploadEnabled
|
|
23
|
+
headers
|
|
25
24
|
} = config
|
|
26
25
|
|
|
27
26
|
this.getAgentInfo((err, agentInfo) => {
|
|
@@ -38,9 +37,6 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
38
37
|
url: this._url,
|
|
39
38
|
evpProxyPrefix: AGENT_EVP_PROXY_PATH
|
|
40
39
|
})
|
|
41
|
-
if (isGitUploadEnabled) {
|
|
42
|
-
this.sendGitMetadata({ url: this._url, isEvpProxy: true })
|
|
43
|
-
}
|
|
44
40
|
} else {
|
|
45
41
|
this._writer = new AgentWriter({
|
|
46
42
|
url: this._url,
|
|
@@ -9,7 +9,7 @@ const log = require('../../../log')
|
|
|
9
9
|
class AgentlessCiVisibilityExporter extends CiVisibilityExporter {
|
|
10
10
|
constructor (config) {
|
|
11
11
|
super(config)
|
|
12
|
-
const { tags, site, url
|
|
12
|
+
const { tags, site, url } = config
|
|
13
13
|
// we don't need to request /info because we are using agentless by configuration
|
|
14
14
|
this._isInitialized = true
|
|
15
15
|
this._resolveCanUseCiVisProtocol(true)
|
|
@@ -21,10 +21,6 @@ class AgentlessCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
21
21
|
this._coverageWriter = new CoverageWriter({ url: this._coverageUrl })
|
|
22
22
|
|
|
23
23
|
this._apiUrl = url || new URL(`https://api.${site}`)
|
|
24
|
-
|
|
25
|
-
if (isGitUploadEnabled) {
|
|
26
|
-
this.sendGitMetadata({ url: this._getApiUrl() })
|
|
27
|
-
}
|
|
28
24
|
}
|
|
29
25
|
|
|
30
26
|
setUrl (url, coverageUrl = url, apiUrl = url) {
|
|
@@ -14,6 +14,9 @@ function getIsTestSessionTrace (trace) {
|
|
|
14
14
|
)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
const GIT_UPLOAD_TIMEOUT = 60000 // 60 seconds
|
|
18
|
+
const CAN_USE_CI_VIS_PROTOCOL_TIMEOUT = GIT_UPLOAD_TIMEOUT
|
|
19
|
+
|
|
17
20
|
class CiVisibilityExporter extends AgentInfoExporter {
|
|
18
21
|
constructor (config) {
|
|
19
22
|
super(config)
|
|
@@ -24,14 +27,24 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
24
27
|
// AKA CI Vis Protocol
|
|
25
28
|
this._canUseCiVisProtocol = false
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
const gitUploadTimeoutId = setTimeout(() => {
|
|
31
|
+
this._resolveGit(new Error('Timeout while uploading git metadata'))
|
|
32
|
+
}, GIT_UPLOAD_TIMEOUT).unref()
|
|
33
|
+
|
|
34
|
+
const canUseCiVisProtocolTimeoutId = setTimeout(() => {
|
|
35
|
+
this._resolveCanUseCiVisProtocol(false)
|
|
36
|
+
}, CAN_USE_CI_VIS_PROTOCOL_TIMEOUT).unref()
|
|
37
|
+
|
|
28
38
|
this._gitUploadPromise = new Promise(resolve => {
|
|
29
|
-
this._resolveGit =
|
|
39
|
+
this._resolveGit = (err) => {
|
|
40
|
+
clearTimeout(gitUploadTimeoutId)
|
|
41
|
+
resolve(err)
|
|
42
|
+
}
|
|
30
43
|
})
|
|
31
44
|
|
|
32
|
-
// TODO: add timeout to reject this promise
|
|
33
45
|
this._canUseCiVisProtocolPromise = new Promise(resolve => {
|
|
34
46
|
this._resolveCanUseCiVisProtocol = (canUseCiVisProtocol) => {
|
|
47
|
+
clearTimeout(canUseCiVisProtocolTimeoutId)
|
|
35
48
|
this._canUseCiVisProtocol = canUseCiVisProtocol
|
|
36
49
|
resolve(canUseCiVisProtocol)
|
|
37
50
|
}
|
|
@@ -93,6 +106,7 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
93
106
|
* CI Visibility Protocol, hence the this._canUseCiVisProtocol promise.
|
|
94
107
|
*/
|
|
95
108
|
getItrConfiguration (testConfiguration, callback) {
|
|
109
|
+
this.sendGitMetadata()
|
|
96
110
|
if (!this.shouldRequestItrConfiguration()) {
|
|
97
111
|
return callback(null, {})
|
|
98
112
|
}
|
|
@@ -118,14 +132,22 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
118
132
|
})
|
|
119
133
|
}
|
|
120
134
|
|
|
121
|
-
sendGitMetadata (
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
135
|
+
sendGitMetadata () {
|
|
136
|
+
if (!this._config.isGitUploadEnabled) {
|
|
137
|
+
return
|
|
138
|
+
}
|
|
139
|
+
this._canUseCiVisProtocolPromise.then((canUseCiVisProtocol) => {
|
|
140
|
+
if (!canUseCiVisProtocol) {
|
|
141
|
+
return
|
|
127
142
|
}
|
|
128
|
-
this.
|
|
143
|
+
sendGitMetadataRequest(this._getApiUrl(), !!this._isUsingEvpProxy, (err) => {
|
|
144
|
+
if (err) {
|
|
145
|
+
log.error(`Error uploading git metadata: ${err.message}`)
|
|
146
|
+
} else {
|
|
147
|
+
log.debug('Successfully uploaded git metadata')
|
|
148
|
+
}
|
|
149
|
+
this._resolveGit(err)
|
|
150
|
+
})
|
|
129
151
|
})
|
|
130
152
|
}
|
|
131
153
|
|
|
@@ -51,6 +51,32 @@ function remapify (input, mappings) {
|
|
|
51
51
|
return output
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
function propagationStyle (key, option, defaultValue) {
|
|
55
|
+
// Extract by key if in object-form value
|
|
56
|
+
if (typeof option === 'object' && !Array.isArray(option)) {
|
|
57
|
+
option = option[key]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Should be an array at this point
|
|
61
|
+
if (Array.isArray(option)) return option.map(v => v.toLowerCase())
|
|
62
|
+
|
|
63
|
+
// If it's not an array but not undefined there's something wrong with the input
|
|
64
|
+
if (typeof option !== 'undefined') {
|
|
65
|
+
log.warn('Unexpected input for config.tracePropagationStyle')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Otherwise, fallback to env var parsing
|
|
69
|
+
const envKey = `DD_TRACE_PROPAGATION_STYLE_${key.toUpperCase()}`
|
|
70
|
+
const envVar = coalesce(process.env[envKey], process.env.DD_TRACE_PROPAGATION_STYLE)
|
|
71
|
+
if (typeof envVar !== 'undefined') {
|
|
72
|
+
return envVar.split(',')
|
|
73
|
+
.filter(v => v !== '')
|
|
74
|
+
.map(v => v.trim().toLowerCase())
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return defaultValue
|
|
78
|
+
}
|
|
79
|
+
|
|
54
80
|
class Config {
|
|
55
81
|
constructor (options) {
|
|
56
82
|
options = options || {}
|
|
@@ -192,15 +218,36 @@ class Config {
|
|
|
192
218
|
process.env.DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP,
|
|
193
219
|
'.*'
|
|
194
220
|
)
|
|
221
|
+
// TODO: Remove the experimental env vars as a major?
|
|
195
222
|
const DD_TRACE_B3_ENABLED = coalesce(
|
|
196
223
|
options.experimental && options.experimental.b3,
|
|
197
224
|
process.env.DD_TRACE_EXPERIMENTAL_B3_ENABLED,
|
|
198
225
|
false
|
|
199
226
|
)
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
227
|
+
const defaultPropagationStyle = ['tracecontext', 'datadog']
|
|
228
|
+
if (isTrue(DD_TRACE_B3_ENABLED)) {
|
|
229
|
+
defaultPropagationStyle.push('b3')
|
|
230
|
+
defaultPropagationStyle.push('b3 single header')
|
|
231
|
+
}
|
|
232
|
+
if (process.env.DD_TRACE_PROPAGATION_STYLE && (
|
|
233
|
+
process.env.DD_TRACE_PROPAGATION_STYLE_INJECT ||
|
|
234
|
+
process.env.DD_TRACE_PROPAGATION_STYLE_EXTRACT
|
|
235
|
+
)) {
|
|
236
|
+
log.warn(
|
|
237
|
+
'Use either the DD_TRACE_PROPAGATION_STYLE environment variable or separate ' +
|
|
238
|
+
'DD_TRACE_PROPAGATION_STYLE_INJECT and DD_TRACE_PROPAGATION_STYLE_EXTRACT ' +
|
|
239
|
+
'environment variables'
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
const DD_TRACE_PROPAGATION_STYLE_INJECT = propagationStyle(
|
|
243
|
+
'inject',
|
|
244
|
+
options.tracePropagationStyle,
|
|
245
|
+
defaultPropagationStyle
|
|
246
|
+
)
|
|
247
|
+
const DD_TRACE_PROPAGATION_STYLE_EXTRACT = propagationStyle(
|
|
248
|
+
'extract',
|
|
249
|
+
options.tracePropagationStyle,
|
|
250
|
+
defaultPropagationStyle
|
|
204
251
|
)
|
|
205
252
|
const DD_TRACE_RUNTIME_ID_ENABLED = coalesce(
|
|
206
253
|
options.experimental && options.experimental.runtimeId,
|
|
@@ -386,9 +433,11 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
386
433
|
port: String(coalesce(dogstatsd.port, process.env.DD_DOGSTATSD_PORT, 8125))
|
|
387
434
|
}
|
|
388
435
|
this.runtimeMetrics = isTrue(DD_RUNTIME_METRICS_ENABLED)
|
|
436
|
+
this.tracePropagationStyle = {
|
|
437
|
+
inject: DD_TRACE_PROPAGATION_STYLE_INJECT,
|
|
438
|
+
extract: DD_TRACE_PROPAGATION_STYLE_EXTRACT
|
|
439
|
+
}
|
|
389
440
|
this.experimental = {
|
|
390
|
-
b3: isTrue(DD_TRACE_B3_ENABLED),
|
|
391
|
-
traceparent: isTrue(DD_TRACE_TRACEPARENT_ENABLED),
|
|
392
441
|
runtimeId: isTrue(DD_TRACE_RUNTIME_ID_ENABLED),
|
|
393
442
|
exporter: DD_TRACE_EXPORTER,
|
|
394
443
|
enableGetRumData: isTrue(DD_TRACE_GET_RUM_DATA_ENABLED)
|
|
@@ -38,11 +38,12 @@ function truncateToLength (value, maxLength) {
|
|
|
38
38
|
return value
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
// normally the agent truncates the resource and parses it in certain scenarios (e.g. SQL Queries)
|
|
42
|
+
function truncateSpan (span, shouldTruncateResourceName = true) {
|
|
42
43
|
return fromEntries(Object.entries(span).map(([key, value]) => {
|
|
43
44
|
switch (key) {
|
|
44
45
|
case 'resource':
|
|
45
|
-
return ['resource', truncateToLength(value, MAX_RESOURCE_NAME_LENGTH)]
|
|
46
|
+
return ['resource', shouldTruncateResourceName ? truncateToLength(value, MAX_RESOURCE_NAME_LENGTH) : value]
|
|
46
47
|
case 'meta':
|
|
47
48
|
return ['meta', fromEntries(Object.entries(value).map(([metaKey, metaValue]) =>
|
|
48
49
|
[truncateToLength(metaKey, MAX_META_KEY_LENGTH), truncateToLength(metaValue, MAX_META_VALUE_LENGTH)]
|