dd-trace 5.117.0 → 5.119.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 +162 -21
- package/ci/init.js +0 -1
- package/ci/runbook.md +187 -180
- package/ci/test-optimization-validation/approval-artifacts.js +3 -1
- package/ci/test-optimization-validation/approval.js +52 -15
- package/ci/test-optimization-validation/ci-command-candidate.js +26 -32
- package/ci/test-optimization-validation/ci-discovery.js +1 -1
- package/ci/test-optimization-validation/ci-package-scripts.js +141 -0
- package/ci/test-optimization-validation/ci-remediation.js +112 -39
- package/ci/test-optimization-validation/cli.js +516 -681
- package/ci/test-optimization-validation/command-blocker.js +188 -33
- package/ci/test-optimization-validation/command-output-policy.js +8 -31
- package/ci/test-optimization-validation/command-runner.js +189 -245
- package/ci/test-optimization-validation/environment.js +90 -0
- package/ci/test-optimization-validation/executable.js +159 -388
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +119 -0
- package/ci/test-optimization-validation/framework-adapters/cypress.js +107 -0
- package/ci/test-optimization-validation/framework-adapters/playwright.js +181 -0
- package/ci/test-optimization-validation/generated-files.js +84 -22
- package/ci/test-optimization-validation/generated-test-contract.js +281 -0
- package/ci/test-optimization-validation/generated-verifier.js +49 -16
- package/ci/test-optimization-validation/literal-environment.js +57 -0
- package/ci/test-optimization-validation/manifest-loader.js +2 -22
- package/ci/test-optimization-validation/manifest-scaffold.js +815 -515
- package/ci/test-optimization-validation/manifest-schema.js +494 -702
- package/ci/test-optimization-validation/offline-fixtures.js +4 -1
- package/ci/test-optimization-validation/offline-output.js +6 -6
- package/ci/test-optimization-validation/plan-writer.js +243 -984
- package/ci/test-optimization-validation/preflight-runner.js +49 -55
- package/ci/test-optimization-validation/redaction.js +2 -1
- package/ci/test-optimization-validation/report-writer.js +391 -1357
- package/ci/test-optimization-validation/result-semantics.js +86 -0
- package/ci/test-optimization-validation/runner-command.js +249 -0
- package/ci/test-optimization-validation/runner-contract.js +664 -0
- package/ci/test-optimization-validation/safe-files.js +4 -4
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +29 -3
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +240 -543
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +450 -670
- package/ci/test-optimization-validation/scenarios/early-flake-detection.js +4 -3
- package/ci/test-optimization-validation/scenarios/helpers.js +67 -9
- package/ci/test-optimization-validation/scenarios/test-management.js +6 -5
- package/ci/test-optimization-validation/source-text.js +87 -0
- package/ci/test-optimization-validation/test-output.js +12 -22
- package/ci/vitest-no-worker-init-setup.mjs +348 -51
- package/ext/tags.d.ts +1 -0
- package/index.d.ts +84 -13
- package/package.json +10 -4
- package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
- package/packages/datadog-esbuild/index.js +4 -2
- package/packages/datadog-esbuild/src/utils.js +1 -1
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +4 -4
- package/packages/datadog-instrumentations/src/cucumber.js +9 -6
- package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
- package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/openai-agents.js +31 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +57 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
- package/packages/datadog-instrumentations/src/http/client.js +1 -3
- package/packages/datadog-instrumentations/src/jest.js +8 -14
- package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
- package/packages/datadog-instrumentations/src/mocha/main.js +2 -42
- package/packages/datadog-instrumentations/src/mocha/utils.js +68 -2
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +19 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +446 -42
- package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
- package/packages/datadog-instrumentations/src/openai-agents.js +159 -0
- package/packages/datadog-instrumentations/src/playwright.js +3 -2
- package/packages/datadog-instrumentations/src/rhea.js +1 -1
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +525 -56
- package/packages/datadog-instrumentations/src/vitest-main.js +90 -10
- package/packages/datadog-instrumentations/src/webdriverio.js +914 -0
- package/packages/datadog-plugin-aerospike/src/index.js +1 -3
- package/packages/datadog-plugin-amqplib/src/client.js +1 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
- package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
- package/packages/datadog-plugin-child_process/src/index.js +3 -3
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +5 -8
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
- package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
- package/packages/datadog-plugin-fs/src/index.js +0 -4
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
- package/packages/datadog-plugin-graphql/src/execute.js +1 -0
- package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +2 -1
- package/packages/datadog-plugin-jest/src/index.js +2 -3
- package/packages/datadog-plugin-jest/src/util.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +25 -6
- package/packages/datadog-plugin-openai-agents/src/index.js +74 -0
- package/packages/datadog-plugin-openai-agents/src/integration.js +503 -0
- package/packages/datadog-plugin-openai-agents/src/processor.js +108 -0
- package/packages/datadog-plugin-openai-agents/src/util.js +60 -0
- package/packages/datadog-plugin-prisma/src/index.js +5 -1
- package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-undici/src/index.js +2 -1
- package/packages/datadog-plugin-vitest/src/index.js +84 -11
- package/packages/datadog-webpack/index.js +2 -2
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/track_event.js +1 -1
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +50 -51
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +4 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +161 -33
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +7 -5
- package/packages/dd-trace/src/config/defaults.js +14 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
- package/packages/dd-trace/src/config/index.js +15 -0
- package/packages/dd-trace/src/config/parsers.js +19 -1
- package/packages/dd-trace/src/config/supported-configurations.json +12 -6
- package/packages/dd-trace/src/datastreams/encoding.js +3 -4
- package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
- package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
- package/packages/dd-trace/src/encode/span-stats.js +7 -1
- package/packages/dd-trace/src/encode/tags-processors.js +2 -2
- package/packages/dd-trace/src/exporter.js +16 -9
- package/packages/dd-trace/src/exporters/common/url.js +3 -5
- package/packages/dd-trace/src/exporters/electron/index.js +4 -1
- package/packages/dd-trace/src/external-logger/src/index.js +1 -2
- package/packages/dd-trace/src/flare/index.js +2 -2
- package/packages/dd-trace/src/id.js +1 -1
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
- package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
- package/packages/dd-trace/src/llmobs/experiments/index.js +51 -12
- package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
- package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
- package/packages/dd-trace/src/llmobs/experiments/util.js +218 -0
- package/packages/dd-trace/src/llmobs/index.js +9 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +104 -22
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +5 -9
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +20 -0
- package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +321 -0
- package/packages/dd-trace/src/llmobs/sdk.js +6 -12
- package/packages/dd-trace/src/llmobs/span_processor.js +14 -7
- package/packages/dd-trace/src/llmobs/tagger.js +24 -5
- package/packages/dd-trace/src/llmobs/util.js +56 -3
- package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
- package/packages/dd-trace/src/noop/proxy.js +2 -2
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +3 -6
- package/packages/dd-trace/src/openfeature/configuration_source.js +5 -8
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +5 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/opentracing/span_context.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +114 -23
- package/packages/dd-trace/src/plugins/index.js +2 -0
- package/packages/dd-trace/src/plugins/outbound.js +4 -1
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/tracing.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +7 -6
- package/packages/dd-trace/src/plugins/util/git.js +1 -1
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +1 -1
- package/packages/dd-trace/src/plugins/util/llm.js +2 -2
- package/packages/dd-trace/src/plugins/util/tags.js +2 -0
- package/packages/dd-trace/src/plugins/util/test.js +38 -12
- package/packages/dd-trace/src/plugins/util/url.js +5 -5
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/priority_sampler.js +6 -3
- package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
- package/packages/dd-trace/src/ritm.js +5 -20
- package/packages/dd-trace/src/span_processor.js +1 -1
- package/packages/dd-trace/src/span_stats.js +22 -4
- package/packages/dd-trace/src/startup-log.js +3 -0
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
- package/packages/dd-trace/src/util.js +16 -0
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
- package/vendor/dist/pprof-format/index.js +1 -1
- package/vendor/dist/source-map/index.js +1 -1
- package/ci/test-optimization-validation/command-suitability.js +0 -471
- package/ci/test-optimization-validation/init-probe-preload.js +0 -163
- package/ci/test-optimization-validation/init-probe.js +0 -246
- package/ci/test-optimization-validation/late-initialization.js +0 -63
- package/ci/test-optimization-validation/local-command.js +0 -163
- package/ci/test-optimization-validation/setup-runner.js +0 -97
- package/ci/test-optimization-validation-manifest.schema.json +0 -1
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { relative } from 'node:path'
|
|
3
|
-
import { performance } from 'node:perf_hooks'
|
|
1
|
+
import { afterEach, beforeAll, beforeEach, inject } from 'vitest'
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// Instrumentation-less worker setup for DD_EXPERIMENTAL_TEST_OPT_VITEST_NO_WORKER_INIT.
|
|
8
|
-
// It applies Test Optimization execution changes without initializing dd-trace in Vitest workers.
|
|
3
|
+
// Instrumentation-less setup for DD_EXPERIMENTAL_TEST_OPT_VITEST_NO_WORKER_INIT.
|
|
4
|
+
// It applies Test Optimization execution changes without initializing dd-trace and also supports Browser Mode.
|
|
9
5
|
const VITEST_NO_WORKER_INIT_ACTIVE_ENV = 'DD_TEST_OPT_VITEST_NO_WORKER_INIT_ACTIVE'
|
|
10
|
-
const
|
|
11
|
-
const
|
|
6
|
+
const providedContext = getProvidedContext()
|
|
7
|
+
const isNoWorkerInitActive = providedContext.isActive ?? getIsNoWorkerInitActive()
|
|
12
8
|
const attemptToFixTests = providedContext.attemptToFixTests || {}
|
|
13
9
|
const attemptToFixRetries = providedContext.attemptToFixRetries || 0
|
|
14
10
|
const disabledTests = providedContext.disabledTests || {}
|
|
@@ -22,7 +18,9 @@ const isEarlyFlakeDetectionEnabled = providedContext.isEarlyFlakeDetectionEnable
|
|
|
22
18
|
const knownTests = providedContext.knownTests || {}
|
|
23
19
|
const modifiedFiles = providedContext.modifiedFiles || {}
|
|
24
20
|
const quarantinedTests = providedContext.quarantinedTests || {}
|
|
25
|
-
const
|
|
21
|
+
const isRumCorrelationEnabled = providedContext.isRumCorrelationEnabled !== false
|
|
22
|
+
const rumTestExecutionIdCookieName = providedContext.rumTestExecutionIdCookieName
|
|
23
|
+
const testPropertiesByFilepath = providedContext.testPropertiesByFilepath || {}
|
|
26
24
|
let setVitestTaskFn
|
|
27
25
|
if (isNoWorkerInitActive) {
|
|
28
26
|
try {
|
|
@@ -35,7 +33,21 @@ const earlyFlakeDetectionRetriesByTask = new WeakMap()
|
|
|
35
33
|
const earlyFlakeDetectionSkippedResults = new WeakMap()
|
|
36
34
|
const earlyFlakeDetectionStartByTask = new WeakMap()
|
|
37
35
|
const nextAttemptIndexByTask = new WeakMap()
|
|
38
|
-
const
|
|
36
|
+
const retryAttemptIndexByTask = new WeakMap()
|
|
37
|
+
const usedRumTestExecutionIds = new Set()
|
|
38
|
+
let now
|
|
39
|
+
let timeOrigin
|
|
40
|
+
// Use an unfaked monotonic clock in Node and Vitest's parent frame in Browser Mode.
|
|
41
|
+
if (typeof globalThis.process?.uptime === 'function') {
|
|
42
|
+
now = () => globalThis.process.uptime() * 1000
|
|
43
|
+
timeOrigin = Date.now() - now()
|
|
44
|
+
} else {
|
|
45
|
+
const clock = globalThis.window?.parent && globalThis.window.parent !== globalThis.window
|
|
46
|
+
? globalThis.window.parent.performance
|
|
47
|
+
: globalThis.performance
|
|
48
|
+
now = clock ? clock.now.bind(clock) : Date.now
|
|
49
|
+
timeOrigin = Number.isFinite(clock?.timeOrigin) ? clock.timeOrigin : Date.now() - now()
|
|
50
|
+
}
|
|
39
51
|
|
|
40
52
|
if (isNoWorkerInitActive) {
|
|
41
53
|
// eslint-disable-next-line no-empty-pattern
|
|
@@ -51,11 +63,12 @@ if (isNoWorkerInitActive) {
|
|
|
51
63
|
const isEarlyFlakeDetectionTestAttempt = isEarlyFlakeDetectionTest(testSuite, testName)
|
|
52
64
|
const isQuarantinedTest = quarantinedTests[testSuite]?.[testName] && !isAttemptToFixTest
|
|
53
65
|
const attemptIndex = getNextAttemptIndex(task)
|
|
66
|
+
const attemptStart = now()
|
|
54
67
|
if (attemptIndex > 0) {
|
|
55
68
|
recordTestOptimizationStatus(task, attemptIndex - 1)
|
|
56
69
|
}
|
|
57
70
|
|
|
58
|
-
if (disabledTests[testSuite]?.[testName]
|
|
71
|
+
if (!isAttemptToFixTest && disabledTests[testSuite]?.[testName]) {
|
|
59
72
|
skip('Skipped by Datadog Test Optimization')
|
|
60
73
|
} else if (isAttemptToFixTest && attemptIndex > 0) {
|
|
61
74
|
task.result.state = 'run'
|
|
@@ -66,27 +79,33 @@ if (isNoWorkerInitActive) {
|
|
|
66
79
|
}
|
|
67
80
|
}
|
|
68
81
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
prepareRumCorrelation(task, attemptIndex)
|
|
83
|
+
|
|
84
|
+
onTestFinished(() => {
|
|
85
|
+
recordTestAttemptTiming(task, attemptIndex, attemptStart)
|
|
86
|
+
recordRetryErrorCount(task)
|
|
87
|
+
if (
|
|
88
|
+
(isAttemptToFixTest || isEarlyFlakeDetectionTestAttempt || isQuarantinedTest) &&
|
|
89
|
+
attemptIndex === getFinalAttemptIndex(task)
|
|
90
|
+
) {
|
|
91
|
+
if (isAttemptToFixTest || isEarlyFlakeDetectionTestAttempt) {
|
|
92
|
+
recordTestOptimizationStatus(task, attemptIndex, true)
|
|
76
93
|
}
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
switchQuarantinedFinalFailure(task, attemptIndex)
|
|
95
|
+
}
|
|
96
|
+
finishRumCorrelation(task, attemptIndex)
|
|
97
|
+
})
|
|
79
98
|
})
|
|
80
99
|
|
|
81
100
|
afterEach(function ({ task }) {
|
|
82
101
|
const attemptIndex = task.meta.__ddTestOptCurrentAttemptIndex
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
if (attemptIndex === getFinalAttemptIndex(task)) {
|
|
102
|
+
const restoredEarlyFlakeDetectionResult = restoreEarlyFlakeDetectionSkippedResult(task)
|
|
103
|
+
if (!restoredEarlyFlakeDetectionResult && attemptIndex === getFinalAttemptIndex(task)) {
|
|
87
104
|
recordTestOptimizationStatus(task, attemptIndex)
|
|
88
105
|
}
|
|
89
|
-
|
|
106
|
+
if (!restoredEarlyFlakeDetectionResult) {
|
|
107
|
+
switchQuarantinedFinalFailure(task, attemptIndex)
|
|
108
|
+
}
|
|
90
109
|
})
|
|
91
110
|
}
|
|
92
111
|
|
|
@@ -110,6 +129,7 @@ function applyExecutionChanges (suite) {
|
|
|
110
129
|
task.repeats = earlyFlakeDetectionRetries
|
|
111
130
|
task.meta.__ddTestOptEfdRetries = earlyFlakeDetectionRetries
|
|
112
131
|
}
|
|
132
|
+
wrapRetryCondition(task)
|
|
113
133
|
}
|
|
114
134
|
}
|
|
115
135
|
|
|
@@ -117,9 +137,194 @@ function getNextAttemptIndex (task) {
|
|
|
117
137
|
const attemptIndex = nextAttemptIndexByTask.get(task) || 0
|
|
118
138
|
nextAttemptIndexByTask.set(task, attemptIndex + 1)
|
|
119
139
|
task.meta.__ddTestOptCurrentAttemptIndex = attemptIndex
|
|
140
|
+
|
|
141
|
+
const repeatCount = task.result?.repeatCount || 0
|
|
142
|
+
const retryAttempt = retryAttemptIndexByTask.get(task)
|
|
143
|
+
const retryAttemptIndex = retryAttempt?.repeatCount === repeatCount ? retryAttempt.index + 1 : 0
|
|
144
|
+
retryAttemptIndexByTask.set(task, {
|
|
145
|
+
index: retryAttemptIndex,
|
|
146
|
+
repeatCount,
|
|
147
|
+
})
|
|
148
|
+
|
|
120
149
|
return attemptIndex
|
|
121
150
|
}
|
|
122
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Sets the RUM correlation cookie for a sequential browser test attempt.
|
|
154
|
+
*
|
|
155
|
+
* @param {object} task
|
|
156
|
+
* @param {number} attemptIndex
|
|
157
|
+
* @returns {void}
|
|
158
|
+
*/
|
|
159
|
+
function prepareRumCorrelation (task, attemptIndex) {
|
|
160
|
+
// A per-origin cookie cannot identify overlapping attempts without racing.
|
|
161
|
+
if (!isRumCorrelationEnabled || isConcurrentTask(task)) return
|
|
162
|
+
|
|
163
|
+
if (
|
|
164
|
+
typeof window === 'undefined' ||
|
|
165
|
+
typeof document === 'undefined' ||
|
|
166
|
+
typeof rumTestExecutionIdCookieName !== 'string'
|
|
167
|
+
) {
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const testExecutionId = generateTestExecutionId()
|
|
172
|
+
if (
|
|
173
|
+
!testExecutionId ||
|
|
174
|
+
usedRumTestExecutionIds.has(testExecutionId) ||
|
|
175
|
+
!setRumCorrelationCookie(testExecutionId)
|
|
176
|
+
) {
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
usedRumTestExecutionIds.add(testExecutionId)
|
|
181
|
+
task.meta.__ddTestOptRumTestExecutionIds ||= []
|
|
182
|
+
task.meta.__ddTestOptRumTestExecutionIds[attemptIndex] = testExecutionId
|
|
183
|
+
recordRumActivity(task, attemptIndex)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Records whether RUM was active and clears the attempt cookie.
|
|
188
|
+
*
|
|
189
|
+
* @param {object} task
|
|
190
|
+
* @param {number} attemptIndex
|
|
191
|
+
* @returns {void}
|
|
192
|
+
*/
|
|
193
|
+
function finishRumCorrelation (task, attemptIndex) {
|
|
194
|
+
const testExecutionId = task.meta.__ddTestOptRumTestExecutionIds?.[attemptIndex]
|
|
195
|
+
if (!testExecutionId) return
|
|
196
|
+
|
|
197
|
+
recordRumActivity(task, attemptIndex)
|
|
198
|
+
clearRumCorrelationCookie(testExecutionId)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Retains evidence that RUM was active at any point observed during the attempt.
|
|
203
|
+
*
|
|
204
|
+
* @param {object} task
|
|
205
|
+
* @param {number} attemptIndex
|
|
206
|
+
* @returns {void}
|
|
207
|
+
*/
|
|
208
|
+
function recordRumActivity (task, attemptIndex) {
|
|
209
|
+
if (!getIsRumActive(getRum())) return
|
|
210
|
+
|
|
211
|
+
task.meta.__ddTestOptRumActive ||= []
|
|
212
|
+
task.meta.__ddTestOptRumActive[attemptIndex] = true
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Returns the RUM public API without letting application-defined accessors fail a test.
|
|
217
|
+
*
|
|
218
|
+
* @returns {object|undefined}
|
|
219
|
+
*/
|
|
220
|
+
function getRum () {
|
|
221
|
+
try {
|
|
222
|
+
return window.DD_RUM
|
|
223
|
+
} catch {}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Returns whether the current RUM session is active.
|
|
228
|
+
*
|
|
229
|
+
* @param {object|undefined} rum
|
|
230
|
+
* @returns {boolean}
|
|
231
|
+
*/
|
|
232
|
+
function getIsRumActive (rum) {
|
|
233
|
+
if (!rum) return false
|
|
234
|
+
if (typeof rum.getInternalContext !== 'function') return false
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
return !!rum.getInternalContext()
|
|
238
|
+
} catch {
|
|
239
|
+
return false
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Returns whether a task or any containing suite is concurrent.
|
|
245
|
+
*
|
|
246
|
+
* @param {object} task
|
|
247
|
+
* @returns {boolean}
|
|
248
|
+
*/
|
|
249
|
+
function isConcurrentTask (task) {
|
|
250
|
+
let currentTask = task
|
|
251
|
+
while (currentTask) {
|
|
252
|
+
if (currentTask.concurrent === true) return true
|
|
253
|
+
currentTask = currentTask.suite
|
|
254
|
+
}
|
|
255
|
+
return false
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Generates a positive 63-bit decimal test execution ID.
|
|
260
|
+
*
|
|
261
|
+
* @returns {string|undefined}
|
|
262
|
+
*/
|
|
263
|
+
function generateTestExecutionId () {
|
|
264
|
+
// This setup file executes in a browser even though lint validates it against the package's Node.js target.
|
|
265
|
+
// eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
266
|
+
if (typeof globalThis.crypto?.getRandomValues !== 'function') return
|
|
267
|
+
|
|
268
|
+
const words = new Uint32Array(2)
|
|
269
|
+
try {
|
|
270
|
+
// eslint-disable-next-line n/no-unsupported-features/node-builtins
|
|
271
|
+
globalThis.crypto.getRandomValues(words)
|
|
272
|
+
} catch {
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
words[0] &= 0x7F_FF_FF_FF
|
|
277
|
+
if (words[0] === 0 && words[1] === 0) return
|
|
278
|
+
|
|
279
|
+
return ((BigInt(words[0]) << 32n) | BigInt(words[1])).toString(10)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Sets and verifies the RUM correlation cookie for the current origin.
|
|
284
|
+
*
|
|
285
|
+
* @param {string} testExecutionId
|
|
286
|
+
* @returns {boolean}
|
|
287
|
+
*/
|
|
288
|
+
function setRumCorrelationCookie (testExecutionId) {
|
|
289
|
+
try {
|
|
290
|
+
// eslint-disable-next-line unicorn/no-document-cookie
|
|
291
|
+
document.cookie = `${rumTestExecutionIdCookieName}=${testExecutionId}; path=/`
|
|
292
|
+
return getRumCorrelationCookie() === testExecutionId
|
|
293
|
+
} catch {
|
|
294
|
+
return false
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Clears the RUM correlation cookie if it still belongs to this attempt.
|
|
300
|
+
*
|
|
301
|
+
* @param {string} testExecutionId
|
|
302
|
+
* @returns {void}
|
|
303
|
+
*/
|
|
304
|
+
function clearRumCorrelationCookie (testExecutionId) {
|
|
305
|
+
try {
|
|
306
|
+
if (getRumCorrelationCookie() === testExecutionId) {
|
|
307
|
+
// eslint-disable-next-line unicorn/no-document-cookie
|
|
308
|
+
document.cookie = `${rumTestExecutionIdCookieName}=; path=/; max-age=0`
|
|
309
|
+
}
|
|
310
|
+
} catch {}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Returns the current RUM correlation cookie value.
|
|
315
|
+
*
|
|
316
|
+
* @returns {string|undefined}
|
|
317
|
+
*/
|
|
318
|
+
function getRumCorrelationCookie () {
|
|
319
|
+
const prefix = `${rumTestExecutionIdCookieName}=`
|
|
320
|
+
for (const cookie of document.cookie.split(';')) {
|
|
321
|
+
const normalizedCookie = cookie.trim()
|
|
322
|
+
if (normalizedCookie.startsWith(prefix)) {
|
|
323
|
+
return normalizedCookie.slice(prefix.length)
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
123
328
|
function recordTestOptimizationStatus (task, attemptIndex = task.result?.repeatCount || 0, onlyIfNewErrors = false) {
|
|
124
329
|
const testSuite = getTestSuite(task)
|
|
125
330
|
const testName = getTestName(task)
|
|
@@ -206,6 +411,76 @@ function recordManualRepeatStatus (task, attemptIndex) {
|
|
|
206
411
|
task.meta.__ddTestOptRepeatErrorCounts[attemptIndex] = task.result?.errors?.length || 0
|
|
207
412
|
}
|
|
208
413
|
|
|
414
|
+
/**
|
|
415
|
+
* Records cumulative errors at the end of each configured retry attempt.
|
|
416
|
+
*
|
|
417
|
+
* @param {object} task
|
|
418
|
+
* @returns {void}
|
|
419
|
+
*/
|
|
420
|
+
function recordRetryErrorCount (task) {
|
|
421
|
+
const retryLimit = getRetryLimit(task)
|
|
422
|
+
if (retryLimit <= 0) return
|
|
423
|
+
|
|
424
|
+
const retryCount = task.result?.retryCount || 0
|
|
425
|
+
task.meta.__ddTestOptRetryErrorCounts ||= []
|
|
426
|
+
task.meta.__ddTestOptRetryErrorCounts[retryCount] = task.result?.errors?.length || 0
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Records the wall-clock start and elapsed time for one retry or repeat execution.
|
|
431
|
+
*
|
|
432
|
+
* @param {object} task
|
|
433
|
+
* @param {number} attemptIndex
|
|
434
|
+
* @param {number} attemptStart
|
|
435
|
+
* @returns {void}
|
|
436
|
+
*/
|
|
437
|
+
function recordTestAttemptTiming (task, attemptIndex, attemptStart) {
|
|
438
|
+
task.meta.__ddTestOptAttemptStartTimes ||= []
|
|
439
|
+
task.meta.__ddTestOptAttemptDurations ||= []
|
|
440
|
+
task.meta.__ddTestOptAttemptStartTimes[attemptIndex] = timeOrigin + attemptStart
|
|
441
|
+
task.meta.__ddTestOptAttemptDurations[attemptIndex] = now() - attemptStart
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Returns the configured retry count for numeric and object-form retry options.
|
|
446
|
+
*
|
|
447
|
+
* @param {object} task
|
|
448
|
+
* @returns {number}
|
|
449
|
+
*/
|
|
450
|
+
function getRetryLimit (task) {
|
|
451
|
+
return typeof task.retry === 'number' ? task.retry : task.retry?.count || 0
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Wraps Vitest's retry condition so final-attempt handling follows the condition's actual result.
|
|
456
|
+
*
|
|
457
|
+
* @param {object} task
|
|
458
|
+
* @returns {void}
|
|
459
|
+
*/
|
|
460
|
+
function wrapRetryCondition (task) {
|
|
461
|
+
if (typeof task.retry !== 'object' || !task.retry?.condition || getRetryLimit(task) === 0) return
|
|
462
|
+
|
|
463
|
+
const condition = task.retry.condition
|
|
464
|
+
task.retry = {
|
|
465
|
+
...task.retry,
|
|
466
|
+
condition (error) {
|
|
467
|
+
let shouldRetry = false
|
|
468
|
+
if (condition instanceof RegExp) {
|
|
469
|
+
shouldRetry = condition.test(error?.message || '')
|
|
470
|
+
} else if (typeof condition === 'function') {
|
|
471
|
+
shouldRetry = condition(error)
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (!shouldRetry && (task.result?.repeatCount || 0) >= (task.repeats || 0)) {
|
|
475
|
+
const attemptIndex = task.meta.__ddTestOptCurrentAttemptIndex
|
|
476
|
+
recordTestOptimizationStatus(task, attemptIndex)
|
|
477
|
+
markQuarantinedFailure(task)
|
|
478
|
+
}
|
|
479
|
+
return shouldRetry
|
|
480
|
+
},
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
209
484
|
function restoreEarlyFlakeDetectionSkippedResult (task) {
|
|
210
485
|
if (!task.meta.__ddTestOptEfdSkipCurrentAttempt) {
|
|
211
486
|
return false
|
|
@@ -236,7 +511,18 @@ function getFinalAttemptIndex (task) {
|
|
|
236
511
|
if (isEarlyFlakeDetectionTest(testSuite, testName)) {
|
|
237
512
|
return getEarlyFlakeDetectionRetryCountForTask(task)
|
|
238
513
|
}
|
|
239
|
-
|
|
514
|
+
|
|
515
|
+
const attemptIndex = task.meta.__ddTestOptCurrentAttemptIndex
|
|
516
|
+
const repeatCount = task.result?.repeatCount || 0
|
|
517
|
+
const repeatLimit = task.repeats || 0
|
|
518
|
+
const retryAttemptIndex = retryAttemptIndexByTask.get(task)?.index || 0
|
|
519
|
+
const retryLimit = getRetryLimit(task)
|
|
520
|
+
const retriesRemaining = task.result?.state === 'fail' || task.result?.state === 'run'
|
|
521
|
+
? Math.max(retryLimit - retryAttemptIndex, 0)
|
|
522
|
+
: 0
|
|
523
|
+
const repeatsRemaining = Math.max(repeatLimit - repeatCount, 0)
|
|
524
|
+
|
|
525
|
+
return attemptIndex + retriesRemaining + (repeatsRemaining * (retryLimit + 1))
|
|
240
526
|
}
|
|
241
527
|
|
|
242
528
|
function switchQuarantinedFinalFailure (task, attemptIndex) {
|
|
@@ -250,9 +536,27 @@ function switchQuarantinedFinalFailure (task, attemptIndex) {
|
|
|
250
536
|
return
|
|
251
537
|
}
|
|
252
538
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
539
|
+
if (attemptIndex < getFinalAttemptIndex(task)) {
|
|
540
|
+
return
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
markQuarantinedFailure(task)
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Converts a quarantined failure into the passing runner state expected by Vitest.
|
|
548
|
+
*
|
|
549
|
+
* @param {object} task
|
|
550
|
+
* @returns {void}
|
|
551
|
+
*/
|
|
552
|
+
function markQuarantinedFailure (task) {
|
|
553
|
+
const testSuite = getTestSuite(task)
|
|
554
|
+
const testName = getTestName(task)
|
|
555
|
+
if (
|
|
556
|
+
!quarantinedTests[testSuite]?.[testName] ||
|
|
557
|
+
attemptToFixTests[testSuite]?.[testName] ||
|
|
558
|
+
task.result?.state !== 'fail'
|
|
559
|
+
) {
|
|
256
560
|
return
|
|
257
561
|
}
|
|
258
562
|
|
|
@@ -292,7 +596,7 @@ function getPreviousErrorCount (errorCounts, repeatCount) {
|
|
|
292
596
|
|
|
293
597
|
function prepareEarlyFlakeDetectionAttempt (task, attemptIndex) {
|
|
294
598
|
if (attemptIndex === 0) {
|
|
295
|
-
earlyFlakeDetectionStartByTask.set(task,
|
|
599
|
+
earlyFlakeDetectionStartByTask.set(task, now())
|
|
296
600
|
return false
|
|
297
601
|
}
|
|
298
602
|
|
|
@@ -308,12 +612,12 @@ function prepareEarlyFlakeDetectionAttempt (task, attemptIndex) {
|
|
|
308
612
|
}
|
|
309
613
|
|
|
310
614
|
if (attemptIndex <= retryCount) {
|
|
311
|
-
earlyFlakeDetectionStartByTask.set(task,
|
|
615
|
+
earlyFlakeDetectionStartByTask.set(task, now())
|
|
312
616
|
return false
|
|
313
617
|
}
|
|
314
618
|
|
|
315
619
|
if (!canReplaceVitestTaskFn()) {
|
|
316
|
-
earlyFlakeDetectionStartByTask.set(task,
|
|
620
|
+
earlyFlakeDetectionStartByTask.set(task, now())
|
|
317
621
|
return false
|
|
318
622
|
}
|
|
319
623
|
|
|
@@ -334,7 +638,7 @@ function getEarlyFlakeDetectionRetryCount (task) {
|
|
|
334
638
|
}
|
|
335
639
|
|
|
336
640
|
const executionStart = earlyFlakeDetectionStartByTask.get(task)
|
|
337
|
-
const duration = executionStart === undefined ? task.result?.duration ?? 0 :
|
|
641
|
+
const duration = executionStart === undefined ? task.result?.duration ?? 0 : now() - executionStart
|
|
338
642
|
for (const { key, limitMs } of earlyFlakeDetectionRetryThresholds) {
|
|
339
643
|
if (duration < limitMs) {
|
|
340
644
|
return earlyFlakeDetectionSlowRetries[key] ?? 0
|
|
@@ -376,21 +680,10 @@ function isModifiedTest (testSuite) {
|
|
|
376
680
|
}
|
|
377
681
|
|
|
378
682
|
function getTestSuite (task) {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
return normalizePath(relative(repositoryRoot, filepath))
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function realpath (filepath) {
|
|
389
|
-
try {
|
|
390
|
-
return realpathSync(filepath)
|
|
391
|
-
} catch {
|
|
392
|
-
return filepath
|
|
393
|
-
}
|
|
683
|
+
const filepath = task.file.filepath
|
|
684
|
+
return testPropertiesByFilepath[filepath]?.testSuite ||
|
|
685
|
+
testPropertiesByFilepath[normalizePath(filepath)]?.testSuite ||
|
|
686
|
+
normalizePath(filepath)
|
|
394
687
|
}
|
|
395
688
|
|
|
396
689
|
function getTestName (task) {
|
|
@@ -423,8 +716,12 @@ function getIsNoWorkerInitActive () {
|
|
|
423
716
|
|
|
424
717
|
function getProvidedContext () {
|
|
425
718
|
try {
|
|
426
|
-
return
|
|
719
|
+
return inject('_ddVitestWorkerSetup') || {}
|
|
427
720
|
} catch {
|
|
428
|
-
|
|
721
|
+
try {
|
|
722
|
+
return globalThis.__vitest_worker__.providedContext._ddVitestWorkerSetup || {}
|
|
723
|
+
} catch {
|
|
724
|
+
return {}
|
|
725
|
+
}
|
|
429
726
|
}
|
|
430
727
|
}
|
package/ext/tags.d.ts
CHANGED
package/index.d.ts
CHANGED
|
@@ -293,6 +293,7 @@ interface Plugins {
|
|
|
293
293
|
"next": tracer.plugins.next;
|
|
294
294
|
"nyc": tracer.plugins.nyc;
|
|
295
295
|
"openai": tracer.plugins.openai;
|
|
296
|
+
"openai-agents": tracer.plugins.openai_agents;
|
|
296
297
|
"opensearch": tracer.plugins.opensearch;
|
|
297
298
|
"oracledb": tracer.plugins.oracledb;
|
|
298
299
|
"playwright": tracer.plugins.playwright;
|
|
@@ -3138,6 +3139,12 @@ declare namespace tracer {
|
|
|
3138
3139
|
*/
|
|
3139
3140
|
interface openai extends Instrumentation {}
|
|
3140
3141
|
|
|
3142
|
+
/**
|
|
3143
|
+
* This plugin automatically instruments the
|
|
3144
|
+
* [@openai/agents](https://www.npmjs.com/package/@openai/agents) library.
|
|
3145
|
+
*/
|
|
3146
|
+
interface openai_agents extends Instrumentation {}
|
|
3147
|
+
|
|
3141
3148
|
/**
|
|
3142
3149
|
* This plugin automatically instruments the
|
|
3143
3150
|
* [opensearch](https://github.com/opensearch-project/opensearch-js) module.
|
|
@@ -3924,29 +3931,74 @@ declare namespace tracer {
|
|
|
3924
3931
|
flush (): void
|
|
3925
3932
|
}
|
|
3926
3933
|
|
|
3934
|
+
/** JSON-serializable value accepted by LLMObs Experiments. */
|
|
3935
|
+
type JSONType = string | number | boolean | null | JSONType[] | { [key: string]: JSONType }
|
|
3936
|
+
|
|
3927
3937
|
/**
|
|
3928
3938
|
* A task run over each dataset record during an experiment.
|
|
3929
3939
|
*/
|
|
3930
|
-
type ExperimentTask = (
|
|
3940
|
+
type ExperimentTask = (
|
|
3941
|
+
input: JSONType,
|
|
3942
|
+
config: Record<string, JSONType>,
|
|
3943
|
+
metadata?: Record<string, JSONType>
|
|
3944
|
+
) => JSONType | Promise<JSONType>
|
|
3931
3945
|
|
|
3932
3946
|
/**
|
|
3933
3947
|
* Scores a single task output. The return type selects the metric:
|
|
3934
|
-
* `boolean` -> boolean, `number` -> score, anything else ->
|
|
3948
|
+
* `boolean` -> boolean, `number` -> score, `string` -> categorical, anything else -> json.
|
|
3949
|
+
*/
|
|
3950
|
+
type ExperimentEvaluator = (
|
|
3951
|
+
input: JSONType,
|
|
3952
|
+
output: JSONType,
|
|
3953
|
+
expectedOutput: JSONType
|
|
3954
|
+
) => JSONType | Promise<JSONType>
|
|
3955
|
+
|
|
3956
|
+
/**
|
|
3957
|
+
* Scores all rows in an experiment run and emits a summary metric.
|
|
3935
3958
|
*/
|
|
3936
|
-
type
|
|
3959
|
+
type ExperimentSummaryEvaluator = (
|
|
3960
|
+
inputs: any[],
|
|
3961
|
+
outputs: any[],
|
|
3962
|
+
expectedOutputs: any[],
|
|
3963
|
+
evaluatorResults: Record<string, any[]>,
|
|
3964
|
+
metadata?: Array<Record<string, any>>
|
|
3965
|
+
) => any | Promise<any>
|
|
3966
|
+
|
|
3967
|
+
interface CreateDatasetOptions {
|
|
3968
|
+
description?: string
|
|
3969
|
+
records?: Array<{
|
|
3970
|
+
id?: string,
|
|
3971
|
+
inputData: JSONType,
|
|
3972
|
+
expectedOutput?: JSONType,
|
|
3973
|
+
metadata?: Record<string, JSONType>
|
|
3974
|
+
}>
|
|
3975
|
+
}
|
|
3937
3976
|
|
|
3938
3977
|
interface ExperimentOptions {
|
|
3939
3978
|
name: string
|
|
3940
3979
|
dataset: Dataset
|
|
3941
3980
|
task: ExperimentTask
|
|
3942
|
-
/** Evaluators keyed by metric label. */
|
|
3943
|
-
evaluators?: Record<string, ExperimentEvaluator>
|
|
3981
|
+
/** Evaluators keyed by metric label, or named functions. */
|
|
3982
|
+
evaluators?: Record<string, ExperimentEvaluator> | ExperimentEvaluator[]
|
|
3983
|
+
/** Summary evaluators keyed by metric label, or named functions. */
|
|
3984
|
+
summaryEvaluators?: Record<string, ExperimentSummaryEvaluator> | ExperimentSummaryEvaluator[]
|
|
3944
3985
|
description?: string
|
|
3945
|
-
config?: Record<string,
|
|
3986
|
+
config?: Record<string, JSONType>
|
|
3946
3987
|
tags?: Record<string, string>
|
|
3947
3988
|
}
|
|
3948
3989
|
|
|
3990
|
+
interface ExperimentRunOptions {
|
|
3991
|
+
/** Maximum retries for task and evaluator failures. Default 0. */
|
|
3992
|
+
maxRetries?: number
|
|
3993
|
+
/** Delay before a retry, in milliseconds. Default 100 * (attempt + 1). */
|
|
3994
|
+
retryDelay?: (attempt: number) => number
|
|
3995
|
+
/** Reject on the first task/evaluator error instead of capturing it. Default false. */
|
|
3996
|
+
throwOnErrors?: boolean
|
|
3997
|
+
}
|
|
3998
|
+
|
|
3949
3999
|
interface PullDatasetOptions {
|
|
4000
|
+
/** Dataset version to pull. Defaults to latest. */
|
|
4001
|
+
version?: number
|
|
3950
4002
|
/** Wait until at least this many records are readable (absorbs write lag). */
|
|
3951
4003
|
expectedRecordCount?: number
|
|
3952
4004
|
/** Maximum total time to wait, in ms. Default 30000. */
|
|
@@ -3959,19 +4011,30 @@ declare namespace tracer {
|
|
|
3959
4011
|
traceId: string
|
|
3960
4012
|
startNs: number
|
|
3961
4013
|
durationNs: number
|
|
3962
|
-
input:
|
|
3963
|
-
output:
|
|
3964
|
-
expectedOutput:
|
|
4014
|
+
input: JSONType
|
|
4015
|
+
output: JSONType
|
|
4016
|
+
expectedOutput: JSONType
|
|
3965
4017
|
readonly isError: boolean
|
|
3966
4018
|
errorType: string | null
|
|
3967
4019
|
errorMessage: string | null
|
|
3968
|
-
evaluations: Record<string,
|
|
4020
|
+
evaluations: Record<string, JSONType>
|
|
3969
4021
|
evaluationErrors: Record<string, string>
|
|
3970
4022
|
}
|
|
3971
4023
|
|
|
4024
|
+
interface ExperimentRun {
|
|
4025
|
+
runId: string
|
|
4026
|
+
runIteration: number
|
|
4027
|
+
rows: ExperimentResultRow[]
|
|
4028
|
+
summaryEvaluations: Record<string, { value: any, error: string | null }>
|
|
4029
|
+
}
|
|
4030
|
+
|
|
3972
4031
|
interface ExperimentResult {
|
|
3973
4032
|
experimentId: string
|
|
3974
4033
|
rows: ExperimentResultRow[]
|
|
4034
|
+
/** Single-run summary evaluator results. */
|
|
4035
|
+
summaryEvaluations: Record<string, { value: any, error: string | null }>
|
|
4036
|
+
/** Experiment runs. P0 Node experiments currently return one run. */
|
|
4037
|
+
runs: ExperimentRun[]
|
|
3975
4038
|
/** Dashboard URL for the experiment. */
|
|
3976
4039
|
url: string
|
|
3977
4040
|
}
|
|
@@ -3984,13 +4047,20 @@ declare namespace tracer {
|
|
|
3984
4047
|
}
|
|
3985
4048
|
|
|
3986
4049
|
interface Dataset {
|
|
3987
|
-
addRecord (input:
|
|
4050
|
+
addRecord (input: JSONType, expectedOutput?: JSONType, metadata?: Record<string, JSONType>): Dataset
|
|
3988
4051
|
/** Creates the dataset remotely if needed and pushes any unpushed records. */
|
|
3989
4052
|
push (): Promise<DatasetPushResult>
|
|
3990
4053
|
name (): string
|
|
3991
4054
|
id (): string | null
|
|
3992
4055
|
projectId (): string | null
|
|
3993
|
-
|
|
4056
|
+
version (): number | null
|
|
4057
|
+
latestVersion (): number | null
|
|
4058
|
+
records (): Array<{
|
|
4059
|
+
id: string | null,
|
|
4060
|
+
input: JSONType,
|
|
4061
|
+
expectedOutput: JSONType,
|
|
4062
|
+
metadata: Record<string, JSONType>
|
|
4063
|
+
}>
|
|
3994
4064
|
/** Dashboard URL for the dataset, or null until pushed. */
|
|
3995
4065
|
url (): string | null
|
|
3996
4066
|
}
|
|
@@ -3999,12 +4069,13 @@ declare namespace tracer {
|
|
|
3999
4069
|
name (): string
|
|
4000
4070
|
experimentId (): string | null
|
|
4001
4071
|
url (): string | null
|
|
4002
|
-
run (): Promise<ExperimentResult>
|
|
4072
|
+
run (options?: ExperimentRunOptions): Promise<ExperimentResult>
|
|
4003
4073
|
}
|
|
4004
4074
|
|
|
4005
4075
|
interface Experiments {
|
|
4006
4076
|
/** Create a local dataset buffer; pushed on the first experiment run. */
|
|
4007
4077
|
createDataset (name: string, description?: string): Dataset
|
|
4078
|
+
createDataset (name: string, options?: CreateDatasetOptions): Dataset
|
|
4008
4079
|
/** Pull an existing dataset (with records) by name. */
|
|
4009
4080
|
pullDataset (name: string, options?: PullDatasetOptions): Promise<Dataset>
|
|
4010
4081
|
/** Build an experiment to run over a dataset. */
|