dd-trace 6.8.0 → 6.9.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/ci/diagnose.js +27 -25
- package/ci/init.js +6 -6
- package/ci/runbook.md +114 -20
- package/ci/test-optimization-validation/approval-artifacts.js +36 -3
- package/ci/test-optimization-validation/approval.js +78 -22
- package/ci/test-optimization-validation/blocker-category.js +24 -0
- package/ci/test-optimization-validation/ci-discovery.js +23 -17
- package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
- package/ci/test-optimization-validation/ci-remediation.js +1 -1
- package/ci/test-optimization-validation/cli.js +280 -52
- package/ci/test-optimization-validation/command-blocker.js +159 -20
- package/ci/test-optimization-validation/command-output-policy.js +9 -3
- package/ci/test-optimization-validation/command-runner.js +9 -7
- package/ci/test-optimization-validation/environment.js +4 -2
- package/ci/test-optimization-validation/executable.js +15 -13
- package/ci/test-optimization-validation/execution-lock.js +70 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
- package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
- package/ci/test-optimization-validation/generated-files.js +38 -28
- package/ci/test-optimization-validation/generated-test-contract.js +8 -4
- package/ci/test-optimization-validation/generated-verifier.js +24 -17
- package/ci/test-optimization-validation/literal-glob.js +52 -0
- package/ci/test-optimization-validation/manifest-loader.js +3 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +300 -50
- package/ci/test-optimization-validation/manifest-schema.js +80 -17
- package/ci/test-optimization-validation/offline-fixtures.js +13 -4
- package/ci/test-optimization-validation/package-check.js +94 -0
- package/ci/test-optimization-validation/plan-writer.js +183 -10
- package/ci/test-optimization-validation/preflight-runner.js +110 -31
- package/ci/test-optimization-validation/project-build-artifact.js +31 -0
- package/ci/test-optimization-validation/redaction.js +18 -27
- package/ci/test-optimization-validation/report-writer.js +182 -48
- package/ci/test-optimization-validation/result-semantics.js +20 -3
- package/ci/test-optimization-validation/runner-command.js +40 -20
- package/ci/test-optimization-validation/runner-contract.js +79 -43
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +59 -5
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
- package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
- package/ci/test-optimization-validation/static-diagnosis.js +10 -3
- package/ci/test-optimization-validation/test-output.js +2 -1
- package/ci/test-optimization-validation/validation-blocker.js +21 -0
- package/ci/vitest-no-worker-init-setup.mjs +30 -34
- package/index.d.ts +98 -1
- package/init.js +1 -17
- package/initialize.mjs +11 -0
- package/loader-hook.mjs +6 -4
- package/package.json +5 -3
- package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
- package/packages/datadog-esbuild/src/utils.js +16 -1
- package/packages/datadog-instrumentations/src/ai.js +61 -34
- package/packages/datadog-instrumentations/src/bluebird.js +6 -6
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +81 -5
- package/packages/datadog-instrumentations/src/cucumber.js +124 -47
- package/packages/datadog-instrumentations/src/dns.js +21 -2
- package/packages/datadog-instrumentations/src/electron.js +1 -0
- package/packages/datadog-instrumentations/src/fastify.js +3 -1
- package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +33 -9
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +118 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +61 -0
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +37 -6
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +979 -233
- package/packages/datadog-instrumentations/src/mocha/main.js +107 -9
- package/packages/datadog-instrumentations/src/mocha/utils.js +64 -42
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +25 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +12 -18
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +155 -23
- package/packages/datadog-instrumentations/src/openai.js +14 -0
- package/packages/datadog-instrumentations/src/pg.js +180 -6
- package/packages/datadog-instrumentations/src/playwright.js +173 -79
- package/packages/datadog-instrumentations/src/promise-js.js +4 -4
- package/packages/datadog-instrumentations/src/promise.js +3 -3
- package/packages/datadog-instrumentations/src/router.js +195 -19
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +43 -10
- package/packages/datadog-instrumentations/src/vitest-main.js +360 -56
- package/packages/datadog-instrumentations/src/vitest-util.js +42 -7
- package/packages/datadog-instrumentations/src/vitest-worker.js +234 -17
- package/packages/datadog-instrumentations/src/webdriverio.js +194 -18
- package/packages/datadog-instrumentations/src/when.js +3 -3
- package/packages/datadog-instrumentations/src/ws.js +5 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -3
- package/packages/datadog-plugin-cucumber/src/index.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +50 -46
- package/packages/datadog-plugin-cypress/src/support.js +7 -4
- package/packages/datadog-plugin-electron/src/net.js +10 -4
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +1 -18
- package/packages/datadog-plugin-jest/src/util.js +2 -0
- package/packages/datadog-plugin-kafkajs/src/producer.js +2 -1
- package/packages/datadog-plugin-mocha/src/index.js +318 -1
- package/packages/datadog-plugin-next/src/index.js +57 -9
- package/packages/datadog-plugin-openai/src/tracing.js +4 -0
- package/packages/datadog-plugin-pg/src/index.js +65 -1
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +95 -7
- package/packages/datadog-shimmer/src/shimmer.js +6 -2
- package/packages/dd-trace/src/aiguard/sdk.js +3 -0
- package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
- package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +215 -0
- package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
- package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
- package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +48 -476
- package/packages/dd-trace/src/appsec/sdk/track_event.js +9 -0
- package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
- package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +27 -13
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +17 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +21 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +1 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
- package/packages/dd-trace/src/config/generated-config-types.d.ts +2 -0
- package/packages/dd-trace/src/config/helper.js +2 -0
- package/packages/dd-trace/src/config/index.js +16 -5
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +8 -0
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
- package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
- package/packages/dd-trace/src/guardrails/log.js +1 -10
- package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
- package/packages/dd-trace/src/llmobs/experiments/index.js +33 -25
- package/packages/dd-trace/src/llmobs/experiments/util.js +4 -2
- package/packages/dd-trace/src/llmobs/noop.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +149 -68
- package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
- package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
- package/packages/dd-trace/src/log/channels.js +1 -9
- package/packages/dd-trace/src/log/levels.js +12 -0
- package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -1
- package/packages/dd-trace/src/opentelemetry/span.js +4 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +21 -5
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +6 -0
- package/packages/dd-trace/src/plugins/util/git.js +6 -4
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +2 -2
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
- package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
- package/packages/dd-trace/src/plugins/util/test.js +319 -75
- package/packages/dd-trace/src/plugins/util/url.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +23 -1
- package/packages/dd-trace/src/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
- package/packages/dd-trace/src/proxy.js +1 -0
- package/packages/dd-trace/src/ritm.js +5 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
- package/packages/dd-trace/src/sampling_rule.js +4 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
- package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
- package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
- package/vendor/dist/pprof-format/index.js +1 -1
- package/version.js +10 -8
- /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { AsyncResource } = require('node:async_hooks')
|
|
4
4
|
const { fileURLToPath } = require('node:url')
|
|
5
5
|
|
|
6
|
+
const { EMPTY_EFD_RETRY_POLICY } = require('../../dd-trace/src/ci-visibility/efd-retry-policy')
|
|
6
7
|
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
|
|
7
8
|
const log = require('../../dd-trace/src/log')
|
|
8
9
|
const {
|
|
@@ -11,6 +12,7 @@ const {
|
|
|
11
12
|
getTestSuitePath,
|
|
12
13
|
logTestOptimizationSummary,
|
|
13
14
|
MOCHA_WORKER_LOGS_PAYLOAD_CODE,
|
|
15
|
+
MOCHA_WORKER_TELEMETRY_PAYLOAD_CODE,
|
|
14
16
|
MOCHA_WORKER_TRACE_PAYLOAD_CODE,
|
|
15
17
|
TEST_SUITE_EXECUTION_ID,
|
|
16
18
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
@@ -18,31 +20,43 @@ const { addHook, channel, tracingChannel } = require('./helpers/instrument')
|
|
|
18
20
|
const {
|
|
19
21
|
CONFIGURATION_REQUEST,
|
|
20
22
|
CONFIGURATION_RESPONSE,
|
|
23
|
+
sendWebdriverioWorkerMessage,
|
|
21
24
|
SUITE_FINISH,
|
|
22
25
|
WEBDRIVERIO_WORKER_ENV,
|
|
23
26
|
WEBDRIVERIO_WORKER_EVENT,
|
|
24
27
|
WEBDRIVERIO_WORKER_ORIGIN,
|
|
25
28
|
WORKER_READY,
|
|
29
|
+
WORKER_READY_RESPONSE,
|
|
26
30
|
} = require('./mocha/webdriverio-protocol')
|
|
27
31
|
|
|
32
|
+
const jasmineDoneCh = channel('ci:webdriverio:jasmine:done')
|
|
28
33
|
const testFinishCh = channel('ci:mocha:test:finish')
|
|
29
34
|
const testSessionStartCh = channel('ci:mocha:session:start')
|
|
30
35
|
const testSessionFinishCh = channel('ci:mocha:session:finish')
|
|
36
|
+
const testSuiteErrorCh = channel('ci:mocha:test-suite:error')
|
|
31
37
|
const testSuiteStartCh = channel('ci:mocha:test-suite:start')
|
|
32
38
|
const testSuiteFinishCh = channel('ci:mocha:test-suite:finish')
|
|
33
39
|
const knownTestsCh = channel('ci:mocha:known-tests')
|
|
34
40
|
const libraryConfigurationCh = channel('ci:mocha:library-configuration')
|
|
35
41
|
const modifiedFilesCh = channel('ci:mocha:modified-files')
|
|
36
42
|
const testManagementTestsCh = channel('ci:mocha:test-management-tests')
|
|
43
|
+
const workerConfigurationCh = channel('ci:mocha:worker:configuration')
|
|
37
44
|
const workerReportLogsCh = channel('ci:mocha:worker-report:logs')
|
|
45
|
+
const workerReportTelemetryCh = channel('ci:mocha:worker-report:telemetry')
|
|
38
46
|
const workerReportTraceCh = channel('ci:mocha:worker-report:trace')
|
|
39
47
|
|
|
48
|
+
const jasmineAdapterInitCh = tracingChannel('orchestrion:@wdio/jasmine-framework:JasmineAdapter_init')
|
|
40
49
|
const launcherStartInstanceCh = tracingChannel('orchestrion:@wdio/cli:Launcher_startInstance')
|
|
41
50
|
const localRunnerRunCh = tracingChannel('orchestrion:@wdio/local-runner:LocalRunner_run')
|
|
42
51
|
const localRunnerShutdownCh = tracingChannel('orchestrion:@wdio/local-runner:LocalRunner_shutdown')
|
|
43
52
|
|
|
44
53
|
const NODE_OPTIONS_SEPARATOR_RE = /\s/
|
|
54
|
+
const JASMINE_FRAMEWORK_ADAPTER = 'jasmine'
|
|
55
|
+
const MOCHA_FRAMEWORK_ADAPTER = 'mocha'
|
|
56
|
+
const SUPPORTED_FRAMEWORK_ADAPTERS = new Set([JASMINE_FRAMEWORK_ADAPTER, MOCHA_FRAMEWORK_ADAPTER])
|
|
45
57
|
const TEST_FRAMEWORK = 'webdriverio'
|
|
58
|
+
const isWebdriverioWorker = !!getEnvironmentVariable(WEBDRIVERIO_WORKER_ENV)
|
|
59
|
+
let jasmineWorkerRequestId = 0
|
|
46
60
|
|
|
47
61
|
const loadCh = channel('dd-trace:instrumentation:load')
|
|
48
62
|
if (loadCh.hasSubscribers) {
|
|
@@ -66,7 +80,7 @@ addHook({
|
|
|
66
80
|
* @typedef {object} WebdriverioRunnerConfig
|
|
67
81
|
* @property {string} framework
|
|
68
82
|
* @property {string|undefined} rootDir
|
|
69
|
-
* @property {
|
|
83
|
+
* @property {typeof process.env|undefined} runnerEnv
|
|
70
84
|
*/
|
|
71
85
|
|
|
72
86
|
/**
|
|
@@ -79,6 +93,7 @@ addHook({
|
|
|
79
93
|
* @typedef {object} WorkerRecord
|
|
80
94
|
* @property {object} worker
|
|
81
95
|
* @property {string[]} specs
|
|
96
|
+
* @property {Map<string, WebdriverioSuiteResult>} reportedSuiteResults
|
|
82
97
|
* @property {Map<string, WebdriverioSuiteContext>} suiteContexts
|
|
83
98
|
* @property {string} testSuiteExecutionId
|
|
84
99
|
* @property {boolean|undefined} hasTests
|
|
@@ -89,11 +104,18 @@ addHook({
|
|
|
89
104
|
/**
|
|
90
105
|
* @typedef {object} WebdriverioSuiteContext
|
|
91
106
|
* @property {object|undefined} currentStore
|
|
107
|
+
* @property {Error|undefined} error
|
|
92
108
|
* @property {string|undefined} status
|
|
93
109
|
* @property {string} testSuiteAbsolutePath
|
|
94
110
|
* @property {string} testSuiteExecutionId
|
|
95
111
|
*/
|
|
96
112
|
|
|
113
|
+
/**
|
|
114
|
+
* @typedef {object} WebdriverioSuiteResult
|
|
115
|
+
* @property {{message?: string, stack?: string}|undefined} error
|
|
116
|
+
* @property {string|undefined} status
|
|
117
|
+
*/
|
|
118
|
+
|
|
97
119
|
/**
|
|
98
120
|
* @typedef {object} CoordinatorState
|
|
99
121
|
* @property {WebdriverioLocalRunner} localRunner
|
|
@@ -112,21 +134,21 @@ addHook({
|
|
|
112
134
|
* @property {Set<string>} newTestsWithDynamicNames
|
|
113
135
|
* @property {number} nextWorkerId
|
|
114
136
|
* @property {Set<string>} scheduledFiles
|
|
137
|
+
* @property {Map<string, object>} testManagementExecutions
|
|
115
138
|
* @property {unknown} runError
|
|
116
139
|
* @property {Set<WorkerRecord>} workers
|
|
117
140
|
* @property {Map<object, string>} suiteStatuses
|
|
118
141
|
*/
|
|
119
142
|
|
|
120
143
|
/**
|
|
121
|
-
* Creates the configuration consumed by
|
|
144
|
+
* Creates the configuration consumed by WebdriverIO workers.
|
|
122
145
|
*
|
|
123
146
|
* @returns {object}
|
|
124
147
|
*/
|
|
125
148
|
function createWorkerConfiguration () {
|
|
126
149
|
return {
|
|
127
150
|
earlyFlakeDetectionFaultyThreshold: 30,
|
|
128
|
-
|
|
129
|
-
earlyFlakeDetectionSlowTestRetries: {},
|
|
151
|
+
earlyFlakeDetectionRetryPolicy: EMPTY_EFD_RETRY_POLICY,
|
|
130
152
|
flakyTestRetriesCount: 0,
|
|
131
153
|
isCodeCoverageEnabled: false,
|
|
132
154
|
isCoverageReportUploadEnabled: false,
|
|
@@ -148,6 +170,103 @@ function createWorkerConfiguration () {
|
|
|
148
170
|
}
|
|
149
171
|
}
|
|
150
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Configures a Jasmine worker for reporting-only execution and notifies its coordinator.
|
|
175
|
+
*
|
|
176
|
+
* @param {{_jrunner?: {env?: {addReporter?: (reporter: object) => void}}, _specs?: string[]}} adapter
|
|
177
|
+
* @param {{
|
|
178
|
+
* resolveCallback?: (onDone: () => void) => void,
|
|
179
|
+
* rejectCallback?: (onDone: () => void) => void
|
|
180
|
+
* }} context
|
|
181
|
+
* @returns {void}
|
|
182
|
+
*/
|
|
183
|
+
function initializeJasmineWorker (adapter, context) {
|
|
184
|
+
if (!isWebdriverioWorker) {
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
workerConfigurationCh.publish({
|
|
189
|
+
libraryConfig: createWorkerConfiguration(),
|
|
190
|
+
repositoryRoot: undefined,
|
|
191
|
+
specs: adapter?._specs || [],
|
|
192
|
+
testFramework: TEST_FRAMEWORK,
|
|
193
|
+
testFrameworkAdapter: JASMINE_FRAMEWORK_ADAPTER,
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
if (jasmineDoneCh.hasSubscribers) {
|
|
197
|
+
adapter?._jrunner?.env?.addReporter?.({
|
|
198
|
+
/**
|
|
199
|
+
* Publishes run-level failures that are absent from suiteDone.
|
|
200
|
+
*
|
|
201
|
+
* @param {object} result
|
|
202
|
+
* @returns {void}
|
|
203
|
+
*/
|
|
204
|
+
jasmineDone (result) {
|
|
205
|
+
jasmineDoneCh.publish({ result })
|
|
206
|
+
},
|
|
207
|
+
})
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Waits until the coordinator has started this worker's parent spans.
|
|
212
|
+
*
|
|
213
|
+
* @param {() => void} onDone
|
|
214
|
+
* @returns {void}
|
|
215
|
+
*/
|
|
216
|
+
const waitForCoordinator = onDone => {
|
|
217
|
+
const requestId = `${process.pid}-${++jasmineWorkerRequestId}`
|
|
218
|
+
let finished = false
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Releases Jasmine initialization exactly once.
|
|
222
|
+
*
|
|
223
|
+
* @returns {void}
|
|
224
|
+
*/
|
|
225
|
+
function finish () {
|
|
226
|
+
if (finished) {
|
|
227
|
+
return
|
|
228
|
+
}
|
|
229
|
+
finished = true
|
|
230
|
+
clearTimeout(timeout)
|
|
231
|
+
process.off('message', onMessage)
|
|
232
|
+
process.off('disconnect', finish)
|
|
233
|
+
onDone()
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Receives coordinator readiness for this worker.
|
|
238
|
+
*
|
|
239
|
+
* @param {object} message
|
|
240
|
+
* @returns {void}
|
|
241
|
+
*/
|
|
242
|
+
function onMessage (message) {
|
|
243
|
+
if (message?.name === WORKER_READY_RESPONSE && message.content?.requestId === requestId) {
|
|
244
|
+
finish()
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const timeout = setTimeout(finish, 30_000)
|
|
249
|
+
process.on('message', onMessage)
|
|
250
|
+
process.once('disconnect', finish)
|
|
251
|
+
sendWebdriverioWorkerMessage({
|
|
252
|
+
origin: 'datadog',
|
|
253
|
+
name: WORKER_READY,
|
|
254
|
+
content: {
|
|
255
|
+
requestId,
|
|
256
|
+
testFrameworkAdapter: JASMINE_FRAMEWORK_ADAPTER,
|
|
257
|
+
},
|
|
258
|
+
}, error => {
|
|
259
|
+
if (error) {
|
|
260
|
+
log.error('WebdriverIO Test Optimization IPC error', error)
|
|
261
|
+
}
|
|
262
|
+
finish()
|
|
263
|
+
})
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
context.resolveCallback = waitForCoordinator
|
|
267
|
+
context.rejectCallback = waitForCoordinator
|
|
268
|
+
}
|
|
269
|
+
|
|
151
270
|
/**
|
|
152
271
|
* Gets the public runner configuration, or the private equivalent used by older releases.
|
|
153
272
|
*
|
|
@@ -187,6 +306,7 @@ function getCoordinatorState (localRunner) {
|
|
|
187
306
|
newTestsWithDynamicNames: new Set(),
|
|
188
307
|
nextWorkerId: 0,
|
|
189
308
|
scheduledFiles: new Set(),
|
|
309
|
+
testManagementExecutions: new Map(),
|
|
190
310
|
runError: undefined,
|
|
191
311
|
workers: new Set(),
|
|
192
312
|
suiteStatuses: new Map(),
|
|
@@ -247,7 +367,7 @@ function includesNodeOptions (workerNodeOptions, launcherNodeOptions) {
|
|
|
247
367
|
}
|
|
248
368
|
|
|
249
369
|
/**
|
|
250
|
-
* Starts the single
|
|
370
|
+
* Starts the single test session owned by the WebdriverIO launcher.
|
|
251
371
|
*
|
|
252
372
|
* @param {CoordinatorState} state
|
|
253
373
|
* @returns {void}
|
|
@@ -349,8 +469,7 @@ function configureCoordinator (state, response) {
|
|
|
349
469
|
}
|
|
350
470
|
|
|
351
471
|
configuration.earlyFlakeDetectionFaultyThreshold = libraryConfig.earlyFlakeDetectionFaultyThreshold
|
|
352
|
-
configuration.
|
|
353
|
-
configuration.earlyFlakeDetectionSlowTestRetries = libraryConfig.earlyFlakeDetectionSlowTestRetries ?? {}
|
|
472
|
+
configuration.earlyFlakeDetectionRetryPolicy = libraryConfig.earlyFlakeDetectionRetryPolicy ?? EMPTY_EFD_RETRY_POLICY
|
|
354
473
|
configuration.flakyTestRetriesCount = libraryConfig.flakyTestRetriesCount
|
|
355
474
|
configuration.isDiEnabled = libraryConfig.isDiEnabled
|
|
356
475
|
configuration.isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
|
|
@@ -445,6 +564,7 @@ function initializeCoordinator (state, onDone) {
|
|
|
445
564
|
|
|
446
565
|
try {
|
|
447
566
|
libraryConfigurationCh.runStores({
|
|
567
|
+
basicReportingOnly: state.testFrameworkAdapter === JASMINE_FRAMEWORK_ADAPTER,
|
|
448
568
|
disableTestImpactAnalysis: true,
|
|
449
569
|
frameworkVersion: state.frameworkVersion,
|
|
450
570
|
isParallel: state.maxActiveWorkers > 1,
|
|
@@ -476,7 +596,10 @@ function startWorkerSuites (workerRecord, files) {
|
|
|
476
596
|
continue
|
|
477
597
|
}
|
|
478
598
|
|
|
599
|
+
const reportedResult = workerRecord.reportedSuiteResults.get(file)
|
|
479
600
|
const suiteContext = {
|
|
601
|
+
error: getWebdriverioSuiteError(reportedResult?.error),
|
|
602
|
+
status: reportedResult?.status,
|
|
480
603
|
testSuiteAbsolutePath: file,
|
|
481
604
|
testSuiteExecutionId: workerRecord.testSuiteExecutionId,
|
|
482
605
|
}
|
|
@@ -502,6 +625,9 @@ function finishWorkerSuite (state, workerRecord, rawFile, status) {
|
|
|
502
625
|
}
|
|
503
626
|
|
|
504
627
|
state.suiteStatuses.set(suiteContext, status)
|
|
628
|
+
if (suiteContext.error) {
|
|
629
|
+
testSuiteErrorCh.runStores(suiteContext, () => {})
|
|
630
|
+
}
|
|
505
631
|
testSuiteFinishCh.publish({ status, ...suiteContext.currentStore })
|
|
506
632
|
}
|
|
507
633
|
|
|
@@ -552,7 +678,7 @@ function sendWorkerMessage (workerRecord, message) {
|
|
|
552
678
|
}
|
|
553
679
|
|
|
554
680
|
/**
|
|
555
|
-
* Handles a worker request for its
|
|
681
|
+
* Handles a worker request for its execution configuration.
|
|
556
682
|
*
|
|
557
683
|
* @param {CoordinatorState} state
|
|
558
684
|
* @param {WorkerRecord} workerRecord
|
|
@@ -608,7 +734,25 @@ function updateEarlyFlakeDetectionFaultyState (state, files) {
|
|
|
608
734
|
}
|
|
609
735
|
|
|
610
736
|
/**
|
|
611
|
-
*
|
|
737
|
+
* Reconstructs an Error received from a WebdriverIO worker.
|
|
738
|
+
*
|
|
739
|
+
* @param {{message?: string, stack?: string}|undefined} error
|
|
740
|
+
* @returns {Error|undefined}
|
|
741
|
+
*/
|
|
742
|
+
function getWebdriverioSuiteError (error) {
|
|
743
|
+
if (!error?.message) {
|
|
744
|
+
return
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
const suiteError = new Error(error.message)
|
|
748
|
+
if (error.stack) {
|
|
749
|
+
suiteError.stack = error.stack
|
|
750
|
+
}
|
|
751
|
+
return suiteError
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Handles suite results reported by a WebdriverIO worker.
|
|
612
756
|
*
|
|
613
757
|
* @param {WorkerRecord} workerRecord
|
|
614
758
|
* @param {object} message
|
|
@@ -616,9 +760,12 @@ function updateEarlyFlakeDetectionFaultyState (state, files) {
|
|
|
616
760
|
*/
|
|
617
761
|
function handleSuiteResults (workerRecord, message) {
|
|
618
762
|
const { results = [] } = message.content || {}
|
|
619
|
-
for (const { file, status } of results) {
|
|
620
|
-
const
|
|
763
|
+
for (const { error, file, status } of results) {
|
|
764
|
+
const normalizedFile = normalizeFile(file)
|
|
765
|
+
workerRecord.reportedSuiteResults.set(normalizedFile, { error, status })
|
|
766
|
+
const suiteContext = workerRecord.suiteContexts.get(normalizedFile)
|
|
621
767
|
if (suiteContext) {
|
|
768
|
+
suiteContext.error = getWebdriverioSuiteError(error)
|
|
622
769
|
suiteContext.status = status
|
|
623
770
|
}
|
|
624
771
|
}
|
|
@@ -643,6 +790,7 @@ function handleWorkerMessage (state, workerRecord, message) {
|
|
|
643
790
|
collectTestOptimizationSummariesFromTraces(payload, {
|
|
644
791
|
attemptToFixExecutions: state.attemptToFixExecutions,
|
|
645
792
|
newTestsWithDynamicNames: state.newTestsWithDynamicNames,
|
|
793
|
+
testManagementExecutions: state.testManagementExecutions,
|
|
646
794
|
})
|
|
647
795
|
workerReportTraceCh.publish({
|
|
648
796
|
traces: payload,
|
|
@@ -650,6 +798,8 @@ function handleWorkerMessage (state, workerRecord, message) {
|
|
|
650
798
|
})
|
|
651
799
|
} else if (messageCode === MOCHA_WORKER_LOGS_PAYLOAD_CODE) {
|
|
652
800
|
workerReportLogsCh.publish(payload)
|
|
801
|
+
} else if (messageCode === MOCHA_WORKER_TELEMETRY_PAYLOAD_CODE) {
|
|
802
|
+
workerReportTelemetryCh.publish(payload)
|
|
653
803
|
}
|
|
654
804
|
return
|
|
655
805
|
}
|
|
@@ -659,7 +809,18 @@ function handleWorkerMessage (state, workerRecord, message) {
|
|
|
659
809
|
}
|
|
660
810
|
|
|
661
811
|
if (message.name === WORKER_READY) {
|
|
662
|
-
initializeCoordinator(state)
|
|
812
|
+
initializeCoordinator(state, () => {
|
|
813
|
+
if (state.testFrameworkAdapter === JASMINE_FRAMEWORK_ADAPTER) {
|
|
814
|
+
startWorkerSuites(workerRecord, workerRecord.specs)
|
|
815
|
+
}
|
|
816
|
+
if (message.content?.requestId) {
|
|
817
|
+
sendWorkerMessage(workerRecord, {
|
|
818
|
+
origin: 'datadog',
|
|
819
|
+
name: WORKER_READY_RESPONSE,
|
|
820
|
+
content: { requestId: message.content.requestId },
|
|
821
|
+
})
|
|
822
|
+
}
|
|
823
|
+
})
|
|
663
824
|
return
|
|
664
825
|
}
|
|
665
826
|
if (message.name === CONFIGURATION_REQUEST) {
|
|
@@ -721,6 +882,7 @@ function registerWorker (state, worker, specs) {
|
|
|
721
882
|
const workerRecord = {
|
|
722
883
|
worker,
|
|
723
884
|
specs: normalizedSpecs,
|
|
885
|
+
reportedSuiteResults: new Map(),
|
|
724
886
|
suiteContexts: new Map(),
|
|
725
887
|
testSuiteExecutionId: String(++state.nextWorkerId),
|
|
726
888
|
hasTests: undefined,
|
|
@@ -768,7 +930,7 @@ function getSessionStatus (state) {
|
|
|
768
930
|
}
|
|
769
931
|
|
|
770
932
|
/**
|
|
771
|
-
* Finishes the single WebdriverIO-owned
|
|
933
|
+
* Finishes the single WebdriverIO-owned test session.
|
|
772
934
|
*
|
|
773
935
|
* @param {CoordinatorState} state
|
|
774
936
|
* @param {unknown} error
|
|
@@ -801,6 +963,7 @@ function finishCoordinator (state, error, onDone) {
|
|
|
801
963
|
logTestOptimizationSummary({
|
|
802
964
|
attemptToFixExecutions: state.attemptToFixExecutions,
|
|
803
965
|
newTestsWithDynamicNames: state.newTestsWithDynamicNames,
|
|
966
|
+
testManagementExecutions: state.testManagementExecutions,
|
|
804
967
|
})
|
|
805
968
|
onDone()
|
|
806
969
|
return
|
|
@@ -819,24 +982,37 @@ function finishCoordinator (state, error, onDone) {
|
|
|
819
982
|
logTestOptimizationSummary({
|
|
820
983
|
attemptToFixExecutions: state.attemptToFixExecutions,
|
|
821
984
|
newTestsWithDynamicNames: state.newTestsWithDynamicNames,
|
|
985
|
+
testManagementExecutions: state.testManagementExecutions,
|
|
822
986
|
})
|
|
823
987
|
}
|
|
824
988
|
|
|
989
|
+
// dc-polyfill supports partial tracing-channel subscribers, unlike the Node.js type definition.
|
|
990
|
+
// @ts-expect-error
|
|
991
|
+
jasmineAdapterInitCh.subscribe({
|
|
992
|
+
asyncEnd (context) {
|
|
993
|
+
initializeJasmineWorker(context.result || context.self, context)
|
|
994
|
+
},
|
|
995
|
+
})
|
|
996
|
+
|
|
825
997
|
// dc-polyfill supports partial tracing-channel subscribers, unlike the Node.js type definition.
|
|
826
998
|
// @ts-expect-error
|
|
827
999
|
launcherStartInstanceCh.subscribe({
|
|
828
1000
|
start (context) {
|
|
829
1001
|
const localRunner = context.self?.runner
|
|
830
1002
|
const runnerConfiguration = localRunner && getRunnerConfiguration(localRunner)
|
|
831
|
-
if (!testFinishCh.hasSubscribers || runnerConfiguration?.framework
|
|
1003
|
+
if (!testFinishCh.hasSubscribers || !SUPPORTED_FRAMEWORK_ADAPTERS.has(runnerConfiguration?.framework)) {
|
|
832
1004
|
return
|
|
833
1005
|
}
|
|
834
1006
|
|
|
835
1007
|
const state = getCoordinatorState(localRunner)
|
|
836
1008
|
addScheduledFiles(state, context.arguments?.[0] || [])
|
|
837
|
-
|
|
838
|
-
for (const
|
|
839
|
-
|
|
1009
|
+
if (context.self._schedule) {
|
|
1010
|
+
for (const schedule of context.self._schedule) {
|
|
1011
|
+
if (schedule.specs) {
|
|
1012
|
+
for (const { files } of schedule.specs) {
|
|
1013
|
+
addScheduledFiles(state, files)
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
840
1016
|
}
|
|
841
1017
|
}
|
|
842
1018
|
},
|
|
@@ -847,7 +1023,7 @@ launcherStartInstanceCh.subscribe({
|
|
|
847
1023
|
localRunnerRunCh.subscribe({
|
|
848
1024
|
start (context) {
|
|
849
1025
|
const runnerConfiguration = getRunnerConfiguration(context.self)
|
|
850
|
-
if (!testFinishCh.hasSubscribers || runnerConfiguration?.framework
|
|
1026
|
+
if (!testFinishCh.hasSubscribers || !SUPPORTED_FRAMEWORK_ADAPTERS.has(runnerConfiguration?.framework)) {
|
|
851
1027
|
return
|
|
852
1028
|
}
|
|
853
1029
|
|
|
@@ -8,7 +8,7 @@ addHook({
|
|
|
8
8
|
name: 'when',
|
|
9
9
|
file: 'lib/Promise.js',
|
|
10
10
|
versions: ['>=3'],
|
|
11
|
-
},
|
|
12
|
-
shimmer.wrap(
|
|
13
|
-
return
|
|
11
|
+
}, LibraryPromise => {
|
|
12
|
+
shimmer.wrap(LibraryPromise.prototype, 'then', wrapThen)
|
|
13
|
+
return LibraryPromise
|
|
14
14
|
})
|
|
@@ -49,7 +49,11 @@ const setSocketCh = channel('tracing:ws:server:connect:setSocket')
|
|
|
49
49
|
*/
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
* @typedef {
|
|
52
|
+
* @typedef {{ buffer: ArrayBuffer | SharedArrayBuffer, byteLength: number, byteOffset: number }} BufferView
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @typedef {string | Buffer | ArrayBuffer | BufferView | Blob | Buffer[]} WebSocketMessageData
|
|
53
57
|
*/
|
|
54
58
|
|
|
55
59
|
/**
|
|
@@ -487,16 +487,18 @@ function extractMessagesFromConverseContent (role, contentBlocks) {
|
|
|
487
487
|
const toolCalls = []
|
|
488
488
|
const toolResults = []
|
|
489
489
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
490
|
+
if (contentBlocks) {
|
|
491
|
+
for (const block of contentBlocks) {
|
|
492
|
+
if (block == null || typeof block !== 'object') continue
|
|
493
|
+
if (typeof block.text === 'string') {
|
|
494
|
+
content += block.text
|
|
495
|
+
} else if (block.toolUse) {
|
|
496
|
+
toolCalls.push(buildToolCall(block.toolUse))
|
|
497
|
+
} else if (block.toolResult) {
|
|
498
|
+
toolResults.push(buildToolResult(block.toolResult))
|
|
499
|
+
} else {
|
|
500
|
+
content += `[Unsupported content type: ${getContentBlockType(block)}]`
|
|
501
|
+
}
|
|
500
502
|
}
|
|
501
503
|
}
|
|
502
504
|
|
|
@@ -572,14 +574,17 @@ function buildUsage (usage = {}) {
|
|
|
572
574
|
*/
|
|
573
575
|
function extractConverseToolDefinitions (params) {
|
|
574
576
|
const toolDefinitions = []
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
577
|
+
const tools = params.toolConfig?.tools
|
|
578
|
+
if (tools) {
|
|
579
|
+
for (const tool of tools) {
|
|
580
|
+
const toolSpec = tool?.toolSpec
|
|
581
|
+
if (!toolSpec?.name) continue
|
|
582
|
+
toolDefinitions.push({
|
|
583
|
+
name: toolSpec.name,
|
|
584
|
+
description: toolSpec.description ?? '',
|
|
585
|
+
schema: toolSpec.inputSchema ?? {},
|
|
586
|
+
})
|
|
587
|
+
}
|
|
583
588
|
}
|
|
584
589
|
return toolDefinitions
|
|
585
590
|
}
|
|
@@ -593,13 +598,17 @@ function extractConverseToolDefinitions (params) {
|
|
|
593
598
|
*/
|
|
594
599
|
function extractRequestParamsConverse (params) {
|
|
595
600
|
const prompt = []
|
|
596
|
-
|
|
597
|
-
|
|
601
|
+
if (params.system) {
|
|
602
|
+
for (const block of params.system) {
|
|
603
|
+
if (typeof block?.text === 'string') prompt.push({ content: block.text, role: 'system' })
|
|
604
|
+
}
|
|
598
605
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
606
|
+
if (params.messages) {
|
|
607
|
+
for (const msg of params.messages) {
|
|
608
|
+
if (msg == null || typeof msg !== 'object') continue
|
|
609
|
+
const message = extractMessagesFromConverseContent(msg.role || 'user', msg.content)
|
|
610
|
+
if (message) prompt.push(message)
|
|
611
|
+
}
|
|
603
612
|
}
|
|
604
613
|
|
|
605
614
|
const { temperature, topP, maxTokens, stopSequences } = params.inferenceConfig || {}
|
|
@@ -632,7 +641,7 @@ function extractTextAndResponseReasonConverse (response) {
|
|
|
632
641
|
* response, spread across start/delta chunks. We reassemble those chunks
|
|
633
642
|
* into a normalized content-block array and reuse the non-stream extractor.
|
|
634
643
|
*
|
|
635
|
-
* @param {Array<object>} chunks - Ordered ConverseStreamOutput events.
|
|
644
|
+
* @param {Array<object> | undefined} chunks - Ordered ConverseStreamOutput events.
|
|
636
645
|
* @returns {Generation}
|
|
637
646
|
*/
|
|
638
647
|
function extractTextAndResponseReasonConverseFromStream (chunks) {
|
|
@@ -641,29 +650,31 @@ function extractTextAndResponseReasonConverseFromStream (chunks) {
|
|
|
641
650
|
let usage = {}
|
|
642
651
|
const blocksByIdx = new Map()
|
|
643
652
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
653
|
+
if (chunks) {
|
|
654
|
+
for (const chunk of chunks) {
|
|
655
|
+
if (chunk.messageStart?.role) {
|
|
656
|
+
role = chunk.messageStart.role
|
|
657
|
+
} else if (chunk.messageStop?.stopReason) {
|
|
658
|
+
stopReason = chunk.messageStop.stopReason
|
|
659
|
+
} else if (chunk.metadata?.usage) {
|
|
660
|
+
usage = chunk.metadata.usage
|
|
661
|
+
} else if (chunk.contentBlockStart?.start?.toolUse) {
|
|
662
|
+
const { contentBlockIndex, start: { toolUse } } = chunk.contentBlockStart
|
|
663
|
+
blocksByIdx.set(contentBlockIndex, {
|
|
664
|
+
toolUse: { toolUseId: toolUse.toolUseId, name: toolUse.name, inputStr: '' },
|
|
665
|
+
})
|
|
666
|
+
} else if (chunk.contentBlockDelta) {
|
|
667
|
+
const { contentBlockIndex, delta } = chunk.contentBlockDelta
|
|
668
|
+
if (typeof delta?.text === 'string') {
|
|
669
|
+
const block = blocksByIdx.get(contentBlockIndex) ?? {}
|
|
670
|
+
block.text = (block.text ?? '') + delta.text
|
|
671
|
+
blocksByIdx.set(contentBlockIndex, block)
|
|
672
|
+
} else if (typeof delta?.toolUse?.input === 'string') {
|
|
673
|
+
const block = blocksByIdx.get(contentBlockIndex) ?? { toolUse: { inputStr: '' } }
|
|
674
|
+
block.toolUse ??= { inputStr: '' }
|
|
675
|
+
block.toolUse.inputStr += delta.toolUse.input
|
|
676
|
+
blocksByIdx.set(contentBlockIndex, block)
|
|
677
|
+
}
|
|
667
678
|
}
|
|
668
679
|
}
|
|
669
680
|
}
|
|
@@ -58,9 +58,7 @@ function scrubChildProcessCmd (expression) {
|
|
|
58
58
|
for (let index = 0; index < expressionTokens.length; index++) {
|
|
59
59
|
const token = expressionTokens[index]
|
|
60
60
|
|
|
61
|
-
if (token ===
|
|
62
|
-
continue
|
|
63
|
-
} else if (typeof token === 'object') {
|
|
61
|
+
if (token !== null && typeof token === 'object') {
|
|
64
62
|
if (token.pattern) {
|
|
65
63
|
result.push(token.pattern)
|
|
66
64
|
} else if (token.op) {
|
|
@@ -308,6 +308,7 @@ class CucumberPlugin extends CiPlugin {
|
|
|
308
308
|
isNew,
|
|
309
309
|
isEfdRetry,
|
|
310
310
|
isFlakyRetry,
|
|
311
|
+
isExternalRetry,
|
|
311
312
|
isAttemptToFix,
|
|
312
313
|
isAttemptToFixRetry,
|
|
313
314
|
hasFailedAllRetries,
|
|
@@ -348,9 +349,12 @@ class CucumberPlugin extends CiPlugin {
|
|
|
348
349
|
span.setTag(ERROR_MESSAGE, errorMessage)
|
|
349
350
|
}
|
|
350
351
|
|
|
351
|
-
if (isFlakyRetry
|
|
352
|
+
if (isFlakyRetry) {
|
|
352
353
|
span.setTag(TEST_IS_RETRY, 'true')
|
|
353
354
|
span.setTag(TEST_RETRY_REASON, TEST_RETRY_REASON_TYPES.atr)
|
|
355
|
+
} else if (isExternalRetry) {
|
|
356
|
+
span.setTag(TEST_IS_RETRY, 'true')
|
|
357
|
+
span.setTag(TEST_RETRY_REASON, TEST_RETRY_REASON_TYPES.ext)
|
|
354
358
|
}
|
|
355
359
|
|
|
356
360
|
if (hasFailedAllRetries) {
|