dd-trace 6.8.0 → 6.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ci/diagnose.js +27 -25
- package/ci/init.js +6 -6
- package/ci/runbook.md +114 -20
- package/ci/test-optimization-validation/approval-artifacts.js +36 -3
- package/ci/test-optimization-validation/approval.js +78 -22
- package/ci/test-optimization-validation/blocker-category.js +24 -0
- package/ci/test-optimization-validation/ci-discovery.js +23 -17
- package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
- package/ci/test-optimization-validation/ci-remediation.js +1 -1
- package/ci/test-optimization-validation/cli.js +280 -52
- package/ci/test-optimization-validation/command-blocker.js +159 -20
- package/ci/test-optimization-validation/command-output-policy.js +9 -3
- package/ci/test-optimization-validation/command-runner.js +9 -7
- package/ci/test-optimization-validation/environment.js +4 -2
- package/ci/test-optimization-validation/executable.js +15 -13
- package/ci/test-optimization-validation/execution-lock.js +70 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
- package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
- package/ci/test-optimization-validation/generated-files.js +38 -28
- package/ci/test-optimization-validation/generated-test-contract.js +8 -4
- package/ci/test-optimization-validation/generated-verifier.js +24 -17
- package/ci/test-optimization-validation/literal-glob.js +52 -0
- package/ci/test-optimization-validation/manifest-loader.js +3 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +300 -50
- package/ci/test-optimization-validation/manifest-schema.js +80 -17
- package/ci/test-optimization-validation/offline-fixtures.js +13 -4
- package/ci/test-optimization-validation/package-check.js +94 -0
- package/ci/test-optimization-validation/plan-writer.js +183 -10
- package/ci/test-optimization-validation/preflight-runner.js +110 -31
- package/ci/test-optimization-validation/project-build-artifact.js +31 -0
- package/ci/test-optimization-validation/redaction.js +18 -27
- package/ci/test-optimization-validation/report-writer.js +182 -48
- package/ci/test-optimization-validation/result-semantics.js +20 -3
- package/ci/test-optimization-validation/runner-command.js +40 -20
- package/ci/test-optimization-validation/runner-contract.js +79 -43
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +59 -5
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
- package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
- package/ci/test-optimization-validation/static-diagnosis.js +10 -3
- package/ci/test-optimization-validation/test-output.js +2 -1
- package/ci/test-optimization-validation/validation-blocker.js +21 -0
- package/ci/vitest-no-worker-init-setup.mjs +30 -34
- package/index.d.ts +98 -1
- package/init.js +1 -17
- package/initialize.mjs +11 -0
- package/loader-hook.mjs +6 -4
- package/package.json +5 -3
- package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
- package/packages/datadog-esbuild/src/utils.js +16 -1
- package/packages/datadog-instrumentations/src/ai.js +61 -34
- package/packages/datadog-instrumentations/src/bluebird.js +6 -6
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +81 -5
- package/packages/datadog-instrumentations/src/cucumber.js +124 -47
- package/packages/datadog-instrumentations/src/dns.js +21 -2
- package/packages/datadog-instrumentations/src/electron.js +1 -0
- package/packages/datadog-instrumentations/src/fastify.js +3 -1
- package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +33 -9
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +118 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +61 -0
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +37 -6
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +979 -233
- package/packages/datadog-instrumentations/src/mocha/main.js +107 -9
- package/packages/datadog-instrumentations/src/mocha/utils.js +64 -42
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +25 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +12 -18
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +155 -23
- package/packages/datadog-instrumentations/src/openai.js +14 -0
- package/packages/datadog-instrumentations/src/pg.js +180 -6
- package/packages/datadog-instrumentations/src/playwright.js +173 -79
- package/packages/datadog-instrumentations/src/promise-js.js +4 -4
- package/packages/datadog-instrumentations/src/promise.js +3 -3
- package/packages/datadog-instrumentations/src/router.js +195 -19
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +43 -10
- package/packages/datadog-instrumentations/src/vitest-main.js +360 -56
- package/packages/datadog-instrumentations/src/vitest-util.js +42 -7
- package/packages/datadog-instrumentations/src/vitest-worker.js +234 -17
- package/packages/datadog-instrumentations/src/webdriverio.js +194 -18
- package/packages/datadog-instrumentations/src/when.js +3 -3
- package/packages/datadog-instrumentations/src/ws.js +5 -1
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -3
- package/packages/datadog-plugin-cucumber/src/index.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +50 -46
- package/packages/datadog-plugin-cypress/src/support.js +7 -4
- package/packages/datadog-plugin-electron/src/net.js +10 -4
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +1 -18
- package/packages/datadog-plugin-jest/src/util.js +2 -0
- package/packages/datadog-plugin-kafkajs/src/producer.js +2 -1
- package/packages/datadog-plugin-mocha/src/index.js +318 -1
- package/packages/datadog-plugin-next/src/index.js +57 -9
- package/packages/datadog-plugin-openai/src/tracing.js +4 -0
- package/packages/datadog-plugin-pg/src/index.js +65 -1
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +95 -7
- package/packages/datadog-shimmer/src/shimmer.js +6 -2
- package/packages/dd-trace/src/aiguard/sdk.js +3 -0
- package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
- package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +215 -0
- package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
- package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
- package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +48 -476
- package/packages/dd-trace/src/appsec/sdk/track_event.js +9 -0
- package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
- package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +27 -13
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +17 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +21 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +1 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
- package/packages/dd-trace/src/config/generated-config-types.d.ts +2 -0
- package/packages/dd-trace/src/config/helper.js +2 -0
- package/packages/dd-trace/src/config/index.js +16 -5
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +8 -0
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
- package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
- package/packages/dd-trace/src/guardrails/log.js +1 -10
- package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
- package/packages/dd-trace/src/llmobs/experiments/index.js +33 -25
- package/packages/dd-trace/src/llmobs/experiments/util.js +4 -2
- package/packages/dd-trace/src/llmobs/noop.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +149 -68
- package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
- package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
- package/packages/dd-trace/src/log/channels.js +1 -9
- package/packages/dd-trace/src/log/levels.js +12 -0
- package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -1
- package/packages/dd-trace/src/opentelemetry/span.js +4 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +21 -5
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +6 -0
- package/packages/dd-trace/src/plugins/util/git.js +6 -4
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +2 -2
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
- package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
- package/packages/dd-trace/src/plugins/util/test.js +319 -75
- package/packages/dd-trace/src/plugins/util/url.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +23 -1
- package/packages/dd-trace/src/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
- package/packages/dd-trace/src/proxy.js +1 -0
- package/packages/dd-trace/src/ritm.js +5 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
- package/packages/dd-trace/src/sampling_rule.js +4 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
- package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
- package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
- package/vendor/dist/pprof-format/index.js +1 -1
- package/version.js +10 -8
- /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
|
@@ -4,6 +4,7 @@ const fs = require('node:fs')
|
|
|
4
4
|
const path = require('path')
|
|
5
5
|
|
|
6
6
|
const { getArtifactId } = require('../artifact-id')
|
|
7
|
+
const { BLOCKER_CATEGORIES } = require('../blocker-category')
|
|
7
8
|
const { buildDatadogEnv, buildOfflineCaptureEnv, runCommand } = require('../command-runner')
|
|
8
9
|
const {
|
|
9
10
|
cleanupGeneratedRuntimeFiles,
|
|
@@ -19,8 +20,10 @@ const { readOfflineOutput } = require('../offline-output')
|
|
|
19
20
|
const { sanitizeForReport, sanitizeString } = require('../redaction')
|
|
20
21
|
const { getGeneratedCommand } = require('../runner-command')
|
|
21
22
|
const { ensureSafeDirectory, writeFileSafely } = require('../safe-files')
|
|
23
|
+
const { getValidationBlockerEvidence } = require('../validation-blocker')
|
|
22
24
|
|
|
23
|
-
const ANSI_PATTERN =
|
|
25
|
+
const ANSI_PATTERN =
|
|
26
|
+
new RegExp(`${String.fromCharCode(27)}${String.raw`\[[\u0030-\u003F]*[\u0020-\u002F]*[\u0040-\u007E]`}`, 'g')
|
|
24
27
|
|
|
25
28
|
function frameworkOutDir (out, framework, scenario) {
|
|
26
29
|
return path.join(out, 'runs', getArtifactId(framework.id), scenario)
|
|
@@ -193,10 +196,11 @@ async function prepareGeneratedScenario (framework, scenarioId) {
|
|
|
193
196
|
function requireGeneratedScenario (framework, scenarioId, scenarioName) {
|
|
194
197
|
const strategy = framework.generatedTestStrategy
|
|
195
198
|
if (strategy?.status === 'not_possible') {
|
|
196
|
-
return
|
|
199
|
+
return incomplete(
|
|
197
200
|
framework,
|
|
198
201
|
scenarioName,
|
|
199
|
-
`
|
|
202
|
+
`The validator cannot create a collectible test for this advanced feature: ${strategy.reason} ` +
|
|
203
|
+
'No conclusion was reached for this advanced feature.',
|
|
200
204
|
getGeneratedStrategySkipEvidence(framework, scenarioName, scenarioId)
|
|
201
205
|
)
|
|
202
206
|
}
|
|
@@ -254,9 +258,9 @@ function getGeneratedStrategySkipEvidence (framework, scenarioName, scenarioId)
|
|
|
254
258
|
reasonCode = 'generated-test-strategy-not-verified'
|
|
255
259
|
}
|
|
256
260
|
|
|
257
|
-
|
|
261
|
+
const evidence = {
|
|
258
262
|
featureEligibility: {
|
|
259
|
-
eligible: false,
|
|
263
|
+
...(reasonCode === 'generated-test-strategy-not-possible' ? {} : { eligible: false }),
|
|
260
264
|
blockedBy: 'generated-test-strategy',
|
|
261
265
|
reason: strategy?.reason,
|
|
262
266
|
reasonCode,
|
|
@@ -265,6 +269,12 @@ function getGeneratedStrategySkipEvidence (framework, scenarioName, scenarioId)
|
|
|
265
269
|
requiredGeneratedScenario: scenarioId,
|
|
266
270
|
},
|
|
267
271
|
}
|
|
272
|
+
if (reasonCode === 'generated-test-strategy-not-possible') {
|
|
273
|
+
evidence.blockerCategory = BLOCKER_CATEGORIES.VALIDATOR_LIMITATION
|
|
274
|
+
evidence.recommendation = 'Report that the selected runner configuration cannot collect validator-generated ' +
|
|
275
|
+
'tests to validator engineering. Basic Reporting remains valid; project setup changes are not required.'
|
|
276
|
+
}
|
|
277
|
+
return evidence
|
|
268
278
|
}
|
|
269
279
|
|
|
270
280
|
function basicEventEvidence (events) {
|
|
@@ -442,6 +452,8 @@ function copy (target, source, key) {
|
|
|
442
452
|
|
|
443
453
|
function summarizeDebugRerun ({ result, events, offline, outDir }) {
|
|
444
454
|
const output = `${result.stdout}\n${result.stderr}`
|
|
455
|
+
const testEvents = eventsOfType(events, 'test')
|
|
456
|
+
const sourceFiles = new Set(testEvents.map(test => test.testSourceFile).filter(Boolean))
|
|
445
457
|
|
|
446
458
|
return {
|
|
447
459
|
ran: true,
|
|
@@ -449,8 +461,12 @@ function summarizeDebugRerun ({ result, events, offline, outDir }) {
|
|
|
449
461
|
commandTimedOut: result.timedOut,
|
|
450
462
|
debugCommandFailed: result.exitCode !== 0 || result.timedOut === true,
|
|
451
463
|
offlineExporterInitialized: offline.initialized,
|
|
464
|
+
settingsLoadedFromCache: offline.inputs.settings?.status === 'loaded',
|
|
452
465
|
artifactDirectory: outDir,
|
|
453
466
|
...basicEventEvidence(events),
|
|
467
|
+
testEventsWithoutSourceFile: testEvents.length - testEvents.filter(test => test.testSourceFile).length,
|
|
468
|
+
testSourceFileCount: sourceFiles.size,
|
|
469
|
+
testSourceFiles: [...sourceFiles].slice(0, 5),
|
|
454
470
|
debugLines: findInterestingLines(output, [
|
|
455
471
|
/dd-trace/i,
|
|
456
472
|
/test optimization/i,
|
|
@@ -541,7 +557,15 @@ function inconclusive (framework, scenario, diagnosis, evidence = {}, outDir, ex
|
|
|
541
557
|
}
|
|
542
558
|
|
|
543
559
|
function error (framework, scenario, err, outDir = err?.artifactDirectory) {
|
|
544
|
-
|
|
560
|
+
const blockerEvidence = getValidationBlockerEvidence(err)
|
|
561
|
+
return result(
|
|
562
|
+
framework,
|
|
563
|
+
scenario,
|
|
564
|
+
blockerEvidence ? 'blocked' : 'error',
|
|
565
|
+
blockerEvidence ? err.message : (err && err.stack ? err.stack : String(err)),
|
|
566
|
+
blockerEvidence || {},
|
|
567
|
+
outDir
|
|
568
|
+
)
|
|
545
569
|
}
|
|
546
570
|
|
|
547
571
|
function result (framework, scenario, status, diagnosis, evidence, outDir, extraArtifacts) {
|
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
getFrameworkDefinitions,
|
|
9
9
|
runDiagnosis,
|
|
10
10
|
} = require('../diagnose')
|
|
11
|
+
const { BLOCKER_CATEGORIES } = require('./blocker-category')
|
|
11
12
|
const { sanitizeForReport } = require('./redaction')
|
|
12
13
|
const { writeFileSafely } = require('./safe-files')
|
|
13
14
|
|
|
@@ -45,6 +46,7 @@ function runStaticDiagnosis ({ manifest, out }) {
|
|
|
45
46
|
function getStaticBlocker (framework, diagnosis) {
|
|
46
47
|
if (!SUPPORTED_FRAMEWORKS.has(framework.framework)) {
|
|
47
48
|
return {
|
|
49
|
+
blockerCategory: BLOCKER_CATEGORIES.VALIDATOR_LIMITATION,
|
|
48
50
|
reason: `Unsupported test framework detected: ${getUnsupportedFrameworkName(framework)}.`,
|
|
49
51
|
recommendation: 'Choose Jest, Mocha, Cucumber, Cypress, Playwright, or Vitest for live validation.',
|
|
50
52
|
}
|
|
@@ -56,6 +58,7 @@ function getStaticBlocker (framework, diagnosis) {
|
|
|
56
58
|
const version = parseVersion(framework.frameworkVersion)
|
|
57
59
|
if (version && !satisfies(version, definition.supportedRange)) {
|
|
58
60
|
return {
|
|
61
|
+
blockerCategory: BLOCKER_CATEGORIES.UNSUPPORTED_VERSION,
|
|
59
62
|
reason:
|
|
60
63
|
`${definition.name} ${version} is not supported. Supported range is ${definition.supportedRange}.`,
|
|
61
64
|
recommendation: definition.recommendation,
|
|
@@ -65,6 +68,7 @@ function getStaticBlocker (framework, diagnosis) {
|
|
|
65
68
|
const staticVersionError = findStaticVersionError(definition, diagnosis, framework, version)
|
|
66
69
|
if (staticVersionError) {
|
|
67
70
|
return {
|
|
71
|
+
blockerCategory: BLOCKER_CATEGORIES.UNSUPPORTED_VERSION,
|
|
68
72
|
reason: staticVersionError.title,
|
|
69
73
|
recommendation: staticVersionError.recommendation || staticVersionError.message,
|
|
70
74
|
}
|
|
@@ -117,8 +121,11 @@ function getExactFrameworkLocations (diagnosis, framework) {
|
|
|
117
121
|
const locations = new Set()
|
|
118
122
|
addRelativeFrameworkLocation(locations, diagnosis, framework.project?.packageJson)
|
|
119
123
|
|
|
120
|
-
|
|
121
|
-
|
|
124
|
+
const configFiles = framework.project?.configFiles
|
|
125
|
+
if (configFiles) {
|
|
126
|
+
for (const configFile of configFiles) {
|
|
127
|
+
addRelativeFrameworkLocation(locations, diagnosis, configFile)
|
|
128
|
+
}
|
|
122
129
|
}
|
|
123
130
|
|
|
124
131
|
return locations
|
|
@@ -149,7 +156,7 @@ function normalizeRelativePath (location) {
|
|
|
149
156
|
|
|
150
157
|
function parseVersion (rawVersion) {
|
|
151
158
|
if (typeof rawVersion !== 'string') return null
|
|
152
|
-
const match = rawVersion.match(
|
|
159
|
+
const match = rawVersion.match(/(?<!\d)\d+\.\d+\.\d+/)
|
|
153
160
|
return match ? match[0] : null
|
|
154
161
|
}
|
|
155
162
|
|
|
@@ -4,7 +4,8 @@ const cypressAdapter = require('./framework-adapters/cypress')
|
|
|
4
4
|
const cucumberAdapter = require('./framework-adapters/cucumber')
|
|
5
5
|
const playwrightAdapter = require('./framework-adapters/playwright')
|
|
6
6
|
|
|
7
|
-
const ANSI_PATTERN =
|
|
7
|
+
const ANSI_PATTERN =
|
|
8
|
+
new RegExp(`${String.fromCharCode(27)}${String.raw`\[[\u0030-\u003F]*[\u0020-\u002F]*[\u0040-\u007E]`}`, 'g')
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Extracts the final test count from common JavaScript test-runner summaries.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
function createValidationBlocker (message, { kind, recommendation, suppressReport = false }) {
|
|
4
|
+
const error = new Error(message)
|
|
5
|
+
error.validationBlocker = { kind, recommendation }
|
|
6
|
+
error.validationExitCode = 2
|
|
7
|
+
error.suppressReport = suppressReport
|
|
8
|
+
return error
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function getValidationBlockerEvidence (error) {
|
|
12
|
+
if (!error?.validationBlocker) return
|
|
13
|
+
return {
|
|
14
|
+
blockerKind: error.validationBlocker.kind,
|
|
15
|
+
domain: 'validator_state',
|
|
16
|
+
recommendation: error.validationBlocker.recommendation,
|
|
17
|
+
validationIncomplete: true,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = { createValidationBlocker, getValidationBlockerEvidence }
|
|
@@ -8,12 +8,11 @@ const isNoWorkerInitActive = providedContext.isActive ?? getIsNoWorkerInitActive
|
|
|
8
8
|
const attemptToFixTests = providedContext.attemptToFixTests || {}
|
|
9
9
|
const attemptToFixRetries = providedContext.attemptToFixRetries || 0
|
|
10
10
|
const disabledTests = providedContext.disabledTests || {}
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const hasEarlyFlakeDetectionSlowRetries = Object.keys(earlyFlakeDetectionSlowRetries).length > 0
|
|
11
|
+
const earlyFlakeDetectionRetryPolicy = providedContext.earlyFlakeDetectionRetryPolicy || {
|
|
12
|
+
durationRetryCounts: [],
|
|
13
|
+
schedulingRetryCount: 0,
|
|
14
|
+
}
|
|
15
|
+
const earlyFlakeDetectionRetries = earlyFlakeDetectionRetryPolicy.schedulingRetryCount
|
|
17
16
|
const isEarlyFlakeDetectionEnabled = providedContext.isEarlyFlakeDetectionEnabled === true
|
|
18
17
|
const knownTests = providedContext.knownTests || {}
|
|
19
18
|
const modifiedFiles = providedContext.modifiedFiles || {}
|
|
@@ -110,26 +109,29 @@ if (isNoWorkerInitActive) {
|
|
|
110
109
|
}
|
|
111
110
|
|
|
112
111
|
function applyExecutionChanges (suite) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
const tasks = suite?.tasks
|
|
113
|
+
if (tasks) {
|
|
114
|
+
for (const task of tasks) {
|
|
115
|
+
if (task.type === 'suite') {
|
|
116
|
+
applyExecutionChanges(task)
|
|
117
|
+
continue
|
|
118
|
+
}
|
|
118
119
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
120
|
+
const testSuite = getTestSuite(task)
|
|
121
|
+
const testName = getTestName(task)
|
|
122
|
+
if (attemptToFixTests[testSuite]?.[testName]) {
|
|
123
|
+
task.retry = 0
|
|
124
|
+
task.repeats = attemptToFixRetries
|
|
125
|
+
task.meta.__ddTestOptAtfRetries = attemptToFixRetries
|
|
126
|
+
} else if (disabledTests[testSuite]?.[testName]) {
|
|
127
|
+
task.mode = 'skip'
|
|
128
|
+
} else if (isEarlyFlakeDetectionTest(testSuite, testName)) {
|
|
129
|
+
task.retry = 0
|
|
130
|
+
task.repeats = earlyFlakeDetectionRetries
|
|
131
|
+
task.meta.__ddTestOptEfdRetries = earlyFlakeDetectionRetries
|
|
132
|
+
}
|
|
133
|
+
wrapRetryCondition(task)
|
|
131
134
|
}
|
|
132
|
-
wrapRetryCondition(task)
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
|
|
@@ -380,7 +382,7 @@ function recordEarlyFlakeDetectionStatus (task, attemptIndex, onlyIfNewErrors) {
|
|
|
380
382
|
earlyFlakeDetectionRetriesByTask.set(task, retryCount)
|
|
381
383
|
task.repeats = retryCount
|
|
382
384
|
task.meta.__ddTestOptEfdRetries = retryCount
|
|
383
|
-
if (retryCount === 0
|
|
385
|
+
if (retryCount === 0) {
|
|
384
386
|
task.meta.__ddTestOptEfdAbortReason = 'slow'
|
|
385
387
|
}
|
|
386
388
|
}
|
|
@@ -606,7 +608,7 @@ function prepareEarlyFlakeDetectionAttempt (task, attemptIndex) {
|
|
|
606
608
|
earlyFlakeDetectionRetriesByTask.set(task, retryCount)
|
|
607
609
|
task.repeats = retryCount
|
|
608
610
|
task.meta.__ddTestOptEfdRetries = retryCount
|
|
609
|
-
if (retryCount === 0
|
|
611
|
+
if (retryCount === 0) {
|
|
610
612
|
task.meta.__ddTestOptEfdAbortReason = 'slow'
|
|
611
613
|
}
|
|
612
614
|
}
|
|
@@ -633,16 +635,10 @@ function prepareEarlyFlakeDetectionAttempt (task, attemptIndex) {
|
|
|
633
635
|
}
|
|
634
636
|
|
|
635
637
|
function getEarlyFlakeDetectionRetryCount (task) {
|
|
636
|
-
if (!hasEarlyFlakeDetectionSlowRetries) {
|
|
637
|
-
return earlyFlakeDetectionRetries
|
|
638
|
-
}
|
|
639
|
-
|
|
640
638
|
const executionStart = earlyFlakeDetectionStartByTask.get(task)
|
|
641
639
|
const duration = executionStart === undefined ? task.result?.duration ?? 0 : now() - executionStart
|
|
642
|
-
for (const {
|
|
643
|
-
if (duration <
|
|
644
|
-
return earlyFlakeDetectionSlowRetries[key] ?? 0
|
|
645
|
-
}
|
|
640
|
+
for (const { durationLimitMs, retryCount } of earlyFlakeDetectionRetryPolicy.durationRetryCounts) {
|
|
641
|
+
if (duration < durationLimitMs) return retryCount
|
|
646
642
|
}
|
|
647
643
|
return 0
|
|
648
644
|
}
|
package/index.d.ts
CHANGED
|
@@ -71,7 +71,7 @@ interface Tracer extends opentracing.Tracer {
|
|
|
71
71
|
* @param plugin The name of a built-in plugin.
|
|
72
72
|
* @param config Configuration options. Can also be `false` to disable the plugin.
|
|
73
73
|
*/
|
|
74
|
-
use<P extends
|
|
74
|
+
use<P extends tracer.PluginName> (plugin: P, config?: tracer.PluginOptions[P] | boolean): this;
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
77
|
* Returns a reference to the current scope.
|
|
@@ -314,6 +314,9 @@ interface Plugins {
|
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
declare namespace tracer {
|
|
317
|
+
export interface PluginOptions extends Plugins {}
|
|
318
|
+
export type PluginName = keyof PluginOptions;
|
|
319
|
+
|
|
317
320
|
export type SpanOptions = Omit<opentracing.SpanOptions, 'childOf'> & {
|
|
318
321
|
/**
|
|
319
322
|
* Set childOf to 'null' to create a root span without a parent, even when a parent span
|
|
@@ -3711,6 +3714,13 @@ declare namespace tracer {
|
|
|
3711
3714
|
*/
|
|
3712
3715
|
submitEvaluation (spanContext: llmobs.ExportedLLMObsSpan, options: llmobs.EvaluationOptions): void
|
|
3713
3716
|
|
|
3717
|
+
/**
|
|
3718
|
+
* Submits end-user feedback for a span, trace, session, or customer-defined entity.
|
|
3719
|
+
* Exactly one target must be provided in the options.
|
|
3720
|
+
* @param options An object containing the label, metric type, value, submitter and target of the feedback.
|
|
3721
|
+
*/
|
|
3722
|
+
submitFeedback (options: llmobs.FeedbackOptions): void
|
|
3723
|
+
|
|
3714
3724
|
|
|
3715
3725
|
/**
|
|
3716
3726
|
* Annotates all spans, including auto-instrumented spans, with the provided tags created in the context of the callback function.
|
|
@@ -3957,6 +3967,93 @@ declare namespace tracer {
|
|
|
3957
3967
|
metadata?: { [key: string]: any }
|
|
3958
3968
|
}
|
|
3959
3969
|
|
|
3970
|
+
interface FeedbackSubmitter {
|
|
3971
|
+
/**
|
|
3972
|
+
* The identifier of the end user who submitted the feedback.
|
|
3973
|
+
*/
|
|
3974
|
+
id: string,
|
|
3975
|
+
|
|
3976
|
+
/**
|
|
3977
|
+
* The type of submitter, e.g. 'user'.
|
|
3978
|
+
*/
|
|
3979
|
+
type?: string
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3982
|
+
interface FeedbackOptions {
|
|
3983
|
+
/**
|
|
3984
|
+
* The name of the feedback metric
|
|
3985
|
+
*/
|
|
3986
|
+
label: string,
|
|
3987
|
+
|
|
3988
|
+
/**
|
|
3989
|
+
* The type of feedback metric, one of 'categorical', 'score', 'boolean', 'json' or 'text'
|
|
3990
|
+
*/
|
|
3991
|
+
metricType: 'categorical' | 'score' | 'boolean' | 'json' | 'text',
|
|
3992
|
+
|
|
3993
|
+
/**
|
|
3994
|
+
* The value of the feedback metric.
|
|
3995
|
+
* Must be string for 'categorical' and 'text' metrics, number for 'score' metrics, boolean for 'boolean' metrics and a JSON object for 'json' metrics.
|
|
3996
|
+
*/
|
|
3997
|
+
value: string | number | boolean | { [key: string]: any },
|
|
3998
|
+
|
|
3999
|
+
/**
|
|
4000
|
+
* Who submitted the feedback.
|
|
4001
|
+
*/
|
|
4002
|
+
submitter: llmobs.FeedbackSubmitter,
|
|
4003
|
+
|
|
4004
|
+
/**
|
|
4005
|
+
* The span context of the span to attach the feedback to, as returned by `llmobs.exportSpan()`.
|
|
4006
|
+
* Exactly one of `span`, `spanId`, `traceId`, `sessionId` or `feedbackJoinKey` must be provided.
|
|
4007
|
+
*/
|
|
4008
|
+
span?: llmobs.ExportedLLMObsSpan,
|
|
4009
|
+
|
|
4010
|
+
/**
|
|
4011
|
+
* The ID of the span to attach the feedback to.
|
|
4012
|
+
*/
|
|
4013
|
+
spanId?: string,
|
|
4014
|
+
|
|
4015
|
+
/**
|
|
4016
|
+
* The ID of the trace to attach the feedback to.
|
|
4017
|
+
*/
|
|
4018
|
+
traceId?: string,
|
|
4019
|
+
|
|
4020
|
+
/**
|
|
4021
|
+
* The ID of the session to attach the feedback to.
|
|
4022
|
+
*/
|
|
4023
|
+
sessionId?: string,
|
|
4024
|
+
|
|
4025
|
+
/**
|
|
4026
|
+
* A customer-defined key to attach the feedback to.
|
|
4027
|
+
*/
|
|
4028
|
+
feedbackJoinKey?: string,
|
|
4029
|
+
|
|
4030
|
+
/**
|
|
4031
|
+
* An object of string key-value pairs to tag the feedback with.
|
|
4032
|
+
* A `null` or `undefined` value is sent as the string `"null"` or `"undefined"`.
|
|
4033
|
+
*/
|
|
4034
|
+
tags?: { [key: string]: string | null | undefined },
|
|
4035
|
+
|
|
4036
|
+
/**
|
|
4037
|
+
* The name of the ML application
|
|
4038
|
+
*/
|
|
4039
|
+
mlApp?: string,
|
|
4040
|
+
|
|
4041
|
+
/**
|
|
4042
|
+
* The timestamp in milliseconds when the feedback was generated.
|
|
4043
|
+
*/
|
|
4044
|
+
timestampMs?: number,
|
|
4045
|
+
|
|
4046
|
+
/**
|
|
4047
|
+
* Reasoning for the feedback.
|
|
4048
|
+
*/
|
|
4049
|
+
reasoning?: string,
|
|
4050
|
+
|
|
4051
|
+
/**
|
|
4052
|
+
* Whether the feedback passed or failed. Valid values are pass and fail.
|
|
4053
|
+
*/
|
|
4054
|
+
assessment?: 'pass' | 'fail'
|
|
4055
|
+
}
|
|
4056
|
+
|
|
3960
4057
|
interface Document {
|
|
3961
4058
|
/**
|
|
3962
4059
|
* Document text
|
package/init.js
CHANGED
|
@@ -1,22 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
// JSON string after --require has already run so we extract them
|
|
5
|
-
// manually if present.
|
|
6
|
-
var pm2EnvStr = process.env.pm2_env
|
|
7
|
-
if (typeof pm2EnvStr === 'string') {
|
|
8
|
-
try {
|
|
9
|
-
var pm2Config = JSON.parse(pm2EnvStr)
|
|
10
|
-
var pm2Keys = Object.keys(pm2Config)
|
|
11
|
-
for (var i = 0; i < pm2Keys.length; i++) {
|
|
12
|
-
var k = pm2Keys[i]
|
|
13
|
-
var v = pm2Config[k]
|
|
14
|
-
if (v != null) {
|
|
15
|
-
process.env[k] = String(v)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
} catch (e) {}
|
|
19
|
-
}
|
|
3
|
+
require('./packages/dd-trace/src/guardrails/apply-pm2-env')
|
|
20
4
|
|
|
21
5
|
var guard = require('./packages/dd-trace/src/guardrails')
|
|
22
6
|
|
package/initialize.mjs
CHANGED
|
@@ -20,6 +20,7 @@ import { isMainThread } from 'worker_threads'
|
|
|
20
20
|
|
|
21
21
|
import {
|
|
22
22
|
iitmExclusionRegExp,
|
|
23
|
+
initialize as hookInitialize,
|
|
23
24
|
load as hookLoad,
|
|
24
25
|
resolve as hookResolve,
|
|
25
26
|
} from './loader-hook.mjs?initialize'
|
|
@@ -66,7 +67,17 @@ const [NODE_MAJOR, NODE_MINOR] = process.versions.node.split('.').map(Number)
|
|
|
66
67
|
|
|
67
68
|
const brokenLoaders = NODE_MAJOR === 18 && NODE_MINOR === 0
|
|
68
69
|
|
|
70
|
+
// Node calls `initialize` only through `module.register`, never for `--loader`; without it
|
|
71
|
+
// import-in-the-middle keeps its default matcher and proxies every application module. Loaders
|
|
72
|
+
// before Node 18.19 share the application thread, where `loader-hook.mjs` builds no matcher.
|
|
73
|
+
let needsHookInitialize = !isMainThread && !brokenLoaders
|
|
74
|
+
|
|
69
75
|
export async function load (url, context, nextLoad) {
|
|
76
|
+
if (needsHookInitialize) {
|
|
77
|
+
needsHookInitialize = false
|
|
78
|
+
hookInitialize()
|
|
79
|
+
}
|
|
80
|
+
|
|
70
81
|
const loadHook = (brokenLoaders || iitmExclusionRegExp.test(url)) ? nextLoad : hookLoad
|
|
71
82
|
return insertInit(await loadHook(url, context, nextLoad), url, context)
|
|
72
83
|
}
|
package/loader-hook.mjs
CHANGED
|
@@ -16,7 +16,6 @@ const require = Module.createRequire(import.meta.url)
|
|
|
16
16
|
const isInitializeMainThread = isMainThread && import.meta.url.endsWith('?initialize')
|
|
17
17
|
let syncImportInTheMiddleHook
|
|
18
18
|
|
|
19
|
-
let getValueFromEnvSources
|
|
20
19
|
let regexpEscape
|
|
21
20
|
|
|
22
21
|
// Substrings of resolved URLs that import-in-the-middle must never wrap: re-export
|
|
@@ -32,13 +31,12 @@ const includeModuleNames = new Set()
|
|
|
32
31
|
let moduleNameAlternation = ''
|
|
33
32
|
|
|
34
33
|
if (!isInitializeMainThread) {
|
|
34
|
+
require('./packages/dd-trace/src/guardrails/apply-pm2-env.js')
|
|
35
35
|
const regexpEscapeModule = require('./vendor/dist/escape-string-regexp/index.js')
|
|
36
36
|
const hooks = require('./packages/datadog-instrumentations/src/helpers/hooks.js')
|
|
37
|
-
const configHelper = require('./packages/dd-trace/src/config/helper.js')
|
|
38
37
|
const { isRelativeRequire } = require('./packages/datadog-instrumentations/src/helpers/shared-utils.js')
|
|
39
38
|
|
|
40
39
|
regexpEscape = regexpEscapeModule.default
|
|
41
|
-
getValueFromEnvSources = configHelper.getValueFromEnvSources
|
|
42
40
|
|
|
43
41
|
for (const moduleName of Object.keys(hooks)) {
|
|
44
42
|
// Relative hooks resolve outside node_modules and are not instrumented here.
|
|
@@ -63,7 +61,11 @@ function prepareImportInTheMiddleOptions (data = {}) {
|
|
|
63
61
|
// A consumer-owned shouldInclude predicate takes over the wrapping decision, so
|
|
64
62
|
// iitm ignores the include/exclude arrays. Building the matcher here keeps the
|
|
65
63
|
// synchronous and asynchronous loaders on one matching implementation.
|
|
66
|
-
|
|
64
|
+
// Lazily required and read without its registered default so a loader worker
|
|
65
|
+
// never loads the configuration defaults table. The default is unset regardless.
|
|
66
|
+
const { getValueFromEnvSources } = require('./packages/dd-trace/src/config/helper.js')
|
|
67
|
+
|
|
68
|
+
data.shouldInclude = createShouldInclude(getValueFromEnvSources('DD_IAST_SECURITY_CONTROLS_CONFIGURATION', true))
|
|
67
69
|
|
|
68
70
|
return data
|
|
69
71
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.9.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
"generate:electron-package": "node scripts/generate-electron-package.js",
|
|
16
16
|
"verify:config:types": "node scripts/generate-config-types.js --check",
|
|
17
17
|
"verify:electron-package": "node scripts/generate-electron-package.js --check",
|
|
18
|
+
"generate:rewriter:targets": "node scripts/generate-rewriter-targets.js",
|
|
19
|
+
"verify:rewriter:targets": "node scripts/generate-rewriter-targets.js --check",
|
|
18
20
|
"generate:supported-integrations": "node scripts/generate-supported-integrations.js",
|
|
19
21
|
"verify:supported-integrations": "node scripts/generate-supported-integrations.js --check",
|
|
20
22
|
"type:check": "tsc --noEmit -p tsconfig.dev.json",
|
|
@@ -24,7 +26,7 @@
|
|
|
24
26
|
"lint:fix": "node scripts/check_licenses.js && node scripts/check-no-coverage-artifacts.js && node scripts/check-no-mcr-images.js && node scripts/check-docker-image-shas.js && eslint . --concurrency=auto --max-warnings 0 --fix",
|
|
25
27
|
"lint:inspect": "npx @eslint/config-inspector@latest",
|
|
26
28
|
"lint:codeowners": "codeowners-audit",
|
|
27
|
-
"lint:codeowners:ci": "codeowners-audit --glob='**/*.spec.js' --glob='benchmark/sirun/**' --glob='.agents/**' --glob='.claude/**' --glob='integration-tests/**'",
|
|
29
|
+
"lint:codeowners:ci": "codeowners-audit --glob='**/*.spec.js' --glob='benchmark/sirun/**' --glob='.agents/**' --glob='.claude/**' --glob='integration-tests/**' --glob='packages/dd-trace/src/guardrails/**'",
|
|
28
30
|
"lint:editorconfig": "docker build -q -t ec .github/editorconfig-checker && docker run --rm --volume=$PWD:/check ec",
|
|
29
31
|
"release:proposal": "node scripts/release/proposal",
|
|
30
32
|
"services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
|
|
@@ -217,7 +219,7 @@
|
|
|
217
219
|
"eslint-plugin-n": "^18.2.1",
|
|
218
220
|
"eslint-plugin-promise": "^7.3.0",
|
|
219
221
|
"eslint-plugin-sonarjs": "^4.2.0",
|
|
220
|
-
"eslint-plugin-unicorn": "^
|
|
222
|
+
"eslint-plugin-unicorn": "^73.0.0",
|
|
221
223
|
"express": "^5.1.0",
|
|
222
224
|
"glob": "^10.4.5",
|
|
223
225
|
"globals": "^17.7.0",
|
|
@@ -85,10 +85,25 @@ function getSource (url, { format }) {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
/**
|
|
89
|
+
* @typedef {[typeof LOAD_OPERATION, URL, object] | [typeof RESOLVE_OPERATION, string, object]} GetExportsOperation
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @typedef {{ done: false, value: GetExportsOperation } | { done: true, value: Set<string> }} GetExportsResult
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @typedef {{
|
|
98
|
+
* next: (value?: unknown) => GetExportsResult,
|
|
99
|
+
* throw: (error?: unknown) => GetExportsResult,
|
|
100
|
+
* }} GetExportsGenerator
|
|
101
|
+
*/
|
|
102
|
+
|
|
88
103
|
/**
|
|
89
104
|
* Drives the generator returned by import-in-the-middle >=3.1.0 export discovery.
|
|
90
105
|
*
|
|
91
|
-
* @param {
|
|
106
|
+
* @param {GetExportsGenerator} exportsGenerator Generator returned by getExports
|
|
92
107
|
* @param {(url: URL, context: object) => { source: string, format: string }} getSource
|
|
93
108
|
* Function that loads module source
|
|
94
109
|
* @returns {Set<string>}
|