dd-trace 5.117.0 → 5.118.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.
Files changed (83) hide show
  1. package/ci/diagnose.js +162 -21
  2. package/ci/init.js +0 -1
  3. package/ci/runbook.md +187 -180
  4. package/ci/test-optimization-validation/approval-artifacts.js +3 -1
  5. package/ci/test-optimization-validation/approval.js +52 -15
  6. package/ci/test-optimization-validation/ci-command-candidate.js +26 -32
  7. package/ci/test-optimization-validation/ci-discovery.js +1 -1
  8. package/ci/test-optimization-validation/ci-package-scripts.js +141 -0
  9. package/ci/test-optimization-validation/ci-remediation.js +112 -39
  10. package/ci/test-optimization-validation/cli.js +516 -681
  11. package/ci/test-optimization-validation/command-blocker.js +188 -33
  12. package/ci/test-optimization-validation/command-output-policy.js +3 -26
  13. package/ci/test-optimization-validation/command-runner.js +189 -245
  14. package/ci/test-optimization-validation/environment.js +90 -0
  15. package/ci/test-optimization-validation/executable.js +159 -388
  16. package/ci/test-optimization-validation/framework-adapters/cucumber.js +119 -0
  17. package/ci/test-optimization-validation/framework-adapters/cypress.js +107 -0
  18. package/ci/test-optimization-validation/framework-adapters/playwright.js +181 -0
  19. package/ci/test-optimization-validation/generated-files.js +75 -13
  20. package/ci/test-optimization-validation/generated-test-contract.js +283 -0
  21. package/ci/test-optimization-validation/generated-verifier.js +49 -16
  22. package/ci/test-optimization-validation/literal-environment.js +57 -0
  23. package/ci/test-optimization-validation/manifest-loader.js +2 -22
  24. package/ci/test-optimization-validation/manifest-scaffold.js +816 -515
  25. package/ci/test-optimization-validation/manifest-schema.js +494 -702
  26. package/ci/test-optimization-validation/offline-fixtures.js +4 -1
  27. package/ci/test-optimization-validation/plan-writer.js +243 -984
  28. package/ci/test-optimization-validation/preflight-runner.js +49 -55
  29. package/ci/test-optimization-validation/redaction.js +2 -1
  30. package/ci/test-optimization-validation/report-writer.js +391 -1357
  31. package/ci/test-optimization-validation/result-semantics.js +86 -0
  32. package/ci/test-optimization-validation/runner-command.js +249 -0
  33. package/ci/test-optimization-validation/runner-contract.js +664 -0
  34. package/ci/test-optimization-validation/scenarios/auto-test-retries.js +29 -3
  35. package/ci/test-optimization-validation/scenarios/basic-reporting.js +240 -543
  36. package/ci/test-optimization-validation/scenarios/ci-wiring.js +450 -670
  37. package/ci/test-optimization-validation/scenarios/early-flake-detection.js +4 -3
  38. package/ci/test-optimization-validation/scenarios/helpers.js +67 -9
  39. package/ci/test-optimization-validation/scenarios/test-management.js +4 -3
  40. package/ci/test-optimization-validation/source-text.js +87 -0
  41. package/ci/test-optimization-validation/test-output.js +12 -22
  42. package/ext/tags.d.ts +1 -0
  43. package/index.d.ts +7 -0
  44. package/package.json +2 -2
  45. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
  46. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  47. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/openai-agents.js +31 -0
  48. package/packages/datadog-instrumentations/src/openai-agents.js +159 -0
  49. package/packages/datadog-plugin-openai-agents/src/index.js +74 -0
  50. package/packages/datadog-plugin-openai-agents/src/integration.js +503 -0
  51. package/packages/datadog-plugin-openai-agents/src/processor.js +108 -0
  52. package/packages/datadog-plugin-openai-agents/src/util.js +60 -0
  53. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +48 -49
  54. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +161 -33
  55. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +6 -4
  56. package/packages/dd-trace/src/config/generated-config-types.d.ts +2 -0
  57. package/packages/dd-trace/src/config/supported-configurations.json +7 -0
  58. package/packages/dd-trace/src/encode/span-stats.js +7 -1
  59. package/packages/dd-trace/src/exporter.js +16 -9
  60. package/packages/dd-trace/src/llmobs/index.js +9 -1
  61. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +104 -22
  62. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +5 -9
  63. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +20 -0
  64. package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +321 -0
  65. package/packages/dd-trace/src/llmobs/sdk.js +2 -1
  66. package/packages/dd-trace/src/llmobs/span_processor.js +7 -2
  67. package/packages/dd-trace/src/llmobs/tagger.js +23 -3
  68. package/packages/dd-trace/src/llmobs/util.js +56 -3
  69. package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +3 -6
  70. package/packages/dd-trace/src/openfeature/configuration_source.js +5 -8
  71. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +5 -1
  72. package/packages/dd-trace/src/plugins/ci_plugin.js +9 -3
  73. package/packages/dd-trace/src/plugins/index.js +1 -0
  74. package/packages/dd-trace/src/plugins/outbound.js +4 -1
  75. package/packages/dd-trace/src/span_processor.js +1 -1
  76. package/packages/dd-trace/src/span_stats.js +22 -4
  77. package/ci/test-optimization-validation/command-suitability.js +0 -471
  78. package/ci/test-optimization-validation/init-probe-preload.js +0 -163
  79. package/ci/test-optimization-validation/init-probe.js +0 -246
  80. package/ci/test-optimization-validation/late-initialization.js +0 -63
  81. package/ci/test-optimization-validation/local-command.js +0 -163
  82. package/ci/test-optimization-validation/setup-runner.js +0 -97
  83. package/ci/test-optimization-validation-manifest.schema.json +0 -1
