dd-trace 6.3.0 → 6.5.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/README.electron.md +7 -0
- package/README.md +17 -0
- package/ci/diagnose.js +2100 -0
- package/ci/init.js +23 -2
- package/ci/runbook.md +198 -0
- package/ci/test-optimization-validation/approval-artifacts.js +143 -0
- package/ci/test-optimization-validation/approval.js +299 -0
- package/ci/test-optimization-validation/artifact-id.js +20 -0
- package/ci/test-optimization-validation/bounded-json.js +121 -0
- package/ci/test-optimization-validation/ci-command-candidate.js +83 -0
- package/ci/test-optimization-validation/ci-discovery.js +181 -0
- package/ci/test-optimization-validation/ci-remediation.js +210 -0
- package/ci/test-optimization-validation/cli.js +903 -0
- package/ci/test-optimization-validation/command-blocker.js +81 -0
- package/ci/test-optimization-validation/command-output-policy.js +206 -0
- package/ci/test-optimization-validation/command-runner.js +707 -0
- package/ci/test-optimization-validation/command-suitability.js +471 -0
- package/ci/test-optimization-validation/executable-approval.js +48 -0
- package/ci/test-optimization-validation/executable.js +480 -0
- package/ci/test-optimization-validation/generated-file-policy.js +63 -0
- package/ci/test-optimization-validation/generated-files.js +351 -0
- package/ci/test-optimization-validation/generated-verifier.js +196 -0
- package/ci/test-optimization-validation/init-probe-preload.js +163 -0
- package/ci/test-optimization-validation/init-probe.js +246 -0
- package/ci/test-optimization-validation/late-initialization.js +63 -0
- package/ci/test-optimization-validation/local-command.js +163 -0
- package/ci/test-optimization-validation/manifest-loader.js +133 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +738 -0
- package/ci/test-optimization-validation/manifest-schema.js +862 -0
- package/ci/test-optimization-validation/offline-fixtures.js +327 -0
- package/ci/test-optimization-validation/offline-output.js +406 -0
- package/ci/test-optimization-validation/payload-normalizer.js +72 -0
- package/ci/test-optimization-validation/plan-writer.js +1120 -0
- package/ci/test-optimization-validation/preflight-runner.js +114 -0
- package/ci/test-optimization-validation/redaction.js +331 -0
- package/ci/test-optimization-validation/report-writer.js +1508 -0
- package/ci/test-optimization-validation/safe-files.js +203 -0
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +159 -0
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +657 -0
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +780 -0
- package/ci/test-optimization-validation/scenarios/early-flake-detection.js +141 -0
- package/ci/test-optimization-validation/scenarios/helpers.js +539 -0
- package/ci/test-optimization-validation/scenarios/test-management.js +218 -0
- package/ci/test-optimization-validation/setup-runner.js +97 -0
- package/ci/test-optimization-validation/static-diagnosis.js +159 -0
- package/ci/test-optimization-validation/test-output.js +129 -0
- package/ci/test-optimization-validation-manifest.schema.json +1 -0
- package/ci/validate-test-optimization.js +3 -0
- package/ext/exporters.js +1 -0
- package/index.d.ts +121 -8
- package/index.electron.js +3 -0
- package/init.js +18 -0
- package/initialize.mjs +1 -1
- package/loader-hook.mjs +28 -18
- package/openfeature.d.ts +1 -0
- package/openfeature.js +4 -0
- package/package.json +15 -8
- package/packages/datadog-instrumentations/src/ai.js +37 -26
- package/packages/datadog-instrumentations/src/child_process.js +1 -1
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber-worker-threads.js +9 -3
- package/packages/datadog-instrumentations/src/cucumber.js +24 -10
- package/packages/datadog-instrumentations/src/cypress-config.js +398 -52
- package/packages/datadog-instrumentations/src/express.js +20 -2
- package/packages/datadog-instrumentations/src/fastify.js +7 -11
- package/packages/datadog-instrumentations/src/grpc/server.js +18 -0
- package/packages/datadog-instrumentations/src/helpers/hook.js +27 -6
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +8 -8
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +28 -2
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +8 -8
- package/packages/datadog-instrumentations/src/http2/server.js +143 -17
- package/packages/datadog-instrumentations/src/jest.js +36 -4
- package/packages/datadog-instrumentations/src/mariadb.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +0 -2
- package/packages/datadog-instrumentations/src/mocha/utils.js +0 -4
- package/packages/datadog-instrumentations/src/mongodb.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +3 -3
- package/packages/datadog-instrumentations/src/mquery.js +2 -2
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +24 -0
- package/packages/datadog-instrumentations/src/nyc.js +0 -2
- package/packages/datadog-instrumentations/src/oracledb.js +2 -2
- package/packages/datadog-instrumentations/src/pg.js +2 -2
- package/packages/datadog-instrumentations/src/playwright.js +159 -22
- package/packages/datadog-instrumentations/src/process.js +3 -0
- package/packages/datadog-instrumentations/src/router.js +191 -106
- package/packages/datadog-instrumentations/src/selenium.js +52 -26
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +2 -2
- package/packages/datadog-instrumentations/src/vitest-main.js +0 -2
- package/packages/datadog-instrumentations/src/ws.js +2 -1
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +41 -16
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +21 -21
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +14 -8
- package/packages/datadog-plugin-aws-sdk/src/util.js +2 -24
- package/packages/datadog-plugin-cucumber/src/index.js +1 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +24 -62
- package/packages/datadog-plugin-cypress/src/index.js +6 -1
- package/packages/datadog-plugin-cypress/src/support.js +92 -26
- package/packages/datadog-plugin-electron/src/ipc.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +177 -59
- package/packages/datadog-plugin-graphql/src/parse.js +22 -1
- package/packages/datadog-plugin-graphql/src/request.js +32 -1
- package/packages/datadog-plugin-graphql/src/utils.js +42 -0
- package/packages/datadog-plugin-graphql/src/validate.js +15 -3
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +38 -6
- package/packages/datadog-plugin-jest/src/util.js +21 -6
- package/packages/datadog-plugin-langchain/src/handlers/embedding.js +2 -1
- package/packages/datadog-plugin-langchain/src/handlers/language_models.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +177 -64
- package/packages/datadog-plugin-router/src/index.js +11 -2
- package/packages/datadog-plugin-selenium/src/index.js +5 -36
- package/packages/datadog-plugin-vitest/src/index.js +4 -2
- package/packages/datadog-plugin-ws/src/close.js +2 -1
- package/packages/datadog-plugin-ws/src/producer.js +2 -1
- package/packages/datadog-plugin-ws/src/receiver.js +2 -1
- package/packages/datadog-plugin-ws/src/server.js +2 -1
- package/packages/dd-trace/index.electron.js +3 -0
- package/packages/dd-trace/index.js +2 -37
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +3 -1
- package/packages/dd-trace/src/azure_metadata.js +2 -1
- package/packages/dd-trace/src/bootstrap.js +39 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +93 -28
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +160 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +288 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/payload-projection.js +84 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +369 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +60 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +55 -5
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +22 -6
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +5 -0
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +62 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -2
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +6 -2
- package/packages/dd-trace/src/ci-visibility/rum.js +7 -0
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +137 -9
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +173 -9
- package/packages/dd-trace/src/ci-visibility/test-screenshot.js +90 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +20 -0
- package/packages/dd-trace/src/config/helper.js +1 -0
- package/packages/dd-trace/src/config/index.js +10 -0
- package/packages/dd-trace/src/config/supported-configurations.json +83 -0
- package/packages/dd-trace/src/constants.js +7 -0
- package/packages/dd-trace/src/datastreams/pathway.js +6 -4
- package/packages/dd-trace/src/exporter.js +2 -0
- package/packages/dd-trace/src/exporters/common/client-library-headers.js +21 -0
- package/packages/dd-trace/src/exporters/common/request.js +59 -30
- package/packages/dd-trace/src/exporters/common/url.js +15 -1
- package/packages/dd-trace/src/feature-registry.js +29 -0
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
- package/packages/dd-trace/src/llmobs/experiments/client.js +113 -0
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +154 -0
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +283 -0
- package/packages/dd-trace/src/llmobs/experiments/index.js +152 -0
- package/packages/dd-trace/src/llmobs/experiments/noop.js +30 -0
- package/packages/dd-trace/src/llmobs/experiments/result.js +34 -0
- package/packages/dd-trace/src/llmobs/index.js +10 -2
- package/packages/dd-trace/src/llmobs/noop.js +6 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +20 -3
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +8 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +48 -14
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +43 -0
- package/packages/dd-trace/src/llmobs/sdk.js +17 -0
- package/packages/dd-trace/src/llmobs/tagger.js +79 -7
- package/packages/dd-trace/src/llmobs/telemetry.js +2 -1
- package/packages/dd-trace/src/llmobs/util.js +32 -0
- package/packages/dd-trace/src/noop/proxy.js +5 -4
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +322 -0
- package/packages/dd-trace/src/openfeature/configuration_source.js +90 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +14 -23
- package/packages/dd-trace/src/openfeature/index.js +0 -2
- package/packages/dd-trace/src/openfeature/noop.js +1 -28
- package/packages/dd-trace/src/openfeature/register.js +35 -0
- package/packages/dd-trace/src/openfeature/remote_config.js +15 -18
- package/packages/dd-trace/src/openfeature/require-provider.js +18 -0
- package/packages/dd-trace/src/opentelemetry/span-ending-hook.js +10 -0
- package/packages/dd-trace/src/opentelemetry/span.js +5 -0
- package/packages/dd-trace/src/opentracing/propagation/log.js +11 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +80 -14
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +10 -1
- package/packages/dd-trace/src/opentracing/tracer.js +7 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +20 -6
- package/packages/dd-trace/src/plugins/util/git.js +3 -2
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +29 -5
- package/packages/dd-trace/src/plugins/util/test.js +65 -8
- package/packages/dd-trace/src/plugins/util/web.js +12 -0
- package/packages/dd-trace/src/proxy.js +99 -10
- package/packages/dd-trace/src/span_processor.js +5 -0
- package/packages/dd-trace/src/standalone/index.js +0 -36
- package/packages/dd-trace/src/telemetry/send-data.js +2 -2
- package/packages/dd-trace/src/util.js +26 -0
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +1 -1
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/require-optional-peer.js +0 -17
|
@@ -6,7 +6,10 @@ const path = require('node:path')
|
|
|
6
6
|
const log = require('../log')
|
|
7
7
|
const { getNumFromKnownTests } = require('../plugins/util/test')
|
|
8
8
|
const { parseKnownTestsResponse } = require('./early-flake-detection/get-known-tests')
|
|
9
|
-
const {
|
|
9
|
+
const {
|
|
10
|
+
logSkippableSuitesResponse,
|
|
11
|
+
parseSkippableSuitesResponse,
|
|
12
|
+
} = require('./intelligent-test-runner/get-skippable-suites')
|
|
10
13
|
const { parseLibraryConfigurationResponse } = require('./requests/get-library-configuration')
|
|
11
14
|
const {
|
|
12
15
|
getNumFromTestManagementTests,
|
|
@@ -45,6 +48,10 @@ const SKIPPABLE_TESTS_FILE_NAME = 'skippable_tests.json'
|
|
|
45
48
|
const TEST_MANAGEMENT_FILE_NAME = 'test_management.json'
|
|
46
49
|
|
|
47
50
|
const RUNFILES_MANIFEST_SEPARATOR = ' '
|
|
51
|
+
const DEFAULT_VALIDATION_MAX_FILE_BYTES = 1024 * 1024
|
|
52
|
+
const DEFAULT_VALIDATION_MAX_ENTRIES = 100_000
|
|
53
|
+
const DEFAULT_VALIDATION_MAX_NESTING_DEPTH = 32
|
|
54
|
+
const DEFAULT_VALIDATION_MAX_STRING_BYTES = 4096
|
|
48
55
|
|
|
49
56
|
function parseManifestVersion (content) {
|
|
50
57
|
// Supported just the number version or 'version=x'
|
|
@@ -54,12 +61,22 @@ function parseManifestVersion (content) {
|
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
class TestOptimizationHttpCache {
|
|
57
|
-
constructor ({
|
|
64
|
+
constructor ({
|
|
65
|
+
cwd = process.cwd(),
|
|
66
|
+
env,
|
|
67
|
+
validationManifestPath,
|
|
68
|
+
maxFileBytes = DEFAULT_VALIDATION_MAX_FILE_BYTES,
|
|
69
|
+
} = {}) {
|
|
58
70
|
this._cwd = cwd
|
|
59
71
|
// This cache intentionally consumes env vars that are not tracer config keys. (??)
|
|
60
72
|
// eslint-disable-next-line eslint-rules/eslint-process-env
|
|
61
73
|
this._env = env ?? process.env
|
|
62
|
-
this.
|
|
74
|
+
this._validationManifestPath = validationManifestPath
|
|
75
|
+
this._maxFileBytes = maxFileBytes
|
|
76
|
+
this._lastError = undefined
|
|
77
|
+
this._manifestPath = validationManifestPath
|
|
78
|
+
? this._resolveValidationManifestPath(validationManifestPath)
|
|
79
|
+
: this._resolveManifestPath()
|
|
63
80
|
this._testOptimizationPath = undefined
|
|
64
81
|
this._httpCachePath = undefined
|
|
65
82
|
this._available = false
|
|
@@ -71,6 +88,10 @@ class TestOptimizationHttpCache {
|
|
|
71
88
|
return this._available
|
|
72
89
|
}
|
|
73
90
|
|
|
91
|
+
getLastError () {
|
|
92
|
+
return this._lastError
|
|
93
|
+
}
|
|
94
|
+
|
|
74
95
|
readSettings () {
|
|
75
96
|
const payload = this._readFile(SETTINGS_FILE_NAME)
|
|
76
97
|
if (payload === CACHE_MISS) {
|
|
@@ -79,7 +100,11 @@ class TestOptimizationHttpCache {
|
|
|
79
100
|
}
|
|
80
101
|
|
|
81
102
|
try {
|
|
82
|
-
const settings = parseLibraryConfigurationResponse(
|
|
103
|
+
const settings = parseLibraryConfigurationResponse(
|
|
104
|
+
this._parsePayload(payload, SETTINGS_FILE_NAME),
|
|
105
|
+
undefined,
|
|
106
|
+
{ validateRequiredFields: true, validationMode: Boolean(this._validationManifestPath) }
|
|
107
|
+
)
|
|
83
108
|
incrementCountMetric(TELEMETRY_GIT_REQUESTS_SETTINGS_RESPONSE, settings)
|
|
84
109
|
return settings
|
|
85
110
|
} catch (err) {
|
|
@@ -94,7 +119,10 @@ class TestOptimizationHttpCache {
|
|
|
94
119
|
if (payload === CACHE_MISS) return CACHE_MISS
|
|
95
120
|
|
|
96
121
|
try {
|
|
97
|
-
const knownTests = parseKnownTestsResponse(
|
|
122
|
+
const knownTests = parseKnownTestsResponse(
|
|
123
|
+
this._parsePayload(payload, KNOWN_TESTS_FILE_NAME),
|
|
124
|
+
{ validateRequiredFields: true, validationMode: Boolean(this._validationManifestPath) }
|
|
125
|
+
)
|
|
98
126
|
distributionMetric(TELEMETRY_KNOWN_TESTS_RESPONSE_TESTS, {}, getNumFromKnownTests(knownTests))
|
|
99
127
|
distributionMetric(TELEMETRY_KNOWN_TESTS_RESPONSE_BYTES, {}, payload.length)
|
|
100
128
|
return knownTests
|
|
@@ -109,9 +137,15 @@ class TestOptimizationHttpCache {
|
|
|
109
137
|
if (payload === CACHE_MISS) return CACHE_MISS
|
|
110
138
|
|
|
111
139
|
try {
|
|
112
|
-
const
|
|
113
|
-
const
|
|
140
|
+
const boundedPayload = this._parsePayload(payload, SKIPPABLE_TESTS_FILE_NAME)
|
|
141
|
+
const parsedResponse = typeof boundedPayload === 'string' ? JSON.parse(boundedPayload) : boundedPayload
|
|
142
|
+
const result = parseSkippableSuitesResponse(parsedResponse, {
|
|
143
|
+
...options,
|
|
144
|
+
validateRequiredFields: true,
|
|
145
|
+
validationMode: Boolean(this._validationManifestPath),
|
|
146
|
+
})
|
|
114
147
|
const testLevel = options.testLevel || 'suite'
|
|
148
|
+
logSkippableSuitesResponse(result, testLevel)
|
|
115
149
|
const skippableItems = parsedResponse.data.filter(({ type }) => type === testLevel)
|
|
116
150
|
incrementCountMetric(
|
|
117
151
|
testLevel === 'test'
|
|
@@ -133,7 +167,10 @@ class TestOptimizationHttpCache {
|
|
|
133
167
|
if (payload === CACHE_MISS) return false
|
|
134
168
|
|
|
135
169
|
try {
|
|
136
|
-
parseSkippableSuitesResponse(
|
|
170
|
+
parseSkippableSuitesResponse(
|
|
171
|
+
this._parsePayload(payload, SKIPPABLE_TESTS_FILE_NAME),
|
|
172
|
+
{ ...options, validateRequiredFields: true, validationMode: Boolean(this._validationManifestPath) }
|
|
173
|
+
)
|
|
137
174
|
return true
|
|
138
175
|
} catch {
|
|
139
176
|
return false
|
|
@@ -145,7 +182,10 @@ class TestOptimizationHttpCache {
|
|
|
145
182
|
if (payload === CACHE_MISS) return CACHE_MISS
|
|
146
183
|
|
|
147
184
|
try {
|
|
148
|
-
const testManagementTests = parseTestManagementTestsResponse(
|
|
185
|
+
const testManagementTests = parseTestManagementTestsResponse(
|
|
186
|
+
this._parsePayload(payload, TEST_MANAGEMENT_FILE_NAME),
|
|
187
|
+
{ validateRequiredFields: true, validationMode: Boolean(this._validationManifestPath) }
|
|
188
|
+
)
|
|
149
189
|
distributionMetric(
|
|
150
190
|
TELEMETRY_TEST_MANAGEMENT_TESTS_RESPONSE_TESTS,
|
|
151
191
|
{},
|
|
@@ -161,12 +201,18 @@ class TestOptimizationHttpCache {
|
|
|
161
201
|
|
|
162
202
|
_buildReader () {
|
|
163
203
|
if (!this._manifestPath) {
|
|
204
|
+
if (this._validationManifestPath && !this._lastError) {
|
|
205
|
+
this._setError('Offline Test Optimization validation manifest was not found.')
|
|
206
|
+
}
|
|
164
207
|
log.debug('Test Optimization HTTP cache manifest not found')
|
|
165
208
|
return
|
|
166
209
|
}
|
|
167
210
|
|
|
168
211
|
const version = this._readManifestVersion(this._manifestPath)
|
|
169
212
|
if (version !== SUPPORTED_MANIFEST_VERSION) {
|
|
213
|
+
if (this._validationManifestPath) {
|
|
214
|
+
this._setError(`Unsupported offline Test Optimization validation manifest version: ${version || 'missing'}.`)
|
|
215
|
+
}
|
|
170
216
|
log.debug('Unsupported Test Optimization HTTP cache manifest version %j at %s', version, this._manifestPath)
|
|
171
217
|
return
|
|
172
218
|
}
|
|
@@ -180,6 +226,9 @@ class TestOptimizationHttpCache {
|
|
|
180
226
|
|
|
181
227
|
const settingsPath = path.join(this._httpCachePath, SETTINGS_FILE_NAME)
|
|
182
228
|
if (!fs.existsSync(settingsPath)) {
|
|
229
|
+
if (this._validationManifestPath) {
|
|
230
|
+
this._setError('Offline Test Optimization validation settings fixture is missing.')
|
|
231
|
+
}
|
|
183
232
|
log.debug('Test Optimization HTTP cache settings file not found at %s', settingsPath)
|
|
184
233
|
return
|
|
185
234
|
}
|
|
@@ -203,6 +252,30 @@ class TestOptimizationHttpCache {
|
|
|
203
252
|
}
|
|
204
253
|
}
|
|
205
254
|
|
|
255
|
+
_resolveValidationManifestPath (manifestPath) {
|
|
256
|
+
if (!path.isAbsolute(manifestPath)) {
|
|
257
|
+
this._setError('Offline Test Optimization validation manifest path must be absolute.')
|
|
258
|
+
return
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const resolvedManifestPath = path.resolve(manifestPath)
|
|
262
|
+
const testOptimizationPath = path.dirname(resolvedManifestPath)
|
|
263
|
+
const fixtureRoot = path.dirname(testOptimizationPath)
|
|
264
|
+
if (path.basename(resolvedManifestPath) !== MANIFEST_FILE_NAME ||
|
|
265
|
+
path.basename(testOptimizationPath) !== PLAN_FOLDER) {
|
|
266
|
+
this._setError('Offline Test Optimization validation manifest must use the fixed .testoptimization layout.')
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
try {
|
|
271
|
+
assertPathComponentsAreNotSymlinks(fixtureRoot, resolvedManifestPath)
|
|
272
|
+
assertRegularFixtureFile(resolvedManifestPath)
|
|
273
|
+
return resolvedManifestPath
|
|
274
|
+
} catch (err) {
|
|
275
|
+
this._setError(err.message)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
206
279
|
_resolveRunfilePath (manifestFile) {
|
|
207
280
|
if (fs.existsSync(manifestFile)) {
|
|
208
281
|
return manifestFile
|
|
@@ -253,8 +326,10 @@ class TestOptimizationHttpCache {
|
|
|
253
326
|
|
|
254
327
|
_readManifestVersion (manifestPath) {
|
|
255
328
|
try {
|
|
329
|
+
this._assertValidationFixtureFile(manifestPath)
|
|
256
330
|
return parseManifestVersion(fs.readFileSync(manifestPath, 'utf8'))
|
|
257
331
|
} catch (err) {
|
|
332
|
+
if (this._validationManifestPath) this._setError(err.message)
|
|
258
333
|
log.debug('Failed to read Test Optimization HTTP cache manifest %s: %s', manifestPath, err.message)
|
|
259
334
|
}
|
|
260
335
|
}
|
|
@@ -264,24 +339,113 @@ class TestOptimizationHttpCache {
|
|
|
264
339
|
|
|
265
340
|
const filePath = path.join(this._httpCachePath, fileName)
|
|
266
341
|
try {
|
|
342
|
+
this._assertValidationFixtureFile(filePath)
|
|
267
343
|
log.debug('Reading Test Optimization HTTP cache file %s', filePath)
|
|
268
344
|
return fs.readFileSync(filePath, 'utf8')
|
|
269
345
|
} catch (err) {
|
|
346
|
+
if (this._validationManifestPath) this._setError(err.message)
|
|
270
347
|
log.debug('Test Optimization HTTP cache file %s could not be read: %s', filePath, err.message)
|
|
271
348
|
return CACHE_MISS
|
|
272
349
|
}
|
|
273
350
|
}
|
|
274
351
|
|
|
275
352
|
_logInvalidCacheFile (fileName, err) {
|
|
353
|
+
if (this._validationManifestPath) {
|
|
354
|
+
this._setError(`Invalid offline Test Optimization ${fileName} fixture: ${err.message}`)
|
|
355
|
+
}
|
|
276
356
|
log.debug('Test Optimization HTTP cache file %s could not be parsed: %s', fileName, err.message)
|
|
277
357
|
}
|
|
278
358
|
|
|
359
|
+
_assertValidationFixtureFile (filePath) {
|
|
360
|
+
if (!this._validationManifestPath) return
|
|
361
|
+
const fixtureRoot = path.dirname(path.dirname(this._manifestPath))
|
|
362
|
+
assertPathComponentsAreNotSymlinks(fixtureRoot, filePath)
|
|
363
|
+
const stat = assertRegularFixtureFile(filePath)
|
|
364
|
+
if (stat.size > this._maxFileBytes) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
`Offline Test Optimization fixture ${path.basename(filePath)} exceeds ${this._maxFileBytes} bytes.`
|
|
367
|
+
)
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
_parsePayload (payload, fileName) {
|
|
372
|
+
if (!this._validationManifestPath) return payload
|
|
373
|
+
|
|
374
|
+
const parsed = JSON.parse(payload)
|
|
375
|
+
assertBoundedValidationValue(parsed, fileName)
|
|
376
|
+
return parsed
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
_setError (message) {
|
|
380
|
+
this._lastError = new Error(message)
|
|
381
|
+
}
|
|
382
|
+
|
|
279
383
|
_disable () {
|
|
280
384
|
this._available = false
|
|
281
385
|
}
|
|
282
386
|
}
|
|
283
387
|
|
|
388
|
+
function assertPathComponentsAreNotSymlinks (root, filename) {
|
|
389
|
+
const resolvedRoot = path.resolve(root)
|
|
390
|
+
const resolvedFilename = path.resolve(filename)
|
|
391
|
+
const rootStat = fs.lstatSync(resolvedRoot)
|
|
392
|
+
if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) {
|
|
393
|
+
throw new Error(`Offline Test Optimization fixture root must be a regular directory: ${resolvedRoot}`)
|
|
394
|
+
}
|
|
395
|
+
const relative = path.relative(resolvedRoot, resolvedFilename)
|
|
396
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
397
|
+
throw new Error('Offline Test Optimization fixture path escapes its validation root.')
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
let current = resolvedRoot
|
|
401
|
+
for (const segment of relative ? relative.split(path.sep) : []) {
|
|
402
|
+
current = path.join(current, segment)
|
|
403
|
+
const stat = fs.lstatSync(current)
|
|
404
|
+
if (stat.isSymbolicLink()) {
|
|
405
|
+
throw new Error(`Offline Test Optimization fixture path contains a symbolic link: ${current}`)
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function assertRegularFixtureFile (filename) {
|
|
411
|
+
const stat = fs.lstatSync(filename)
|
|
412
|
+
if (!stat.isFile()) {
|
|
413
|
+
throw new Error(`Offline Test Optimization fixture is not a regular file: ${filename}`)
|
|
414
|
+
}
|
|
415
|
+
if (stat.nlink > 1) {
|
|
416
|
+
throw new Error(`Offline Test Optimization fixture must not be hard-linked: ${filename}`)
|
|
417
|
+
}
|
|
418
|
+
return stat
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function assertBoundedValidationValue (value, fileName) {
|
|
422
|
+
const pending = [{ depth: 0, value }]
|
|
423
|
+
let entries = 0
|
|
424
|
+
|
|
425
|
+
while (pending.length > 0) {
|
|
426
|
+
const current = pending.pop()
|
|
427
|
+
if (current.depth > DEFAULT_VALIDATION_MAX_NESTING_DEPTH) {
|
|
428
|
+
throw new Error(`${fileName} exceeds the validation nesting limit.`)
|
|
429
|
+
}
|
|
430
|
+
if (typeof current.value === 'string' &&
|
|
431
|
+
Buffer.byteLength(current.value) > DEFAULT_VALIDATION_MAX_STRING_BYTES) {
|
|
432
|
+
throw new Error(`${fileName} contains a string that exceeds the validation limit.`)
|
|
433
|
+
}
|
|
434
|
+
if (!current.value || typeof current.value !== 'object') continue
|
|
435
|
+
|
|
436
|
+
const values = Array.isArray(current.value) ? current.value : Object.values(current.value)
|
|
437
|
+
entries += values.length
|
|
438
|
+
if (entries > DEFAULT_VALIDATION_MAX_ENTRIES) {
|
|
439
|
+
throw new Error(`${fileName} exceeds the validation collection-entry limit.`)
|
|
440
|
+
}
|
|
441
|
+
for (const nestedValue of values) {
|
|
442
|
+
pending.push({ depth: current.depth + 1, value: nestedValue })
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
284
447
|
module.exports = {
|
|
285
448
|
CACHE_MISS,
|
|
449
|
+
DEFAULT_VALIDATION_MAX_FILE_BYTES,
|
|
286
450
|
TestOptimizationHttpCache,
|
|
287
451
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { statSync } = require('node:fs')
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
TEST_FAILURE_SCREENSHOT_UPLOADED,
|
|
7
|
+
TEST_FAILURE_SCREENSHOT_UPLOAD_ERROR,
|
|
8
|
+
} = require('../plugins/util/test')
|
|
9
|
+
|
|
10
|
+
const dateNow = Date.now
|
|
11
|
+
|
|
12
|
+
const SCREENSHOT_UPLOAD_RESULT_UPLOADED = 'uploaded'
|
|
13
|
+
const SCREENSHOT_UPLOAD_RESULT_ERROR = 'error'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Resolves a screenshot's capture time in epoch milliseconds.
|
|
17
|
+
*
|
|
18
|
+
* @param {object|string} screenshot - Framework screenshot metadata or its file path
|
|
19
|
+
* @param {string} filePath - Resolved screenshot file path
|
|
20
|
+
* @returns {number} Capture time in epoch milliseconds
|
|
21
|
+
*/
|
|
22
|
+
function getScreenshotCapturedAtMs (screenshot, filePath) {
|
|
23
|
+
const takenAt = screenshot !== null && typeof screenshot === 'object' ? screenshot.takenAt : undefined
|
|
24
|
+
if (takenAt) {
|
|
25
|
+
const parsedMs = new Date(takenAt).getTime()
|
|
26
|
+
if (Number.isInteger(parsedMs) && parsedMs > 0) {
|
|
27
|
+
return parsedMs
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
return Math.floor(statSync(filePath).mtimeMs)
|
|
32
|
+
} catch {
|
|
33
|
+
return dateNow()
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Combines screenshot upload results, giving errors precedence over successes.
|
|
39
|
+
*
|
|
40
|
+
* @param {Array<string|undefined>} uploadResults - Per-screenshot upload results
|
|
41
|
+
* @returns {string|undefined} Combined upload result
|
|
42
|
+
*/
|
|
43
|
+
function getScreenshotUploadResult (uploadResults) {
|
|
44
|
+
let hasUploaded = false
|
|
45
|
+
for (const uploadResult of uploadResults) {
|
|
46
|
+
if (uploadResult === SCREENSHOT_UPLOAD_RESULT_ERROR) {
|
|
47
|
+
return SCREENSHOT_UPLOAD_RESULT_ERROR
|
|
48
|
+
}
|
|
49
|
+
if (uploadResult === SCREENSHOT_UPLOAD_RESULT_UPLOADED) {
|
|
50
|
+
hasUploaded = true
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return hasUploaded ? SCREENSHOT_UPLOAD_RESULT_UPLOADED : undefined
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Returns the test tag that represents an aggregate screenshot upload outcome.
|
|
58
|
+
*
|
|
59
|
+
* @param {string|undefined} uploadResult - Aggregate screenshot upload result
|
|
60
|
+
* @returns {string|undefined} Screenshot upload result tag
|
|
61
|
+
*/
|
|
62
|
+
function getScreenshotUploadTag (uploadResult) {
|
|
63
|
+
if (uploadResult === SCREENSHOT_UPLOAD_RESULT_ERROR) {
|
|
64
|
+
return TEST_FAILURE_SCREENSHOT_UPLOAD_ERROR
|
|
65
|
+
}
|
|
66
|
+
if (uploadResult === SCREENSHOT_UPLOAD_RESULT_UPLOADED) {
|
|
67
|
+
return TEST_FAILURE_SCREENSHOT_UPLOADED
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Tags a test span with the aggregate screenshot upload outcome.
|
|
73
|
+
*
|
|
74
|
+
* @param {object} testSpan - Test span to tag
|
|
75
|
+
* @param {string|undefined} uploadResult - Aggregate screenshot upload result
|
|
76
|
+
* @returns {void}
|
|
77
|
+
*/
|
|
78
|
+
function setScreenshotUploadTags (testSpan, uploadResult) {
|
|
79
|
+
const uploadTag = getScreenshotUploadTag(uploadResult)
|
|
80
|
+
if (uploadTag) testSpan.setTag(uploadTag, 'true')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
module.exports = {
|
|
84
|
+
SCREENSHOT_UPLOAD_RESULT_ERROR,
|
|
85
|
+
SCREENSHOT_UPLOAD_RESULT_UPLOADED,
|
|
86
|
+
getScreenshotCapturedAtMs,
|
|
87
|
+
getScreenshotUploadResult,
|
|
88
|
+
getScreenshotUploadTag,
|
|
89
|
+
setScreenshotUploadTags,
|
|
90
|
+
}
|
|
@@ -16,6 +16,7 @@ export interface GeneratedConfig {
|
|
|
16
16
|
DD_API_SECURITY_MAX_DOWNSTREAM_BODY_BYTES: number;
|
|
17
17
|
DD_API_SECURITY_MAX_DOWNSTREAM_REQUEST_BODY_ANALYSIS: number;
|
|
18
18
|
DD_API_SECURITY_SAMPLE_DELAY: number;
|
|
19
|
+
DD_APPSEC_AGENTIC_ONBOARDING: string;
|
|
19
20
|
DD_APPSEC_SCA_ENABLED: boolean | undefined;
|
|
20
21
|
enabled: boolean | undefined;
|
|
21
22
|
eventTracking: {
|
|
@@ -431,6 +432,13 @@ export interface GeneratedConfig {
|
|
|
431
432
|
};
|
|
432
433
|
};
|
|
433
434
|
};
|
|
435
|
+
featureFlags: {
|
|
436
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE: "agentless" | "remote_config";
|
|
437
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_BASE_URL: string | undefined;
|
|
438
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_POLL_INTERVAL_SECONDS: number;
|
|
439
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_REQUEST_TIMEOUT_SECONDS: number;
|
|
440
|
+
DD_FEATURE_FLAGS_ENABLED: boolean;
|
|
441
|
+
};
|
|
434
442
|
flushInterval: number;
|
|
435
443
|
flushMinSpans: number;
|
|
436
444
|
headerTags: string[];
|
|
@@ -546,6 +554,7 @@ export interface GeneratedConfig {
|
|
|
546
554
|
DD_CIVISIBILITY_AGENTLESS_ENABLED: boolean;
|
|
547
555
|
DD_CIVISIBILITY_AGENTLESS_URL: URL | undefined;
|
|
548
556
|
DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER: string | undefined;
|
|
557
|
+
DD_CIVISIBILITY_CODE_COVERAGE_REPORT_UPLOAD_ENABLED: boolean;
|
|
549
558
|
DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE: boolean;
|
|
550
559
|
DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING: boolean;
|
|
551
560
|
DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED: boolean;
|
|
@@ -561,6 +570,8 @@ export interface GeneratedConfig {
|
|
|
561
570
|
DD_CIVISIBILITY_TEST_COMMAND: string | undefined;
|
|
562
571
|
DD_CIVISIBILITY_TEST_MODULE_ID: string | undefined;
|
|
563
572
|
DD_CIVISIBILITY_TEST_SESSION_ID: string | undefined;
|
|
573
|
+
DD_CODE_COVERAGE_FLAGS: string | undefined;
|
|
574
|
+
DD_TEST_EARLY_FLAKE_DETECTION_RETRY_COUNT: number | undefined;
|
|
564
575
|
DD_TEST_FAILED_TEST_REPLAY_ENABLED: boolean;
|
|
565
576
|
DD_TEST_FAILURE_SCREENSHOTS_ENABLED: boolean | undefined;
|
|
566
577
|
DD_TEST_FLEET_CONFIG_PATH: string | undefined;
|
|
@@ -610,6 +621,7 @@ export interface GeneratedEnvVarConfig {
|
|
|
610
621
|
DD_APM_FLUSH_DEADLINE_MILLISECONDS: number;
|
|
611
622
|
DD_APM_TRACING_ENABLED: boolean;
|
|
612
623
|
DD_APP_KEY: string | undefined;
|
|
624
|
+
DD_APPSEC_AGENTIC_ONBOARDING: string;
|
|
613
625
|
DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE: string;
|
|
614
626
|
DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING: string;
|
|
615
627
|
DD_APPSEC_COLLECT_ALL_HEADERS: boolean;
|
|
@@ -636,6 +648,7 @@ export interface GeneratedEnvVarConfig {
|
|
|
636
648
|
DD_CIVISIBILITY_AGENTLESS_ENABLED: boolean;
|
|
637
649
|
DD_CIVISIBILITY_AGENTLESS_URL: URL | undefined;
|
|
638
650
|
DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER: string | undefined;
|
|
651
|
+
DD_CIVISIBILITY_CODE_COVERAGE_REPORT_UPLOAD_ENABLED: boolean;
|
|
639
652
|
DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE: boolean;
|
|
640
653
|
DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING: boolean;
|
|
641
654
|
DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED: boolean;
|
|
@@ -651,6 +664,7 @@ export interface GeneratedEnvVarConfig {
|
|
|
651
664
|
DD_CIVISIBILITY_TEST_COMMAND: string | undefined;
|
|
652
665
|
DD_CIVISIBILITY_TEST_MODULE_ID: string | undefined;
|
|
653
666
|
DD_CIVISIBILITY_TEST_SESSION_ID: string | undefined;
|
|
667
|
+
DD_CODE_COVERAGE_FLAGS: string | undefined;
|
|
654
668
|
DD_CODE_ORIGIN_FOR_SPANS_ENABLED: boolean;
|
|
655
669
|
DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED: boolean;
|
|
656
670
|
DD_CRASHTRACKING_ENABLED: boolean;
|
|
@@ -685,6 +699,11 @@ export interface GeneratedEnvVarConfig {
|
|
|
685
699
|
DD_EXPERIMENTAL_TEST_OPT_VITEST_NO_WORKER_INIT: boolean | undefined;
|
|
686
700
|
DD_EXPERIMENTAL_TEST_REQUESTS_FS_CACHE: boolean;
|
|
687
701
|
DD_EXTERNAL_ENV: string | undefined;
|
|
702
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE: "agentless" | "remote_config";
|
|
703
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_BASE_URL: string | undefined;
|
|
704
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_POLL_INTERVAL_SECONDS: number;
|
|
705
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_REQUEST_TIMEOUT_SECONDS: number;
|
|
706
|
+
DD_FEATURE_FLAGS_ENABLED: boolean;
|
|
688
707
|
DD_GIT_BRANCH: string | undefined;
|
|
689
708
|
DD_GIT_COMMIT_AUTHOR_DATE: string | undefined;
|
|
690
709
|
DD_GIT_COMMIT_AUTHOR_EMAIL: string | undefined;
|
|
@@ -794,6 +813,7 @@ export interface GeneratedEnvVarConfig {
|
|
|
794
813
|
DD_TELEMETRY_HEARTBEAT_INTERVAL: number;
|
|
795
814
|
DD_TELEMETRY_LOG_COLLECTION_ENABLED: boolean;
|
|
796
815
|
DD_TELEMETRY_METRICS_ENABLED: boolean;
|
|
816
|
+
DD_TEST_EARLY_FLAKE_DETECTION_RETRY_COUNT: number | undefined;
|
|
797
817
|
DD_TEST_FAILED_TEST_REPLAY_ENABLED: boolean;
|
|
798
818
|
DD_TEST_FAILURE_SCREENSHOTS_ENABLED: boolean | undefined;
|
|
799
819
|
DD_TEST_FLEET_CONFIG_PATH: string | undefined;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* @property {string} [namespace] Nests the canonical env name under this property path (e.g. `telemetry`).
|
|
14
14
|
* @property {string} [transform]
|
|
15
15
|
* @property {string} [allowed]
|
|
16
|
+
* @property {string} [description]
|
|
16
17
|
* @property {string|boolean} [deprecated]
|
|
17
18
|
* @property {boolean} [sensitive] Excludes the configuration value from configuration telemetry.
|
|
18
19
|
*/
|
|
@@ -333,6 +333,16 @@ class Config extends ConfigBase {
|
|
|
333
333
|
#applyCalculated () {
|
|
334
334
|
undo(this, 'calculated')
|
|
335
335
|
|
|
336
|
+
if (this.featureFlags.DD_FEATURE_FLAGS_ENABLED &&
|
|
337
|
+
!trackedConfigOrigins.has('featureFlags.DD_FEATURE_FLAGS_CONFIGURATION_SOURCE') &&
|
|
338
|
+
trackedConfigOrigins.has('experimental.flaggingProvider.enabled')) {
|
|
339
|
+
if (this.experimental.flaggingProvider.enabled) {
|
|
340
|
+
setAndTrack(this, 'featureFlags.DD_FEATURE_FLAGS_CONFIGURATION_SOURCE', 'remote_config')
|
|
341
|
+
} else {
|
|
342
|
+
setAndTrack(this, 'featureFlags.DD_FEATURE_FLAGS_ENABLED', false)
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
336
346
|
if (this.url ||
|
|
337
347
|
os.type() !== 'Windows_NT' &&
|
|
338
348
|
!trackedConfigOrigins.has('hostname') &&
|
|
@@ -206,6 +206,15 @@
|
|
|
206
206
|
]
|
|
207
207
|
}
|
|
208
208
|
],
|
|
209
|
+
"DD_APPSEC_AGENTIC_ONBOARDING": [
|
|
210
|
+
{
|
|
211
|
+
"implementation": "A",
|
|
212
|
+
"type": "string",
|
|
213
|
+
"default": "",
|
|
214
|
+
"namespace": "appsec",
|
|
215
|
+
"description": "Set automatically by Datadog's agentic onboarding solution when it configures App & API Protection for a service. Reported verbatim in configuration telemetry only; it has no effect on tracer behavior."
|
|
216
|
+
}
|
|
217
|
+
],
|
|
209
218
|
"DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE": [
|
|
210
219
|
{
|
|
211
220
|
"implementation": "E",
|
|
@@ -470,6 +479,14 @@
|
|
|
470
479
|
"namespace": "testOptimization"
|
|
471
480
|
}
|
|
472
481
|
],
|
|
482
|
+
"DD_CIVISIBILITY_CODE_COVERAGE_REPORT_UPLOAD_ENABLED": [
|
|
483
|
+
{
|
|
484
|
+
"implementation": "A",
|
|
485
|
+
"type": "boolean",
|
|
486
|
+
"default": "true",
|
|
487
|
+
"namespace": "testOptimization"
|
|
488
|
+
}
|
|
489
|
+
],
|
|
473
490
|
"DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE": [
|
|
474
491
|
{
|
|
475
492
|
"implementation": "A",
|
|
@@ -494,6 +511,15 @@
|
|
|
494
511
|
"namespace": "testOptimization"
|
|
495
512
|
}
|
|
496
513
|
],
|
|
514
|
+
"DD_TEST_EARLY_FLAKE_DETECTION_RETRY_COUNT": [
|
|
515
|
+
{
|
|
516
|
+
"implementation": "A",
|
|
517
|
+
"type": "int",
|
|
518
|
+
"allowed": "0|[1-9][0-9]*",
|
|
519
|
+
"default": null,
|
|
520
|
+
"namespace": "testOptimization"
|
|
521
|
+
}
|
|
522
|
+
],
|
|
497
523
|
"DD_CIVISIBILITY_ENABLED": [
|
|
498
524
|
{
|
|
499
525
|
"implementation": "A",
|
|
@@ -597,6 +623,14 @@
|
|
|
597
623
|
"namespace": "testOptimization"
|
|
598
624
|
}
|
|
599
625
|
],
|
|
626
|
+
"DD_CODE_COVERAGE_FLAGS": [
|
|
627
|
+
{
|
|
628
|
+
"implementation": "A",
|
|
629
|
+
"type": "string",
|
|
630
|
+
"default": null,
|
|
631
|
+
"namespace": "testOptimization"
|
|
632
|
+
}
|
|
633
|
+
],
|
|
600
634
|
"DD_CODE_ORIGIN_FOR_SPANS_ENABLED": [
|
|
601
635
|
{
|
|
602
636
|
"implementation": "A",
|
|
@@ -810,6 +844,55 @@
|
|
|
810
844
|
"default": "false"
|
|
811
845
|
}
|
|
812
846
|
],
|
|
847
|
+
"DD_FEATURE_FLAGS_CONFIGURATION_SOURCE": [
|
|
848
|
+
{
|
|
849
|
+
"implementation": "A",
|
|
850
|
+
"type": "string",
|
|
851
|
+
"default": "agentless",
|
|
852
|
+
"allowed": "agentless|remote_config",
|
|
853
|
+
"description": "Experimental: Select where Feature Flagging loads Universal Flag Configuration. Supported values are agentless and remote_config.",
|
|
854
|
+
"namespace": "featureFlags",
|
|
855
|
+
"transform": "toLowerCase"
|
|
856
|
+
}
|
|
857
|
+
],
|
|
858
|
+
"DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_BASE_URL": [
|
|
859
|
+
{
|
|
860
|
+
"implementation": "A",
|
|
861
|
+
"type": "string",
|
|
862
|
+
"default": null,
|
|
863
|
+
"description": "Experimental: Override the agentless Feature Flagging UFC endpoint or base URL.",
|
|
864
|
+
"namespace": "featureFlags",
|
|
865
|
+
"sensitive": true
|
|
866
|
+
}
|
|
867
|
+
],
|
|
868
|
+
"DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_POLL_INTERVAL_SECONDS": [
|
|
869
|
+
{
|
|
870
|
+
"implementation": "A",
|
|
871
|
+
"type": "int",
|
|
872
|
+
"default": "30",
|
|
873
|
+
"description": "Experimental: Set the agentless Feature Flagging UFC polling interval in seconds, capped at one hour.",
|
|
874
|
+
"allowed": "[1-9]\\d*",
|
|
875
|
+
"namespace": "featureFlags"
|
|
876
|
+
}
|
|
877
|
+
],
|
|
878
|
+
"DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_REQUEST_TIMEOUT_SECONDS": [
|
|
879
|
+
{
|
|
880
|
+
"implementation": "A",
|
|
881
|
+
"type": "int",
|
|
882
|
+
"default": "5",
|
|
883
|
+
"description": "Experimental: Set the agentless Feature Flagging UFC request timeout in seconds.",
|
|
884
|
+
"allowed": "[1-9]\\d*",
|
|
885
|
+
"namespace": "featureFlags"
|
|
886
|
+
}
|
|
887
|
+
],
|
|
888
|
+
"DD_FEATURE_FLAGS_ENABLED": [
|
|
889
|
+
{
|
|
890
|
+
"implementation": "A",
|
|
891
|
+
"type": "boolean",
|
|
892
|
+
"default": "true",
|
|
893
|
+
"namespace": "featureFlags"
|
|
894
|
+
}
|
|
895
|
+
],
|
|
813
896
|
"DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED": [
|
|
814
897
|
{
|
|
815
898
|
"implementation": "B",
|
|
@@ -31,6 +31,13 @@ module.exports = {
|
|
|
31
31
|
ERROR_MESSAGE: 'error.message',
|
|
32
32
|
ERROR_STACK: 'error.stack',
|
|
33
33
|
IGNORE_OTEL_ERROR: Symbol('ignore.otel.error'),
|
|
34
|
+
// Marks an `Http2Server` that another instrumentation (currently @grpc/grpc-js)
|
|
35
|
+
// owns and traces through its own span lifecycle over the raw HTTP/2 stream
|
|
36
|
+
// API. The http2 server instrumentation reads this to leave such servers
|
|
37
|
+
// untraced, so a gRPC call keeps a single span with gRPC as the top frame
|
|
38
|
+
// instead of gaining an extra web.request span. A module-local Symbol keeps
|
|
39
|
+
// the mark private to dd-trace and unforgeable from user code.
|
|
40
|
+
FOREIGN_HTTP2_SERVER: Symbol('foreign.http2.server'),
|
|
34
41
|
COMPONENT: 'component',
|
|
35
42
|
CLIENT_PORT_KEY: 'network.destination.port',
|
|
36
43
|
PEER_SERVICE_KEY: 'peer.service',
|
|
@@ -136,16 +136,18 @@ const DsmPathwayCodec = {
|
|
|
136
136
|
* @param {Buffer} dataStreamsContext.hash
|
|
137
137
|
* @param {number} dataStreamsContext.pathwayStartNs
|
|
138
138
|
* @param {number} dataStreamsContext.edgeStartNs
|
|
139
|
-
* @param {object} carrier
|
|
139
|
+
* @param {object} [carrier]
|
|
140
|
+
* @returns {object | undefined}
|
|
140
141
|
*/
|
|
141
142
|
encode (dataStreamsContext, carrier) {
|
|
142
|
-
if (!dataStreamsContext || !dataStreamsContext.hash)
|
|
143
|
-
|
|
144
|
-
}
|
|
143
|
+
if (!dataStreamsContext || !dataStreamsContext.hash) return
|
|
144
|
+
carrier ??= {}
|
|
145
145
|
carrier[CONTEXT_PROPAGATION_KEY_BASE64] = encodePathwayContextBase64(dataStreamsContext)
|
|
146
146
|
|
|
147
147
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
148
148
|
log.debug(() => `Injected into DSM carrier: ${JSON.stringify(pick(carrier, logKeys))}.`)
|
|
149
|
+
|
|
150
|
+
return carrier
|
|
149
151
|
},
|
|
150
152
|
|
|
151
153
|
/**
|
|
@@ -19,6 +19,8 @@ module.exports = function getExporter (name) {
|
|
|
19
19
|
return require('./ci-visibility/exporters/agentless')
|
|
20
20
|
case exporters.AGENT_PROXY:
|
|
21
21
|
return require('./ci-visibility/exporters/agent-proxy')
|
|
22
|
+
case exporters.CI_VALIDATION:
|
|
23
|
+
return require('./ci-visibility/exporters/ci-validation')
|
|
22
24
|
case exporters.JEST_WORKER:
|
|
23
25
|
case exporters.CUCUMBER_WORKER:
|
|
24
26
|
case exporters.MOCHA_WORKER:
|