dd-trace 5.5.0 → 5.6.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/README.md +7 -0
- package/ci/cypress/after-spec.js +1 -0
- package/index.d.ts +1498 -1488
- package/package.json +3 -3
- package/packages/datadog-core/src/utils/src/get.js +11 -0
- package/packages/datadog-core/src/utils/src/has.js +14 -0
- package/packages/datadog-core/src/utils/src/set.js +16 -0
- package/packages/datadog-instrumentations/src/amqplib.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +2 -1
- package/packages/datadog-instrumentations/src/grpc/server.js +3 -1
- package/packages/datadog-instrumentations/src/jest.js +11 -5
- package/packages/datadog-instrumentations/src/mocha.js +4 -1
- package/packages/datadog-instrumentations/src/mongodb-core.js +34 -3
- package/packages/datadog-instrumentations/src/playwright.js +78 -16
- package/packages/datadog-plugin-amqplib/src/consumer.js +5 -4
- package/packages/datadog-plugin-amqplib/src/producer.js +3 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -11
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -6
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +5 -7
- package/packages/datadog-plugin-cypress/src/after-spec.js +3 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +123 -58
- package/packages/datadog-plugin-cypress/src/support.js +50 -3
- package/packages/datadog-plugin-graphql/src/index.js +1 -1
- package/packages/datadog-plugin-graphql/src/resolve.js +10 -8
- package/packages/datadog-plugin-grpc/src/util.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +11 -2
- package/packages/datadog-plugin-kafkajs/src/consumer.js +4 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -5
- package/packages/datadog-plugin-playwright/src/index.js +34 -3
- package/packages/datadog-plugin-rhea/src/consumer.js +5 -3
- package/packages/datadog-plugin-rhea/src/producer.js +3 -4
- package/packages/dd-trace/src/appsec/iast/index.js +10 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +18 -5
- package/packages/dd-trace/src/appsec/recommended.json +67 -27
- package/packages/dd-trace/src/appsec/remote_config/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -3
- package/packages/dd-trace/src/config.js +451 -460
- package/packages/dd-trace/src/data_streams_context.js +1 -1
- package/packages/dd-trace/src/datastreams/pathway.js +58 -1
- package/packages/dd-trace/src/datastreams/processor.js +3 -5
- package/packages/dd-trace/src/format.js +0 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -1
- package/packages/dd-trace/src/plugins/util/test.js +2 -0
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +38 -2
- package/packages/dd-trace/src/telemetry/index.js +22 -34
- package/packages/dd-trace/src/tracer.js +3 -3
- package/register.js +4 -0
- /package/packages/{utils → datadog-core/src/utils}/src/kebabcase.js +0 -0
- /package/packages/{utils → datadog-core/src/utils}/src/pick.js +0 -0
- /package/packages/{utils → datadog-core/src/utils}/src/uniq.js +0 -0
|
@@ -25,7 +25,10 @@ const {
|
|
|
25
25
|
TEST_ITR_UNSKIPPABLE,
|
|
26
26
|
TEST_ITR_FORCED_RUN,
|
|
27
27
|
ITR_CORRELATION_ID,
|
|
28
|
-
TEST_SOURCE_FILE
|
|
28
|
+
TEST_SOURCE_FILE,
|
|
29
|
+
TEST_IS_NEW,
|
|
30
|
+
TEST_EARLY_FLAKE_IS_RETRY,
|
|
31
|
+
TEST_EARLY_FLAKE_IS_ENABLED
|
|
29
32
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
30
33
|
const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')
|
|
31
34
|
const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
|
|
@@ -113,12 +116,9 @@ function getLibraryConfiguration (tracer, testConfiguration) {
|
|
|
113
116
|
})
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
function getSkippableTests (
|
|
117
|
-
if (!isSuitesSkippingEnabled) {
|
|
118
|
-
return Promise.resolve({ skippableTests: [] })
|
|
119
|
-
}
|
|
119
|
+
function getSkippableTests (tracer, testConfiguration) {
|
|
120
120
|
return new Promise(resolve => {
|
|
121
|
-
if (!tracer._tracer._exporter?.
|
|
121
|
+
if (!tracer._tracer._exporter?.getSkippableSuites) {
|
|
122
122
|
return resolve({ err: new Error('CI Visibility was not initialized correctly') })
|
|
123
123
|
}
|
|
124
124
|
tracer._tracer._exporter.getSkippableSuites(testConfiguration, (err, skippableTests, correlationId) => {
|
|
@@ -131,6 +131,20 @@ function getSkippableTests (isSuitesSkippingEnabled, tracer, testConfiguration)
|
|
|
131
131
|
})
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
function getKnownTests (tracer, testConfiguration) {
|
|
135
|
+
return new Promise(resolve => {
|
|
136
|
+
if (!tracer._tracer._exporter?.getKnownTests) {
|
|
137
|
+
return resolve({ err: new Error('CI Visibility was not initialized correctly') })
|
|
138
|
+
}
|
|
139
|
+
tracer._tracer._exporter.getKnownTests(testConfiguration, (err, knownTests) => {
|
|
140
|
+
resolve({
|
|
141
|
+
err,
|
|
142
|
+
knownTests
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
|
|
134
148
|
function getSuiteStatus (suiteStats) {
|
|
135
149
|
if (!suiteStats) {
|
|
136
150
|
return 'skip'
|
|
@@ -183,10 +197,14 @@ class CypressPlugin {
|
|
|
183
197
|
this.isTestsSkipped = false
|
|
184
198
|
this.isSuitesSkippingEnabled = false
|
|
185
199
|
this.isCodeCoverageEnabled = false
|
|
200
|
+
this.isEarlyFlakeDetectionEnabled = false
|
|
201
|
+
this.earlyFlakeDetectionNumRetries = 0
|
|
202
|
+
this.testsToSkip = []
|
|
186
203
|
this.skippedTests = []
|
|
187
204
|
this.hasForcedToRunSuites = false
|
|
188
205
|
this.hasUnskippableSuites = false
|
|
189
206
|
this.unskippableSuites = []
|
|
207
|
+
this.knownTests = []
|
|
190
208
|
}
|
|
191
209
|
|
|
192
210
|
init (tracer, cypressConfig) {
|
|
@@ -274,66 +292,101 @@ class CypressPlugin {
|
|
|
274
292
|
})
|
|
275
293
|
}
|
|
276
294
|
|
|
277
|
-
|
|
295
|
+
isNewTest (testName, testSuite) {
|
|
296
|
+
return !this.knownTestsByTestSuite?.[testSuite]?.includes(testName)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async beforeRun (details) {
|
|
278
300
|
this.command = getCypressCommand(details)
|
|
279
301
|
this.frameworkVersion = getCypressVersion(details)
|
|
280
302
|
this.rootDir = getRootDir(details)
|
|
281
303
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
304
|
+
const libraryConfigurationResponse = await getLibraryConfiguration(this.tracer, this.testConfiguration)
|
|
305
|
+
|
|
306
|
+
if (libraryConfigurationResponse.err) {
|
|
307
|
+
log.error(libraryConfigurationResponse.err)
|
|
308
|
+
} else {
|
|
309
|
+
const {
|
|
310
|
+
libraryConfig: {
|
|
311
|
+
isSuitesSkippingEnabled,
|
|
312
|
+
isCodeCoverageEnabled,
|
|
313
|
+
isEarlyFlakeDetectionEnabled,
|
|
314
|
+
earlyFlakeDetectionNumRetries
|
|
315
|
+
}
|
|
316
|
+
} = libraryConfigurationResponse
|
|
317
|
+
this.isSuitesSkippingEnabled = isSuitesSkippingEnabled
|
|
318
|
+
this.isCodeCoverageEnabled = isCodeCoverageEnabled
|
|
319
|
+
this.isEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
|
|
320
|
+
this.earlyFlakeDetectionNumRetries = earlyFlakeDetectionNumRetries
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (this.isEarlyFlakeDetectionEnabled) {
|
|
324
|
+
const knownTestsResponse = await getKnownTests(
|
|
325
|
+
this.tracer,
|
|
326
|
+
this.testConfiguration
|
|
327
|
+
)
|
|
328
|
+
if (knownTestsResponse.err) {
|
|
329
|
+
log.error(knownTestsResponse.err)
|
|
285
330
|
} else {
|
|
286
|
-
|
|
287
|
-
this.
|
|
331
|
+
// We use TEST_FRAMEWORK_NAME for the name of the module
|
|
332
|
+
this.knownTestsByTestSuite = knownTestsResponse.knownTests[TEST_FRAMEWORK_NAME]
|
|
288
333
|
}
|
|
334
|
+
}
|
|
289
335
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
336
|
+
if (this.isSuitesSkippingEnabled) {
|
|
337
|
+
const skippableTestsResponse = await getSkippableTests(
|
|
338
|
+
this.tracer,
|
|
339
|
+
this.testConfiguration
|
|
340
|
+
)
|
|
341
|
+
if (skippableTestsResponse.err) {
|
|
342
|
+
log.error(skippableTestsResponse.err)
|
|
343
|
+
} else {
|
|
344
|
+
const { skippableTests, correlationId } = skippableTestsResponse
|
|
345
|
+
this.testsToSkip = skippableTests || []
|
|
346
|
+
this.itrCorrelationId = correlationId
|
|
347
|
+
}
|
|
348
|
+
}
|
|
298
349
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
350
|
+
// `details.specs` are test files
|
|
351
|
+
details.specs?.forEach(({ absolute, relative }) => {
|
|
352
|
+
const isUnskippableSuite = isMarkedAsUnskippable({ path: absolute })
|
|
353
|
+
if (isUnskippableSuite) {
|
|
354
|
+
this.unskippableSuites.push(relative)
|
|
355
|
+
}
|
|
356
|
+
})
|
|
306
357
|
|
|
307
|
-
|
|
358
|
+
const childOf = getTestParentSpan(this.tracer)
|
|
308
359
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
360
|
+
const testSessionSpanMetadata =
|
|
361
|
+
getTestSessionCommonTags(this.command, this.frameworkVersion, TEST_FRAMEWORK_NAME)
|
|
362
|
+
const testModuleSpanMetadata =
|
|
363
|
+
getTestModuleCommonTags(this.command, this.frameworkVersion, TEST_FRAMEWORK_NAME)
|
|
313
364
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
318
|
-
...this.testEnvironmentMetadata,
|
|
319
|
-
...testSessionSpanMetadata
|
|
320
|
-
}
|
|
321
|
-
})
|
|
322
|
-
this.ciVisEvent(TELEMETRY_EVENT_CREATED, 'session')
|
|
323
|
-
|
|
324
|
-
this.testModuleSpan = this.tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_module`, {
|
|
325
|
-
childOf: this.testSessionSpan,
|
|
326
|
-
tags: {
|
|
327
|
-
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
328
|
-
...this.testEnvironmentMetadata,
|
|
329
|
-
...testModuleSpanMetadata
|
|
330
|
-
}
|
|
331
|
-
})
|
|
332
|
-
this.ciVisEvent(TELEMETRY_EVENT_CREATED, 'module')
|
|
365
|
+
if (this.isEarlyFlakeDetectionEnabled) {
|
|
366
|
+
testSessionSpanMetadata[TEST_EARLY_FLAKE_IS_ENABLED] = 'true'
|
|
367
|
+
}
|
|
333
368
|
|
|
334
|
-
|
|
335
|
-
|
|
369
|
+
this.testSessionSpan = this.tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_session`, {
|
|
370
|
+
childOf,
|
|
371
|
+
tags: {
|
|
372
|
+
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
373
|
+
...this.testEnvironmentMetadata,
|
|
374
|
+
...testSessionSpanMetadata
|
|
375
|
+
}
|
|
336
376
|
})
|
|
377
|
+
this.ciVisEvent(TELEMETRY_EVENT_CREATED, 'session')
|
|
378
|
+
|
|
379
|
+
this.testModuleSpan = this.tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_module`, {
|
|
380
|
+
childOf: this.testSessionSpan,
|
|
381
|
+
tags: {
|
|
382
|
+
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
383
|
+
...this.testEnvironmentMetadata,
|
|
384
|
+
...testModuleSpanMetadata
|
|
385
|
+
}
|
|
386
|
+
})
|
|
387
|
+
this.ciVisEvent(TELEMETRY_EVENT_CREATED, 'module')
|
|
388
|
+
|
|
389
|
+
return details
|
|
337
390
|
}
|
|
338
391
|
|
|
339
392
|
afterRun (suiteStats) {
|
|
@@ -471,12 +524,18 @@ class CypressPlugin {
|
|
|
471
524
|
|
|
472
525
|
getTasks () {
|
|
473
526
|
return {
|
|
474
|
-
'dd:testSuiteStart': (
|
|
527
|
+
'dd:testSuiteStart': (testSuite) => {
|
|
528
|
+
const suitePayload = {
|
|
529
|
+
isEarlyFlakeDetectionEnabled: this.isEarlyFlakeDetectionEnabled,
|
|
530
|
+
knownTestsForSuite: this.knownTestsByTestSuite?.[testSuite] || [],
|
|
531
|
+
earlyFlakeDetectionNumRetries: this.earlyFlakeDetectionNumRetries
|
|
532
|
+
}
|
|
533
|
+
|
|
475
534
|
if (this.testSuiteSpan) {
|
|
476
|
-
return
|
|
535
|
+
return suitePayload
|
|
477
536
|
}
|
|
478
|
-
this.testSuiteSpan = this.getTestSuiteSpan(
|
|
479
|
-
return
|
|
537
|
+
this.testSuiteSpan = this.getTestSuiteSpan(testSuite)
|
|
538
|
+
return suitePayload
|
|
480
539
|
},
|
|
481
540
|
'dd:beforeEach': (test) => {
|
|
482
541
|
const { testName, testSuite } = test
|
|
@@ -500,7 +559,7 @@ class CypressPlugin {
|
|
|
500
559
|
return this.activeTestSpan ? { traceId: this.activeTestSpan.context().toTraceId() } : {}
|
|
501
560
|
},
|
|
502
561
|
'dd:afterEach': ({ test, coverage }) => {
|
|
503
|
-
const { state, error, isRUMActive, testSourceLine, testSuite, testName } = test
|
|
562
|
+
const { state, error, isRUMActive, testSourceLine, testSuite, testName, isNew, isEfdRetry } = test
|
|
504
563
|
if (this.activeTestSpan) {
|
|
505
564
|
if (coverage && this.isCodeCoverageEnabled && this.tracer._tracer._exporter?.exportCoverage) {
|
|
506
565
|
const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
|
|
@@ -530,6 +589,12 @@ class CypressPlugin {
|
|
|
530
589
|
if (testSourceLine) {
|
|
531
590
|
this.activeTestSpan.setTag(TEST_SOURCE_START, testSourceLine)
|
|
532
591
|
}
|
|
592
|
+
if (isNew) {
|
|
593
|
+
this.activeTestSpan.setTag(TEST_IS_NEW, 'true')
|
|
594
|
+
if (isEfdRetry) {
|
|
595
|
+
this.activeTestSpan.setTag(TEST_EARLY_FLAKE_IS_RETRY, 'true')
|
|
596
|
+
}
|
|
597
|
+
}
|
|
533
598
|
const finishedTest = {
|
|
534
599
|
testName,
|
|
535
600
|
testStatus,
|
|
@@ -1,4 +1,43 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
+
let isEarlyFlakeDetectionEnabled = false
|
|
3
|
+
let knownTestsForSuite = []
|
|
4
|
+
let suiteTests = []
|
|
5
|
+
let earlyFlakeDetectionNumRetries = 0
|
|
6
|
+
|
|
7
|
+
function isNewTest (test) {
|
|
8
|
+
return !knownTestsForSuite.includes(test.fullTitle())
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function retryTest (test, suiteTests) {
|
|
12
|
+
for (let retryIndex = 0; retryIndex < earlyFlakeDetectionNumRetries; retryIndex++) {
|
|
13
|
+
const clonedTest = test.clone()
|
|
14
|
+
// TODO: signal in framework logs that this is a retry.
|
|
15
|
+
// TODO: Change it so these tests are allowed to fail.
|
|
16
|
+
// TODO: figure out if reported duration is skewed.
|
|
17
|
+
suiteTests.unshift(clonedTest)
|
|
18
|
+
clonedTest._ddIsNew = true
|
|
19
|
+
clonedTest._ddIsEfdRetry = true
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
const oldRunTests = Cypress.mocha.getRunner().runTests
|
|
25
|
+
Cypress.mocha.getRunner().runTests = function (suite, fn) {
|
|
26
|
+
if (!isEarlyFlakeDetectionEnabled) {
|
|
27
|
+
return oldRunTests.apply(this, arguments)
|
|
28
|
+
}
|
|
29
|
+
// We copy the new tests at the beginning of the suite run (runTests), so that they're run
|
|
30
|
+
// multiple times.
|
|
31
|
+
suite.tests.forEach(test => {
|
|
32
|
+
if (!test._ddIsNew && !test.isPending() && isNewTest(test)) {
|
|
33
|
+
test._ddIsNew = true
|
|
34
|
+
retryTest(test, suite.tests)
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
return oldRunTests.apply(this, [suite, fn])
|
|
39
|
+
}
|
|
40
|
+
|
|
2
41
|
beforeEach(function () {
|
|
3
42
|
cy.task('dd:beforeEach', {
|
|
4
43
|
testName: Cypress.mocha.getRunner().suite.ctx.currentTest.fullTitle(),
|
|
@@ -11,8 +50,14 @@ beforeEach(function () {
|
|
|
11
50
|
})
|
|
12
51
|
})
|
|
13
52
|
|
|
14
|
-
before(()
|
|
15
|
-
cy.task('dd:testSuiteStart', Cypress.mocha.getRootSuite().file)
|
|
53
|
+
before(function () {
|
|
54
|
+
cy.task('dd:testSuiteStart', Cypress.mocha.getRootSuite().file).then((suiteConfig) => {
|
|
55
|
+
if (suiteConfig) {
|
|
56
|
+
isEarlyFlakeDetectionEnabled = suiteConfig.isEarlyFlakeDetectionEnabled
|
|
57
|
+
knownTestsForSuite = suiteConfig.knownTestsForSuite
|
|
58
|
+
earlyFlakeDetectionNumRetries = suiteConfig.earlyFlakeDetectionNumRetries
|
|
59
|
+
}
|
|
60
|
+
})
|
|
16
61
|
})
|
|
17
62
|
|
|
18
63
|
after(() => {
|
|
@@ -24,7 +69,7 @@ after(() => {
|
|
|
24
69
|
})
|
|
25
70
|
|
|
26
71
|
|
|
27
|
-
afterEach(()
|
|
72
|
+
afterEach(function () {
|
|
28
73
|
cy.window().then(win => {
|
|
29
74
|
const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest
|
|
30
75
|
const testInfo = {
|
|
@@ -32,6 +77,8 @@ afterEach(() => {
|
|
|
32
77
|
testSuite: Cypress.mocha.getRootSuite().file,
|
|
33
78
|
state: currentTest.state,
|
|
34
79
|
error: currentTest.err,
|
|
80
|
+
isNew: currentTest._ddIsNew,
|
|
81
|
+
isEfdRetry: currentTest._ddIsEfdRetry
|
|
35
82
|
}
|
|
36
83
|
try {
|
|
37
84
|
testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const pick = require('../../utils/src/pick')
|
|
3
|
+
const pick = require('../../datadog-core/src/utils/src/pick')
|
|
4
4
|
const CompositePlugin = require('../../dd-trace/src/plugins/composite')
|
|
5
5
|
const log = require('../../dd-trace/src/log')
|
|
6
6
|
const GraphQLExecutePlugin = require('./execute')
|
|
@@ -122,15 +122,17 @@ function getResolverInfo (info, args) {
|
|
|
122
122
|
Object.assign(resolverVars, args)
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
const directives = info.fieldNodes[0]
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
125
|
+
const directives = info.fieldNodes?.[0]?.directives
|
|
126
|
+
if (Array.isArray(directives)) {
|
|
127
|
+
for (const directive of directives) {
|
|
128
|
+
const argList = {}
|
|
129
|
+
for (const argument of directive['arguments']) {
|
|
130
|
+
argList[argument.name.value] = argument.value.value
|
|
131
|
+
}
|
|
131
132
|
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
if (Object.keys(argList).length) {
|
|
134
|
+
resolverVars[directive.name.value] = argList
|
|
135
|
+
}
|
|
134
136
|
}
|
|
135
137
|
}
|
|
136
138
|
|
|
@@ -18,7 +18,8 @@ const {
|
|
|
18
18
|
TEST_SOURCE_FILE,
|
|
19
19
|
TEST_IS_NEW,
|
|
20
20
|
TEST_EARLY_FLAKE_IS_RETRY,
|
|
21
|
-
TEST_EARLY_FLAKE_IS_ENABLED
|
|
21
|
+
TEST_EARLY_FLAKE_IS_ENABLED,
|
|
22
|
+
JEST_DISPLAY_NAME
|
|
22
23
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
23
24
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
24
25
|
const id = require('../../dd-trace/src/id')
|
|
@@ -144,7 +145,7 @@ class JestPlugin extends CiPlugin {
|
|
|
144
145
|
})
|
|
145
146
|
})
|
|
146
147
|
|
|
147
|
-
this.addSub('ci:jest:test-suite:start', ({ testSuite, testEnvironmentOptions, frameworkVersion }) => {
|
|
148
|
+
this.addSub('ci:jest:test-suite:start', ({ testSuite, testEnvironmentOptions, frameworkVersion, displayName }) => {
|
|
148
149
|
const {
|
|
149
150
|
_ddTestSessionId: testSessionId,
|
|
150
151
|
_ddTestCommand: testCommand,
|
|
@@ -179,6 +180,9 @@ class JestPlugin extends CiPlugin {
|
|
|
179
180
|
if (itrCorrelationId) {
|
|
180
181
|
testSuiteMetadata[ITR_CORRELATION_ID] = itrCorrelationId
|
|
181
182
|
}
|
|
183
|
+
if (displayName) {
|
|
184
|
+
testSuiteMetadata[JEST_DISPLAY_NAME] = displayName
|
|
185
|
+
}
|
|
182
186
|
|
|
183
187
|
this.testSuiteSpan = this.tracer.startSpan('jest.test_suite', {
|
|
184
188
|
childOf: testSessionSpanContext,
|
|
@@ -308,6 +312,7 @@ class JestPlugin extends CiPlugin {
|
|
|
308
312
|
suite,
|
|
309
313
|
name,
|
|
310
314
|
runner,
|
|
315
|
+
displayName,
|
|
311
316
|
testParameters,
|
|
312
317
|
frameworkVersion,
|
|
313
318
|
testStartLine,
|
|
@@ -327,6 +332,10 @@ class JestPlugin extends CiPlugin {
|
|
|
327
332
|
// If for whatever we don't have the source file, we'll fall back to the suite name
|
|
328
333
|
extraTags[TEST_SOURCE_FILE] = testSourceFile || suite
|
|
329
334
|
|
|
335
|
+
if (displayName) {
|
|
336
|
+
extraTags[JEST_DISPLAY_NAME] = displayName
|
|
337
|
+
}
|
|
338
|
+
|
|
330
339
|
if (isNew) {
|
|
331
340
|
extraTags[TEST_IS_NEW] = 'true'
|
|
332
341
|
if (isEfdRetry) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const dc = require('dc-polyfill')
|
|
4
|
-
const { getMessageSize
|
|
4
|
+
const { getMessageSize } = require('../../dd-trace/src/datastreams/processor')
|
|
5
|
+
const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
|
|
5
6
|
const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
|
|
6
7
|
|
|
7
8
|
const afterStartCh = dc.channel('dd-trace:kafkajs:consumer:afterStart')
|
|
@@ -77,9 +78,9 @@ class KafkajsConsumerPlugin extends ConsumerPlugin {
|
|
|
77
78
|
'kafka.partition': partition
|
|
78
79
|
}
|
|
79
80
|
})
|
|
80
|
-
if (this.config.dsmEnabled) {
|
|
81
|
+
if (this.config.dsmEnabled && message?.headers && DsmPathwayCodec.contextExists(message.headers)) {
|
|
81
82
|
const payloadSize = getMessageSize(message)
|
|
82
|
-
this.tracer.decodeDataStreamsContext(message.headers
|
|
83
|
+
this.tracer.decodeDataStreamsContext(message.headers)
|
|
83
84
|
this.tracer
|
|
84
85
|
.setCheckpoint(['direction:in', `group:${groupId}`, `topic:${topic}`, 'type:kafka'], span, payloadSize)
|
|
85
86
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
|
|
4
|
-
const {
|
|
5
|
-
const { getMessageSize
|
|
4
|
+
const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
|
|
5
|
+
const { getMessageSize } = require('../../dd-trace/src/datastreams/processor')
|
|
6
6
|
|
|
7
7
|
const BOOTSTRAP_SERVERS_KEY = 'messaging.kafka.bootstrap.servers'
|
|
8
8
|
|
|
@@ -67,7 +67,6 @@ class KafkajsProducerPlugin extends ProducerPlugin {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
start ({ topic, messages, bootstrapServers }) {
|
|
70
|
-
let pathwayCtx
|
|
71
70
|
const span = this.startSpan({
|
|
72
71
|
resource: topic,
|
|
73
72
|
meta: {
|
|
@@ -88,8 +87,7 @@ class KafkajsProducerPlugin extends ProducerPlugin {
|
|
|
88
87
|
const payloadSize = getMessageSize(message)
|
|
89
88
|
const dataStreamsContext = this.tracer
|
|
90
89
|
.setCheckpoint(['direction:out', `topic:${topic}`, 'type:kafka'], span, payloadSize)
|
|
91
|
-
|
|
92
|
-
message.headers[CONTEXT_PROPAGATION_KEY] = pathwayCtx
|
|
90
|
+
DsmPathwayCodec.encode(dataStreamsContext, message.headers)
|
|
93
91
|
}
|
|
94
92
|
}
|
|
95
93
|
}
|
|
@@ -30,11 +30,23 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
30
30
|
super(...args)
|
|
31
31
|
|
|
32
32
|
this._testSuites = new Map()
|
|
33
|
+
this.numFailedTests = 0
|
|
34
|
+
this.numFailedSuites = 0
|
|
33
35
|
|
|
34
36
|
this.addSub('ci:playwright:session:finish', ({ status, onDone }) => {
|
|
35
37
|
this.testModuleSpan.setTag(TEST_STATUS, status)
|
|
36
38
|
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
37
39
|
|
|
40
|
+
if (this.numFailedSuites > 0) {
|
|
41
|
+
let errorMessage = `Test suites failed: ${this.numFailedSuites}.`
|
|
42
|
+
if (this.numFailedTests > 0) {
|
|
43
|
+
errorMessage += ` Tests failed: ${this.numFailedTests}`
|
|
44
|
+
}
|
|
45
|
+
const error = new Error(errorMessage)
|
|
46
|
+
this.testModuleSpan.setTag('error', error)
|
|
47
|
+
this.testSessionSpan.setTag('error', error)
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
this.testModuleSpan.finish()
|
|
39
51
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
40
52
|
this.testSessionSpan.finish()
|
|
@@ -42,6 +54,7 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
42
54
|
finishAllTraceSpans(this.testSessionSpan)
|
|
43
55
|
appClosingTelemetry()
|
|
44
56
|
this.tracer._exporter.flush(onDone)
|
|
57
|
+
this.numFailedTests = 0
|
|
45
58
|
})
|
|
46
59
|
|
|
47
60
|
this.addSub('ci:playwright:test-suite:start', (testSuiteAbsolutePath) => {
|
|
@@ -69,11 +82,21 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
69
82
|
this._testSuites.set(testSuite, testSuiteSpan)
|
|
70
83
|
})
|
|
71
84
|
|
|
72
|
-
this.addSub('ci:playwright:test-suite:finish', (status) => {
|
|
85
|
+
this.addSub('ci:playwright:test-suite:finish', ({ status, error }) => {
|
|
73
86
|
const store = storage.getStore()
|
|
74
87
|
const span = store && store.span
|
|
75
88
|
if (!span) return
|
|
76
|
-
|
|
89
|
+
if (error) {
|
|
90
|
+
span.setTag('error', error)
|
|
91
|
+
span.setTag(TEST_STATUS, 'fail')
|
|
92
|
+
} else {
|
|
93
|
+
span.setTag(TEST_STATUS, status)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (status === 'fail' || error) {
|
|
97
|
+
this.numFailedSuites++
|
|
98
|
+
}
|
|
99
|
+
|
|
77
100
|
span.finish()
|
|
78
101
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
79
102
|
})
|
|
@@ -114,11 +137,19 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
114
137
|
if (step.error) {
|
|
115
138
|
stepSpan.setTag('error', step.error)
|
|
116
139
|
}
|
|
117
|
-
|
|
140
|
+
let stepDuration = step.duration
|
|
141
|
+
if (stepDuration <= 0 || isNaN(stepDuration)) {
|
|
142
|
+
stepDuration = 0
|
|
143
|
+
}
|
|
144
|
+
stepSpan.finish(stepStartTime + stepDuration)
|
|
118
145
|
})
|
|
119
146
|
|
|
120
147
|
span.finish()
|
|
121
148
|
|
|
149
|
+
if (testStatus === 'fail') {
|
|
150
|
+
this.numFailedTests++
|
|
151
|
+
}
|
|
152
|
+
|
|
122
153
|
this.telemetry.ciVisEvent(
|
|
123
154
|
TELEMETRY_EVENT_FINISHED,
|
|
124
155
|
'test',
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
|
-
const { getAmqpMessageSize
|
|
5
|
+
const { getAmqpMessageSize } = require('../../dd-trace/src/datastreams/processor')
|
|
6
|
+
const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
|
|
6
7
|
|
|
7
8
|
class RheaConsumerPlugin extends ConsumerPlugin {
|
|
8
9
|
static get id () { return 'rhea' }
|
|
@@ -33,12 +34,13 @@ class RheaConsumerPlugin extends ConsumerPlugin {
|
|
|
33
34
|
|
|
34
35
|
if (
|
|
35
36
|
this.config.dsmEnabled &&
|
|
36
|
-
msgObj?.message?.delivery_annotations
|
|
37
|
+
msgObj?.message?.delivery_annotations &&
|
|
38
|
+
DsmPathwayCodec.contextExists(msgObj.message.delivery_annotations)
|
|
37
39
|
) {
|
|
38
40
|
const payloadSize = getAmqpMessageSize(
|
|
39
41
|
{ headers: msgObj.message.delivery_annotations, content: msgObj.message.body }
|
|
40
42
|
)
|
|
41
|
-
this.tracer.decodeDataStreamsContext(msgObj.message.delivery_annotations
|
|
43
|
+
this.tracer.decodeDataStreamsContext(msgObj.message.delivery_annotations)
|
|
42
44
|
this.tracer
|
|
43
45
|
.setCheckpoint(['direction:in', `topic:${name}`, 'type:rabbitmq'], span, payloadSize)
|
|
44
46
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
|
|
4
4
|
const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
|
|
5
|
-
const {
|
|
6
|
-
const { getAmqpMessageSize
|
|
5
|
+
const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
|
|
6
|
+
const { getAmqpMessageSize } = require('../../dd-trace/src/datastreams/processor')
|
|
7
7
|
|
|
8
8
|
class RheaProducerPlugin extends ProducerPlugin {
|
|
9
9
|
static get id () { return 'rhea' }
|
|
@@ -44,8 +44,7 @@ function addDeliveryAnnotations (msg, tracer, span) {
|
|
|
44
44
|
const payloadSize = getAmqpMessageSize({ content: msg.body, headers: msg.delivery_annotations })
|
|
45
45
|
const dataStreamsContext = tracer
|
|
46
46
|
.setCheckpoint(['direction:out', `exchange:${targetName}`, 'type:rabbitmq'], span, payloadSize)
|
|
47
|
-
|
|
48
|
-
msg.delivery_annotations[CONTEXT_PROPAGATION_KEY] = pathwayCtx
|
|
47
|
+
DsmPathwayCodec.encode(dataStreamsContext, msg.delivery_annotations)
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
50
|
}
|
|
@@ -21,7 +21,11 @@ const requestStart = dc.channel('dd-trace:incomingHttpRequestStart')
|
|
|
21
21
|
const requestClose = dc.channel('dd-trace:incomingHttpRequestEnd')
|
|
22
22
|
const iastResponseEnd = dc.channel('datadog:iast:response-end')
|
|
23
23
|
|
|
24
|
+
let isEnabled = false
|
|
25
|
+
|
|
24
26
|
function enable (config, _tracer) {
|
|
27
|
+
if (isEnabled) return
|
|
28
|
+
|
|
25
29
|
iastTelemetry.configure(config, config.iast?.telemetryVerbosity)
|
|
26
30
|
enableAllAnalyzers(config)
|
|
27
31
|
enableTaintTracking(config.iast, iastTelemetry.verbosity)
|
|
@@ -30,9 +34,15 @@ function enable (config, _tracer) {
|
|
|
30
34
|
overheadController.configure(config.iast)
|
|
31
35
|
overheadController.startGlobalContext()
|
|
32
36
|
vulnerabilityReporter.start(config, _tracer)
|
|
37
|
+
|
|
38
|
+
isEnabled = true
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
function disable () {
|
|
42
|
+
if (!isEnabled) return
|
|
43
|
+
|
|
44
|
+
isEnabled = false
|
|
45
|
+
|
|
36
46
|
iastTelemetry.stop()
|
|
37
47
|
disableAllAnalyzers()
|
|
38
48
|
disableTaintTracking()
|
|
@@ -65,16 +65,18 @@ function getRewriter (telemetryVerbosity) {
|
|
|
65
65
|
return rewriter
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
let originalPrepareStackTrace
|
|
68
|
+
let originalPrepareStackTrace
|
|
69
|
+
let actualPrepareStackTrace
|
|
69
70
|
function getPrepareStackTraceAccessor () {
|
|
70
|
-
|
|
71
|
+
originalPrepareStackTrace = Error.prepareStackTrace
|
|
72
|
+
actualPrepareStackTrace = getPrepareStackTrace(originalPrepareStackTrace)
|
|
71
73
|
return {
|
|
72
74
|
configurable: true,
|
|
73
75
|
get () {
|
|
74
|
-
return
|
|
76
|
+
return actualPrepareStackTrace
|
|
75
77
|
},
|
|
76
78
|
set (value) {
|
|
77
|
-
|
|
79
|
+
actualPrepareStackTrace = getPrepareStackTrace(value)
|
|
78
80
|
originalPrepareStackTrace = value
|
|
79
81
|
}
|
|
80
82
|
}
|
|
@@ -121,7 +123,18 @@ function enableRewriter (telemetryVerbosity) {
|
|
|
121
123
|
|
|
122
124
|
function disableRewriter () {
|
|
123
125
|
shimmer.unwrap(Module.prototype, '_compile')
|
|
124
|
-
|
|
126
|
+
|
|
127
|
+
if (!actualPrepareStackTrace) return
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
delete Error.prepareStackTrace
|
|
131
|
+
|
|
132
|
+
Error.prepareStackTrace = originalPrepareStackTrace
|
|
133
|
+
|
|
134
|
+
actualPrepareStackTrace = undefined
|
|
135
|
+
} catch (e) {
|
|
136
|
+
iastLog.warn(e)
|
|
137
|
+
}
|
|
125
138
|
}
|
|
126
139
|
|
|
127
140
|
function getOriginalPathAndLineFromSourceMap ({ path, line, column }) {
|