@@ -2,23 +2,22 @@
2
2
 
3
3
  const { getCommandBlocker } = require('./command-blocker')
4
4
  const { runCommand, serializeDisplayCommand } = require('./command-runner')
5
- const { getDatadogCleanCommand } = require('./local-command')
6
- const { getBasicReportingCommand, summarizeTestOutput } = require('./scenarios/basic-reporting')
7
- const { frameworkOutDir } = require('./scenarios/helpers')
5
+ const { getBasicCommand } = require('./runner-command')
6
+ const { summarizeTestOutput } = require('./scenarios/basic-reporting')
7
+ const { findInterestingLines, frameworkOutDir } = require('./scenarios/helpers')
8
8
  const { getObservedTestCount } = require('./test-output')
9
9
 
10
10
  /**
11
- * Runs the selected Basic Reporting command without inherited Datadog initialization.
11
+ * Runs one direct representative test without Datadog initialization.
12
12
  *
13
13
  * @param {object} input preflight inputs
14
- * @param {object} input.framework manifest framework entry
14
+ * @param {object} input.framework framework manifest entry
15
15
  * @param {string} input.out validation output directory
16
16
  * @param {object} input.options validator options
17
17
  * @returns {Promise<{ok: boolean, failure?: object, preflight: object}>} preflight outcome
18
18
  */
