dd-trace 5.3.0 → 5.5.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/CONTRIBUTING.md +98 -0
- package/README.md +4 -102
- package/ci/cypress/after-run.js +1 -0
- package/package.json +2 -2
- package/packages/datadog-instrumentations/src/cucumber.js +156 -42
- package/packages/datadog-instrumentations/src/jest.js +84 -49
- package/packages/datadog-instrumentations/src/mocha.js +139 -13
- package/packages/datadog-plugin-amqplib/src/consumer.js +5 -2
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +60 -50
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +40 -17
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +62 -26
- package/packages/datadog-plugin-cucumber/src/index.js +25 -9
- package/packages/datadog-plugin-cypress/src/after-run.js +3 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +560 -0
- package/packages/datadog-plugin-cypress/src/plugin.js +6 -533
- package/packages/datadog-plugin-jest/src/index.js +4 -8
- package/packages/datadog-plugin-kafkajs/src/consumer.js +16 -0
- package/packages/datadog-plugin-mocha/src/index.js +38 -17
- package/packages/datadog-plugin-rhea/src/consumer.js +4 -1
- package/packages/dd-trace/src/appsec/iast/context/context-plugin.js +90 -0
- package/packages/dd-trace/src/appsec/iast/context/kafka-ctx-plugin.js +14 -0
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +8 -0
- package/packages/dd-trace/src/appsec/iast/index.js +4 -4
- package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +1 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +10 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +53 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +10 -46
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +13 -9
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +47 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +3 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +29 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +1 -0
- package/packages/dd-trace/src/config.js +3 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -1
- package/packages/dd-trace/src/opentracing/span.js +4 -4
- package/packages/dd-trace/src/plugins/ci_plugin.js +1 -1
- package/packages/dd-trace/src/plugins/util/test.js +17 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +40 -31
- package/packages/dd-trace/src/telemetry/index.js +3 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +2 -2
- package/packages/dd-trace/src/telemetry/send-data.js +0 -3
|
@@ -1,155 +1,5 @@
|
|
|
1
|
-
const {
|
|
2
|
-
TEST_STATUS,
|
|
3
|
-
TEST_IS_RUM_ACTIVE,
|
|
4
|
-
TEST_CODE_OWNERS,
|
|
5
|
-
getTestEnvironmentMetadata,
|
|
6
|
-
CI_APP_ORIGIN,
|
|
7
|
-
getTestParentSpan,
|
|
8
|
-
getCodeOwnersFileEntries,
|
|
9
|
-
getCodeOwnersForFilename,
|
|
10
|
-
getTestCommonTags,
|
|
11
|
-
getTestSessionCommonTags,
|
|
12
|
-
getTestModuleCommonTags,
|
|
13
|
-
getTestSuiteCommonTags,
|
|
14
|
-
TEST_SUITE_ID,
|
|
15
|
-
TEST_MODULE_ID,
|
|
16
|
-
TEST_SESSION_ID,
|
|
17
|
-
TEST_COMMAND,
|
|
18
|
-
TEST_MODULE,
|
|
19
|
-
TEST_SOURCE_START,
|
|
20
|
-
finishAllTraceSpans,
|
|
21
|
-
getCoveredFilenamesFromCoverage,
|
|
22
|
-
getTestSuitePath,
|
|
23
|
-
addIntelligentTestRunnerSpanTags,
|
|
24
|
-
TEST_SKIPPED_BY_ITR,
|
|
25
|
-
TEST_ITR_UNSKIPPABLE,
|
|
26
|
-
TEST_ITR_FORCED_RUN,
|
|
27
|
-
ITR_CORRELATION_ID,
|
|
28
|
-
TEST_SOURCE_FILE
|
|
29
|
-
} = require('../../dd-trace/src/plugins/util/test')
|
|
30
|
-
const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
|
|
31
|
-
const log = require('../../dd-trace/src/log')
|
|
32
1
|
const NoopTracer = require('../../dd-trace/src/noop/tracer')
|
|
33
|
-
const
|
|
34
|
-
const {
|
|
35
|
-
TELEMETRY_EVENT_CREATED,
|
|
36
|
-
TELEMETRY_EVENT_FINISHED,
|
|
37
|
-
TELEMETRY_ITR_FORCED_TO_RUN,
|
|
38
|
-
TELEMETRY_CODE_COVERAGE_EMPTY,
|
|
39
|
-
TELEMETRY_ITR_UNSKIPPABLE,
|
|
40
|
-
TELEMETRY_CODE_COVERAGE_NUM_FILES,
|
|
41
|
-
incrementCountMetric,
|
|
42
|
-
distributionMetric
|
|
43
|
-
} = require('../../dd-trace/src/ci-visibility/telemetry')
|
|
44
|
-
const { appClosing: appClosingTelemetry } = require('../../dd-trace/src/telemetry')
|
|
45
|
-
const {
|
|
46
|
-
GIT_REPOSITORY_URL,
|
|
47
|
-
GIT_COMMIT_SHA,
|
|
48
|
-
GIT_BRANCH,
|
|
49
|
-
CI_PROVIDER_NAME,
|
|
50
|
-
CI_WORKSPACE_PATH
|
|
51
|
-
} = require('../../dd-trace/src/plugins/util/tags')
|
|
52
|
-
const {
|
|
53
|
-
OS_VERSION,
|
|
54
|
-
OS_PLATFORM,
|
|
55
|
-
OS_ARCHITECTURE,
|
|
56
|
-
RUNTIME_NAME,
|
|
57
|
-
RUNTIME_VERSION
|
|
58
|
-
} = require('../../dd-trace/src/plugins/util/env')
|
|
59
|
-
|
|
60
|
-
const TEST_FRAMEWORK_NAME = 'cypress'
|
|
61
|
-
|
|
62
|
-
const CYPRESS_STATUS_TO_TEST_STATUS = {
|
|
63
|
-
passed: 'pass',
|
|
64
|
-
failed: 'fail',
|
|
65
|
-
pending: 'skip',
|
|
66
|
-
skipped: 'skip'
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function getTestSpanMetadata (tracer, testName, testSuite, cypressConfig) {
|
|
70
|
-
const childOf = getTestParentSpan(tracer)
|
|
71
|
-
|
|
72
|
-
const commonTags = getTestCommonTags(testName, testSuite, cypressConfig.version, TEST_FRAMEWORK_NAME)
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
childOf,
|
|
76
|
-
...commonTags
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function getCypressVersion (details) {
|
|
81
|
-
if (details && details.cypressVersion) {
|
|
82
|
-
return details.cypressVersion
|
|
83
|
-
}
|
|
84
|
-
if (details && details.config && details.config.version) {
|
|
85
|
-
return details.config.version
|
|
86
|
-
}
|
|
87
|
-
return ''
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function getRootDir (details) {
|
|
91
|
-
if (details && details.config) {
|
|
92
|
-
return details.config.projectRoot || details.config.repoRoot || process.cwd()
|
|
93
|
-
}
|
|
94
|
-
return process.cwd()
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function getCypressCommand (details) {
|
|
98
|
-
if (!details) {
|
|
99
|
-
return TEST_FRAMEWORK_NAME
|
|
100
|
-
}
|
|
101
|
-
return `${TEST_FRAMEWORK_NAME} ${details.specPattern || ''}`
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function getSessionStatus (summary) {
|
|
105
|
-
if (summary.totalFailed !== undefined && summary.totalFailed > 0) {
|
|
106
|
-
return 'fail'
|
|
107
|
-
}
|
|
108
|
-
if (summary.totalSkipped !== undefined && summary.totalSkipped === summary.totalTests) {
|
|
109
|
-
return 'skip'
|
|
110
|
-
}
|
|
111
|
-
return 'pass'
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function getSuiteStatus (suiteStats) {
|
|
115
|
-
if (suiteStats.failures !== undefined && suiteStats.failures > 0) {
|
|
116
|
-
return 'fail'
|
|
117
|
-
}
|
|
118
|
-
if (suiteStats.tests !== undefined && suiteStats.tests === suiteStats.pending) {
|
|
119
|
-
return 'skip'
|
|
120
|
-
}
|
|
121
|
-
return 'pass'
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function getLibraryConfiguration (tracer, testConfiguration) {
|
|
125
|
-
return new Promise(resolve => {
|
|
126
|
-
if (!tracer._tracer._exporter?.getLibraryConfiguration) {
|
|
127
|
-
return resolve({ err: new Error('CI Visibility was not initialized correctly') })
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
tracer._tracer._exporter.getLibraryConfiguration(testConfiguration, (err, libraryConfig) => {
|
|
131
|
-
resolve({ err, libraryConfig })
|
|
132
|
-
})
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function getSkippableTests (isSuitesSkippingEnabled, tracer, testConfiguration) {
|
|
137
|
-
if (!isSuitesSkippingEnabled) {
|
|
138
|
-
return Promise.resolve({ skippableTests: [] })
|
|
139
|
-
}
|
|
140
|
-
return new Promise(resolve => {
|
|
141
|
-
if (!tracer._tracer._exporter?.getLibraryConfiguration) {
|
|
142
|
-
return resolve({ err: new Error('CI Visibility was not initialized correctly') })
|
|
143
|
-
}
|
|
144
|
-
tracer._tracer._exporter.getSkippableSuites(testConfiguration, (err, skippableTests, correlationId) => {
|
|
145
|
-
resolve({
|
|
146
|
-
err,
|
|
147
|
-
skippableTests,
|
|
148
|
-
correlationId
|
|
149
|
-
})
|
|
150
|
-
})
|
|
151
|
-
})
|
|
152
|
-
}
|
|
2
|
+
const cypressPlugin = require('./cypress-plugin')
|
|
153
3
|
|
|
154
4
|
const noopTask = {
|
|
155
5
|
'dd:testSuiteStart': () => {
|
|
@@ -167,8 +17,6 @@ const noopTask = {
|
|
|
167
17
|
}
|
|
168
18
|
|
|
169
19
|
module.exports = (on, config) => {
|
|
170
|
-
let isTestsSkipped = false
|
|
171
|
-
const skippedTests = []
|
|
172
20
|
const tracer = require('../../dd-trace')
|
|
173
21
|
|
|
174
22
|
// The tracer was not init correctly for whatever reason (such as invalid DD_SITE)
|
|
@@ -177,385 +25,10 @@ module.exports = (on, config) => {
|
|
|
177
25
|
return on('task', noopTask)
|
|
178
26
|
}
|
|
179
27
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const {
|
|
183
|
-
[GIT_REPOSITORY_URL]: repositoryUrl,
|
|
184
|
-
[GIT_COMMIT_SHA]: sha,
|
|
185
|
-
[OS_VERSION]: osVersion,
|
|
186
|
-
[OS_PLATFORM]: osPlatform,
|
|
187
|
-
[OS_ARCHITECTURE]: osArchitecture,
|
|
188
|
-
[RUNTIME_NAME]: runtimeName,
|
|
189
|
-
[RUNTIME_VERSION]: runtimeVersion,
|
|
190
|
-
[GIT_BRANCH]: branch,
|
|
191
|
-
[CI_PROVIDER_NAME]: ciProviderName,
|
|
192
|
-
[CI_WORKSPACE_PATH]: repositoryRoot
|
|
193
|
-
} = testEnvironmentMetadata
|
|
194
|
-
|
|
195
|
-
const isUnsupportedCIProvider = !ciProviderName
|
|
196
|
-
|
|
197
|
-
const finishedTestsByFile = {}
|
|
198
|
-
|
|
199
|
-
const testConfiguration = {
|
|
200
|
-
repositoryUrl,
|
|
201
|
-
sha,
|
|
202
|
-
osVersion,
|
|
203
|
-
osPlatform,
|
|
204
|
-
osArchitecture,
|
|
205
|
-
runtimeName,
|
|
206
|
-
runtimeVersion,
|
|
207
|
-
branch,
|
|
208
|
-
testLevel: 'test'
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const codeOwnersEntries = getCodeOwnersFileEntries(repositoryRoot)
|
|
212
|
-
|
|
213
|
-
let activeSpan = null
|
|
214
|
-
let testSessionSpan = null
|
|
215
|
-
let testModuleSpan = null
|
|
216
|
-
let testSuiteSpan = null
|
|
217
|
-
let command = null
|
|
218
|
-
let frameworkVersion
|
|
219
|
-
let rootDir
|
|
220
|
-
let isSuitesSkippingEnabled = false
|
|
221
|
-
let isCodeCoverageEnabled = false
|
|
222
|
-
let testsToSkip = []
|
|
223
|
-
let itrCorrelationId = ''
|
|
224
|
-
const unskippableSuites = []
|
|
225
|
-
let hasForcedToRunSuites = false
|
|
226
|
-
let hasUnskippableSuites = false
|
|
227
|
-
|
|
228
|
-
function ciVisEvent (name, testLevel, tags = {}) {
|
|
229
|
-
incrementCountMetric(name, {
|
|
230
|
-
testLevel,
|
|
231
|
-
testFramework: 'cypress',
|
|
232
|
-
isUnsupportedCIProvider,
|
|
233
|
-
...tags
|
|
234
|
-
})
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function getTestSpan (testName, testSuite, isUnskippable, isForcedToRun) {
|
|
238
|
-
const testSuiteTags = {
|
|
239
|
-
[TEST_COMMAND]: command,
|
|
240
|
-
[TEST_COMMAND]: command,
|
|
241
|
-
[TEST_MODULE]: TEST_FRAMEWORK_NAME
|
|
242
|
-
}
|
|
243
|
-
if (testSuiteSpan) {
|
|
244
|
-
testSuiteTags[TEST_SUITE_ID] = testSuiteSpan.context().toSpanId()
|
|
245
|
-
}
|
|
246
|
-
if (testSessionSpan && testModuleSpan) {
|
|
247
|
-
testSuiteTags[TEST_SESSION_ID] = testSessionSpan.context().toTraceId()
|
|
248
|
-
testSuiteTags[TEST_MODULE_ID] = testModuleSpan.context().toSpanId()
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const {
|
|
252
|
-
childOf,
|
|
253
|
-
resource,
|
|
254
|
-
...testSpanMetadata
|
|
255
|
-
} = getTestSpanMetadata(tracer, testName, testSuite, config)
|
|
256
|
-
|
|
257
|
-
const codeOwners = getCodeOwnersForFilename(testSuite, codeOwnersEntries)
|
|
258
|
-
|
|
259
|
-
if (codeOwners) {
|
|
260
|
-
testSpanMetadata[TEST_CODE_OWNERS] = codeOwners
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (isUnskippable) {
|
|
264
|
-
hasUnskippableSuites = true
|
|
265
|
-
incrementCountMetric(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
|
|
266
|
-
testSpanMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (isForcedToRun) {
|
|
270
|
-
hasForcedToRunSuites = true
|
|
271
|
-
incrementCountMetric(TELEMETRY_ITR_FORCED_TO_RUN, { testLevel: 'suite' })
|
|
272
|
-
testSpanMetadata[TEST_ITR_FORCED_RUN] = 'true'
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
ciVisEvent(TELEMETRY_EVENT_CREATED, 'test', { hasCodeOwners: !!codeOwners })
|
|
276
|
-
|
|
277
|
-
return tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test`, {
|
|
278
|
-
childOf,
|
|
279
|
-
tags: {
|
|
280
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
281
|
-
[ORIGIN_KEY]: CI_APP_ORIGIN,
|
|
282
|
-
...testSpanMetadata,
|
|
283
|
-
...testEnvironmentMetadata,
|
|
284
|
-
...testSuiteTags
|
|
285
|
-
}
|
|
286
|
-
})
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
on('before:run', (details) => {
|
|
290
|
-
return getLibraryConfiguration(tracer, testConfiguration).then(({ err, libraryConfig }) => {
|
|
291
|
-
if (err) {
|
|
292
|
-
log.error(err)
|
|
293
|
-
} else {
|
|
294
|
-
isSuitesSkippingEnabled = libraryConfig.isSuitesSkippingEnabled
|
|
295
|
-
isCodeCoverageEnabled = libraryConfig.isCodeCoverageEnabled
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return getSkippableTests(isSuitesSkippingEnabled, tracer, testConfiguration)
|
|
299
|
-
.then(({ err, skippableTests, correlationId }) => {
|
|
300
|
-
if (err) {
|
|
301
|
-
log.error(err)
|
|
302
|
-
} else {
|
|
303
|
-
testsToSkip = skippableTests || []
|
|
304
|
-
itrCorrelationId = correlationId
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// `details.specs` are test files
|
|
308
|
-
details.specs.forEach(({ absolute, relative }) => {
|
|
309
|
-
const isUnskippableSuite = isMarkedAsUnskippable({ path: absolute })
|
|
310
|
-
if (isUnskippableSuite) {
|
|
311
|
-
unskippableSuites.push(relative)
|
|
312
|
-
}
|
|
313
|
-
})
|
|
314
|
-
|
|
315
|
-
const childOf = getTestParentSpan(tracer)
|
|
316
|
-
rootDir = getRootDir(details)
|
|
317
|
-
|
|
318
|
-
command = getCypressCommand(details)
|
|
319
|
-
frameworkVersion = getCypressVersion(details)
|
|
320
|
-
|
|
321
|
-
const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion, TEST_FRAMEWORK_NAME)
|
|
322
|
-
const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion, TEST_FRAMEWORK_NAME)
|
|
323
|
-
|
|
324
|
-
testSessionSpan = tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_session`, {
|
|
325
|
-
childOf,
|
|
326
|
-
tags: {
|
|
327
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
328
|
-
...testEnvironmentMetadata,
|
|
329
|
-
...testSessionSpanMetadata
|
|
330
|
-
}
|
|
331
|
-
})
|
|
332
|
-
ciVisEvent(TELEMETRY_EVENT_CREATED, 'session')
|
|
333
|
-
|
|
334
|
-
testModuleSpan = tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_module`, {
|
|
335
|
-
childOf: testSessionSpan,
|
|
336
|
-
tags: {
|
|
337
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
338
|
-
...testEnvironmentMetadata,
|
|
339
|
-
...testModuleSpanMetadata
|
|
340
|
-
}
|
|
341
|
-
})
|
|
342
|
-
ciVisEvent(TELEMETRY_EVENT_CREATED, 'module')
|
|
343
|
-
|
|
344
|
-
return details
|
|
345
|
-
})
|
|
346
|
-
})
|
|
347
|
-
})
|
|
348
|
-
on('after:spec', (spec, { tests, stats }) => {
|
|
349
|
-
const cypressTests = tests || []
|
|
350
|
-
const finishedTests = finishedTestsByFile[spec.relative] || []
|
|
351
|
-
|
|
352
|
-
// Get tests that didn't go through `dd:afterEach`
|
|
353
|
-
// and create a skipped test span for each of them
|
|
354
|
-
cypressTests.filter(({ title }) => {
|
|
355
|
-
const cypressTestName = title.join(' ')
|
|
356
|
-
const isTestFinished = finishedTests.find(({ testName }) => cypressTestName === testName)
|
|
357
|
-
|
|
358
|
-
return !isTestFinished
|
|
359
|
-
}).forEach(({ title }) => {
|
|
360
|
-
const cypressTestName = title.join(' ')
|
|
361
|
-
const isSkippedByItr = testsToSkip.find(test =>
|
|
362
|
-
cypressTestName === test.name && spec.relative === test.suite
|
|
363
|
-
)
|
|
364
|
-
const skippedTestSpan = getTestSpan(cypressTestName, spec.relative)
|
|
365
|
-
if (spec.absolute && repositoryRoot) {
|
|
366
|
-
skippedTestSpan.setTag(TEST_SOURCE_FILE, getTestSuitePath(spec.absolute, repositoryRoot))
|
|
367
|
-
} else {
|
|
368
|
-
skippedTestSpan.setTag(TEST_SOURCE_FILE, spec.relative)
|
|
369
|
-
}
|
|
370
|
-
skippedTestSpan.setTag(TEST_STATUS, 'skip')
|
|
371
|
-
if (isSkippedByItr) {
|
|
372
|
-
skippedTestSpan.setTag(TEST_SKIPPED_BY_ITR, 'true')
|
|
373
|
-
}
|
|
374
|
-
if (itrCorrelationId) {
|
|
375
|
-
skippedTestSpan.setTag(ITR_CORRELATION_ID, itrCorrelationId)
|
|
376
|
-
}
|
|
377
|
-
skippedTestSpan.finish()
|
|
378
|
-
})
|
|
379
|
-
|
|
380
|
-
// Make sure that reported test statuses are the same as Cypress reports.
|
|
381
|
-
// This is not always the case, such as when an `after` hook fails:
|
|
382
|
-
// Cypress will report the last run test as failed, but we don't know that yet at `dd:afterEach`
|
|
383
|
-
let latestError
|
|
384
|
-
finishedTests.forEach((finishedTest) => {
|
|
385
|
-
const cypressTest = cypressTests.find(test => test.title.join(' ') === finishedTest.testName)
|
|
386
|
-
if (!cypressTest) {
|
|
387
|
-
return
|
|
388
|
-
}
|
|
389
|
-
if (cypressTest.displayError) {
|
|
390
|
-
latestError = new Error(cypressTest.displayError)
|
|
391
|
-
}
|
|
392
|
-
const cypressTestStatus = CYPRESS_STATUS_TO_TEST_STATUS[cypressTest.state]
|
|
393
|
-
// update test status
|
|
394
|
-
if (cypressTestStatus !== finishedTest.testStatus) {
|
|
395
|
-
finishedTest.testSpan.setTag(TEST_STATUS, cypressTestStatus)
|
|
396
|
-
finishedTest.testSpan.setTag('error', latestError)
|
|
397
|
-
}
|
|
398
|
-
if (itrCorrelationId) {
|
|
399
|
-
finishedTest.testSpan.setTag(ITR_CORRELATION_ID, itrCorrelationId)
|
|
400
|
-
}
|
|
401
|
-
if (spec.absolute && repositoryRoot) {
|
|
402
|
-
finishedTest.testSpan.setTag(TEST_SOURCE_FILE, getTestSuitePath(spec.absolute, repositoryRoot))
|
|
403
|
-
} else {
|
|
404
|
-
finishedTest.testSpan.setTag(TEST_SOURCE_FILE, spec.relative)
|
|
405
|
-
}
|
|
406
|
-
finishedTest.testSpan.finish(finishedTest.finishTime)
|
|
407
|
-
})
|
|
408
|
-
|
|
409
|
-
if (testSuiteSpan) {
|
|
410
|
-
const status = getSuiteStatus(stats)
|
|
411
|
-
testSuiteSpan.setTag(TEST_STATUS, status)
|
|
412
|
-
|
|
413
|
-
if (latestError) {
|
|
414
|
-
testSuiteSpan.setTag('error', latestError)
|
|
415
|
-
}
|
|
416
|
-
testSuiteSpan.finish()
|
|
417
|
-
testSuiteSpan = null
|
|
418
|
-
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
419
|
-
}
|
|
420
|
-
})
|
|
421
|
-
|
|
422
|
-
on('after:run', (suiteStats) => {
|
|
423
|
-
if (testSessionSpan && testModuleSpan) {
|
|
424
|
-
const testStatus = getSessionStatus(suiteStats)
|
|
425
|
-
testModuleSpan.setTag(TEST_STATUS, testStatus)
|
|
426
|
-
testSessionSpan.setTag(TEST_STATUS, testStatus)
|
|
427
|
-
|
|
428
|
-
addIntelligentTestRunnerSpanTags(
|
|
429
|
-
testSessionSpan,
|
|
430
|
-
testModuleSpan,
|
|
431
|
-
{
|
|
432
|
-
isSuitesSkipped: isTestsSkipped,
|
|
433
|
-
isSuitesSkippingEnabled,
|
|
434
|
-
isCodeCoverageEnabled,
|
|
435
|
-
skippingType: 'test',
|
|
436
|
-
skippingCount: skippedTests.length,
|
|
437
|
-
hasForcedToRunSuites,
|
|
438
|
-
hasUnskippableSuites
|
|
439
|
-
}
|
|
440
|
-
)
|
|
441
|
-
|
|
442
|
-
testModuleSpan.finish()
|
|
443
|
-
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
444
|
-
testSessionSpan.finish()
|
|
445
|
-
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
446
|
-
|
|
447
|
-
finishAllTraceSpans(testSessionSpan)
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
return new Promise(resolve => {
|
|
451
|
-
const exporter = tracer._tracer._exporter
|
|
452
|
-
if (!exporter) {
|
|
453
|
-
return resolve(null)
|
|
454
|
-
}
|
|
455
|
-
if (exporter.flush) {
|
|
456
|
-
exporter.flush(() => {
|
|
457
|
-
appClosingTelemetry()
|
|
458
|
-
resolve(null)
|
|
459
|
-
})
|
|
460
|
-
} else if (exporter._writer) {
|
|
461
|
-
exporter._writer.flush(() => {
|
|
462
|
-
appClosingTelemetry()
|
|
463
|
-
resolve(null)
|
|
464
|
-
})
|
|
465
|
-
}
|
|
466
|
-
})
|
|
467
|
-
})
|
|
468
|
-
on('task', {
|
|
469
|
-
'dd:testSuiteStart': (suite) => {
|
|
470
|
-
if (testSuiteSpan) {
|
|
471
|
-
return null
|
|
472
|
-
}
|
|
473
|
-
const testSuiteSpanMetadata = getTestSuiteCommonTags(command, frameworkVersion, suite, TEST_FRAMEWORK_NAME)
|
|
474
|
-
testSuiteSpan = tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_suite`, {
|
|
475
|
-
childOf: testModuleSpan,
|
|
476
|
-
tags: {
|
|
477
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
478
|
-
...testEnvironmentMetadata,
|
|
479
|
-
...testSuiteSpanMetadata
|
|
480
|
-
}
|
|
481
|
-
})
|
|
482
|
-
ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
483
|
-
return null
|
|
484
|
-
},
|
|
485
|
-
'dd:beforeEach': (test) => {
|
|
486
|
-
const { testName, testSuite } = test
|
|
487
|
-
const shouldSkip = !!testsToSkip.find(test => {
|
|
488
|
-
return testName === test.name && testSuite === test.suite
|
|
489
|
-
})
|
|
490
|
-
const isUnskippable = unskippableSuites.includes(testSuite)
|
|
491
|
-
const isForcedToRun = shouldSkip && isUnskippable
|
|
492
|
-
|
|
493
|
-
// skip test
|
|
494
|
-
if (shouldSkip && !isUnskippable) {
|
|
495
|
-
skippedTests.push(test)
|
|
496
|
-
isTestsSkipped = true
|
|
497
|
-
return { shouldSkip: true }
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
if (!activeSpan) {
|
|
501
|
-
activeSpan = getTestSpan(testName, testSuite, isUnskippable, isForcedToRun)
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
return activeSpan ? { traceId: activeSpan.context().toTraceId() } : {}
|
|
505
|
-
},
|
|
506
|
-
'dd:afterEach': ({ test, coverage }) => {
|
|
507
|
-
const { state, error, isRUMActive, testSourceLine, testSuite, testName } = test
|
|
508
|
-
if (activeSpan) {
|
|
509
|
-
if (coverage && isCodeCoverageEnabled && tracer._tracer._exporter && tracer._tracer._exporter.exportCoverage) {
|
|
510
|
-
const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
|
|
511
|
-
const relativeCoverageFiles = coverageFiles.map(file => getTestSuitePath(file, rootDir))
|
|
512
|
-
if (!relativeCoverageFiles.length) {
|
|
513
|
-
incrementCountMetric(TELEMETRY_CODE_COVERAGE_EMPTY)
|
|
514
|
-
}
|
|
515
|
-
distributionMetric(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
|
|
516
|
-
const { _traceId, _spanId } = testSuiteSpan.context()
|
|
517
|
-
const formattedCoverage = {
|
|
518
|
-
sessionId: _traceId,
|
|
519
|
-
suiteId: _spanId,
|
|
520
|
-
testId: activeSpan.context()._spanId,
|
|
521
|
-
files: relativeCoverageFiles
|
|
522
|
-
}
|
|
523
|
-
tracer._tracer._exporter.exportCoverage(formattedCoverage)
|
|
524
|
-
}
|
|
525
|
-
const testStatus = CYPRESS_STATUS_TO_TEST_STATUS[state]
|
|
526
|
-
activeSpan.setTag(TEST_STATUS, testStatus)
|
|
28
|
+
cypressPlugin.init(tracer, config)
|
|
527
29
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
activeSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
|
|
533
|
-
}
|
|
534
|
-
if (testSourceLine) {
|
|
535
|
-
activeSpan.setTag(TEST_SOURCE_START, testSourceLine)
|
|
536
|
-
}
|
|
537
|
-
const finishedTest = {
|
|
538
|
-
testName,
|
|
539
|
-
testStatus,
|
|
540
|
-
finishTime: activeSpan._getTime(), // we store the finish time here
|
|
541
|
-
testSpan: activeSpan
|
|
542
|
-
}
|
|
543
|
-
if (finishedTestsByFile[testSuite]) {
|
|
544
|
-
finishedTestsByFile[testSuite].push(finishedTest)
|
|
545
|
-
} else {
|
|
546
|
-
finishedTestsByFile[testSuite] = [finishedTest]
|
|
547
|
-
}
|
|
548
|
-
// test spans are finished at after:spec
|
|
549
|
-
}
|
|
550
|
-
activeSpan = null
|
|
551
|
-
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'test')
|
|
552
|
-
return null
|
|
553
|
-
},
|
|
554
|
-
'dd:addTags': (tags) => {
|
|
555
|
-
if (activeSpan) {
|
|
556
|
-
activeSpan.addTags(tags)
|
|
557
|
-
}
|
|
558
|
-
return null
|
|
559
|
-
}
|
|
560
|
-
})
|
|
30
|
+
on('before:run', cypressPlugin.beforeRun.bind(cypressPlugin))
|
|
31
|
+
on('after:spec', cypressPlugin.afterSpec.bind(cypressPlugin))
|
|
32
|
+
on('after:run', cypressPlugin.afterRun.bind(cypressPlugin))
|
|
33
|
+
on('task', cypressPlugin.getTasks())
|
|
561
34
|
}
|
|
@@ -16,7 +16,6 @@ const {
|
|
|
16
16
|
TEST_CODE_OWNERS,
|
|
17
17
|
ITR_CORRELATION_ID,
|
|
18
18
|
TEST_SOURCE_FILE,
|
|
19
|
-
getTestSuitePath,
|
|
20
19
|
TEST_IS_NEW,
|
|
21
20
|
TEST_EARLY_FLAKE_IS_RETRY,
|
|
22
21
|
TEST_EARLY_FLAKE_IS_ENABLED
|
|
@@ -141,6 +140,7 @@ class JestPlugin extends CiPlugin {
|
|
|
141
140
|
config._ddItrCorrelationId = this.itrCorrelationId
|
|
142
141
|
config._ddIsEarlyFlakeDetectionEnabled = !!this.libraryConfig?.isEarlyFlakeDetectionEnabled
|
|
143
142
|
config._ddEarlyFlakeDetectionNumRetries = this.libraryConfig?.earlyFlakeDetectionNumRetries ?? 0
|
|
143
|
+
config._ddRepositoryRoot = this.repositoryRoot
|
|
144
144
|
})
|
|
145
145
|
})
|
|
146
146
|
|
|
@@ -311,7 +311,7 @@ class JestPlugin extends CiPlugin {
|
|
|
311
311
|
testParameters,
|
|
312
312
|
frameworkVersion,
|
|
313
313
|
testStartLine,
|
|
314
|
-
|
|
314
|
+
testSourceFile,
|
|
315
315
|
isNew,
|
|
316
316
|
isEfdRetry
|
|
317
317
|
} = test
|
|
@@ -324,12 +324,8 @@ class JestPlugin extends CiPlugin {
|
|
|
324
324
|
if (testStartLine) {
|
|
325
325
|
extraTags[TEST_SOURCE_START] = testStartLine
|
|
326
326
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
} else {
|
|
330
|
-
// If for whatever we don't have the full path, we'll set the source file to the suite name
|
|
331
|
-
extraTags[TEST_SOURCE_FILE] = suite
|
|
332
|
-
}
|
|
327
|
+
// If for whatever we don't have the source file, we'll fall back to the suite name
|
|
328
|
+
extraTags[TEST_SOURCE_FILE] = testSourceFile || suite
|
|
333
329
|
|
|
334
330
|
if (isNew) {
|
|
335
331
|
extraTags[TEST_IS_NEW] = 'true'
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const dc = require('dc-polyfill')
|
|
3
4
|
const { getMessageSize, CONTEXT_PROPAGATION_KEY } = require('../../dd-trace/src/datastreams/processor')
|
|
4
5
|
const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
|
|
5
6
|
|
|
7
|
+
const afterStartCh = dc.channel('dd-trace:kafkajs:consumer:afterStart')
|
|
8
|
+
const beforeFinishCh = dc.channel('dd-trace:kafkajs:consumer:beforeFinish')
|
|
9
|
+
|
|
6
10
|
class KafkajsConsumerPlugin extends ConsumerPlugin {
|
|
7
11
|
static get id () { return 'kafkajs' }
|
|
8
12
|
static get operation () { return 'consume' }
|
|
@@ -79,6 +83,18 @@ class KafkajsConsumerPlugin extends ConsumerPlugin {
|
|
|
79
83
|
this.tracer
|
|
80
84
|
.setCheckpoint(['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka'], span, payloadSize)
|
|
81
85
|
}
|
|
86
|
+
|
|
87
|
+
if (afterStartCh.hasSubscribers) {
|
|
88
|
+
afterStartCh.publish({ topic, partition, message, groupId })
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
finish () {
|
|
93
|
+
if (beforeFinishCh.hasSubscribers) {
|
|
94
|
+
beforeFinishCh.publish()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
super.finish()
|
|
82
98
|
}
|
|
83
99
|
}
|
|
84
100
|
|