dd-trace 6.6.0 → 6.8.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
|
@@ -291,6 +291,7 @@ interface Plugins {
|
|
|
291
291
|
"next": tracer.plugins.next;
|
|
292
292
|
"nyc": tracer.plugins.nyc;
|
|
293
293
|
"openai": tracer.plugins.openai;
|
|
294
|
+
"openai-agents": tracer.plugins.openai_agents;
|
|
294
295
|
"opensearch": tracer.plugins.opensearch;
|
|
295
296
|
"oracledb": tracer.plugins.oracledb;
|
|
296
297
|
"playwright": tracer.plugins.playwright;
|
|
@@ -2968,6 +2969,12 @@ declare namespace tracer {
|
|
|
2968
2969
|
*/
|
|
2969
2970
|
interface openai extends Instrumentation {}
|
|
2970
2971
|
|
|
2972
|
+
/**
|
|
2973
|
+
* This plugin automatically instruments the
|
|
2974
|
+
* [@openai/agents](https://www.npmjs.com/package/@openai/agents) library.
|
|
2975
|
+
*/
|
|
2976
|
+
interface openai_agents extends Instrumentation {}
|
|
2977
|
+
|
|
2971
2978
|
/**
|
|
2972
2979
|
* This plugin automatically instruments the
|
|
2973
2980
|
* [opensearch](https://github.com/opensearch-project/opensearch-js) module.
|
|
@@ -3727,29 +3734,74 @@ declare namespace tracer {
|
|
|
3727
3734
|
flush (): void
|
|
3728
3735
|
}
|
|
3729
3736
|
|
|
3737
|
+
/** JSON-serializable value accepted by LLMObs Experiments. */
|
|
3738
|
+
type JSONType = string | number | boolean | null | JSONType[] | { [key: string]: JSONType }
|
|
3739
|
+
|
|
3730
3740
|
/**
|
|
3731
3741
|
* A task run over each dataset record during an experiment.
|
|
3732
3742
|
*/
|
|
3733
|
-
type ExperimentTask = (
|
|
3743
|
+
type ExperimentTask = (
|
|
3744
|
+
input: JSONType,
|
|
3745
|
+
config: Record<string, JSONType>,
|
|
3746
|
+
metadata?: Record<string, JSONType>
|
|
3747
|
+
) => JSONType | Promise<JSONType>
|
|
3734
3748
|
|
|
3735
3749
|
/**
|
|
3736
3750
|
* Scores a single task output. The return type selects the metric:
|
|
3737
|
-
* `boolean` -> boolean, `number` -> score, anything else ->
|
|
3751
|
+
* `boolean` -> boolean, `number` -> score, `string` -> categorical, anything else -> json.
|
|
3752
|
+
*/
|
|
3753
|
+
type ExperimentEvaluator = (
|
|
3754
|
+
input: JSONType,
|
|
3755
|
+
output: JSONType,
|
|
3756
|
+
expectedOutput: JSONType
|
|
3757
|
+
) => JSONType | Promise<JSONType>
|
|
3758
|
+
|
|
3759
|
+
/**
|
|
3760
|
+
* Scores all rows in an experiment run and emits a summary metric.
|
|
3738
3761
|
*/
|
|
3739
|
-
type
|
|
3762
|
+
type ExperimentSummaryEvaluator = (
|
|
3763
|
+
inputs: any[],
|
|
3764
|
+
outputs: any[],
|
|
3765
|
+
expectedOutputs: any[],
|
|
3766
|
+
evaluatorResults: Record<string, any[]>,
|
|
3767
|
+
metadata?: Array<Record<string, any>>
|
|
3768
|
+
) => any | Promise<any>
|
|
3769
|
+
|
|
3770
|
+
interface CreateDatasetOptions {
|
|
3771
|
+
description?: string
|
|
3772
|
+
records?: Array<{
|
|
3773
|
+
id?: string,
|
|
3774
|
+
inputData: JSONType,
|
|
3775
|
+
expectedOutput?: JSONType,
|
|
3776
|
+
metadata?: Record<string, JSONType>
|
|
3777
|
+
}>
|
|
3778
|
+
}
|
|
3740
3779
|
|
|
3741
3780
|
interface ExperimentOptions {
|
|
3742
3781
|
name: string
|
|
3743
3782
|
dataset: Dataset
|
|
3744
3783
|
task: ExperimentTask
|
|
3745
|
-
/** Evaluators keyed by metric label. */
|
|
3746
|
-
evaluators?: Record<string, ExperimentEvaluator>
|
|
3784
|
+
/** Evaluators keyed by metric label, or named functions. */
|
|
3785
|
+
evaluators?: Record<string, ExperimentEvaluator> | ExperimentEvaluator[]
|
|
3786
|
+
/** Summary evaluators keyed by metric label, or named functions. */
|
|
3787
|
+
summaryEvaluators?: Record<string, ExperimentSummaryEvaluator> | ExperimentSummaryEvaluator[]
|
|
3747
3788
|
description?: string
|
|
3748
|
-
config?: Record<string,
|
|
3789
|
+
config?: Record<string, JSONType>
|
|
3749
3790
|
tags?: Record<string, string>
|
|
3750
3791
|
}
|
|
3751
3792
|
|
|
3793
|
+
interface ExperimentRunOptions {
|
|
3794
|
+
/** Maximum retries for task and evaluator failures. Default 0. */
|
|
3795
|
+
maxRetries?: number
|
|
3796
|
+
/** Delay before a retry, in milliseconds. Default 100 * (attempt + 1). */
|
|
3797
|
+
retryDelay?: (attempt: number) => number
|
|
3798
|
+
/** Reject on the first task/evaluator error instead of capturing it. Default false. */
|
|
3799
|
+
throwOnErrors?: boolean
|
|
3800
|
+
}
|
|
3801
|
+
|
|
3752
3802
|
interface PullDatasetOptions {
|
|
3803
|
+
/** Dataset version to pull. Defaults to latest. */
|
|
3804
|
+
version?: number
|
|
3753
3805
|
/** Wait until at least this many records are readable (absorbs write lag). */
|
|
3754
3806
|
expectedRecordCount?: number
|
|
3755
3807
|
/** Maximum total time to wait, in ms. Default 30000. */
|
|
@@ -3762,19 +3814,30 @@ declare namespace tracer {
|
|
|
3762
3814
|
traceId: string
|
|
3763
3815
|
startNs: number
|
|
3764
3816
|
durationNs: number
|
|
3765
|
-
input:
|
|
3766
|
-
output:
|
|
3767
|
-
expectedOutput:
|
|
3817
|
+
input: JSONType
|
|
3818
|
+
output: JSONType
|
|
3819
|
+
expectedOutput: JSONType
|
|
3768
3820
|
readonly isError: boolean
|
|
3769
3821
|
errorType: string | null
|
|
3770
3822
|
errorMessage: string | null
|
|
3771
|
-
evaluations: Record<string,
|
|
3823
|
+
evaluations: Record<string, JSONType>
|
|
3772
3824
|
evaluationErrors: Record<string, string>
|
|
3773
3825
|
}
|
|
3774
3826
|
|
|
3827
|
+
interface ExperimentRun {
|
|
3828
|
+
runId: string
|
|
3829
|
+
runIteration: number
|
|
3830
|
+
rows: ExperimentResultRow[]
|
|
3831
|
+
summaryEvaluations: Record<string, { value: any, error: string | null }>
|
|
3832
|
+
}
|
|
3833
|
+
|
|
3775
3834
|
interface ExperimentResult {
|
|
3776
3835
|
experimentId: string
|
|
3777
3836
|
rows: ExperimentResultRow[]
|
|
3837
|
+
/** Single-run summary evaluator results. */
|
|
3838
|
+
summaryEvaluations: Record<string, { value: any, error: string | null }>
|
|
3839
|
+
/** Experiment runs. P0 Node experiments currently return one run. */
|
|
3840
|
+
runs: ExperimentRun[]
|
|
3778
3841
|
/** Dashboard URL for the experiment. */
|
|
3779
3842
|
url: string
|
|
3780
3843
|
}
|
|
@@ -3787,13 +3850,20 @@ declare namespace tracer {
|
|
|
3787
3850
|
}
|
|
3788
3851
|
|
|
3789
3852
|
interface Dataset {
|
|
3790
|
-
addRecord (input:
|
|
3853
|
+
addRecord (input: JSONType, expectedOutput?: JSONType, metadata?: Record<string, JSONType>): Dataset
|
|
3791
3854
|
/** Creates the dataset remotely if needed and pushes any unpushed records. */
|
|
3792
3855
|
push (): Promise<DatasetPushResult>
|
|
3793
3856
|
name (): string
|
|
3794
3857
|
id (): string | null
|
|
3795
3858
|
projectId (): string | null
|
|
3796
|
-
|
|
3859
|
+
version (): number | null
|
|
3860
|
+
latestVersion (): number | null
|
|
3861
|
+
records (): Array<{
|
|
3862
|
+
id: string | null,
|
|
3863
|
+
input: JSONType,
|
|
3864
|
+
expectedOutput: JSONType,
|
|
3865
|
+
metadata: Record<string, JSONType>
|
|
3866
|
+
}>
|
|
3797
3867
|
/** Dashboard URL for the dataset, or null until pushed. */
|
|
3798
3868
|
url (): string | null
|
|
3799
3869
|
}
|
|
@@ -3802,12 +3872,13 @@ declare namespace tracer {
|
|
|
3802
3872
|
name (): string
|
|
3803
3873
|
experimentId (): string | null
|
|
3804
3874
|
url (): string | null
|
|
3805
|
-
run (): Promise<ExperimentResult>
|
|
3875
|
+
run (options?: ExperimentRunOptions): Promise<ExperimentResult>
|
|
3806
3876
|
}
|
|
3807
3877
|
|
|
3808
3878
|
interface Experiments {
|
|
3809
3879
|
/** Create a local dataset buffer; pushed on the first experiment run. */
|
|
3810
3880
|
createDataset (name: string, description?: string): Dataset
|
|
3881
|
+
createDataset (name: string, options?: CreateDatasetOptions): Dataset
|
|
3811
3882
|
/** Pull an existing dataset (with records) by name. */
|
|
3812
3883
|
pullDataset (name: string, options?: PullDatasetOptions): Promise<Dataset>
|
|
3813
3884
|
/** Build an experiment to run over a dataset. */
|