19
19
  async function runFrameworkPreflight ({ framework, out, options }) {
20
- const maxTestCount = framework.preflight.maxTestCount
21
- const command = getDatadogCleanCommand(getBasicReportingCommand(framework))
20
+ const command = getBasicCommand(framework)
22
21
  const outDir = frameworkOutDir(out, framework, 'preflight')
23
22
  const result = await runCommand(command, {
24
23
  artifactRoot: out,
@@ -30,49 +29,52 @@ async function runFrameworkPreflight ({ framework, out, options }) {
30
29
  verbose: options.verbose,
31
30
  })
32
31
  const observedTestCount = getObservedTestCount(framework.framework, result.stdout, result.stderr)
32
+ const commandFailure = getCommandBlocker(result, {
33
+ browserRequired: framework.browserRequired,
34
+ framework: framework.framework,
35
+ testsRan: Number.isInteger(observedTestCount) && observedTestCount > 0,
36
+ })
33
37
  const preflight = {
34
- ran: true,
35
- source: 'validator',
36
- maxTestCount,
37
38
  command: serializeDisplayCommand(command),
38
- exitCode: result.exitCode,
39
+ diagnosticSummary: findInterestingLines(`${result.stdout}\n${result.stderr}`, [
40
+ /\b(?:Abort trap|Cannot find|Error|ERR_[A-Z_]+|Failed to|Received signal|SIGABRT)\b/i,
41
+ ], 4),
39
42
  durationMs: result.durationMs,
43
+ exitCode: result.exitCode,
40
44
  observedTestCount,
41
- stdoutSummary: summarizeTestOutput(result.stdout).join('\n'),
45
+ ran: true,
46
+ selectorVerification: framework.validation.selectorScope === 'instrumented_event_identity'
47
+ ? 'requires_instrumented_event_identity'
48
+ : 'bounded_direct_runner',
49
+ source: 'validator',
42
50
  stderrSummary: summarizeTestOutput('', result.stderr).join('\n'),
51
+ stdoutSummary: summarizeTestOutput(result.stdout).join('\n'),
52
+ timedOut: result.timedOut,
53
+ ...(commandFailure ? { commandFailure } : {}),
43
54
  }
44
55
  framework.preflight = preflight
45
56
 
46
- const testCountKnown = Number.isInteger(observedTestCount)
47
- const scopeMatched = testCountKnown && observedTestCount >= 1 && observedTestCount <= maxTestCount
48
- preflight.scopeMatched = scopeMatched
49
-
50
- if (!result.timedOut && scopeMatched && (result.exitCode === 0 || observedTestCount > 0)) {
57
+ if (!result.timedOut && result.exitCode === 0 && observedTestCount !== 0) {
51
58
  return { ok: true, preflight }
52
59
  }
53
60
 
54
- const commandFailure = getCommandBlocker(result)
55
- const diagnosis = commandFailure?.summary || getPreflightFailureDiagnosis({
56
- maxTestCount,
57
- observedTestCount,
58
- result,
59
- testCountKnown,
60
- })
61
-
61
+ const domain = commandFailure?.blockedByExecutionEnvironment
62
+ ? 'execution_environment'
63
+ : commandFailure?.localRuntimeBlocked
64
+ ? 'local_runtime'
65
+ : 'project_setup'
62
66
  return {
63
67
  ok: false,
64
68
  preflight,
65
69
  failure: {
66
70
  frameworkId: framework.id,
67
71
  scenario: 'basic-reporting',
68
- status: commandFailure ? 'blocked' : 'error',
69
- diagnosis,
72
+ status: 'blocked',
73
+ diagnosis: getFailureDiagnosis(result, observedTestCount, commandFailure),
70
74
  evidence: {
71
- commandExitCode: result.exitCode,
72
- commandTimedOut: result.timedOut,
73
- representativeScopeMismatch: !commandFailure && !scopeMatched,
74
- ...(commandFailure ? { commandFailure } : {}),
75
- preflight,
75
+ commandFailure,
76
+ domain,
77
+ validationIncomplete: true,
76
78
  },
77
79
  artifacts: Object.values(result.artifacts),
78
80
  },
@@ -80,35 +82,27 @@ async function runFrameworkPreflight ({ framework, out, options }) {
80
82
  }
81
83
 
82
84
  /**
83
- * Produces the narrowest diagnosis supported by a failed clean preflight.
85
+ * Explains why direct Basic Reporting could not start reliably.
84
86
  *
85
- * @param {object} input diagnosis inputs
86
- * @param {number} input.maxTestCount approved representative test limit
87
- * @param {number|undefined} input.observedTestCount parsed test count
88
- * @param {object} input.result command result
89
- * @param {boolean} input.testCountKnown whether the test count was parsed
87
+ * @param {object} result command result
88
+ * @param {number|null} observedTestCount parsed test count
89
+ * @param {object|undefined} commandFailure classified blocker
90
90
  * @returns {string} customer-facing diagnosis
91
91
  */
92
- function getPreflightFailureDiagnosis ({ maxTestCount, observedTestCount, result, testCountKnown }) {
93
- if (result.timedOut) {
94
- return 'The selected test command timed out during the validator-controlled uninstrumented preflight. No Test ' +
95
- 'Optimization conclusion was reached.'
92
+ function getFailureDiagnosis (result, observedTestCount, commandFailure) {
93
+ if (commandFailure?.summary) {
94
+ return `${commandFailure.summary} Basic Reporting could not be tested reliably.`
96
95
  }
97
- if (!testCountKnown) {
98
- return 'The validator could not determine how many tests the selected command ran, so it could not confirm ' +
99
- `the approved representative scope of at most ${maxTestCount} tests. Select a command whose output ` +
100
- 'reports the test count before validating Test Optimization.'
101
- }
102
- if (observedTestCount > maxTestCount) {
103
- return `The selected command ran ${observedTestCount} tests, exceeding the approved representative scope ` +
104
- `of at most ${maxTestCount}. Select a narrower test command before validating Test Optimization.`
96
+ if (result.timedOut) {
97
+ return 'The direct representative test exceeded its approved timeout. Basic Reporting could not be tested ' +
98
+ 'reliably; rerun the test normally and confirm its prerequisites before trying again.'
105
99
  }
106
- if (observedTestCount < 1) {
107
- return 'The selected command did not report any tests. Select a runnable representative before validating ' +
108
- 'Test Optimization.'
100
+ if (observedTestCount === 0) {
101
+ return 'The direct runner completed without reporting a test. The selected file may require project wrapper or ' +
102
+ 'configuration semantics, so Basic Reporting remains incomplete.'
109
103
  }
110
- return 'The selected test command failed before the validator could confirm that tests ran without Datadog ' +
111
- 'initialization. Fix the project command or its setup before validating Test Optimization.'
104
+ return `The direct representative test exited ${result.exitCode} without Datadog initialization. Fix or prepare ` +
105
+ 'that test normally, then create a fresh validation plan.'
112
106
  }
113
107
 
114
108
  module.exports = { runFrameworkPreflight }
@@ -276,7 +276,8 @@ function sanitizeValue (value, seen, key, depth) {
276
276
 
277
277
  const sanitized = {}
278
278
  for (const [entryKey, entryValue] of Object.entries(value)) {
279
- if (isSensitiveName(entryKey) && !SECRET_NAME_ONLY_KEYS.has(entryKey)) {
279
+ if (isSensitiveName(entryKey) && !SECRET_NAME_ONLY_KEYS.has(entryKey) &&
280
+ typeof entryValue !== 'boolean') {
280
281
  sanitized[entryKey] = REDACTED
281
282
  continue
282
283
  }