dd-trace 5.101.0 → 5.103.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/ext/exporters.js +1 -0
- package/package.json +20 -17
- package/packages/datadog-esbuild/src/utils.js +2 -2
- package/packages/datadog-instrumentations/src/aerospike.js +2 -2
- package/packages/datadog-instrumentations/src/ai.js +9 -9
- package/packages/datadog-instrumentations/src/amqplib.js +6 -7
- package/packages/datadog-instrumentations/src/anthropic.js +10 -10
- package/packages/datadog-instrumentations/src/apollo-server-core.js +3 -3
- package/packages/datadog-instrumentations/src/apollo-server.js +5 -5
- package/packages/datadog-instrumentations/src/avsc.js +6 -6
- package/packages/datadog-instrumentations/src/aws-sdk.js +151 -67
- package/packages/datadog-instrumentations/src/azure-durable-functions.js +8 -8
- package/packages/datadog-instrumentations/src/bluebird.js +2 -2
- package/packages/datadog-instrumentations/src/body-parser.js +2 -2
- package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
- package/packages/datadog-instrumentations/src/child_process.js +12 -12
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +41 -24
- package/packages/datadog-instrumentations/src/connect.js +7 -7
- package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
- package/packages/datadog-instrumentations/src/cookie.js +2 -2
- package/packages/datadog-instrumentations/src/couchbase.js +73 -238
- package/packages/datadog-instrumentations/src/crypto.js +4 -4
- package/packages/datadog-instrumentations/src/cucumber.js +78 -17
- package/packages/datadog-instrumentations/src/dns.js +0 -3
- package/packages/datadog-instrumentations/src/elasticsearch.js +8 -11
- package/packages/datadog-instrumentations/src/electron/preload.js +42 -0
- package/packages/datadog-instrumentations/src/electron.js +240 -0
- package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +6 -6
- package/packages/datadog-instrumentations/src/express-session.js +4 -4
- package/packages/datadog-instrumentations/src/express.js +10 -11
- package/packages/datadog-instrumentations/src/fastify.js +2 -2
- package/packages/datadog-instrumentations/src/fetch.js +5 -5
- package/packages/datadog-instrumentations/src/fs.js +14 -14
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +5 -7
- package/packages/datadog-instrumentations/src/google-genai.js +4 -4
- package/packages/datadog-instrumentations/src/graphql.js +13 -12
- package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
- package/packages/datadog-instrumentations/src/hapi.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +9 -9
- package/packages/datadog-instrumentations/src/helpers/hook.js +4 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/kafka.js +41 -0
- package/packages/datadog-instrumentations/src/helpers/promise.js +2 -2
- package/packages/datadog-instrumentations/src/hono.js +2 -2
- package/packages/datadog-instrumentations/src/http/client.js +6 -6
- package/packages/datadog-instrumentations/src/http/server.js +9 -9
- package/packages/datadog-instrumentations/src/ioredis.js +16 -12
- package/packages/datadog-instrumentations/src/jest.js +382 -81
- package/packages/datadog-instrumentations/src/kafkajs.js +165 -174
- package/packages/datadog-instrumentations/src/knex.js +17 -17
- package/packages/datadog-instrumentations/src/koa.js +12 -12
- package/packages/datadog-instrumentations/src/ldapjs.js +5 -5
- package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
- package/packages/datadog-instrumentations/src/limitd-client.js +4 -4
- package/packages/datadog-instrumentations/src/lodash.js +4 -4
- package/packages/datadog-instrumentations/src/mariadb.js +13 -13
- package/packages/datadog-instrumentations/src/memcached.js +2 -2
- package/packages/datadog-instrumentations/src/microgateway-core.js +2 -2
- package/packages/datadog-instrumentations/src/mocha/common.js +3 -3
- package/packages/datadog-instrumentations/src/mocha/main.js +85 -11
- package/packages/datadog-instrumentations/src/mocha/utils.js +133 -16
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
- package/packages/datadog-instrumentations/src/mongodb-core.js +42 -30
- package/packages/datadog-instrumentations/src/mongodb.js +5 -5
- package/packages/datadog-instrumentations/src/mongoose.js +21 -21
- package/packages/datadog-instrumentations/src/mquery.js +5 -5
- package/packages/datadog-instrumentations/src/multer.js +4 -4
- package/packages/datadog-instrumentations/src/mysql.js +16 -16
- package/packages/datadog-instrumentations/src/mysql2.js +4 -4
- package/packages/datadog-instrumentations/src/net.js +14 -8
- package/packages/datadog-instrumentations/src/nyc.js +5 -5
- package/packages/datadog-instrumentations/src/openai.js +19 -19
- package/packages/datadog-instrumentations/src/oracledb.js +6 -6
- package/packages/datadog-instrumentations/src/passport-utils.js +5 -5
- package/packages/datadog-instrumentations/src/pg.js +39 -25
- package/packages/datadog-instrumentations/src/pino.js +6 -10
- package/packages/datadog-instrumentations/src/playwright.js +445 -68
- package/packages/datadog-instrumentations/src/protobufjs.js +16 -16
- package/packages/datadog-instrumentations/src/redis.js +20 -12
- package/packages/datadog-instrumentations/src/restify.js +2 -2
- package/packages/datadog-instrumentations/src/router.js +12 -12
- package/packages/datadog-instrumentations/src/stripe.js +12 -12
- package/packages/datadog-instrumentations/src/vitest.js +107 -26
- package/packages/datadog-instrumentations/src/winston.js +4 -4
- package/packages/datadog-instrumentations/src/ws.js +7 -7
- package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -21
- package/packages/datadog-plugin-aws-sdk/src/base.js +70 -28
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +20 -13
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +46 -36
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +34 -23
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +14 -15
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +74 -55
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +20 -18
- package/packages/datadog-plugin-aws-sdk/src/util.js +22 -0
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -6
- package/packages/datadog-plugin-couchbase/src/index.js +58 -52
- package/packages/datadog-plugin-cucumber/src/index.js +5 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +215 -26
- package/packages/datadog-plugin-cypress/src/support.js +13 -1
- package/packages/datadog-plugin-electron/src/index.js +17 -0
- package/packages/datadog-plugin-electron/src/ipc.js +143 -0
- package/packages/datadog-plugin-electron/src/net.js +82 -0
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -5
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +27 -18
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +3 -1
- package/packages/datadog-plugin-graphql/src/execute.js +6 -28
- package/packages/datadog-plugin-graphql/src/resolve.js +30 -35
- package/packages/datadog-plugin-graphql/src/tools/signature.js +32 -7
- package/packages/datadog-plugin-graphql/src/tools/transforms.js +118 -100
- package/packages/datadog-plugin-graphql/src/utils.js +29 -0
- package/packages/datadog-plugin-grpc/src/client.js +6 -7
- package/packages/datadog-plugin-grpc/src/util.js +57 -22
- package/packages/datadog-plugin-http/src/client.js +3 -7
- package/packages/datadog-plugin-jest/src/index.js +92 -50
- package/packages/datadog-plugin-jest/src/util.js +1 -2
- package/packages/datadog-plugin-mocha/src/index.js +5 -0
- package/packages/datadog-plugin-mongodb-core/src/index.js +36 -69
- package/packages/datadog-plugin-mysql/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/services.js +2 -1
- package/packages/datadog-plugin-openai/src/tracing.js +12 -23
- package/packages/datadog-plugin-pg/src/index.js +3 -3
- package/packages/datadog-plugin-playwright/src/index.js +5 -1
- package/packages/datadog-plugin-redis/src/index.js +18 -23
- package/packages/datadog-plugin-vitest/src/index.js +8 -1
- package/packages/datadog-shimmer/src/shimmer.js +7 -1
- package/packages/dd-trace/src/aiguard/index.js +3 -1
- package/packages/dd-trace/src/aiguard/sdk.js +36 -30
- package/packages/dd-trace/src/aiguard/tags.js +20 -11
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +81 -81
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +4 -4
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +83 -48
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +21 -24
- package/packages/dd-trace/src/appsec/reporter.js +3 -1
- package/packages/dd-trace/src/appsec/rule_manager.js +4 -2
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +31 -16
- package/packages/dd-trace/src/azure_metadata.js +17 -6
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +4 -4
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +6 -4
- package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +1 -1
- package/packages/dd-trace/src/config/defaults.js +3 -14
- package/packages/dd-trace/src/config/generated-config-types.d.ts +3 -1
- package/packages/dd-trace/src/config/git_properties.js +2 -2
- package/packages/dd-trace/src/config/helper.js +4 -0
- package/packages/dd-trace/src/config/index.js +2 -2
- package/packages/dd-trace/src/config/major-overrides.js +98 -0
- package/packages/dd-trace/src/config/parsers.js +7 -1
- package/packages/dd-trace/src/config/supported-configurations.json +51 -38
- package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
- package/packages/dd-trace/src/datastreams/index.js +2 -1
- package/packages/dd-trace/src/datastreams/manager.js +1 -1
- package/packages/dd-trace/src/datastreams/processor.js +3 -4
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/state.js +2 -1
- package/packages/dd-trace/src/debugger/index.js +7 -7
- package/packages/dd-trace/src/dogstatsd.js +2 -2
- package/packages/dd-trace/src/encode/0.4.js +748 -232
- package/packages/dd-trace/src/encode/0.5.js +47 -10
- package/packages/dd-trace/src/encode/agentless-json.js +1 -1
- package/packages/dd-trace/src/exporter.js +2 -0
- package/packages/dd-trace/src/exporters/agent/index.js +2 -1
- package/packages/dd-trace/src/exporters/agentless/index.js +3 -2
- package/packages/dd-trace/src/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -1
- package/packages/dd-trace/src/exporters/common/request.js +1 -1
- package/packages/dd-trace/src/exporters/electron/index.js +49 -0
- package/packages/dd-trace/src/external-logger/src/index.js +2 -1
- package/packages/dd-trace/src/git_metadata.js +10 -8
- package/packages/dd-trace/src/lambda/handler-paths.js +52 -0
- package/packages/dd-trace/src/lambda/index.js +62 -14
- package/packages/dd-trace/src/lambda/runtime/patch.js +21 -46
- package/packages/dd-trace/src/llmobs/index.js +13 -2
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -2
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +45 -15
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +6 -3
- package/packages/dd-trace/src/llmobs/sdk.js +24 -26
- package/packages/dd-trace/src/llmobs/span_processor.js +25 -5
- package/packages/dd-trace/src/llmobs/util.js +1 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -1
- package/packages/dd-trace/src/msgpack/chunk.js +6 -3
- package/packages/dd-trace/src/openfeature/noop.js +40 -36
- package/packages/dd-trace/src/openfeature/writers/base.js +2 -1
- package/packages/dd-trace/src/openfeature/writers/exposures.js +33 -52
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +1 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +0 -22
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +20 -9
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -11
- package/packages/dd-trace/src/payload-tagging/config/index.js +2 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +49 -4
- package/packages/dd-trace/src/plugins/database.js +54 -12
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/plugin.js +2 -4
- package/packages/dd-trace/src/plugins/util/ci.js +9 -9
- package/packages/dd-trace/src/plugins/util/git-cache.js +23 -23
- package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -2
- package/packages/dd-trace/src/plugins/util/test.js +56 -12
- package/packages/dd-trace/src/plugins/util/url.js +1 -3
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +18 -16
- package/packages/dd-trace/src/plugins/util/web.js +5 -7
- package/packages/dd-trace/src/priority_sampler.js +1 -1
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +3 -23
- package/packages/dd-trace/src/profiling/profilers/wall.js +5 -6
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +1 -1
- package/packages/dd-trace/src/rate_limiter.js +1 -1
- package/packages/dd-trace/src/remote_config/scheduler.js +1 -1
- package/packages/dd-trace/src/ritm.js +2 -1
- package/packages/dd-trace/src/runtime_metrics/index.js +2 -2
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -8
- package/packages/dd-trace/src/scope.js +3 -10
- package/packages/dd-trace/src/serverless.js +6 -6
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +27 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +24 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
- package/packages/dd-trace/src/span_stats.js +1 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
- package/packages/dd-trace/src/telemetry/endpoints.js +1 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +2 -2
- package/packages/dd-trace/src/tracer.js +7 -7
- package/packages/dd-trace/src/lambda/runtime/ritm.js +0 -133
|
@@ -31,11 +31,13 @@ const {
|
|
|
31
31
|
TEST_SKIPPED_BY_ITR,
|
|
32
32
|
TEST_ITR_UNSKIPPABLE,
|
|
33
33
|
TEST_ITR_FORCED_RUN,
|
|
34
|
+
TEST_ITR_SKIPPING_ENABLED,
|
|
34
35
|
ITR_CORRELATION_ID,
|
|
35
36
|
TEST_SOURCE_FILE,
|
|
36
37
|
TEST_IS_NEW,
|
|
37
38
|
TEST_IS_RETRY,
|
|
38
39
|
TEST_EARLY_FLAKE_ENABLED,
|
|
40
|
+
TEST_EARLY_FLAKE_ABORT_REASON,
|
|
39
41
|
getTestSessionName,
|
|
40
42
|
TEST_SESSION_NAME,
|
|
41
43
|
TEST_LEVEL_EVENT_TYPES,
|
|
@@ -52,19 +54,26 @@ const {
|
|
|
52
54
|
getPullRequestDiff,
|
|
53
55
|
getModifiedFilesFromDiff,
|
|
54
56
|
getSessionRequestErrorTags,
|
|
55
|
-
|
|
57
|
+
DD_CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS,
|
|
58
|
+
DD_CI_LIBRARY_CONFIGURATION_ERROR_KNOWN_TESTS,
|
|
59
|
+
DD_CI_LIBRARY_CONFIGURATION_ERROR_SKIPPABLE_TESTS,
|
|
60
|
+
DD_CI_LIBRARY_CONFIGURATION_ERROR_TEST_MANAGEMENT_TESTS,
|
|
61
|
+
getSessionItrSkippingEnabledTags,
|
|
56
62
|
TEST_IS_MODIFIED,
|
|
57
63
|
TEST_HAS_DYNAMIC_NAME,
|
|
64
|
+
getIsFaultyEarlyFlakeDetection,
|
|
58
65
|
DYNAMIC_NAME_RE,
|
|
59
66
|
recordAttemptToFixExecution,
|
|
60
67
|
logAttemptToFixTestExecution,
|
|
61
68
|
logTestOptimizationSummary,
|
|
69
|
+
getEfdRetryCount,
|
|
70
|
+
getMaxEfdRetryCount,
|
|
62
71
|
getPullRequestBaseBranch,
|
|
63
72
|
TEST_FINAL_STATUS,
|
|
64
73
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
65
74
|
const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')
|
|
66
75
|
const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
|
|
67
|
-
const
|
|
76
|
+
const getConfig = require('../../dd-trace/src/config')
|
|
68
77
|
const { appClosing: appClosingTelemetry } = require('../../dd-trace/src/telemetry')
|
|
69
78
|
const log = require('../../dd-trace/src/log')
|
|
70
79
|
|
|
@@ -263,6 +272,36 @@ function getSuiteStatus (suiteStats) {
|
|
|
263
272
|
return 'pass'
|
|
264
273
|
}
|
|
265
274
|
|
|
275
|
+
function getMatchingCypressTest (cypressTests, testName, attemptIndex, testStatus, preferIndexedMatch = false) {
|
|
276
|
+
let matchingTestByIndex
|
|
277
|
+
let matchingTestByStatus
|
|
278
|
+
let matchingTestIndex = 0
|
|
279
|
+
|
|
280
|
+
for (const cypressTest of cypressTests) {
|
|
281
|
+
if (cypressTest.title.join(' ') !== testName) {
|
|
282
|
+
continue
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (matchingTestIndex === attemptIndex) {
|
|
286
|
+
matchingTestByIndex = cypressTest
|
|
287
|
+
}
|
|
288
|
+
matchingTestIndex++
|
|
289
|
+
|
|
290
|
+
if (!matchingTestByStatus && CYPRESS_STATUS_TO_TEST_STATUS[cypressTest.state] === testStatus) {
|
|
291
|
+
matchingTestByStatus = cypressTest
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return preferIndexedMatch
|
|
296
|
+
? matchingTestByIndex || matchingTestByStatus
|
|
297
|
+
: matchingTestByStatus || matchingTestByIndex
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function isCypressHookFailure (cypressTest) {
|
|
301
|
+
return CYPRESS_STATUS_TO_TEST_STATUS[cypressTest.state] === 'fail' &&
|
|
302
|
+
/\bhook\b/.test(String(cypressTest.displayError || ''))
|
|
303
|
+
}
|
|
304
|
+
|
|
266
305
|
const FINAL_STATUS_RETRY_KIND = {
|
|
267
306
|
none: 'none',
|
|
268
307
|
atr: 'atr',
|
|
@@ -320,14 +359,20 @@ class CypressPlugin {
|
|
|
320
359
|
|
|
321
360
|
finishedTestsByFile = {}
|
|
322
361
|
testStatuses = {}
|
|
362
|
+
hasLibraryConfiguration = false
|
|
323
363
|
isTestsSkipped = false
|
|
324
364
|
isSuitesSkippingEnabled = false
|
|
325
365
|
isCodeCoverageEnabled = false
|
|
326
366
|
isFlakyTestRetriesEnabled = false
|
|
327
367
|
flakyTestRetriesCount = 0
|
|
328
368
|
isEarlyFlakeDetectionEnabled = false
|
|
369
|
+
isEarlyFlakeDetectionFaulty = false
|
|
329
370
|
isKnownTestsEnabled = false
|
|
330
371
|
earlyFlakeDetectionNumRetries = 0
|
|
372
|
+
earlyFlakeDetectionSlowTestRetries = {}
|
|
373
|
+
efdRetryCountByTest = {}
|
|
374
|
+
efdSlowAbortedTests = {}
|
|
375
|
+
earlyFlakeDetectionFaultyThreshold = 0
|
|
331
376
|
testsToSkip = []
|
|
332
377
|
skippedTests = []
|
|
333
378
|
hasForcedToRunSuites = false
|
|
@@ -393,14 +438,20 @@ class CypressPlugin {
|
|
|
393
438
|
this._isInit = false
|
|
394
439
|
this.finishedTestsByFile = {}
|
|
395
440
|
this.testStatuses = {}
|
|
441
|
+
this.hasLibraryConfiguration = false
|
|
396
442
|
this.isTestsSkipped = false
|
|
397
443
|
this.isSuitesSkippingEnabled = false
|
|
398
444
|
this.isCodeCoverageEnabled = false
|
|
399
445
|
this.isFlakyTestRetriesEnabled = false
|
|
400
446
|
this.flakyTestRetriesCount = 0
|
|
401
447
|
this.isEarlyFlakeDetectionEnabled = false
|
|
448
|
+
this.isEarlyFlakeDetectionFaulty = false
|
|
402
449
|
this.isKnownTestsEnabled = false
|
|
403
450
|
this.earlyFlakeDetectionNumRetries = 0
|
|
451
|
+
this.earlyFlakeDetectionSlowTestRetries = {}
|
|
452
|
+
this.efdRetryCountByTest = {}
|
|
453
|
+
this.efdSlowAbortedTests = {}
|
|
454
|
+
this.earlyFlakeDetectionFaultyThreshold = 0
|
|
404
455
|
this.testsToSkip = []
|
|
405
456
|
this.skippedTests = []
|
|
406
457
|
this.hasForcedToRunSuites = false
|
|
@@ -454,8 +505,7 @@ class CypressPlugin {
|
|
|
454
505
|
|
|
455
506
|
this.isTestIsolationEnabled = getIsTestIsolationEnabled(cypressConfig)
|
|
456
507
|
|
|
457
|
-
|
|
458
|
-
this.rumFlushWaitMillis = Number.isFinite(envFlushWait) ? envFlushWait : undefined
|
|
508
|
+
this.rumFlushWaitMillis = getConfig().DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS
|
|
459
509
|
|
|
460
510
|
if (!this.isTestIsolationEnabled) {
|
|
461
511
|
log.warn('Test isolation is disabled, retries will not be enabled')
|
|
@@ -471,16 +521,19 @@ class CypressPlugin {
|
|
|
471
521
|
if (libraryConfigurationResponse.err) {
|
|
472
522
|
log.error('Cypress plugin library config response error', libraryConfigurationResponse.err)
|
|
473
523
|
this._pendingRequestErrorTags.push({
|
|
474
|
-
tag:
|
|
524
|
+
tag: DD_CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS,
|
|
475
525
|
value: 'true',
|
|
476
526
|
})
|
|
477
527
|
} else {
|
|
528
|
+
this.hasLibraryConfiguration = true
|
|
478
529
|
const {
|
|
479
530
|
libraryConfig: {
|
|
480
531
|
isSuitesSkippingEnabled,
|
|
481
532
|
isCodeCoverageEnabled,
|
|
482
533
|
isEarlyFlakeDetectionEnabled,
|
|
483
534
|
earlyFlakeDetectionNumRetries,
|
|
535
|
+
earlyFlakeDetectionSlowTestRetries,
|
|
536
|
+
earlyFlakeDetectionFaultyThreshold,
|
|
484
537
|
isFlakyTestRetriesEnabled,
|
|
485
538
|
flakyTestRetriesCount,
|
|
486
539
|
isKnownTestsEnabled,
|
|
@@ -493,6 +546,8 @@ class CypressPlugin {
|
|
|
493
546
|
this.isCodeCoverageEnabled = isCodeCoverageEnabled
|
|
494
547
|
this.isEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
|
|
495
548
|
this.earlyFlakeDetectionNumRetries = earlyFlakeDetectionNumRetries
|
|
549
|
+
this.earlyFlakeDetectionSlowTestRetries = earlyFlakeDetectionSlowTestRetries ?? {}
|
|
550
|
+
this.earlyFlakeDetectionFaultyThreshold = earlyFlakeDetectionFaultyThreshold
|
|
496
551
|
this.isKnownTestsEnabled = isKnownTestsEnabled
|
|
497
552
|
if (isFlakyTestRetriesEnabled && this.isTestIsolationEnabled) {
|
|
498
553
|
this.isFlakyTestRetriesEnabled = true
|
|
@@ -533,9 +588,76 @@ class CypressPlugin {
|
|
|
533
588
|
return { isAttemptToFix, isDisabled, isQuarantined }
|
|
534
589
|
}
|
|
535
590
|
|
|
591
|
+
/**
|
|
592
|
+
* Returns how many EFD retries must be scheduled before the first duration is known.
|
|
593
|
+
*
|
|
594
|
+
* @returns {number}
|
|
595
|
+
*/
|
|
596
|
+
getConfiguredEfdRetryCount () {
|
|
597
|
+
const { earlyFlakeDetectionSlowTestRetries } = this
|
|
598
|
+
if (!earlyFlakeDetectionSlowTestRetries || !Object.keys(earlyFlakeDetectionSlowTestRetries).length) {
|
|
599
|
+
return this.earlyFlakeDetectionNumRetries
|
|
600
|
+
}
|
|
601
|
+
return getMaxEfdRetryCount(earlyFlakeDetectionSlowTestRetries)
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Returns the selected EFD retry count for a test, or the scheduling count if it has not run yet.
|
|
606
|
+
*
|
|
607
|
+
* @param {string} testSuite
|
|
608
|
+
* @param {string} testName
|
|
609
|
+
* @returns {number}
|
|
610
|
+
*/
|
|
611
|
+
getEfdRetryCountForTest (testSuite, testName) {
|
|
612
|
+
const testSuiteRetries = this.efdRetryCountByTest[testSuite]
|
|
613
|
+
if (!testSuiteRetries || testSuiteRetries[testName] === undefined) {
|
|
614
|
+
return this.getConfiguredEfdRetryCount()
|
|
615
|
+
}
|
|
616
|
+
return testSuiteRetries[testName]
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Stores the selected EFD retry count for a test after its first execution duration is known.
|
|
621
|
+
*
|
|
622
|
+
* @param {string} testSuite
|
|
623
|
+
* @param {string} testName
|
|
624
|
+
* @param {number | undefined} duration
|
|
625
|
+
* @returns {number}
|
|
626
|
+
*/
|
|
627
|
+
setEfdRetryCountForTest (testSuite, testName, duration) {
|
|
628
|
+
if (!this.efdRetryCountByTest[testSuite]) {
|
|
629
|
+
this.efdRetryCountByTest[testSuite] = {}
|
|
630
|
+
}
|
|
631
|
+
const retryCount = getEfdRetryCount(duration ?? 0, this.earlyFlakeDetectionSlowTestRetries)
|
|
632
|
+
this.efdRetryCountByTest[testSuite][testName] = retryCount
|
|
633
|
+
if (retryCount === 0) {
|
|
634
|
+
if (!this.efdSlowAbortedTests[testSuite]) {
|
|
635
|
+
this.efdSlowAbortedTests[testSuite] = {}
|
|
636
|
+
}
|
|
637
|
+
this.efdSlowAbortedTests[testSuite][testName] = true
|
|
638
|
+
}
|
|
639
|
+
return retryCount
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Returns whether an EFD retry clone is beyond the selected retry count and should be discarded.
|
|
644
|
+
*
|
|
645
|
+
* @param {string} testSuite
|
|
646
|
+
* @param {string} testName
|
|
647
|
+
* @param {number} efdRetryIndex
|
|
648
|
+
* @returns {boolean}
|
|
649
|
+
*/
|
|
650
|
+
shouldSkipEfdRetry (testSuite, testName, efdRetryIndex) {
|
|
651
|
+
const testSuiteRetries = this.efdRetryCountByTest[testSuite]
|
|
652
|
+
return testSuiteRetries?.[testName] !== undefined && efdRetryIndex > testSuiteRetries[testName]
|
|
653
|
+
}
|
|
654
|
+
|
|
536
655
|
getTestSuiteSpan ({ testSuite, testSuiteAbsolutePath }) {
|
|
537
|
-
const testSuiteSpanMetadata =
|
|
538
|
-
getTestSuiteCommonTags(this.command, this.frameworkVersion, testSuite, TEST_FRAMEWORK_NAME)
|
|
656
|
+
const testSuiteSpanMetadata = {
|
|
657
|
+
...getTestSuiteCommonTags(this.command, this.frameworkVersion, testSuite, TEST_FRAMEWORK_NAME),
|
|
658
|
+
...this.getSessionRequestErrorTags(),
|
|
659
|
+
...this.getSessionItrSkippingEnabledTags(),
|
|
660
|
+
}
|
|
539
661
|
|
|
540
662
|
this.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
541
663
|
|
|
@@ -588,6 +710,7 @@ class CypressPlugin {
|
|
|
588
710
|
if (testSourceFile) {
|
|
589
711
|
testSpanMetadata[TEST_SOURCE_FILE] = testSourceFile
|
|
590
712
|
}
|
|
713
|
+
Object.assign(testSpanMetadata, this.getSessionItrSkippingEnabledTags())
|
|
591
714
|
|
|
592
715
|
const codeOwners = this.getTestCodeOwners({ testSuite, testSourceFile })
|
|
593
716
|
if (codeOwners) {
|
|
@@ -637,6 +760,15 @@ class CypressPlugin {
|
|
|
637
760
|
return getSessionRequestErrorTags(this.testSessionSpan)
|
|
638
761
|
}
|
|
639
762
|
|
|
763
|
+
/**
|
|
764
|
+
* Returns ITR skipping-enabled tags from the test session span for propagation to child events.
|
|
765
|
+
*
|
|
766
|
+
* @returns {Record<string, string>}
|
|
767
|
+
*/
|
|
768
|
+
getSessionItrSkippingEnabledTags () {
|
|
769
|
+
return getSessionItrSkippingEnabledTags(this.testSessionSpan)
|
|
770
|
+
}
|
|
771
|
+
|
|
640
772
|
ciVisEvent (name, testLevel, tags = {}) {
|
|
641
773
|
incrementCountMetric(name, {
|
|
642
774
|
testLevel,
|
|
@@ -662,10 +794,11 @@ class CypressPlugin {
|
|
|
662
794
|
)
|
|
663
795
|
if (knownTestsResponse.err) {
|
|
664
796
|
log.error('Cypress known tests response error', knownTestsResponse.err)
|
|
797
|
+
this._pendingRequestErrorTags.push({ tag: DD_CI_LIBRARY_CONFIGURATION_ERROR_KNOWN_TESTS, value: 'true' })
|
|
665
798
|
this.isEarlyFlakeDetectionEnabled = false
|
|
666
799
|
this.isKnownTestsEnabled = false
|
|
667
800
|
} else {
|
|
668
|
-
if (knownTestsResponse.knownTests[TEST_FRAMEWORK_NAME]) {
|
|
801
|
+
if (knownTestsResponse.knownTests?.[TEST_FRAMEWORK_NAME]) {
|
|
669
802
|
this.knownTestsByTestSuite = knownTestsResponse.knownTests[TEST_FRAMEWORK_NAME]
|
|
670
803
|
} else {
|
|
671
804
|
this.isEarlyFlakeDetectionEnabled = false
|
|
@@ -674,6 +807,21 @@ class CypressPlugin {
|
|
|
674
807
|
}
|
|
675
808
|
}
|
|
676
809
|
|
|
810
|
+
if (this.isKnownTestsEnabled && details.specs) {
|
|
811
|
+
const testSuites = details.specs.map(({ relative }) => relative)
|
|
812
|
+
const isFaulty = getIsFaultyEarlyFlakeDetection(
|
|
813
|
+
testSuites,
|
|
814
|
+
this.knownTestsByTestSuite,
|
|
815
|
+
this.earlyFlakeDetectionFaultyThreshold
|
|
816
|
+
)
|
|
817
|
+
if (isFaulty) {
|
|
818
|
+
log.warn('New test detection is disabled because the number of new test files is too high.')
|
|
819
|
+
this.isEarlyFlakeDetectionEnabled = false
|
|
820
|
+
this.isEarlyFlakeDetectionFaulty = true
|
|
821
|
+
this.isKnownTestsEnabled = false
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
677
825
|
if (this.isSuitesSkippingEnabled) {
|
|
678
826
|
const skippableTestsResponse = await getSkippableTests(
|
|
679
827
|
this.tracer,
|
|
@@ -681,6 +829,7 @@ class CypressPlugin {
|
|
|
681
829
|
)
|
|
682
830
|
if (skippableTestsResponse.err) {
|
|
683
831
|
log.error('Cypress skippable tests response error', skippableTestsResponse.err)
|
|
832
|
+
this._pendingRequestErrorTags.push({ tag: DD_CI_LIBRARY_CONFIGURATION_ERROR_SKIPPABLE_TESTS, value: 'true' })
|
|
684
833
|
} else {
|
|
685
834
|
const { skippableTests, correlationId } = skippableTestsResponse
|
|
686
835
|
this.testsToSkip = skippableTests || []
|
|
@@ -696,6 +845,10 @@ class CypressPlugin {
|
|
|
696
845
|
)
|
|
697
846
|
if (testManagementTestsResponse.err) {
|
|
698
847
|
log.error('Cypress test management tests response error', testManagementTestsResponse.err)
|
|
848
|
+
this._pendingRequestErrorTags.push({
|
|
849
|
+
tag: DD_CI_LIBRARY_CONFIGURATION_ERROR_TEST_MANAGEMENT_TESTS,
|
|
850
|
+
value: 'true',
|
|
851
|
+
})
|
|
699
852
|
this.isTestManagementTestsEnabled = false
|
|
700
853
|
} else {
|
|
701
854
|
this.testManagementTests = testManagementTestsResponse.testManagementTests
|
|
@@ -731,6 +884,9 @@ class CypressPlugin {
|
|
|
731
884
|
if (this.isEarlyFlakeDetectionEnabled) {
|
|
732
885
|
testSessionSpanMetadata[TEST_EARLY_FLAKE_ENABLED] = 'true'
|
|
733
886
|
}
|
|
887
|
+
if (this.isEarlyFlakeDetectionFaulty) {
|
|
888
|
+
testSessionSpanMetadata[TEST_EARLY_FLAKE_ABORT_REASON] = 'faulty'
|
|
889
|
+
}
|
|
734
890
|
|
|
735
891
|
const trimmedCommand = DD_MAJOR < 6 ? this.command : 'cypress run'
|
|
736
892
|
|
|
@@ -789,6 +945,11 @@ class CypressPlugin {
|
|
|
789
945
|
},
|
|
790
946
|
integrationName: TEST_FRAMEWORK_NAME,
|
|
791
947
|
})
|
|
948
|
+
if (this.hasLibraryConfiguration) {
|
|
949
|
+
const skippingEnabled = this.isSuitesSkippingEnabled ? 'true' : 'false'
|
|
950
|
+
this.testSessionSpan.setTag(TEST_ITR_SKIPPING_ENABLED, skippingEnabled)
|
|
951
|
+
this.testModuleSpan.setTag(TEST_ITR_SKIPPING_ENABLED, skippingEnabled)
|
|
952
|
+
}
|
|
792
953
|
this.ciVisEvent(TELEMETRY_EVENT_CREATED, 'module')
|
|
793
954
|
|
|
794
955
|
return details
|
|
@@ -833,7 +994,7 @@ class CypressPlugin {
|
|
|
833
994
|
this.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
834
995
|
incrementCountMetric(TELEMETRY_TEST_SESSION, {
|
|
835
996
|
provider: this.ciProviderName,
|
|
836
|
-
autoInjected: !!
|
|
997
|
+
autoInjected: !!getConfig().DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
837
998
|
})
|
|
838
999
|
|
|
839
1000
|
finishAllTraceSpans(this.testSessionSpan)
|
|
@@ -934,17 +1095,25 @@ class CypressPlugin {
|
|
|
934
1095
|
|
|
935
1096
|
for (const [testName, finishedTestAttempts] of Object.entries(finishedTestsByTestName)) {
|
|
936
1097
|
for (const [attemptIndex, finishedTest] of finishedTestAttempts.entries()) {
|
|
937
|
-
//
|
|
938
|
-
|
|
939
|
-
const
|
|
1098
|
+
// We can check if this is the last attempt regardless of the retry mechanism
|
|
1099
|
+
const isLastAttempt = attemptIndex === finishedTestAttempts.length - 1
|
|
1100
|
+
const isDatadogManagedAttempt = finishedTest.isEfdManagedTest || finishedTest.isAttemptToFix
|
|
1101
|
+
const cypressTest = isDatadogManagedAttempt
|
|
1102
|
+
? getMatchingCypressTest(cypressTests, testName, attemptIndex, finishedTest.testStatus, isLastAttempt) ||
|
|
1103
|
+
cypressTests.find(test => test.title.join(' ') === testName)
|
|
1104
|
+
: cypressTests.find(test => test.title.join(' ') === testName)
|
|
940
1105
|
if (!cypressTest) {
|
|
941
1106
|
continue
|
|
942
1107
|
}
|
|
943
1108
|
// finishedTests can include multiple tests with the same name if they have been retried
|
|
944
1109
|
// by early flake detection. Cypress is unaware of this so .attempts does not necessarily have
|
|
945
1110
|
// the same length as `finishedTestAttempts`
|
|
946
|
-
|
|
947
|
-
|
|
1111
|
+
const shouldUseCapturedStatus = isDatadogManagedAttempt && !(isLastAttempt && isCypressHookFailure(cypressTest))
|
|
1112
|
+
let cypressTestStatus = shouldUseCapturedStatus
|
|
1113
|
+
? finishedTest.testStatus
|
|
1114
|
+
: CYPRESS_STATUS_TO_TEST_STATUS[cypressTest.state]
|
|
1115
|
+
if (!finishedTest.isEfdManagedTest && !finishedTest.isAttemptToFix &&
|
|
1116
|
+
cypressTest.attempts && cypressTest.attempts[attemptIndex]) {
|
|
948
1117
|
cypressTestStatus = CYPRESS_STATUS_TO_TEST_STATUS[cypressTest.attempts[attemptIndex].state]
|
|
949
1118
|
const isAtrRetry = attemptIndex > 0 &&
|
|
950
1119
|
this.isFlakyTestRetriesEnabled &&
|
|
@@ -961,6 +1130,9 @@ class CypressPlugin {
|
|
|
961
1130
|
}
|
|
962
1131
|
}
|
|
963
1132
|
}
|
|
1133
|
+
if (finishedTest.isEfdManagedTest && finishedTest.testStatus !== 'skip' && cypressTestStatus === 'skip') {
|
|
1134
|
+
cypressTestStatus = finishedTest.testStatus
|
|
1135
|
+
}
|
|
964
1136
|
if (cypressTest.displayError) {
|
|
965
1137
|
latestError = new Error(cypressTest.displayError)
|
|
966
1138
|
}
|
|
@@ -970,6 +1142,9 @@ class CypressPlugin {
|
|
|
970
1142
|
if (cypressTestStatus !== finishedTest.testStatus && (!isQuarantinedTest || finishedTest.isAttemptToFix)) {
|
|
971
1143
|
finishedTest.testSpan.setTag(TEST_STATUS, cypressTestStatus)
|
|
972
1144
|
finishedTest.testSpan.setTag('error', latestError)
|
|
1145
|
+
if (finishedTest.isAttemptToFix && cypressTestStatus === 'fail') {
|
|
1146
|
+
finishedTest.testSpan.setTag(TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED, 'false')
|
|
1147
|
+
}
|
|
973
1148
|
}
|
|
974
1149
|
if (this.itrCorrelationId) {
|
|
975
1150
|
finishedTest.testSpan.setTag(ITR_CORRELATION_ID, this.itrCorrelationId)
|
|
@@ -989,8 +1164,6 @@ class CypressPlugin {
|
|
|
989
1164
|
finishedTest.testSpan.setTag(TEST_CODE_OWNERS, codeOwners)
|
|
990
1165
|
}
|
|
991
1166
|
|
|
992
|
-
// We can check if this is the last attempt regardless of the retry mechanism
|
|
993
|
-
const isLastAttempt = attemptIndex === finishedTestAttempts.length - 1
|
|
994
1167
|
if (isLastAttempt) {
|
|
995
1168
|
const testSpanTags = finishedTest.testSpan.context()._tags
|
|
996
1169
|
const retryKind = getFinalStatusRetryKind({
|
|
@@ -1042,7 +1215,8 @@ class CypressPlugin {
|
|
|
1042
1215
|
const suitePayload = {
|
|
1043
1216
|
isEarlyFlakeDetectionEnabled: this.isEarlyFlakeDetectionEnabled,
|
|
1044
1217
|
knownTestsForSuite: this.knownTestsByTestSuite?.[testSuite] || [],
|
|
1045
|
-
earlyFlakeDetectionNumRetries: this.
|
|
1218
|
+
earlyFlakeDetectionNumRetries: this.getConfiguredEfdRetryCount(),
|
|
1219
|
+
earlyFlakeDetectionSlowTestRetries: this.earlyFlakeDetectionSlowTestRetries,
|
|
1046
1220
|
isKnownTestsEnabled: this.isKnownTestsEnabled,
|
|
1047
1221
|
isTestManagementEnabled: this.isTestManagementTestsEnabled,
|
|
1048
1222
|
testManagementAttemptToFixRetries: this.testManagementAttemptToFixRetries,
|
|
@@ -1054,14 +1228,14 @@ class CypressPlugin {
|
|
|
1054
1228
|
rumFlushWaitMillis: this.rumFlushWaitMillis,
|
|
1055
1229
|
}
|
|
1056
1230
|
|
|
1057
|
-
|
|
1058
|
-
return suitePayload
|
|
1059
|
-
}
|
|
1060
|
-
this.testSuiteSpan = this.getTestSuiteSpan({ testSuite, testSuiteAbsolutePath })
|
|
1231
|
+
this.testSuiteSpan ||= this.getTestSuiteSpan({ testSuite, testSuiteAbsolutePath })
|
|
1061
1232
|
return suitePayload
|
|
1062
1233
|
},
|
|
1063
1234
|
'dd:beforeEach': (test) => {
|
|
1064
|
-
const { testName, testSuite } = test
|
|
1235
|
+
const { testName, testSuite, isEfdRetry, efdRetryIndex } = test
|
|
1236
|
+
if (isEfdRetry && this.shouldSkipEfdRetry(testSuite, testName, efdRetryIndex)) {
|
|
1237
|
+
return { shouldSkip: true, shouldDiscard: true }
|
|
1238
|
+
}
|
|
1065
1239
|
const shouldSkip = this.testsToSkip.some(test => {
|
|
1066
1240
|
return testName === test.name && testSuite === test.suite
|
|
1067
1241
|
})
|
|
@@ -1118,6 +1292,7 @@ class CypressPlugin {
|
|
|
1118
1292
|
isEfdRetry,
|
|
1119
1293
|
isAttemptToFix,
|
|
1120
1294
|
isModified,
|
|
1295
|
+
duration,
|
|
1121
1296
|
isQuarantined: isQuarantinedFromSupport,
|
|
1122
1297
|
isDisabled: isDisabledFromSupport,
|
|
1123
1298
|
} = test
|
|
@@ -1139,7 +1314,19 @@ class CypressPlugin {
|
|
|
1139
1314
|
}
|
|
1140
1315
|
this.tracer._tracer._exporter.exportCoverage(formattedCoverage)
|
|
1141
1316
|
}
|
|
1142
|
-
const
|
|
1317
|
+
const isEfdManagedTest = (isNew || isModified) && this.isEarlyFlakeDetectionEnabled && !isAttemptToFix
|
|
1318
|
+
let testStatus = CYPRESS_STATUS_TO_TEST_STATUS[state]
|
|
1319
|
+
let didAbortSlowEfdRetries = false
|
|
1320
|
+
if (isEfdManagedTest && !isEfdRetry && this.efdRetryCountByTest[testSuite]?.[testName] === undefined) {
|
|
1321
|
+
const retryCount = this.setEfdRetryCountForTest(testSuite, testName, duration)
|
|
1322
|
+
if (retryCount === 0) {
|
|
1323
|
+
didAbortSlowEfdRetries = true
|
|
1324
|
+
this.activeTestSpan.setTag(TEST_EARLY_FLAKE_ABORT_REASON, 'slow')
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
if (didAbortSlowEfdRetries && testStatus === 'skip' && !error && duration > 0) {
|
|
1328
|
+
testStatus = 'pass'
|
|
1329
|
+
}
|
|
1143
1330
|
this.activeTestSpan.setTag(TEST_STATUS, testStatus)
|
|
1144
1331
|
|
|
1145
1332
|
// Save the test status to know if it has passed all retries
|
|
@@ -1202,9 +1389,10 @@ class CypressPlugin {
|
|
|
1202
1389
|
}
|
|
1203
1390
|
}
|
|
1204
1391
|
// Check if all EFD retries failed
|
|
1205
|
-
if (
|
|
1206
|
-
const
|
|
1207
|
-
|
|
1392
|
+
if (isEfdManagedTest) {
|
|
1393
|
+
const efdRetryCount = this.getEfdRetryCountForTest(testSuite, testName)
|
|
1394
|
+
const isLastEfdAttempt = testStatuses.length === efdRetryCount + 1
|
|
1395
|
+
if (efdRetryCount > 0 && isLastEfdAttempt && testStatuses.every(status => status === 'fail')) {
|
|
1208
1396
|
this.activeTestSpan.setTag(TEST_HAS_FAILED_ALL_RETRIES, 'true')
|
|
1209
1397
|
}
|
|
1210
1398
|
}
|
|
@@ -1255,6 +1443,7 @@ class CypressPlugin {
|
|
|
1255
1443
|
finishTime: this._now(),
|
|
1256
1444
|
testSpan: this.activeTestSpan,
|
|
1257
1445
|
isEfdRetry,
|
|
1446
|
+
isEfdManagedTest,
|
|
1258
1447
|
isAttemptToFix,
|
|
1259
1448
|
}
|
|
1260
1449
|
if (this.finishedTestsByFile[testSuite]) {
|
|
@@ -79,6 +79,9 @@ function getRetriedTests (test, numRetries, tags) {
|
|
|
79
79
|
// TODO: signal in framework logs that this is a retry.
|
|
80
80
|
// TODO: Change it so these tests are allowed to fail.
|
|
81
81
|
const clonedTest = test.clone()
|
|
82
|
+
if (tags.includes('_ddIsEfdRetry')) {
|
|
83
|
+
clonedTest._ddEfdRetryIndex = retryIndex + 1
|
|
84
|
+
}
|
|
82
85
|
for (const tag of tags) {
|
|
83
86
|
if (tag) {
|
|
84
87
|
clonedTest[tag] = true
|
|
@@ -173,7 +176,12 @@ beforeEach(function () {
|
|
|
173
176
|
cy.task('dd:beforeEach', {
|
|
174
177
|
testName,
|
|
175
178
|
testSuite: Cypress.mocha.getRootSuite().file,
|
|
176
|
-
|
|
179
|
+
isEfdRetry: Cypress.mocha.getRunner().suite.ctx.currentTest._ddIsEfdRetry,
|
|
180
|
+
efdRetryIndex: Cypress.mocha.getRunner().suite.ctx.currentTest._ddEfdRetryIndex,
|
|
181
|
+
}).then(({ traceId, shouldSkip, shouldDiscard }) => {
|
|
182
|
+
if (shouldDiscard) {
|
|
183
|
+
this.currentTest._ddShouldDiscard = true
|
|
184
|
+
}
|
|
177
185
|
if (traceId) {
|
|
178
186
|
cy.setCookie(DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME, traceId).then(() => {
|
|
179
187
|
// When testIsolation:false, the page is not reset between tests, so the RUM session
|
|
@@ -242,6 +250,9 @@ after(() => {
|
|
|
242
250
|
|
|
243
251
|
afterEach(function () {
|
|
244
252
|
const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest
|
|
253
|
+
if (currentTest._ddShouldDiscard) {
|
|
254
|
+
return
|
|
255
|
+
}
|
|
245
256
|
const testName = currentTest.fullTitle()
|
|
246
257
|
|
|
247
258
|
// Check if this was a test management test that we suppressed the failure for.
|
|
@@ -267,6 +278,7 @@ afterEach(function () {
|
|
|
267
278
|
isEfdRetry: currentTest._ddIsEfdRetry,
|
|
268
279
|
isAttemptToFix: currentTest._ddIsAttemptToFix,
|
|
269
280
|
isModified: currentTest._ddIsModified,
|
|
281
|
+
duration: currentTest.duration,
|
|
270
282
|
// Mark suppressed tests so the plugin can tag them with the correct test management reason.
|
|
271
283
|
isQuarantined: isTestManagementTestThatFailed && suppressedTestFailure.isQuarantined,
|
|
272
284
|
isDisabled: isTestManagementTestThatFailed && suppressedTestFailure.isDisabled,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const CompositePlugin = require('../../dd-trace/src/plugins/composite')
|
|
4
|
+
const ElectronIpcPlugin = require('./ipc')
|
|
5
|
+
const ElectronNetPlugin = require('./net')
|
|
6
|
+
|
|
7
|
+
class ElectronPlugin extends CompositePlugin {
|
|
8
|
+
static id = 'electron'
|
|
9
|
+
static get plugins () {
|
|
10
|
+
return {
|
|
11
|
+
net: ElectronNetPlugin,
|
|
12
|
+
ipc: ElectronIpcPlugin,
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = ElectronPlugin
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const CompositePlugin = require('../../dd-trace/src/plugins/composite')
|
|
4
|
+
const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
|
|
5
|
+
const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
|
|
6
|
+
|
|
7
|
+
class ElectronIpcPlugin extends CompositePlugin {
|
|
8
|
+
static id = 'electron:ipc'
|
|
9
|
+
static get plugins () {
|
|
10
|
+
return {
|
|
11
|
+
main: ElectronMainPlugin,
|
|
12
|
+
renderer: ElectronRendererPlugin,
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class ElectronMainPlugin extends CompositePlugin {
|
|
18
|
+
static id = 'electron:ipc:main'
|
|
19
|
+
static get plugins () {
|
|
20
|
+
return {
|
|
21
|
+
receive: ElectronMainReceivePlugin,
|
|
22
|
+
handle: ElectronMainHandlePlugin,
|
|
23
|
+
send: ElectronMainSendPlugin,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class ElectronRendererPlugin extends CompositePlugin {
|
|
29
|
+
static id = 'electron:ipc:renderer'
|
|
30
|
+
static get plugins () {
|
|
31
|
+
return {
|
|
32
|
+
receive: ElectronRendererReceivePlugin,
|
|
33
|
+
send: ElectronRendererSendPlugin,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class ElectronRendererReceivePlugin extends ConsumerPlugin {
|
|
39
|
+
static id = 'electron:ipc:renderer:receive'
|
|
40
|
+
static component = 'electron'
|
|
41
|
+
static operation = 'receive'
|
|
42
|
+
static prefix = 'tracing:apm:electron:ipc:renderer:receive'
|
|
43
|
+
|
|
44
|
+
bindStart (ctx) {
|
|
45
|
+
const { args, channel } = ctx
|
|
46
|
+
|
|
47
|
+
if (channel?.startsWith('datadog:')) return
|
|
48
|
+
|
|
49
|
+
const childOf = this._tracer.extract('text_map', args[args.length - 1])
|
|
50
|
+
|
|
51
|
+
if (childOf) {
|
|
52
|
+
args.pop()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.startSpan({
|
|
56
|
+
childOf,
|
|
57
|
+
resource: channel,
|
|
58
|
+
type: 'worker',
|
|
59
|
+
meta: {},
|
|
60
|
+
}, ctx)
|
|
61
|
+
|
|
62
|
+
return ctx.currentStore
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
asyncEnd (ctx) {
|
|
66
|
+
this.finish(ctx)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
class ElectronRendererSendPlugin extends ProducerPlugin {
|
|
71
|
+
static id = 'electron:ipc:renderer:send'
|
|
72
|
+
static component = 'electron'
|
|
73
|
+
static operation = 'send'
|
|
74
|
+
static prefix = 'tracing:apm:electron:ipc:renderer:send'
|
|
75
|
+
|
|
76
|
+
bindStart (ctx) {
|
|
77
|
+
const { args, channel } = ctx
|
|
78
|
+
|
|
79
|
+
if (channel?.startsWith('datadog:')) return
|
|
80
|
+
|
|
81
|
+
const span = this.startSpan({
|
|
82
|
+
resource: channel,
|
|
83
|
+
meta: {},
|
|
84
|
+
}, ctx)
|
|
85
|
+
|
|
86
|
+
if (this._shouldInject(ctx)) {
|
|
87
|
+
const carrier = {}
|
|
88
|
+
|
|
89
|
+
this._tracer.inject(span, 'text_map', carrier)
|
|
90
|
+
|
|
91
|
+
args.push(carrier)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return ctx.currentStore
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
end (ctx) {
|
|
98
|
+
if (ctx.hasOwnProperty('result')) {
|
|
99
|
+
this.finish(ctx)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
asyncEnd (ctx) {
|
|
104
|
+
this.finish(ctx)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Renderer can always inject since main is guaranteed to be patched.
|
|
108
|
+
_shouldInject () {
|
|
109
|
+
return true
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
class ElectronMainReceivePlugin extends ElectronRendererReceivePlugin {
|
|
114
|
+
static id = 'electron:ipc:main:receive'
|
|
115
|
+
static prefix = 'tracing:apm:electron:ipc:main:receive'
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
class ElectronMainHandlePlugin extends ElectronMainReceivePlugin {
|
|
119
|
+
static id = 'electron:ipc:main:handle'
|
|
120
|
+
static prefix = 'tracing:apm:electron:ipc:main:handle'
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
class ElectronMainSendPlugin extends ElectronRendererSendPlugin {
|
|
124
|
+
static id = 'electron:ipc:main:send'
|
|
125
|
+
static prefix = 'tracing:apm:electron:ipc:main:send'
|
|
126
|
+
|
|
127
|
+
constructor (...args) {
|
|
128
|
+
super(...args)
|
|
129
|
+
|
|
130
|
+
this._renderers = new WeakSet()
|
|
131
|
+
|
|
132
|
+
this.addSub('apm:electron:ipc:renderer:patched', event => {
|
|
133
|
+
this._renderers.add(event.sender)
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Only inject when the renderer was patched.
|
|
138
|
+
_shouldInject ({ self }) {
|
|
139
|
+
return this._renderers.has(self)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
module.exports = ElectronIpcPlugin
|