dd-trace 5.132.0 → 5.134.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 +9 -14
- package/ci/init.js +1 -2
- package/ci/test-optimization-validation/ci-discovery.js +9 -4
- package/ci/test-optimization-validation/executable.js +1 -5
- package/ci/test-optimization-validation/framework-adapters/cypress.js +1 -4
- package/ci/test-optimization-validation/framework-adapters/vitest.js +1 -1
- package/ci/test-optimization-validation/generated-files.js +6 -4
- package/ci/test-optimization-validation/generated-test-contract.js +7 -3
- package/ci/test-optimization-validation/manifest-scaffold.js +7 -2
- package/ci/test-optimization-validation/manifest-schema.js +6 -7
- package/ci/test-optimization-validation/report-writer.js +6 -2
- package/ci/test-optimization-validation/runner-command.js +2 -4
- package/ci/test-optimization-validation/runner-contract.js +1 -2
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +1 -15
- package/ci/vitest-no-worker-init-runner-setup.mjs +27 -0
- package/ci/vitest-no-worker-init-setup.mjs +10 -7
- package/index.d.ts +41 -19
- package/initialize.mjs +1 -3
- package/openfeature/rules-based.d.ts +11 -0
- package/openfeature/rules-based.js +7 -0
- package/package.json +25 -22
- package/packages/datadog-core/src/storage.js +16 -0
- package/packages/datadog-esbuild/index.js +18 -12
- package/packages/datadog-instrumentations/index.js +2 -1
- package/packages/datadog-instrumentations/src/aerospike.js +3 -3
- package/packages/datadog-instrumentations/src/ai.js +3 -3
- package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +0 -6
- package/packages/datadog-instrumentations/src/aws-sdk.js +21 -13
- package/packages/datadog-instrumentations/src/cassandra-driver.js +25 -20
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +9 -23
- package/packages/datadog-instrumentations/src/cucumber.js +65 -41
- package/packages/datadog-instrumentations/src/elasticsearch.js +1 -5
- package/packages/datadog-instrumentations/src/electron.js +6 -6
- package/packages/datadog-instrumentations/src/fastify.js +13 -4
- package/packages/datadog-instrumentations/src/fs.js +2 -2
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +9 -5
- package/packages/datadog-instrumentations/src/grpc/client.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +28 -9
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/register.js +45 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +89 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +5 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/jest.js +12 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +48 -31
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/vitest.js +8 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +7 -7
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +5 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +42 -4
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +7 -10
- package/packages/datadog-instrumentations/src/ioredis.js +7 -5
- package/packages/datadog-instrumentations/src/iovalkey.js +7 -5
- package/packages/datadog-instrumentations/src/jest.js +72 -67
- package/packages/datadog-instrumentations/src/knex.js +9 -5
- package/packages/datadog-instrumentations/src/mariadb-bundle.js +3 -3
- package/packages/datadog-instrumentations/src/mocha/common.js +20 -8
- package/packages/datadog-instrumentations/src/mocha/main.js +140 -43
- package/packages/datadog-instrumentations/src/mocha/utils.js +38 -4
- package/packages/datadog-instrumentations/src/mocha/worker.js +1 -2
- package/packages/datadog-instrumentations/src/mongodb-core.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +3 -3
- package/packages/datadog-instrumentations/src/nova-sonic/audio.js +173 -0
- package/packages/datadog-instrumentations/src/nova-sonic/index.js +209 -0
- package/packages/datadog-instrumentations/src/nova-sonic/session.js +492 -0
- package/packages/datadog-instrumentations/src/openai-realtime/index.js +18 -6
- package/packages/datadog-instrumentations/src/openai-realtime/session.js +1 -1
- package/packages/datadog-instrumentations/src/openai.js +7 -0
- package/packages/datadog-instrumentations/src/pino.js +5 -6
- package/packages/datadog-instrumentations/src/playwright.js +2 -0
- package/packages/datadog-instrumentations/src/redis.js +27 -13
- package/packages/datadog-instrumentations/src/router.js +30 -0
- package/packages/datadog-instrumentations/src/rum-browser-scripts.js +2 -6
- package/packages/datadog-instrumentations/src/stripe.js +23 -12
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +8 -5
- package/packages/datadog-instrumentations/src/vitest-main.js +16 -18
- package/packages/datadog-instrumentations/src/vitest-util.js +7 -4
- package/packages/datadog-instrumentations/src/vitest-worker.js +1 -2
- package/packages/datadog-instrumentations/src/vitest.js +9 -1
- package/packages/datadog-instrumentations/src/webdriverio.js +5 -8
- package/packages/datadog-instrumentations/src/ws.js +1 -4
- package/packages/datadog-plugin-amqplib/src/client.js +1 -2
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -5
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/handler.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -8
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +18 -0
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/sonic.js +45 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -5
- package/packages/datadog-plugin-azure-durable-functions/src/index.js +5 -4
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -3
- package/packages/datadog-plugin-claude-agent-sdk/src/index.js +0 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +4 -5
- package/packages/datadog-plugin-cypress/src/index.js +6 -6
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -2
- package/packages/datadog-plugin-cypress/src/support.js +3 -4
- package/packages/datadog-plugin-express/src/code_origin.js +1 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -2
- package/packages/datadog-plugin-graphql/src/execute.js +5 -5
- package/packages/datadog-plugin-grpc/src/util.js +1 -2
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -2
- package/packages/datadog-plugin-mocha/src/index.js +7 -10
- package/packages/datadog-plugin-mocha/src/webdriverio-video.js +8 -4
- package/packages/datadog-plugin-mongodb-core/src/query.js +8 -5
- package/packages/datadog-plugin-next/src/index.js +1 -2
- package/packages/datadog-plugin-openai/src/tracing.js +5 -2
- package/packages/datadog-plugin-openai-agents/src/integration.js +6 -2
- package/packages/datadog-plugin-openai-agents/src/processor.js +2 -4
- package/packages/datadog-plugin-postgres/src/index.js +24 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -5
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -4
- package/packages/datadog-plugin-vitest/src/index.js +5 -2
- package/packages/datadog-shimmer/src/shimmer.js +5 -4
- package/packages/datadog-webpack/index.js +55 -43
- package/packages/datadog-webpack/src/loader.js +56 -8
- package/packages/dd-trace/src/aiguard/evaluation.js +143 -1
- package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -4
- package/packages/dd-trace/src/aiguard/messages/utils.js +1 -2
- package/packages/dd-trace/src/aiguard/redaction.js +8 -2
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +3 -2
- package/packages/dd-trace/src/appsec/api_security/sampler.js +2 -6
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -9
- package/packages/dd-trace/src/appsec/handlers/http-request.js +3 -9
- package/packages/dd-trace/src/appsec/handlers/http-response.js +7 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +1 -4
- package/packages/dd-trace/src/appsec/iast/path-line.js +2 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +7 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -3
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +1 -6
- package/packages/dd-trace/src/appsec/lambda.js +1 -3
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +37 -27
- package/packages/dd-trace/src/appsec/rasp/lfi.js +9 -5
- package/packages/dd-trace/src/appsec/reporter.js +21 -1
- package/packages/dd-trace/src/appsec/stack_trace.js +4 -4
- package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +3 -6
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +13 -7
- package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +1 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +2 -8
- package/packages/dd-trace/src/ci-visibility/resolve-runfile-path.js +54 -0
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +5 -8
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +2 -53
- package/packages/dd-trace/src/config/config-types.d.ts +2 -2
- package/packages/dd-trace/src/config/defaults.js +5 -5
- package/packages/dd-trace/src/config/generated-config-types.d.ts +10 -0
- package/packages/dd-trace/src/config/helper.js +34 -3
- package/packages/dd-trace/src/config/index.js +55 -9
- package/packages/dd-trace/src/config/normalize-service.js +1 -1
- package/packages/dd-trace/src/config/parsers.js +2 -2
- package/packages/dd-trace/src/config/supported-configurations.json +44 -0
- package/packages/dd-trace/src/datastreams/processor.js +3 -2
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -4
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -5
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +5 -5
- package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +4 -6
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -0
- package/packages/dd-trace/src/debugger/guardrail-metrics.js +2 -2
- package/packages/dd-trace/src/debugger/unsupported-runtime.js +16 -0
- package/packages/dd-trace/src/dogstatsd.js +1 -1
- package/packages/dd-trace/src/encode/tags-processors.js +2 -2
- package/packages/dd-trace/src/exporters/common/request.js +1 -5
- package/packages/dd-trace/src/id.js +14 -1
- package/packages/dd-trace/src/lambda/handler.js +179 -19
- package/packages/dd-trace/src/lambda/index.js +15 -1
- package/packages/dd-trace/src/lambda/runtime/patch.js +34 -7
- package/packages/dd-trace/src/llmobs/agent-manifest.js +19 -2
- package/packages/dd-trace/src/llmobs/audio-utils.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +15 -0
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +15 -0
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +1 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +1 -3
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/nova-sonic.js +92 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +5 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +64 -2
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +38 -0
- package/packages/dd-trace/src/llmobs/prompts/manager.js +5 -7
- package/packages/dd-trace/src/llmobs/prompts/prompt.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +15 -4
- package/packages/dd-trace/src/llmobs/span_processor.js +13 -2
- package/packages/dd-trace/src/llmobs/tagger.js +20 -10
- package/packages/dd-trace/src/llmobs/util.js +11 -6
- package/packages/dd-trace/src/llmobs/writers/base.js +4 -5
- package/packages/dd-trace/src/log/log.js +1 -5
- package/packages/dd-trace/src/openfeature/evaluation-telemetry-opt-out-hook.js +51 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +48 -21
- package/packages/dd-trace/src/openfeature/index.js +6 -0
- package/packages/dd-trace/src/openfeature/writers/util.js +4 -4
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -2
- package/packages/dd-trace/src/opentelemetry/otlp/common.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +24 -24
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +53 -13
- package/packages/dd-trace/src/otel-sampling.js +4 -5
- package/packages/dd-trace/src/otel-thread-ctx.js +79 -13
- package/packages/dd-trace/src/plugin_manager.js +1 -2
- package/packages/dd-trace/src/plugins/database.js +7 -16
- package/packages/dd-trace/src/plugins/tracing.js +0 -1
- package/packages/dd-trace/src/plugins/util/git.js +99 -59
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -5
- package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -1
- package/packages/dd-trace/src/plugins/util/test.js +50 -4
- package/packages/dd-trace/src/plugins/util/web.js +90 -20
- package/packages/dd-trace/src/priority_sampler.js +1 -2
- package/packages/dd-trace/src/profiling/profiler.js +4 -6
- package/packages/dd-trace/src/proxy.js +1 -2
- package/packages/dd-trace/src/ritm.js +4 -2
- package/packages/dd-trace/src/serverless.js +5 -0
- package/packages/dd-trace/src/span_processor.js +13 -17
- package/packages/dd-trace/src/span_stats.js +4 -1
- package/packages/dd-trace/src/telemetry/endpoints.js +1 -3
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +1 -1
- package/packages/dd-trace/src/util.js +37 -4
- package/packages/dd-trace/src/web-tags-cache.js +6 -2
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +8 -8
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/LICENSE +201 -0
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.d.ts +925 -0
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.js +1 -0
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
|
@@ -10,6 +10,11 @@ const RealtimeSession = require('./session')
|
|
|
10
10
|
/**
|
|
11
11
|
* @typedef {import('./session').TurnDescriptor} TurnDescriptor
|
|
12
12
|
* @typedef {import('./turns').ResponseTurn} ResponseTurn
|
|
13
|
+
* @typedef {{
|
|
14
|
+
* session: RealtimeSession,
|
|
15
|
+
* socket: object | undefined,
|
|
16
|
+
* finalize: (failed?: boolean) => void,
|
|
17
|
+
* }} Connection
|
|
13
18
|
*/
|
|
14
19
|
|
|
15
20
|
// One span per phase of a turn. `user speech` and `agent speech` share a channel: they differ only
|
|
@@ -36,7 +41,7 @@ const audioChannel = dc.channel('dd-trace:openai:realtime:audio')
|
|
|
36
41
|
const USER_SPEECH = { operation: 'createRealtimeUserSpeech', llmobsName: 'user speech' }
|
|
37
42
|
const AGENT_SPEECH = { operation: 'createRealtimeAgentSpeech', llmobsName: 'agent speech' }
|
|
38
43
|
|
|
39
|
-
/** @type {WeakMap<object,
|
|
44
|
+
/** @type {WeakMap<object, Connection>} */
|
|
40
45
|
const connections = new WeakMap()
|
|
41
46
|
|
|
42
47
|
/**
|
|
@@ -92,7 +97,7 @@ function captureContext (turn) {
|
|
|
92
97
|
* Start tracking a connection, reading the model and base path off the URL the SDK already built.
|
|
93
98
|
*
|
|
94
99
|
* @param {object} emitter
|
|
95
|
-
* @returns {
|
|
100
|
+
* @returns {Connection}
|
|
96
101
|
*/
|
|
97
102
|
function createConnection (emitter) {
|
|
98
103
|
let model
|
|
@@ -135,7 +140,7 @@ function createConnection (emitter) {
|
|
|
135
140
|
session.finishSession(Date.now(), failed)
|
|
136
141
|
}
|
|
137
142
|
|
|
138
|
-
const connection = { session, finalize }
|
|
143
|
+
const connection = { session, socket: emitter.socket, finalize }
|
|
139
144
|
attachSocketClose(emitter, finalize)
|
|
140
145
|
return connection
|
|
141
146
|
}
|
|
@@ -181,14 +186,21 @@ function attachSocketClose (emitter, finalize) {
|
|
|
181
186
|
|
|
182
187
|
/**
|
|
183
188
|
* @param {object} emitter
|
|
184
|
-
* @returns {
|
|
189
|
+
* @returns {Connection | undefined}
|
|
185
190
|
*/
|
|
186
191
|
function getConnection (emitter) {
|
|
187
192
|
const connection = connections.get(emitter)
|
|
188
|
-
if (connection !== undefined)
|
|
193
|
+
if (connection !== undefined) {
|
|
194
|
+
if (connection.socket === emitter.socket) return connection
|
|
195
|
+
|
|
196
|
+
// Opt-in SDK recovery keeps the emitter but replaces its socket with a new server session.
|
|
197
|
+
// Retire the old state before attaching close and exit cleanup to the replacement.
|
|
198
|
+
connection.finalize(true)
|
|
199
|
+
connections.delete(emitter)
|
|
200
|
+
}
|
|
189
201
|
|
|
190
202
|
// Nothing is listening, so never allocate. Checked only on the miss path, so an established
|
|
191
|
-
// connection
|
|
203
|
+
// connection reuses its state while the socket is unchanged.
|
|
192
204
|
if (!turnChannel.start.hasSubscribers) return
|
|
193
205
|
|
|
194
206
|
const created = createConnection(emitter)
|
|
@@ -829,7 +829,7 @@ class RealtimeSession {
|
|
|
829
829
|
input.audio.totalDecodedBytes, inputFormat.mimeType, inputFormat.sampleRate
|
|
830
830
|
)
|
|
831
831
|
const userEnd = input.speechEndTime ??
|
|
832
|
-
(userStart
|
|
832
|
+
(userStart === undefined || inputDurationMs === undefined ? undefined : userStart + inputDurationMs)
|
|
833
833
|
|
|
834
834
|
const agentStart = turn.audio.startTime
|
|
835
835
|
const playbackMs = segmentDurationMs(
|
|
@@ -58,6 +58,13 @@ const V4_PACKAGE_SHIMS = [
|
|
|
58
58
|
versions: ['>=4.87.0'],
|
|
59
59
|
interceptChannel: responsesInterceptChannel,
|
|
60
60
|
},
|
|
61
|
+
{
|
|
62
|
+
file: 'resources/decisions',
|
|
63
|
+
targetClass: 'Decisions',
|
|
64
|
+
baseResource: 'decisions',
|
|
65
|
+
methods: ['create'],
|
|
66
|
+
versions: ['>=7.30.0'],
|
|
67
|
+
},
|
|
61
68
|
{
|
|
62
69
|
file: 'resources/embeddings',
|
|
63
70
|
targetClass: 'Embeddings',
|
|
@@ -10,10 +10,9 @@ const logSubmissionCh = channel('ci:log-submission:log')
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @param {string} symbol
|
|
13
|
-
* @param {(original: Function) => Function} wrapper
|
|
14
13
|
* @param {Function} pino
|
|
15
14
|
*/
|
|
16
|
-
function wrapPino (symbol,
|
|
15
|
+
function wrapPino (symbol, pino) {
|
|
17
16
|
/**
|
|
18
17
|
* @param {unknown[]} args
|
|
19
18
|
* @returns {unknown}
|
|
@@ -25,7 +24,7 @@ function wrapPino (symbol, wrapper, pino) {
|
|
|
25
24
|
configurable: true,
|
|
26
25
|
enumerable: true,
|
|
27
26
|
writable: true,
|
|
28
|
-
value:
|
|
27
|
+
value: wrapAsJson(instance[symbol]),
|
|
29
28
|
})
|
|
30
29
|
|
|
31
30
|
return instance
|
|
@@ -83,19 +82,19 @@ function wrapPrettyFactory (prettyFactory) {
|
|
|
83
82
|
addHook({ name: 'pino', versions: ['2 - 3', '4'], patchDefault: true }, (pino) => {
|
|
84
83
|
const asJsonSym = (pino.symbols && pino.symbols.asJsonSym) || 'asJson'
|
|
85
84
|
|
|
86
|
-
return shimmer.wrapFunction(pino, pino => wrapPino(asJsonSym,
|
|
85
|
+
return shimmer.wrapFunction(pino, pino => wrapPino(asJsonSym, pino))
|
|
87
86
|
})
|
|
88
87
|
|
|
89
88
|
addHook({ name: 'pino', versions: ['>=5 <6.8.0'], patchDefault: true }, (pino) => {
|
|
90
89
|
const asJsonSym = ((pino.default || pino)?.symbols.asJsonSym) || 'asJson'
|
|
91
90
|
|
|
92
|
-
return shimmer.wrapFunction(pino, pino => wrapPino(asJsonSym,
|
|
91
|
+
return shimmer.wrapFunction(pino, pino => wrapPino(asJsonSym, pino.default || pino))
|
|
93
92
|
})
|
|
94
93
|
|
|
95
94
|
addHook({ name: 'pino', versions: ['>=6.8.0'], patchDefault: false }, (pino) => {
|
|
96
95
|
const asJsonSym = pino.symbols.asJsonSym
|
|
97
96
|
|
|
98
|
-
const wrapped = shimmer.wrapFunction(pino, pino => wrapPino(asJsonSym,
|
|
97
|
+
const wrapped = shimmer.wrapFunction(pino, pino => wrapPino(asJsonSym, pino))
|
|
99
98
|
wrapped.pino = wrapped
|
|
100
99
|
wrapped.default = wrapped
|
|
101
100
|
|
|
@@ -1077,6 +1077,7 @@ function testEndHandler ({
|
|
|
1077
1077
|
: undefined
|
|
1078
1078
|
const isAtrRetry = testResult?.retry > 0 &&
|
|
1079
1079
|
isFlakyTestRetriesEnabled &&
|
|
1080
|
+
hasAutomaticRetries(test, projects) &&
|
|
1080
1081
|
!test._ddIsAttemptToFix &&
|
|
1081
1082
|
!test._ddIsEfdRetry
|
|
1082
1083
|
|
|
@@ -1340,6 +1341,7 @@ function onDispatcherCreateWorker (dispatcher, worker) {
|
|
|
1340
1341
|
}
|
|
1341
1342
|
const isAtrRetry = testResult?.retry > 0 &&
|
|
1342
1343
|
isFlakyTestRetriesEnabled &&
|
|
1344
|
+
hasAutomaticRetries(test, projects) &&
|
|
1343
1345
|
!test._ddIsAttemptToFix &&
|
|
1344
1346
|
!test._ddIsEfdRetry
|
|
1345
1347
|
|
|
@@ -25,7 +25,7 @@ function wrapAddCommand (addCommand) {
|
|
|
25
25
|
return startCh.runStores(ctx, () => {
|
|
26
26
|
const res = addCommand.apply(this, arguments)
|
|
27
27
|
|
|
28
|
-
res.then(() => finish(
|
|
28
|
+
res.then(() => finish(ctx), err => finish(ctx, err))
|
|
29
29
|
|
|
30
30
|
return res
|
|
31
31
|
})
|
|
@@ -85,13 +85,11 @@ addHook({ name: '@redis/client', file: 'dist/lib/client/commands-queue.js', vers
|
|
|
85
85
|
|
|
86
86
|
addHook({ name: 'redis', versions: ['>=2.6 <4'] }, redis => {
|
|
87
87
|
shimmer.wrap(redis.RedisClient.prototype, 'internal_send_command', internalSendCommand => function (options) {
|
|
88
|
-
if (!startCh.hasSubscribers) return internalSendCommand.apply(this, arguments)
|
|
89
|
-
|
|
90
|
-
if (!options.callback) return internalSendCommand.apply(this, arguments)
|
|
88
|
+
if (!startCh.hasSubscribers || !options.callback) return internalSendCommand.apply(this, arguments)
|
|
91
89
|
|
|
92
90
|
const ctx = getStartCtx(this, options.command, options.args)
|
|
93
91
|
return startCh.runStores(ctx, () => {
|
|
94
|
-
options.callback = wrapCallback(
|
|
92
|
+
options.callback = wrapCallback(ctx, options.callback)
|
|
95
93
|
|
|
96
94
|
try {
|
|
97
95
|
return internalSendCommand.apply(this, arguments)
|
|
@@ -114,11 +112,11 @@ addHook({ name: 'redis', versions: ['>=0.12 <2.6'] }, redis => {
|
|
|
114
112
|
const ctx = getStartCtx(this, command, args)
|
|
115
113
|
return startCh.runStores(ctx, () => {
|
|
116
114
|
if (typeof callback === 'function') {
|
|
117
|
-
arguments[2] = wrapCallback(
|
|
115
|
+
arguments[2] = wrapCallback(ctx, callback)
|
|
118
116
|
} else if (Array.isArray(args) && typeof args.at(-1) === 'function') {
|
|
119
|
-
args[args.length - 1] = wrapCallback(
|
|
117
|
+
args[args.length - 1] = wrapCallback(ctx, args.at(-1))
|
|
120
118
|
} else {
|
|
121
|
-
arguments[2] = wrapCallback(
|
|
119
|
+
arguments[2] = wrapCallback(ctx)
|
|
122
120
|
}
|
|
123
121
|
|
|
124
122
|
try {
|
|
@@ -155,20 +153,36 @@ function getStartCtx (client, command, args, argsStartIndex) {
|
|
|
155
153
|
}
|
|
156
154
|
}
|
|
157
155
|
|
|
158
|
-
|
|
156
|
+
/**
|
|
157
|
+
* @param {Record<string, unknown> & { error?: Error }} ctx
|
|
158
|
+
* @param {Function} [callback]
|
|
159
|
+
*/
|
|
160
|
+
function wrapCallback (ctx, callback) {
|
|
159
161
|
if (typeof callback !== 'function') return callback
|
|
160
162
|
return function (err) {
|
|
161
|
-
return finish(
|
|
163
|
+
return finish(ctx, err, callback, this, arguments)
|
|
162
164
|
}
|
|
163
165
|
}
|
|
164
166
|
|
|
165
|
-
|
|
167
|
+
/**
|
|
168
|
+
* @param {Record<string, unknown> & { error?: Error }} ctx
|
|
169
|
+
* @param {Error} [error]
|
|
170
|
+
* @param {Function} [callback]
|
|
171
|
+
* @param {object} [thisArg]
|
|
172
|
+
* @param {Iterable<unknown>} [args]
|
|
173
|
+
*/
|
|
174
|
+
function finish (ctx, error, callback, thisArg, args) {
|
|
166
175
|
if (error) {
|
|
167
176
|
ctx.error = error
|
|
168
177
|
errorCh.publish(ctx)
|
|
169
178
|
}
|
|
170
179
|
if (callback) {
|
|
171
|
-
return finishCh.runStores(
|
|
180
|
+
return finishCh.runStores(
|
|
181
|
+
ctx,
|
|
182
|
+
/** @type {Parameters<typeof finishCh.runStores>[1]} */ (callback),
|
|
183
|
+
thisArg,
|
|
184
|
+
...(/** @type {Iterable<unknown>} */ (args))
|
|
185
|
+
)
|
|
172
186
|
}
|
|
173
|
-
finishCh.publish(ctx)
|
|
187
|
+
return finishCh.publish(ctx)
|
|
174
188
|
}
|
|
@@ -91,6 +91,28 @@ function resolveLayerRouteOrForwardError (meta, layer, next) {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
// Wrapped `next` -> the host continuation it calls.
|
|
95
|
+
const hostNexts = new WeakMap()
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Routers store their continuation on `req.next` once per `handle()`, and host
|
|
99
|
+
* APIs call it directly (express `res.format`, `res.sendFile` and `res.render`
|
|
100
|
+
* errors). Point it at the wrapper the current handler receives when that
|
|
101
|
+
* wrapper wraps the same continuation: `req.next` is the host continuation
|
|
102
|
+
* itself, or an earlier layer's wrapper of it. Route handlers receive a
|
|
103
|
+
* route-local continuation from `Route.dispatch`, so `req.next` keeps the
|
|
104
|
+
* router-level one there. A nested router restores its parent's `req.next`
|
|
105
|
+
* when it finishes.
|
|
106
|
+
*
|
|
107
|
+
* @param {import('node:http').IncomingMessage | undefined} req
|
|
108
|
+
* @param {Function} hostNext
|
|
109
|
+
* @param {Function} wrappedNext
|
|
110
|
+
*/
|
|
111
|
+
function adoptRequestNext (req, hostNext, wrappedNext) {
|
|
112
|
+
hostNexts.set(wrappedNext, hostNext)
|
|
113
|
+
if (req && (req.next === hostNext || hostNexts.get(req.next) === hostNext)) req.next = wrappedNext
|
|
114
|
+
}
|
|
115
|
+
|
|
94
116
|
/**
|
|
95
117
|
* Build the request/error dispatch wrappers for one host (`express` / `router`).
|
|
96
118
|
* They wrap the layer's prototype dispatch and read the side-table metadata, so
|
|
@@ -171,6 +193,7 @@ function createLayerDispatchWrappers (name) {
|
|
|
171
193
|
}
|
|
172
194
|
|
|
173
195
|
const wrappedNext = typeof next === 'function' ? wrapNext(req, meta.name, next) : next
|
|
196
|
+
if (wrappedNext !== next) adoptRequestNext(req, next, wrappedNext)
|
|
174
197
|
enterChannel.publish({ name: meta.name, req, route, layer: this })
|
|
175
198
|
|
|
176
199
|
try {
|
|
@@ -199,6 +222,7 @@ function createLayerDispatchWrappers (name) {
|
|
|
199
222
|
}
|
|
200
223
|
|
|
201
224
|
const wrappedNext = typeof next === 'function' ? wrapNext(req, meta.name, next) : next
|
|
225
|
+
if (wrappedNext !== next) adoptRequestNext(req, next, wrappedNext)
|
|
202
226
|
enterChannel.publish({ name: meta.name, req, route, layer: this })
|
|
203
227
|
|
|
204
228
|
try {
|
|
@@ -223,6 +247,7 @@ function createLayerDispatchWrappers (name) {
|
|
|
223
247
|
|
|
224
248
|
let calls = 0
|
|
225
249
|
if (typeof next === 'function') {
|
|
250
|
+
const hostNext = next
|
|
226
251
|
next = shimmer.wrapCallback(next, originalNext => function next (error) {
|
|
227
252
|
calls++
|
|
228
253
|
if (calls === 1) {
|
|
@@ -238,6 +263,7 @@ function createLayerDispatchWrappers (name) {
|
|
|
238
263
|
|
|
239
264
|
originalNext.apply(this, arguments)
|
|
240
265
|
})
|
|
266
|
+
adoptRequestNext(req, hostNext, next)
|
|
241
267
|
}
|
|
242
268
|
|
|
243
269
|
const route = needMultiMatch ? resolveLayerRoute(meta, layer) : captureRoute
|
|
@@ -273,6 +299,7 @@ function createLayerDispatchWrappers (name) {
|
|
|
273
299
|
|
|
274
300
|
let calls = 0
|
|
275
301
|
if (typeof next === 'function') {
|
|
302
|
+
const hostNext = next
|
|
276
303
|
next = shimmer.wrapCallback(next, originalNext => function next (nextError) {
|
|
277
304
|
calls++
|
|
278
305
|
if (calls === 1) {
|
|
@@ -288,6 +315,7 @@ function createLayerDispatchWrappers (name) {
|
|
|
288
315
|
|
|
289
316
|
originalNext.apply(this, arguments)
|
|
290
317
|
})
|
|
318
|
+
adoptRequestNext(req, hostNext, next)
|
|
291
319
|
}
|
|
292
320
|
|
|
293
321
|
const route = needMultiMatch ? resolveLayerRoute(meta, layer) : captureRoute
|
|
@@ -336,6 +364,7 @@ function createLayerDispatchWrappers (name) {
|
|
|
336
364
|
const nextIndex = isErrorHandler ? 3 : 2
|
|
337
365
|
let calls = 0
|
|
338
366
|
if (typeof args[nextIndex] === 'function') {
|
|
367
|
+
const hostNext = args[nextIndex]
|
|
339
368
|
args[nextIndex] = shimmer.wrapCallback(args[nextIndex], originalNext => function next (error) {
|
|
340
369
|
calls++
|
|
341
370
|
if (calls === 1) {
|
|
@@ -351,6 +380,7 @@ function createLayerDispatchWrappers (name) {
|
|
|
351
380
|
|
|
352
381
|
originalNext.apply(this, arguments)
|
|
353
382
|
})
|
|
383
|
+
adoptRequestNext(req, hostNext, args[nextIndex])
|
|
354
384
|
}
|
|
355
385
|
|
|
356
386
|
const route = needMultiMatch ? resolveLayerRoute(meta, layer) : captureRoute
|
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
/** @returns {{ isRumInstrumented: boolean, isRumActive: boolean, rumSamplingRate: number | null }} */
|
|
6
6
|
function detectRum () {
|
|
7
7
|
const isRumInstrumented = !!window.DD_RUM
|
|
8
|
-
const isRumActive = window.DD_RUM && window.DD_RUM.getInternalContext
|
|
9
|
-
? !!window.DD_RUM.getInternalContext()
|
|
10
|
-
: false
|
|
8
|
+
const isRumActive = !!(window.DD_RUM && window.DD_RUM.getInternalContext && window.DD_RUM.getInternalContext())
|
|
11
9
|
const rumInitConfiguration = window.DD_RUM && window.DD_RUM.getInitConfiguration
|
|
12
10
|
? window.DD_RUM.getInitConfiguration()
|
|
13
11
|
: undefined
|
|
@@ -26,9 +24,7 @@ function stopRumSession () {
|
|
|
26
24
|
|
|
27
25
|
function stopRumSessionAndReportActivity () {
|
|
28
26
|
if (window.DD_RUM && window.DD_RUM.stopSession) {
|
|
29
|
-
const isRumActive = window.DD_RUM.getInternalContext
|
|
30
|
-
? !!window.DD_RUM.getInternalContext()
|
|
31
|
-
: false
|
|
27
|
+
const isRumActive = !!(window.DD_RUM.getInternalContext && window.DD_RUM.getInternalContext())
|
|
32
28
|
window.DD_RUM.stopSession()
|
|
33
29
|
return isRumActive
|
|
34
30
|
}
|
|
@@ -58,19 +58,30 @@ function wrapConstructEventAsync (constructEventAsync) {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
const wrappedMethods = new WeakSet()
|
|
62
|
+
|
|
63
|
+
// Stripe >=9 <11.10 and >=18 share `webhooks` across clients. Stripe >=11.10 <18
|
|
64
|
+
// creates it per client. checkout.sessions and paymentIntents are separate for each client.
|
|
65
|
+
// Rewrapping shared webhook methods adds one layer per client, causing duplicate
|
|
66
|
+
// publications and eventually a stack overflow. Track installed functions so replacements
|
|
67
|
+
// still get wrapped and restored wrappers are reused.
|
|
68
|
+
/**
|
|
69
|
+
* @param {object|undefined} target
|
|
70
|
+
* @param {string} name
|
|
71
|
+
* @param {Function} wrapper
|
|
72
|
+
*/
|
|
73
|
+
function wrapOnce (target, name, wrapper) {
|
|
74
|
+
if (typeof target?.[name] !== 'function' || wrappedMethods.has(target[name])) return
|
|
75
|
+
|
|
76
|
+
shimmer.wrap(target, name, wrapper)
|
|
77
|
+
wrappedMethods.add(target[name])
|
|
78
|
+
}
|
|
79
|
+
|
|
61
80
|
function instrumentStripeInstance (stripe) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
shimmer.wrap(stripe.paymentIntents, 'create', wrapPaymentIntentCreate)
|
|
67
|
-
}
|
|
68
|
-
if (typeof stripe.webhooks?.constructEvent === 'function') {
|
|
69
|
-
shimmer.wrap(stripe.webhooks, 'constructEvent', wrapConstructEvent)
|
|
70
|
-
}
|
|
71
|
-
if (typeof stripe.webhooks?.constructEventAsync === 'function') {
|
|
72
|
-
shimmer.wrap(stripe.webhooks, 'constructEventAsync', wrapConstructEventAsync)
|
|
73
|
-
}
|
|
81
|
+
wrapOnce(stripe.checkout?.sessions, 'create', wrapSessionCreate)
|
|
82
|
+
wrapOnce(stripe.paymentIntents, 'create', wrapPaymentIntentCreate)
|
|
83
|
+
wrapOnce(stripe.webhooks, 'constructEvent', wrapConstructEvent)
|
|
84
|
+
wrapOnce(stripe.webhooks, 'constructEventAsync', wrapConstructEventAsync)
|
|
74
85
|
}
|
|
75
86
|
|
|
76
87
|
// stripe <22: the constructor mutates this (when invoked with 'new') and
|
|
@@ -659,8 +659,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
659
659
|
},
|
|
660
660
|
|
|
661
661
|
onTaskUpdate (packs, events) {
|
|
662
|
-
if (!isReporterActive()) return
|
|
663
|
-
if (!events) return
|
|
662
|
+
if (!isReporterActive() || !events) return
|
|
664
663
|
|
|
665
664
|
for (const event of events) {
|
|
666
665
|
if (event[1] === 'test-retried') {
|
|
@@ -685,8 +684,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
685
684
|
},
|
|
686
685
|
|
|
687
686
|
onFinished (files) {
|
|
688
|
-
if (!isReporterActive()) return
|
|
689
|
-
if (!files) return
|
|
687
|
+
if (!isReporterActive() || !files) return
|
|
690
688
|
|
|
691
689
|
for (const file of files) {
|
|
692
690
|
const testModule = createTestModuleFromFile(file)
|
|
@@ -936,6 +934,7 @@ function createMainProcessReporter (reporterState) {
|
|
|
936
934
|
isDynamicAtrEnabled: state.isDynamicAtrEnabled,
|
|
937
935
|
flakyTestRetriesIncludesUnnamedProject: flakyTestRetriesConfiguration.includesUnnamedProject,
|
|
938
936
|
flakyTestRetriesProjectNames: flakyTestRetriesConfiguration.projectNames,
|
|
937
|
+
flakyTestRetriesUseRetryMarker: flakyTestRetriesConfiguration.usesRetryMarker,
|
|
939
938
|
}, task)
|
|
940
939
|
|
|
941
940
|
return {
|
|
@@ -1276,10 +1275,12 @@ function reportFinalTestAttempt (testReport) {
|
|
|
1276
1275
|
isQuarantined: testProperties.isQuarantined,
|
|
1277
1276
|
})
|
|
1278
1277
|
}
|
|
1278
|
+
const attemptIndex = task.meta?.__ddTestOptCurrentAttemptIndex ?? 0
|
|
1279
|
+
const attemptStartTime = task.meta?.__ddTestOptAttemptStartTimes?.[attemptIndex]
|
|
1279
1280
|
const {
|
|
1280
1281
|
isRumActive,
|
|
1281
1282
|
testExecutionId,
|
|
1282
|
-
} = getRumCorrelation(task)
|
|
1283
|
+
} = getRumCorrelation(task, attemptIndex)
|
|
1283
1284
|
testSkipCh.publish({
|
|
1284
1285
|
...browserEnvironment,
|
|
1285
1286
|
testName,
|
|
@@ -1291,6 +1292,8 @@ function reportFinalTestAttempt (testReport) {
|
|
|
1291
1292
|
isRumActive,
|
|
1292
1293
|
isTestFrameworkWorker: true,
|
|
1293
1294
|
requestErrorTags: state.requestErrorTags,
|
|
1295
|
+
startTime: Number.isFinite(attemptStartTime) ? attemptStartTime : undefined,
|
|
1296
|
+
duration: task.meta?.__ddTestOptAttemptDurations?.[attemptIndex],
|
|
1294
1297
|
testStartLine: task.location?.line,
|
|
1295
1298
|
testExecutionId,
|
|
1296
1299
|
...testSuiteStore,
|
|
@@ -300,8 +300,7 @@ function configureEfdSuiteTracker (testFilepaths, repositoryRoot) {
|
|
|
300
300
|
* @param {boolean} hasNewTest
|
|
301
301
|
*/
|
|
302
302
|
function reserveEarlyFlakeDetectionSuite (testSuite, hasNewTest) {
|
|
303
|
-
if (!isEfdSuiteAdmissionEnabled || typeof testSuite !== 'string') return false
|
|
304
|
-
if (isEarlyFlakeDetectionFaulty) return false
|
|
303
|
+
if (!isEfdSuiteAdmissionEnabled || typeof testSuite !== 'string' || isEarlyFlakeDetectionFaulty) return false
|
|
305
304
|
|
|
306
305
|
if (hasNewTest) {
|
|
307
306
|
suitesWithNewTests.add(testSuite)
|
|
@@ -681,6 +680,7 @@ function resetMainProcessProvidedContext (ctx) {
|
|
|
681
680
|
_ddIsEfdSuiteAdmissionEnabled: false,
|
|
682
681
|
_ddIsFlakyTestRetriesEnabled: false,
|
|
683
682
|
_ddFlakyTestRetriesCount: 0,
|
|
683
|
+
_ddFlakyTestRetriesUseRetryMarker: false,
|
|
684
684
|
_ddIsDynamicAtrEnabled: false,
|
|
685
685
|
_ddDynamicAtrBuckets: undefined,
|
|
686
686
|
_ddFlakyTestRetriesIncludesUnnamedProject: false,
|
|
@@ -824,7 +824,7 @@ async function runMainProcessSetup (
|
|
|
824
824
|
}
|
|
825
825
|
}
|
|
826
826
|
|
|
827
|
-
const flakyTestRetriesConfiguration = configureFlakyTestRetries(ctx, testSpecifications)
|
|
827
|
+
const flakyTestRetriesConfiguration = configureFlakyTestRetries(ctx, testSpecifications, frameworkVersion)
|
|
828
828
|
if (flakyTestRetriesConfiguration) {
|
|
829
829
|
setProvidedContext(ctx, {
|
|
830
830
|
_ddIsFlakyTestRetriesEnabled: isFlakyTestRetriesEnabled,
|
|
@@ -833,6 +833,7 @@ async function runMainProcessSetup (
|
|
|
833
833
|
_ddDynamicAtrBuckets: dynamicAtrBuckets,
|
|
834
834
|
_ddFlakyTestRetriesIncludesUnnamedProject: flakyTestRetriesConfiguration.includesUnnamedProject,
|
|
835
835
|
_ddFlakyTestRetriesProjectNames: flakyTestRetriesConfiguration.projectNames,
|
|
836
|
+
_ddFlakyTestRetriesUseRetryMarker: flakyTestRetriesConfiguration.usesRetryMarker,
|
|
836
837
|
}, 'Could not send library configuration to workers.')
|
|
837
838
|
}
|
|
838
839
|
|
|
@@ -1039,7 +1040,7 @@ function shouldUseBrowserReporter (frameworkVersion, testSpecifications) {
|
|
|
1039
1040
|
testSpecifications.some(isBrowserTestSpecification)
|
|
1040
1041
|
}
|
|
1041
1042
|
|
|
1042
|
-
function configureFlakyTestRetries (ctx, testSpecifications) {
|
|
1043
|
+
function configureFlakyTestRetries (ctx, testSpecifications, frameworkVersion) {
|
|
1043
1044
|
if (!isFlakyTestRetriesEnabled || (!isDynamicAtrEnabled && flakyTestRetriesCount <= 0)) return
|
|
1044
1045
|
|
|
1045
1046
|
const maximumDynamicAtrRetries = dynamicAtrBuckets
|
|
@@ -1048,13 +1049,14 @@ function configureFlakyTestRetries (ctx, testSpecifications) {
|
|
|
1048
1049
|
const retryCount = isDynamicAtrEnabled
|
|
1049
1050
|
? Math.max(1, maximumDynamicAtrRetries)
|
|
1050
1051
|
: flakyTestRetriesCount
|
|
1052
|
+
const usesRetryMarker = isDynamicAtrEnabled || satisfies(frameworkVersion, '>=4.1.0')
|
|
1051
1053
|
let configured = false
|
|
1052
1054
|
let includesUnnamedProject = false
|
|
1053
1055
|
const projectNames = []
|
|
1054
1056
|
for (const { config, projectName } of getVitestProjectConfigs(ctx, testSpecifications)) {
|
|
1055
1057
|
if (!config.retry || config.retry.__ddTestOptAtr) {
|
|
1056
1058
|
// The serializable marker survives task inheritance and setup refreshes, unlike numeric retry counts.
|
|
1057
|
-
config.retry =
|
|
1059
|
+
config.retry = usesRetryMarker ? { count: retryCount, __ddTestOptAtr: true } : retryCount
|
|
1058
1060
|
configured = true
|
|
1059
1061
|
if (projectName) {
|
|
1060
1062
|
projectNames.push(projectName)
|
|
@@ -1069,6 +1071,7 @@ function configureFlakyTestRetries (ctx, testSpecifications) {
|
|
|
1069
1071
|
return {
|
|
1070
1072
|
includesUnnamedProject,
|
|
1071
1073
|
projectNames,
|
|
1074
|
+
usesRetryMarker,
|
|
1072
1075
|
}
|
|
1073
1076
|
}
|
|
1074
1077
|
|
|
@@ -1201,11 +1204,7 @@ function getSortWrapper (sort, frameworkVersion) {
|
|
|
1201
1204
|
|
|
1202
1205
|
function getFinishWrapper (exitOrClose) {
|
|
1203
1206
|
return async function () {
|
|
1204
|
-
if (finishedSessionContexts.has(this)) {
|
|
1205
|
-
return exitOrClose.apply(this, arguments)
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
if (!testSessionFinishCh.hasSubscribers) {
|
|
1207
|
+
if (finishedSessionContexts.has(this) || !testSessionFinishCh.hasSubscribers) {
|
|
1209
1208
|
return exitOrClose.apply(this, arguments)
|
|
1210
1209
|
}
|
|
1211
1210
|
finishedSessionContexts.add(this)
|
|
@@ -1230,15 +1229,15 @@ function getFinishWrapper (exitOrClose) {
|
|
|
1230
1229
|
const tests = getTypeTasks(this.state.getFiles())
|
|
1231
1230
|
const hasExecutedTests = tests.some(test =>
|
|
1232
1231
|
test.mode !== 'skip' && test.mode !== 'todo' &&
|
|
1233
|
-
test.result?.state
|
|
1232
|
+
(test.result?.state === 'pass' || test.result?.state === 'fail')
|
|
1234
1233
|
)
|
|
1235
1234
|
const hasErrors = hasRunError || error ||
|
|
1236
1235
|
this.state.getCountOfFailedTests() > 0 || this.state.getUnhandledErrors().length > 0
|
|
1237
|
-
const testSessionEmptyReason =
|
|
1238
|
-
?
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1236
|
+
const testSessionEmptyReason = hasErrors || hasExecutedTests
|
|
1237
|
+
? undefined
|
|
1238
|
+
: isEmptyShard
|
|
1239
|
+
? 'zero_test_shard'
|
|
1240
|
+
: tests.length > 0 || skippedSuites.length > 0 ? 'all_tests_skipped' : 'zero_tests'
|
|
1242
1241
|
const status = hasErrors ? 'fail' : (testSessionEmptyReason ? 'skip' : 'pass')
|
|
1243
1242
|
const flushPromise = getChannelPromise(testSessionFinishCh, {
|
|
1244
1243
|
status,
|
|
@@ -1758,8 +1757,7 @@ async function reportTypecheckFile (file, sessionConfiguration, frameworkVersion
|
|
|
1758
1757
|
}
|
|
1759
1758
|
|
|
1760
1759
|
async function reportTypecheckResults (result, frameworkVersion, ctx, typechecker, files = result?.files) {
|
|
1761
|
-
if (!testSuiteFinishCh.hasSubscribers) return
|
|
1762
|
-
if (!Array.isArray(result?.files) || !Array.isArray(files)) return
|
|
1760
|
+
if (!testSuiteFinishCh.hasSubscribers || !Array.isArray(result?.files) || !Array.isArray(files)) return
|
|
1763
1761
|
|
|
1764
1762
|
const setupState = ctx && mainProcessSetupStates.get(ctx)
|
|
1765
1763
|
if (
|
|
@@ -33,7 +33,7 @@ const testManagementTestsCh = channel('ci:vitest:test-management-tests')
|
|
|
33
33
|
const modifiedFilesCh = channel('ci:vitest:modified-files')
|
|
34
34
|
|
|
35
35
|
const CLOSING_SCRIPT_TAG_RE = /<\/script/i
|
|
36
|
-
const SERIALIZED_CONTEXT_PREFIX = '\
|
|
36
|
+
const SERIALIZED_CONTEXT_PREFIX = '\0dd-vitest-context:'
|
|
37
37
|
|
|
38
38
|
const workerReportTraceCh = channel('ci:vitest:worker-report:trace')
|
|
39
39
|
const workerReportCoverageCh = channel('ci:vitest:worker-report:coverage')
|
|
@@ -182,6 +182,7 @@ function getProvidedContext () {
|
|
|
182
182
|
_ddDynamicAtrBuckets: dynamicAtrBuckets,
|
|
183
183
|
_ddFlakyTestRetriesIncludesUnnamedProject: flakyTestRetriesIncludesUnnamedProject,
|
|
184
184
|
_ddFlakyTestRetriesProjectNames: flakyTestRetriesProjectNames,
|
|
185
|
+
_ddFlakyTestRetriesUseRetryMarker: flakyTestRetriesUseRetryMarker,
|
|
185
186
|
_ddIsImpactedTestsEnabled: isImpactedTestsEnabled,
|
|
186
187
|
_ddTestSessionId: testSessionId,
|
|
187
188
|
_ddTestModuleId: testModuleId,
|
|
@@ -211,6 +212,7 @@ function getProvidedContext () {
|
|
|
211
212
|
dynamicAtrBuckets,
|
|
212
213
|
flakyTestRetriesIncludesUnnamedProject,
|
|
213
214
|
flakyTestRetriesProjectNames,
|
|
215
|
+
flakyTestRetriesUseRetryMarker,
|
|
214
216
|
isImpactedTestsEnabled,
|
|
215
217
|
testSessionId,
|
|
216
218
|
testModuleId,
|
|
@@ -254,8 +256,9 @@ function getProvidedContext () {
|
|
|
254
256
|
}
|
|
255
257
|
|
|
256
258
|
function isFlakyTestRetriesEnabledForTask (providedContext, task) {
|
|
257
|
-
if (!providedContext.isFlakyTestRetriesEnabled) return false
|
|
258
|
-
if (providedContext.isDynamicAtrEnabled
|
|
259
|
+
if (!providedContext.isFlakyTestRetriesEnabled || task.meta?.__ddTestOptNativeRetry) return false
|
|
260
|
+
if ((providedContext.isDynamicAtrEnabled || providedContext.flakyTestRetriesUseRetryMarker) &&
|
|
261
|
+
!task.retry?.__ddTestOptAtr) return false
|
|
259
262
|
|
|
260
263
|
const { flakyTestRetriesProjectNames } = providedContext
|
|
261
264
|
if (!Array.isArray(flakyTestRetriesProjectNames)) return true
|
|
@@ -299,7 +302,7 @@ function getVitestTestProperties (providedContext, testSuiteAbsolutePath, testNa
|
|
|
299
302
|
|
|
300
303
|
return {
|
|
301
304
|
testSuite: testProperties?.testSuite,
|
|
302
|
-
isNew: Array.isArray(knownTests)
|
|
305
|
+
isNew: Array.isArray(knownTests) && !knownTests.includes(testName),
|
|
303
306
|
isModified: testProperties?.isModified === true,
|
|
304
307
|
isAttemptToFix: testManagementProperties.isAttemptToFix,
|
|
305
308
|
isDisabled: testManagementProperties.isDisabled,
|
|
@@ -354,8 +354,7 @@ function hasConcurrentTask (tasks) {
|
|
|
354
354
|
if (!tasks) return false
|
|
355
355
|
|
|
356
356
|
for (const task of tasks) {
|
|
357
|
-
if (task.concurrent === true) return true
|
|
358
|
-
if (hasConcurrentTask(task.tasks)) return true
|
|
357
|
+
if (task.concurrent === true || hasConcurrentTask(task.tasks)) return true
|
|
359
358
|
}
|
|
360
359
|
|
|
361
360
|
return false
|
|
@@ -2,10 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
|
|
4
4
|
const { isTrue } = require('../../dd-trace/src/util')
|
|
5
|
+
const { channel } = require('./helpers/instrument')
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
channel('tracing:orchestrion:@vitest/runner:createTestTask:end').subscribe(({ arguments: args, result: task }) => {
|
|
8
|
+
// Suite options have already been merged here, including overrides equal to ATR's count.
|
|
9
|
+
if (args[1]?.retry !== undefined && task?.meta) {
|
|
10
|
+
task.meta = { ...task.meta, __ddTestOptNativeRetry: true }
|
|
11
|
+
}
|
|
12
|
+
})
|
|
7
13
|
|
|
8
14
|
if (getEnvironmentVariable('DD_VITEST_WORKER') === '1') {
|
|
15
|
+
const VITEST_NO_WORKER_INIT_ACTIVE_ENV = 'DD_TEST_OPT_VITEST_NO_WORKER_INIT_ACTIVE'
|
|
16
|
+
|
|
9
17
|
// In no-worker-init mode the main process reports Vitest events from reporter hooks.
|
|
10
18
|
// Loading worker instrumentation here would reintroduce the worker tracer path.
|
|
11
19
|
// eslint-disable-next-line eslint-rules/eslint-process-env
|
|
@@ -297,8 +297,7 @@ async function preloadRumNavigation () {
|
|
|
297
297
|
try {
|
|
298
298
|
const browser = this
|
|
299
299
|
const testExecutionId = getRumTestExecutionId(browser)
|
|
300
|
-
if (!canCorrelateRumBrowser(browser)) return
|
|
301
|
-
if (!rumRunnerBrowsers.has(browser)) return
|
|
300
|
+
if (!canCorrelateRumBrowser(browser) || !rumRunnerBrowsers.has(browser)) return
|
|
302
301
|
|
|
303
302
|
retainRumBrowser(browser)
|
|
304
303
|
if (!testExecutionId) return
|
|
@@ -371,9 +370,7 @@ async function handleRumNavigation (context) {
|
|
|
371
370
|
log.debug("RUM was detected on the page, but it isn't active because the sampling rate is below 100%")
|
|
372
371
|
}
|
|
373
372
|
const testExecutionId = getRumTestExecutionId(browser, isRumActive)
|
|
374
|
-
if (sampledOut)
|
|
375
|
-
|
|
376
|
-
if (!testExecutionId) {
|
|
373
|
+
if (sampledOut || !testExecutionId) {
|
|
377
374
|
return
|
|
378
375
|
}
|
|
379
376
|
if (!isRumActive && browser.isBidi) return
|
|
@@ -1736,9 +1733,7 @@ function handleWorkerMessage (state, workerRecord, message) {
|
|
|
1736
1733
|
requestId,
|
|
1737
1734
|
},
|
|
1738
1735
|
})
|
|
1739
|
-
if (
|
|
1740
|
-
respond(new Error('WebdriverIO media upload is not available'))
|
|
1741
|
-
} else {
|
|
1736
|
+
if (requestId && uploadCh.hasSubscribers) {
|
|
1742
1737
|
try {
|
|
1743
1738
|
let signal
|
|
1744
1739
|
if (isVideo) {
|
|
@@ -1754,6 +1749,8 @@ function handleWorkerMessage (state, workerRecord, message) {
|
|
|
1754
1749
|
log.error('WebdriverIO media upload error: %s', error?.message || String(error))
|
|
1755
1750
|
respond(error)
|
|
1756
1751
|
}
|
|
1752
|
+
} else {
|
|
1753
|
+
respond(new Error('WebdriverIO media upload is not available'))
|
|
1757
1754
|
}
|
|
1758
1755
|
return
|
|
1759
1756
|
}
|