dd-trace 4.28.0 → 4.29.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 +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +156 -42
- package/packages/datadog-instrumentations/src/jest.js +69 -35
- 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 -549
- package/packages/datadog-plugin-rhea/src/consumer.js +4 -1
- 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/profiling/exporters/agent.js +40 -31
|
@@ -1,156 +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 &&
|
|
119
|
-
(suiteStats.tests === suiteStats.pending || suiteStats.tests === suiteStats.skipped)) {
|
|
120
|
-
return 'skip'
|
|
121
|
-
}
|
|
122
|
-
return 'pass'
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function getLibraryConfiguration (tracer, testConfiguration) {
|
|
126
|
-
return new Promise(resolve => {
|
|
127
|
-
if (!tracer._tracer._exporter?.getLibraryConfiguration) {
|
|
128
|
-
return resolve({ err: new Error('CI Visibility was not initialized correctly') })
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
tracer._tracer._exporter.getLibraryConfiguration(testConfiguration, (err, libraryConfig) => {
|
|
132
|
-
resolve({ err, libraryConfig })
|
|
133
|
-
})
|
|
134
|
-
})
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function getSkippableTests (isSuitesSkippingEnabled, tracer, testConfiguration) {
|
|
138
|
-
if (!isSuitesSkippingEnabled) {
|
|
139
|
-
return Promise.resolve({ skippableTests: [] })
|
|
140
|
-
}
|
|
141
|
-
return new Promise(resolve => {
|
|
142
|
-
if (!tracer._tracer._exporter?.getLibraryConfiguration) {
|
|
143
|
-
return resolve({ err: new Error('CI Visibility was not initialized correctly') })
|
|
144
|
-
}
|
|
145
|
-
tracer._tracer._exporter.getSkippableSuites(testConfiguration, (err, skippableTests, correlationId) => {
|
|
146
|
-
resolve({
|
|
147
|
-
err,
|
|
148
|
-
skippableTests,
|
|
149
|
-
correlationId
|
|
150
|
-
})
|
|
151
|
-
})
|
|
152
|
-
})
|
|
153
|
-
}
|
|
2
|
+
const cypressPlugin = require('./cypress-plugin')
|
|
154
3
|
|
|
155
4
|
const noopTask = {
|
|
156
5
|
'dd:testSuiteStart': () => {
|
|
@@ -168,8 +17,6 @@ const noopTask = {
|
|
|
168
17
|
}
|
|
169
18
|
|
|
170
19
|
module.exports = (on, config) => {
|
|
171
|
-
let isTestsSkipped = false
|
|
172
|
-
const skippedTests = []
|
|
173
20
|
const tracer = require('../../dd-trace')
|
|
174
21
|
|
|
175
22
|
// The tracer was not init correctly for whatever reason (such as invalid DD_SITE)
|
|
@@ -178,400 +25,10 @@ module.exports = (on, config) => {
|
|
|
178
25
|
return on('task', noopTask)
|
|
179
26
|
}
|
|
180
27
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const {
|
|
184
|
-
[GIT_REPOSITORY_URL]: repositoryUrl,
|
|
185
|
-
[GIT_COMMIT_SHA]: sha,
|
|
186
|
-
[OS_VERSION]: osVersion,
|
|
187
|
-
[OS_PLATFORM]: osPlatform,
|
|
188
|
-
[OS_ARCHITECTURE]: osArchitecture,
|
|
189
|
-
[RUNTIME_NAME]: runtimeName,
|
|
190
|
-
[RUNTIME_VERSION]: runtimeVersion,
|
|
191
|
-
[GIT_BRANCH]: branch,
|
|
192
|
-
[CI_PROVIDER_NAME]: ciProviderName,
|
|
193
|
-
[CI_WORKSPACE_PATH]: repositoryRoot
|
|
194
|
-
} = testEnvironmentMetadata
|
|
195
|
-
|
|
196
|
-
const isUnsupportedCIProvider = !ciProviderName
|
|
197
|
-
|
|
198
|
-
const finishedTestsByFile = {}
|
|
199
|
-
|
|
200
|
-
const testConfiguration = {
|
|
201
|
-
repositoryUrl,
|
|
202
|
-
sha,
|
|
203
|
-
osVersion,
|
|
204
|
-
osPlatform,
|
|
205
|
-
osArchitecture,
|
|
206
|
-
runtimeName,
|
|
207
|
-
runtimeVersion,
|
|
208
|
-
branch,
|
|
209
|
-
testLevel: 'test'
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const codeOwnersEntries = getCodeOwnersFileEntries(repositoryRoot)
|
|
213
|
-
|
|
214
|
-
let activeSpan = null
|
|
215
|
-
let testSessionSpan = null
|
|
216
|
-
let testModuleSpan = null
|
|
217
|
-
let testSuiteSpan = null
|
|
218
|
-
let command = null
|
|
219
|
-
let frameworkVersion
|
|
220
|
-
let rootDir
|
|
221
|
-
let isSuitesSkippingEnabled = false
|
|
222
|
-
let isCodeCoverageEnabled = false
|
|
223
|
-
let testsToSkip = []
|
|
224
|
-
let itrCorrelationId = ''
|
|
225
|
-
const unskippableSuites = []
|
|
226
|
-
let hasForcedToRunSuites = false
|
|
227
|
-
let hasUnskippableSuites = false
|
|
228
|
-
|
|
229
|
-
function ciVisEvent (name, testLevel, tags = {}) {
|
|
230
|
-
incrementCountMetric(name, {
|
|
231
|
-
testLevel,
|
|
232
|
-
testFramework: 'cypress',
|
|
233
|
-
isUnsupportedCIProvider,
|
|
234
|
-
...tags
|
|
235
|
-
})
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
function getTestSpan (testName, testSuite, isUnskippable, isForcedToRun) {
|
|
239
|
-
const testSuiteTags = {
|
|
240
|
-
[TEST_COMMAND]: command,
|
|
241
|
-
[TEST_COMMAND]: command,
|
|
242
|
-
[TEST_MODULE]: TEST_FRAMEWORK_NAME
|
|
243
|
-
}
|
|
244
|
-
if (testSuiteSpan) {
|
|
245
|
-
testSuiteTags[TEST_SUITE_ID] = testSuiteSpan.context().toSpanId()
|
|
246
|
-
}
|
|
247
|
-
if (testSessionSpan && testModuleSpan) {
|
|
248
|
-
testSuiteTags[TEST_SESSION_ID] = testSessionSpan.context().toTraceId()
|
|
249
|
-
testSuiteTags[TEST_MODULE_ID] = testModuleSpan.context().toSpanId()
|
|
250
|
-
// If testSuiteSpan couldn't be created, we'll use the testModuleSpan as the parent
|
|
251
|
-
if (!testSuiteSpan) {
|
|
252
|
-
testSuiteTags[TEST_SUITE_ID] = testModuleSpan.context().toSpanId()
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const {
|
|
257
|
-
childOf,
|
|
258
|
-
resource,
|
|
259
|
-
...testSpanMetadata
|
|
260
|
-
} = getTestSpanMetadata(tracer, testName, testSuite, config)
|
|
261
|
-
|
|
262
|
-
const codeOwners = getCodeOwnersForFilename(testSuite, codeOwnersEntries)
|
|
263
|
-
|
|
264
|
-
if (codeOwners) {
|
|
265
|
-
testSpanMetadata[TEST_CODE_OWNERS] = codeOwners
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (isUnskippable) {
|
|
269
|
-
hasUnskippableSuites = true
|
|
270
|
-
incrementCountMetric(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
|
|
271
|
-
testSpanMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (isForcedToRun) {
|
|
275
|
-
hasForcedToRunSuites = true
|
|
276
|
-
incrementCountMetric(TELEMETRY_ITR_FORCED_TO_RUN, { testLevel: 'suite' })
|
|
277
|
-
testSpanMetadata[TEST_ITR_FORCED_RUN] = 'true'
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
ciVisEvent(TELEMETRY_EVENT_CREATED, 'test', { hasCodeOwners: !!codeOwners })
|
|
281
|
-
|
|
282
|
-
return tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test`, {
|
|
283
|
-
childOf,
|
|
284
|
-
tags: {
|
|
285
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
286
|
-
[ORIGIN_KEY]: CI_APP_ORIGIN,
|
|
287
|
-
...testSpanMetadata,
|
|
288
|
-
...testEnvironmentMetadata,
|
|
289
|
-
...testSuiteTags
|
|
290
|
-
}
|
|
291
|
-
})
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function getTestSuiteSpan (suite) {
|
|
295
|
-
const testSuiteSpanMetadata = getTestSuiteCommonTags(command, frameworkVersion, suite, TEST_FRAMEWORK_NAME)
|
|
296
|
-
ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
297
|
-
return tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_suite`, {
|
|
298
|
-
childOf: testModuleSpan,
|
|
299
|
-
tags: {
|
|
300
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
301
|
-
...testEnvironmentMetadata,
|
|
302
|
-
...testSuiteSpanMetadata
|
|
303
|
-
}
|
|
304
|
-
})
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
on('before:run', (details) => {
|
|
308
|
-
return getLibraryConfiguration(tracer, testConfiguration).then(({ err, libraryConfig }) => {
|
|
309
|
-
if (err) {
|
|
310
|
-
log.error(err)
|
|
311
|
-
} else {
|
|
312
|
-
isSuitesSkippingEnabled = libraryConfig.isSuitesSkippingEnabled
|
|
313
|
-
isCodeCoverageEnabled = libraryConfig.isCodeCoverageEnabled
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return getSkippableTests(isSuitesSkippingEnabled, tracer, testConfiguration)
|
|
317
|
-
.then(({ err, skippableTests, correlationId }) => {
|
|
318
|
-
if (err) {
|
|
319
|
-
log.error(err)
|
|
320
|
-
} else {
|
|
321
|
-
testsToSkip = skippableTests || []
|
|
322
|
-
itrCorrelationId = correlationId
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// `details.specs` are test files
|
|
326
|
-
details.specs.forEach(({ absolute, relative }) => {
|
|
327
|
-
const isUnskippableSuite = isMarkedAsUnskippable({ path: absolute })
|
|
328
|
-
if (isUnskippableSuite) {
|
|
329
|
-
unskippableSuites.push(relative)
|
|
330
|
-
}
|
|
331
|
-
})
|
|
332
|
-
|
|
333
|
-
const childOf = getTestParentSpan(tracer)
|
|
334
|
-
rootDir = getRootDir(details)
|
|
335
|
-
|
|
336
|
-
command = getCypressCommand(details)
|
|
337
|
-
frameworkVersion = getCypressVersion(details)
|
|
338
|
-
|
|
339
|
-
const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion, TEST_FRAMEWORK_NAME)
|
|
340
|
-
const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion, TEST_FRAMEWORK_NAME)
|
|
341
|
-
|
|
342
|
-
testSessionSpan = tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_session`, {
|
|
343
|
-
childOf,
|
|
344
|
-
tags: {
|
|
345
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
346
|
-
...testEnvironmentMetadata,
|
|
347
|
-
...testSessionSpanMetadata
|
|
348
|
-
}
|
|
349
|
-
})
|
|
350
|
-
ciVisEvent(TELEMETRY_EVENT_CREATED, 'session')
|
|
351
|
-
|
|
352
|
-
testModuleSpan = tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_module`, {
|
|
353
|
-
childOf: testSessionSpan,
|
|
354
|
-
tags: {
|
|
355
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
356
|
-
...testEnvironmentMetadata,
|
|
357
|
-
...testModuleSpanMetadata
|
|
358
|
-
}
|
|
359
|
-
})
|
|
360
|
-
ciVisEvent(TELEMETRY_EVENT_CREATED, 'module')
|
|
361
|
-
|
|
362
|
-
return details
|
|
363
|
-
})
|
|
364
|
-
})
|
|
365
|
-
})
|
|
366
|
-
on('after:spec', (spec, { tests, stats }) => {
|
|
367
|
-
const cypressTests = tests || []
|
|
368
|
-
const finishedTests = finishedTestsByFile[spec.relative] || []
|
|
369
|
-
|
|
370
|
-
if (!testSuiteSpan) {
|
|
371
|
-
// dd:testSuiteStart hasn't been triggered for whatever reason
|
|
372
|
-
// We will create the test suite span on the spot if that's the case
|
|
373
|
-
log.warn('There was an error creating the test suite event.')
|
|
374
|
-
testSuiteSpan = getTestSuiteSpan(spec.relative)
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Get tests that didn't go through `dd:afterEach`
|
|
378
|
-
// and create a skipped test span for each of them
|
|
379
|
-
cypressTests.filter(({ title }) => {
|
|
380
|
-
const cypressTestName = title.join(' ')
|
|
381
|
-
const isTestFinished = finishedTests.find(({ testName }) => cypressTestName === testName)
|
|
382
|
-
|
|
383
|
-
return !isTestFinished
|
|
384
|
-
}).forEach(({ title }) => {
|
|
385
|
-
const cypressTestName = title.join(' ')
|
|
386
|
-
const isSkippedByItr = testsToSkip.find(test =>
|
|
387
|
-
cypressTestName === test.name && spec.relative === test.suite
|
|
388
|
-
)
|
|
389
|
-
const skippedTestSpan = getTestSpan(cypressTestName, spec.relative)
|
|
390
|
-
if (spec.absolute && repositoryRoot) {
|
|
391
|
-
skippedTestSpan.setTag(TEST_SOURCE_FILE, getTestSuitePath(spec.absolute, repositoryRoot))
|
|
392
|
-
} else {
|
|
393
|
-
skippedTestSpan.setTag(TEST_SOURCE_FILE, spec.relative)
|
|
394
|
-
}
|
|
395
|
-
skippedTestSpan.setTag(TEST_STATUS, 'skip')
|
|
396
|
-
if (isSkippedByItr) {
|
|
397
|
-
skippedTestSpan.setTag(TEST_SKIPPED_BY_ITR, 'true')
|
|
398
|
-
}
|
|
399
|
-
if (itrCorrelationId) {
|
|
400
|
-
skippedTestSpan.setTag(ITR_CORRELATION_ID, itrCorrelationId)
|
|
401
|
-
}
|
|
402
|
-
skippedTestSpan.finish()
|
|
403
|
-
})
|
|
404
|
-
|
|
405
|
-
// Make sure that reported test statuses are the same as Cypress reports.
|
|
406
|
-
// This is not always the case, such as when an `after` hook fails:
|
|
407
|
-
// Cypress will report the last run test as failed, but we don't know that yet at `dd:afterEach`
|
|
408
|
-
let latestError
|
|
409
|
-
finishedTests.forEach((finishedTest) => {
|
|
410
|
-
const cypressTest = cypressTests.find(test => test.title.join(' ') === finishedTest.testName)
|
|
411
|
-
if (!cypressTest) {
|
|
412
|
-
return
|
|
413
|
-
}
|
|
414
|
-
if (cypressTest.displayError) {
|
|
415
|
-
latestError = new Error(cypressTest.displayError)
|
|
416
|
-
}
|
|
417
|
-
const cypressTestStatus = CYPRESS_STATUS_TO_TEST_STATUS[cypressTest.state]
|
|
418
|
-
// update test status
|
|
419
|
-
if (cypressTestStatus !== finishedTest.testStatus) {
|
|
420
|
-
finishedTest.testSpan.setTag(TEST_STATUS, cypressTestStatus)
|
|
421
|
-
finishedTest.testSpan.setTag('error', latestError)
|
|
422
|
-
}
|
|
423
|
-
if (itrCorrelationId) {
|
|
424
|
-
finishedTest.testSpan.setTag(ITR_CORRELATION_ID, itrCorrelationId)
|
|
425
|
-
}
|
|
426
|
-
if (spec.absolute && repositoryRoot) {
|
|
427
|
-
finishedTest.testSpan.setTag(TEST_SOURCE_FILE, getTestSuitePath(spec.absolute, repositoryRoot))
|
|
428
|
-
} else {
|
|
429
|
-
finishedTest.testSpan.setTag(TEST_SOURCE_FILE, spec.relative)
|
|
430
|
-
}
|
|
431
|
-
finishedTest.testSpan.finish(finishedTest.finishTime)
|
|
432
|
-
})
|
|
433
|
-
|
|
434
|
-
if (testSuiteSpan) {
|
|
435
|
-
const status = getSuiteStatus(stats)
|
|
436
|
-
testSuiteSpan.setTag(TEST_STATUS, status)
|
|
437
|
-
|
|
438
|
-
if (latestError) {
|
|
439
|
-
testSuiteSpan.setTag('error', latestError)
|
|
440
|
-
}
|
|
441
|
-
testSuiteSpan.finish()
|
|
442
|
-
testSuiteSpan = null
|
|
443
|
-
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
444
|
-
}
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
on('after:run', (suiteStats) => {
|
|
448
|
-
if (testSessionSpan && testModuleSpan) {
|
|
449
|
-
const testStatus = getSessionStatus(suiteStats)
|
|
450
|
-
testModuleSpan.setTag(TEST_STATUS, testStatus)
|
|
451
|
-
testSessionSpan.setTag(TEST_STATUS, testStatus)
|
|
452
|
-
|
|
453
|
-
addIntelligentTestRunnerSpanTags(
|
|
454
|
-
testSessionSpan,
|
|
455
|
-
testModuleSpan,
|
|
456
|
-
{
|
|
457
|
-
isSuitesSkipped: isTestsSkipped,
|
|
458
|
-
isSuitesSkippingEnabled,
|
|
459
|
-
isCodeCoverageEnabled,
|
|
460
|
-
skippingType: 'test',
|
|
461
|
-
skippingCount: skippedTests.length,
|
|
462
|
-
hasForcedToRunSuites,
|
|
463
|
-
hasUnskippableSuites
|
|
464
|
-
}
|
|
465
|
-
)
|
|
466
|
-
|
|
467
|
-
testModuleSpan.finish()
|
|
468
|
-
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
469
|
-
testSessionSpan.finish()
|
|
470
|
-
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
471
|
-
|
|
472
|
-
finishAllTraceSpans(testSessionSpan)
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
return new Promise(resolve => {
|
|
476
|
-
const exporter = tracer._tracer._exporter
|
|
477
|
-
if (!exporter) {
|
|
478
|
-
return resolve(null)
|
|
479
|
-
}
|
|
480
|
-
if (exporter.flush) {
|
|
481
|
-
exporter.flush(() => {
|
|
482
|
-
appClosingTelemetry()
|
|
483
|
-
resolve(null)
|
|
484
|
-
})
|
|
485
|
-
} else if (exporter._writer) {
|
|
486
|
-
exporter._writer.flush(() => {
|
|
487
|
-
appClosingTelemetry()
|
|
488
|
-
resolve(null)
|
|
489
|
-
})
|
|
490
|
-
}
|
|
491
|
-
})
|
|
492
|
-
})
|
|
493
|
-
on('task', {
|
|
494
|
-
'dd:testSuiteStart': (suite) => {
|
|
495
|
-
if (testSuiteSpan) {
|
|
496
|
-
return null
|
|
497
|
-
}
|
|
498
|
-
testSuiteSpan = getTestSuiteSpan(suite)
|
|
499
|
-
return null
|
|
500
|
-
},
|
|
501
|
-
'dd:beforeEach': (test) => {
|
|
502
|
-
const { testName, testSuite } = test
|
|
503
|
-
const shouldSkip = !!testsToSkip.find(test => {
|
|
504
|
-
return testName === test.name && testSuite === test.suite
|
|
505
|
-
})
|
|
506
|
-
const isUnskippable = unskippableSuites.includes(testSuite)
|
|
507
|
-
const isForcedToRun = shouldSkip && isUnskippable
|
|
508
|
-
|
|
509
|
-
// skip test
|
|
510
|
-
if (shouldSkip && !isUnskippable) {
|
|
511
|
-
skippedTests.push(test)
|
|
512
|
-
isTestsSkipped = true
|
|
513
|
-
return { shouldSkip: true }
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
if (!activeSpan) {
|
|
517
|
-
activeSpan = getTestSpan(testName, testSuite, isUnskippable, isForcedToRun)
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
return activeSpan ? { traceId: activeSpan.context().toTraceId() } : {}
|
|
521
|
-
},
|
|
522
|
-
'dd:afterEach': ({ test, coverage }) => {
|
|
523
|
-
const { state, error, isRUMActive, testSourceLine, testSuite, testName } = test
|
|
524
|
-
if (activeSpan) {
|
|
525
|
-
if (coverage && isCodeCoverageEnabled && tracer._tracer._exporter && tracer._tracer._exporter.exportCoverage) {
|
|
526
|
-
const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
|
|
527
|
-
const relativeCoverageFiles = coverageFiles.map(file => getTestSuitePath(file, rootDir))
|
|
528
|
-
if (!relativeCoverageFiles.length) {
|
|
529
|
-
incrementCountMetric(TELEMETRY_CODE_COVERAGE_EMPTY)
|
|
530
|
-
}
|
|
531
|
-
distributionMetric(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
|
|
532
|
-
const { _traceId, _spanId } = testSuiteSpan.context()
|
|
533
|
-
const formattedCoverage = {
|
|
534
|
-
sessionId: _traceId,
|
|
535
|
-
suiteId: _spanId,
|
|
536
|
-
testId: activeSpan.context()._spanId,
|
|
537
|
-
files: relativeCoverageFiles
|
|
538
|
-
}
|
|
539
|
-
tracer._tracer._exporter.exportCoverage(formattedCoverage)
|
|
540
|
-
}
|
|
541
|
-
const testStatus = CYPRESS_STATUS_TO_TEST_STATUS[state]
|
|
542
|
-
activeSpan.setTag(TEST_STATUS, testStatus)
|
|
28
|
+
cypressPlugin.init(tracer, config)
|
|
543
29
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
activeSpan.setTag(TEST_IS_RUM_ACTIVE, 'true')
|
|
549
|
-
}
|
|
550
|
-
if (testSourceLine) {
|
|
551
|
-
activeSpan.setTag(TEST_SOURCE_START, testSourceLine)
|
|
552
|
-
}
|
|
553
|
-
const finishedTest = {
|
|
554
|
-
testName,
|
|
555
|
-
testStatus,
|
|
556
|
-
finishTime: activeSpan._getTime(), // we store the finish time here
|
|
557
|
-
testSpan: activeSpan
|
|
558
|
-
}
|
|
559
|
-
if (finishedTestsByFile[testSuite]) {
|
|
560
|
-
finishedTestsByFile[testSuite].push(finishedTest)
|
|
561
|
-
} else {
|
|
562
|
-
finishedTestsByFile[testSuite] = [finishedTest]
|
|
563
|
-
}
|
|
564
|
-
// test spans are finished at after:spec
|
|
565
|
-
}
|
|
566
|
-
activeSpan = null
|
|
567
|
-
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'test')
|
|
568
|
-
return null
|
|
569
|
-
},
|
|
570
|
-
'dd:addTags': (tags) => {
|
|
571
|
-
if (activeSpan) {
|
|
572
|
-
activeSpan.addTags(tags)
|
|
573
|
-
}
|
|
574
|
-
return null
|
|
575
|
-
}
|
|
576
|
-
})
|
|
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())
|
|
577
34
|
}
|
|
@@ -31,7 +31,10 @@ class RheaConsumerPlugin extends ConsumerPlugin {
|
|
|
31
31
|
}
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
-
if (
|
|
34
|
+
if (
|
|
35
|
+
this.config.dsmEnabled &&
|
|
36
|
+
msgObj?.message?.delivery_annotations?.[CONTEXT_PROPAGATION_KEY]
|
|
37
|
+
) {
|
|
35
38
|
const payloadSize = getAmqpMessageSize(
|
|
36
39
|
{ headers: msgObj.message.delivery_annotations, content: msgObj.message.body }
|
|
37
40
|
)
|
|
@@ -209,10 +209,12 @@ class Config {
|
|
|
209
209
|
|
|
210
210
|
const inServerlessEnvironment = inAWSLambda || isGCPFunction || isAzureFunctionConsumptionPlan
|
|
211
211
|
|
|
212
|
+
const isJestWorker = !!process.env.JEST_WORKER_ID
|
|
213
|
+
|
|
212
214
|
const DD_INSTRUMENTATION_TELEMETRY_ENABLED = coalesce(
|
|
213
215
|
process.env.DD_TRACE_TELEMETRY_ENABLED, // for backward compatibility
|
|
214
216
|
process.env.DD_INSTRUMENTATION_TELEMETRY_ENABLED, // to comply with instrumentation telemetry specs
|
|
215
|
-
!inServerlessEnvironment
|
|
217
|
+
!(inServerlessEnvironment || isJestWorker)
|
|
216
218
|
)
|
|
217
219
|
const DD_TELEMETRY_HEARTBEAT_INTERVAL = process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL
|
|
218
220
|
? Math.floor(parseFloat(process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL) * 1000)
|
|
@@ -611,7 +613,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
611
613
|
this.peerServiceMapping = DD_TRACE_PEER_SERVICE_MAPPING
|
|
612
614
|
this.lookup = options.lookup
|
|
613
615
|
this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
|
|
614
|
-
// Disabled for CI Visibility's agentless
|
|
615
616
|
this.telemetry = {
|
|
616
617
|
enabled: isTrue(DD_INSTRUMENTATION_TELEMETRY_ENABLED),
|
|
617
618
|
heartbeatInterval: DD_TELEMETRY_HEARTBEAT_INTERVAL,
|
|
@@ -29,8 +29,8 @@ const OTEL_ENABLED = !!process.env.DD_TRACE_OTEL_ENABLED
|
|
|
29
29
|
const ALLOWED = ['string', 'number', 'boolean']
|
|
30
30
|
|
|
31
31
|
const integrationCounters = {
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
spans_created: {},
|
|
33
|
+
spans_finished: {}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const finishCh = channel('dd-trace:span:finish')
|
|
@@ -72,7 +72,7 @@ class DatadogSpan {
|
|
|
72
72
|
this._name = operationName
|
|
73
73
|
this._integrationName = fields.integrationName || 'opentracing'
|
|
74
74
|
|
|
75
|
-
getIntegrationCounter('
|
|
75
|
+
getIntegrationCounter('spans_created', this._integrationName).inc()
|
|
76
76
|
|
|
77
77
|
this._spanContext = this._createContext(parent, fields)
|
|
78
78
|
this._spanContext._name = operationName
|
|
@@ -172,7 +172,7 @@ class DatadogSpan {
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
getIntegrationCounter('
|
|
175
|
+
getIntegrationCounter('spans_finished', this._integrationName).inc()
|
|
176
176
|
|
|
177
177
|
if (DD_TRACE_EXPERIMENTAL_SPAN_COUNTS && finishedRegistry) {
|
|
178
178
|
runtimeMetrics.decrement('runtime.node.spans.unfinished')
|