dd-trace 6.6.0 → 6.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ci/diagnose.js +162 -21
- package/ci/init.js +0 -1
- package/ci/runbook.md +187 -180
- package/ci/test-optimization-validation/approval-artifacts.js +3 -1
- package/ci/test-optimization-validation/approval.js +52 -15
- package/ci/test-optimization-validation/ci-command-candidate.js +26 -32
- package/ci/test-optimization-validation/ci-discovery.js +1 -1
- package/ci/test-optimization-validation/ci-package-scripts.js +141 -0
- package/ci/test-optimization-validation/ci-remediation.js +112 -39
- package/ci/test-optimization-validation/cli.js +516 -681
- package/ci/test-optimization-validation/command-blocker.js +188 -33
- package/ci/test-optimization-validation/command-output-policy.js +8 -31
- package/ci/test-optimization-validation/command-runner.js +189 -245
- package/ci/test-optimization-validation/environment.js +90 -0
- package/ci/test-optimization-validation/executable.js +159 -388
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +119 -0
- package/ci/test-optimization-validation/framework-adapters/cypress.js +107 -0
- package/ci/test-optimization-validation/framework-adapters/playwright.js +181 -0
- package/ci/test-optimization-validation/generated-files.js +84 -22
- package/ci/test-optimization-validation/generated-test-contract.js +281 -0
- package/ci/test-optimization-validation/generated-verifier.js +49 -16
- package/ci/test-optimization-validation/literal-environment.js +57 -0
- package/ci/test-optimization-validation/manifest-loader.js +2 -22
- package/ci/test-optimization-validation/manifest-scaffold.js +815 -515
- package/ci/test-optimization-validation/manifest-schema.js +494 -702
- package/ci/test-optimization-validation/offline-fixtures.js +4 -1
- package/ci/test-optimization-validation/offline-output.js +6 -6
- package/ci/test-optimization-validation/plan-writer.js +243 -984
- package/ci/test-optimization-validation/preflight-runner.js +49 -55
- package/ci/test-optimization-validation/redaction.js +2 -1
- package/ci/test-optimization-validation/report-writer.js +391 -1357
- package/ci/test-optimization-validation/result-semantics.js +86 -0
- package/ci/test-optimization-validation/runner-command.js +249 -0
- package/ci/test-optimization-validation/runner-contract.js +664 -0
- package/ci/test-optimization-validation/safe-files.js +4 -4
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +29 -3
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +240 -543
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +450 -670
- package/ci/test-optimization-validation/scenarios/early-flake-detection.js +4 -3
- package/ci/test-optimization-validation/scenarios/helpers.js +67 -9
- package/ci/test-optimization-validation/scenarios/test-management.js +6 -5
- package/ci/test-optimization-validation/source-text.js +87 -0
- package/ci/test-optimization-validation/test-output.js +12 -22
- package/ci/vitest-no-worker-init-setup.mjs +348 -51
- package/ext/tags.d.ts +1 -0
- package/index.d.ts +84 -13
- package/package.json +10 -4
- package/packages/datadog-core/src/utils/src/kebabcase.js +8 -2
- package/packages/datadog-esbuild/index.js +4 -2
- package/packages/datadog-esbuild/src/utils.js +1 -1
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +4 -4
- package/packages/datadog-instrumentations/src/cucumber.js +9 -6
- package/packages/datadog-instrumentations/src/helpers/extract-package-and-module-path.js +10 -0
- package/packages/datadog-instrumentations/src/helpers/hook.js +19 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +9 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/openai-agents.js +31 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +57 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +50 -18
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/shared-utils.js +39 -0
- package/packages/datadog-instrumentations/src/http/client.js +1 -3
- package/packages/datadog-instrumentations/src/jest.js +8 -14
- package/packages/datadog-instrumentations/src/mocha/common.js +1 -3
- package/packages/datadog-instrumentations/src/mocha/main.js +2 -42
- package/packages/datadog-instrumentations/src/mocha/utils.js +68 -2
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +19 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +446 -42
- package/packages/datadog-instrumentations/src/moleculer/client.js +1 -1
- package/packages/datadog-instrumentations/src/openai-agents.js +159 -0
- package/packages/datadog-instrumentations/src/playwright.js +3 -2
- package/packages/datadog-instrumentations/src/rhea.js +1 -1
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +525 -56
- package/packages/datadog-instrumentations/src/vitest-main.js +90 -10
- package/packages/datadog-instrumentations/src/webdriverio.js +914 -0
- package/packages/datadog-plugin-aerospike/src/index.js +1 -3
- package/packages/datadog-plugin-amqplib/src/client.js +1 -1
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +2 -2
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -3
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +5 -3
- package/packages/datadog-plugin-bullmq/src/producer.js +3 -3
- package/packages/datadog-plugin-child_process/src/index.js +3 -3
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +5 -8
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -1
- package/packages/datadog-plugin-fastify/src/tracing.js +1 -1
- package/packages/datadog-plugin-fs/src/index.js +0 -4
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +14 -7
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +19 -10
- package/packages/datadog-plugin-graphql/src/execute.js +1 -0
- package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +2 -1
- package/packages/datadog-plugin-jest/src/index.js +2 -3
- package/packages/datadog-plugin-jest/src/util.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +25 -6
- package/packages/datadog-plugin-openai-agents/src/index.js +74 -0
- package/packages/datadog-plugin-openai-agents/src/integration.js +503 -0
- package/packages/datadog-plugin-openai-agents/src/processor.js +108 -0
- package/packages/datadog-plugin-openai-agents/src/util.js +60 -0
- package/packages/datadog-plugin-prisma/src/index.js +5 -1
- package/packages/datadog-plugin-rhea/src/consumer.js +16 -13
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-undici/src/index.js +2 -1
- package/packages/datadog-plugin-vitest/src/index.js +84 -11
- package/packages/datadog-webpack/index.js +2 -2
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-base-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -3
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/track_event.js +1 -1
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +7 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +50 -51
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -1
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +4 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/webdriverio.js +26 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -1
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +161 -33
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -3
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +7 -5
- package/packages/dd-trace/src/config/defaults.js +14 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -2
- package/packages/dd-trace/src/config/index.js +15 -0
- package/packages/dd-trace/src/config/parsers.js +19 -1
- package/packages/dd-trace/src/config/supported-configurations.json +12 -6
- package/packages/dd-trace/src/datastreams/encoding.js +3 -4
- package/packages/dd-trace/src/debugger/devtools_client/log.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +1 -4
- package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +2 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +16 -2
- package/packages/dd-trace/src/encode/span-stats.js +7 -1
- package/packages/dd-trace/src/encode/tags-processors.js +2 -2
- package/packages/dd-trace/src/exporter.js +16 -9
- package/packages/dd-trace/src/exporters/common/url.js +3 -5
- package/packages/dd-trace/src/exporters/electron/index.js +4 -1
- package/packages/dd-trace/src/external-logger/src/index.js +1 -2
- package/packages/dd-trace/src/flare/index.js +2 -2
- package/packages/dd-trace/src/id.js +1 -1
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -1
- package/packages/dd-trace/src/llmobs/experiments/client.js +4 -2
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +66 -14
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +289 -95
- package/packages/dd-trace/src/llmobs/experiments/index.js +51 -12
- package/packages/dd-trace/src/llmobs/experiments/noop.js +95 -10
- package/packages/dd-trace/src/llmobs/experiments/result.js +13 -2
- package/packages/dd-trace/src/llmobs/experiments/util.js +218 -0
- package/packages/dd-trace/src/llmobs/index.js +9 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +104 -22
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +5 -9
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +20 -0
- package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +321 -0
- package/packages/dd-trace/src/llmobs/sdk.js +6 -12
- package/packages/dd-trace/src/llmobs/span_processor.js +14 -7
- package/packages/dd-trace/src/llmobs/tagger.js +24 -5
- package/packages/dd-trace/src/llmobs/util.js +56 -3
- package/packages/dd-trace/src/llmobs/writers/spans.js +12 -6
- package/packages/dd-trace/src/noop/proxy.js +2 -2
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +3 -6
- package/packages/dd-trace/src/openfeature/configuration_source.js +5 -8
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +5 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/opentracing/span_context.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +114 -23
- package/packages/dd-trace/src/plugins/index.js +2 -0
- package/packages/dd-trace/src/plugins/outbound.js +4 -1
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/tracing.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +7 -6
- package/packages/dd-trace/src/plugins/util/git.js +1 -1
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +1 -1
- package/packages/dd-trace/src/plugins/util/llm.js +2 -2
- package/packages/dd-trace/src/plugins/util/tags.js +2 -0
- package/packages/dd-trace/src/plugins/util/test.js +38 -12
- package/packages/dd-trace/src/plugins/util/url.js +5 -5
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/priority_sampler.js +6 -3
- package/packages/dd-trace/src/profiling/profilers/poisson.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/shared.js +2 -2
- package/packages/dd-trace/src/ritm.js +5 -20
- package/packages/dd-trace/src/span_processor.js +1 -1
- package/packages/dd-trace/src/span_stats.js +22 -4
- package/packages/dd-trace/src/startup-log.js +3 -0
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -1
- package/packages/dd-trace/src/util.js +16 -0
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +12 -12
- package/vendor/dist/pprof-format/index.js +1 -1
- package/vendor/dist/source-map/index.js +1 -1
- package/ci/test-optimization-validation/command-suitability.js +0 -471
- package/ci/test-optimization-validation/init-probe-preload.js +0 -163
- package/ci/test-optimization-validation/init-probe.js +0 -246
- package/ci/test-optimization-validation/late-initialization.js +0 -63
- package/ci/test-optimization-validation/local-command.js +0 -163
- package/ci/test-optimization-validation/setup-runner.js +0 -97
- package/ci/test-optimization-validation-manifest.schema.json +0 -1
|
@@ -12,12 +12,145 @@ const {
|
|
|
12
12
|
TELEMETRY_GIT_REQUESTS_SETTINGS_RESPONSE,
|
|
13
13
|
} = require('../telemetry')
|
|
14
14
|
const { writeSettingsToCache } = require('../test-optimization-cache')
|
|
15
|
-
const { validateSettingsResponse } = require('../test-optimization-http-cache-schema')
|
|
15
|
+
const { MAX_RETRIES, validateSettingsResponse } = require('../test-optimization-http-cache-schema')
|
|
16
16
|
const request = require('./request')
|
|
17
17
|
|
|
18
18
|
const DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES = 2
|
|
19
|
-
const DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES = {
|
|
19
|
+
const DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES = Object.freeze({
|
|
20
|
+
'5s': 10,
|
|
21
|
+
'10s': 5,
|
|
22
|
+
'30s': 3,
|
|
23
|
+
'5m': 2,
|
|
24
|
+
})
|
|
20
25
|
const DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD = 30
|
|
26
|
+
const EARLY_FLAKE_DETECTION_RETRY_BUCKETS = Object.keys(DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES)
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @typedef {object} EarlyFlakeDetectionSettings
|
|
30
|
+
* @property {boolean} enabled
|
|
31
|
+
* @property {number} numRetries
|
|
32
|
+
* @property {Readonly<Record<string, number>>} slowTestRetries
|
|
33
|
+
* @property {number} faultyThreshold
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {object} TestManagementSettings
|
|
38
|
+
* @property {boolean} enabled
|
|
39
|
+
* @property {number|undefined} attemptToFixRetries
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {unknown} value
|
|
44
|
+
* @returns {value is Record<string, unknown>}
|
|
45
|
+
*/
|
|
46
|
+
function isRecord (value) {
|
|
47
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {unknown} value
|
|
52
|
+
* @returns {value is number}
|
|
53
|
+
*/
|
|
54
|
+
function isNonNegativeInteger (value) {
|
|
55
|
+
return Number.isInteger(value) && value >= 0
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {unknown} value
|
|
60
|
+
* @returns {value is number}
|
|
61
|
+
*/
|
|
62
|
+
function isRetryCount (value) {
|
|
63
|
+
return isNonNegativeInteger(value) && value <= MAX_RETRIES
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {unknown} value
|
|
68
|
+
* @returns {Readonly<Record<string, number>>|undefined}
|
|
69
|
+
*/
|
|
70
|
+
function parseSlowTestRetries (value) {
|
|
71
|
+
if (!isRecord(value)) return
|
|
72
|
+
|
|
73
|
+
const slowTestRetries = {}
|
|
74
|
+
for (const bucket of EARLY_FLAKE_DETECTION_RETRY_BUCKETS) {
|
|
75
|
+
if (!Object.hasOwn(value, bucket)) continue
|
|
76
|
+
|
|
77
|
+
const retries = value[bucket]
|
|
78
|
+
if (!isRetryCount(retries)) return
|
|
79
|
+
slowTestRetries[bucket] = retries
|
|
80
|
+
}
|
|
81
|
+
return Object.freeze(slowTestRetries)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {unknown} value
|
|
86
|
+
* @param {boolean} isKnownTestsEnabled
|
|
87
|
+
* @returns {EarlyFlakeDetectionSettings}
|
|
88
|
+
*/
|
|
89
|
+
function parseEarlyFlakeDetectionSettings (value, isKnownTestsEnabled) {
|
|
90
|
+
if (!isRecord(value) || value.enabled !== true) {
|
|
91
|
+
return {
|
|
92
|
+
enabled: false,
|
|
93
|
+
numRetries: DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES,
|
|
94
|
+
slowTestRetries: DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES,
|
|
95
|
+
faultyThreshold: DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let isValid = true
|
|
100
|
+
let numRetries = DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES
|
|
101
|
+
let slowTestRetries = DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES
|
|
102
|
+
if (Object.hasOwn(value, 'slow_test_retries')) {
|
|
103
|
+
const parsedSlowTestRetries = parseSlowTestRetries(value.slow_test_retries)
|
|
104
|
+
if (parsedSlowTestRetries) {
|
|
105
|
+
slowTestRetries = parsedSlowTestRetries
|
|
106
|
+
numRetries = parsedSlowTestRetries['5s'] ?? DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES
|
|
107
|
+
} else {
|
|
108
|
+
isValid = false
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let faultyThreshold = DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD
|
|
113
|
+
if (Object.hasOwn(value, 'faulty_session_threshold')) {
|
|
114
|
+
if (isNonNegativeInteger(value.faulty_session_threshold) && value.faulty_session_threshold <= 100) {
|
|
115
|
+
faultyThreshold = value.faulty_session_threshold
|
|
116
|
+
} else {
|
|
117
|
+
isValid = false
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
enabled: isKnownTestsEnabled && isValid,
|
|
123
|
+
numRetries,
|
|
124
|
+
slowTestRetries,
|
|
125
|
+
faultyThreshold,
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {unknown} value
|
|
131
|
+
* @returns {TestManagementSettings}
|
|
132
|
+
*/
|
|
133
|
+
function parseTestManagementSettings (value) {
|
|
134
|
+
if (!isRecord(value) || value.enabled !== true) {
|
|
135
|
+
return {
|
|
136
|
+
enabled: false,
|
|
137
|
+
attemptToFixRetries: undefined,
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const attemptToFixRetries = value.attempt_to_fix_retries
|
|
142
|
+
if (attemptToFixRetries !== undefined && !isRetryCount(attemptToFixRetries)) {
|
|
143
|
+
return {
|
|
144
|
+
enabled: false,
|
|
145
|
+
attemptToFixRetries: undefined,
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
enabled: true,
|
|
151
|
+
attemptToFixRetries,
|
|
152
|
+
}
|
|
153
|
+
}
|
|
21
154
|
|
|
22
155
|
function parseJsonResponse (rawJson) {
|
|
23
156
|
return typeof rawJson === 'string' ? JSON.parse(rawJson) : rawJson
|
|
@@ -28,40 +161,35 @@ function parseLibraryConfigurationResponse (rawJson, config = getConfig(), optio
|
|
|
28
161
|
if (options.validateRequiredFields) {
|
|
29
162
|
validateSettingsResponse(parsedResponse, options)
|
|
30
163
|
}
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
} = parsedResponse?.data?.attributes ?? parsedResponse
|
|
164
|
+
const parsedAttributes = parsedResponse?.data?.attributes ?? parsedResponse
|
|
165
|
+
if (!isRecord(parsedAttributes)) {
|
|
166
|
+
throw new TypeError('Invalid settings response: attributes must be an object')
|
|
167
|
+
}
|
|
168
|
+
const attributes = parsedAttributes
|
|
169
|
+
const isKnownTestsEnabled = attributes.known_tests_enabled === true
|
|
170
|
+
const isFlakyTestRetriesEnabled = attributes.flaky_test_retries_enabled === true
|
|
171
|
+
const earlyFlakeDetection = parseEarlyFlakeDetectionSettings(
|
|
172
|
+
attributes.early_flake_detection,
|
|
173
|
+
isKnownTestsEnabled
|
|
174
|
+
)
|
|
175
|
+
const testManagement = parseTestManagementSettings(attributes.test_management)
|
|
44
176
|
|
|
45
177
|
const settings = {
|
|
46
|
-
isCodeCoverageEnabled,
|
|
47
|
-
isSuitesSkippingEnabled,
|
|
48
|
-
isItrEnabled,
|
|
49
|
-
requireGit,
|
|
50
|
-
isEarlyFlakeDetectionEnabled:
|
|
51
|
-
earlyFlakeDetectionNumRetries:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
earlyFlakeDetectionConfig?.slow_test_retries ?? DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES,
|
|
55
|
-
earlyFlakeDetectionFaultyThreshold:
|
|
56
|
-
earlyFlakeDetectionConfig?.faulty_session_threshold ?? DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD,
|
|
178
|
+
isCodeCoverageEnabled: attributes.code_coverage === true,
|
|
179
|
+
isSuitesSkippingEnabled: attributes.tests_skipping === true,
|
|
180
|
+
isItrEnabled: attributes.itr_enabled === true,
|
|
181
|
+
requireGit: attributes.require_git === true,
|
|
182
|
+
isEarlyFlakeDetectionEnabled: earlyFlakeDetection.enabled,
|
|
183
|
+
earlyFlakeDetectionNumRetries: earlyFlakeDetection.numRetries,
|
|
184
|
+
earlyFlakeDetectionSlowTestRetries: earlyFlakeDetection.slowTestRetries,
|
|
185
|
+
earlyFlakeDetectionFaultyThreshold: earlyFlakeDetection.faultyThreshold,
|
|
57
186
|
isFlakyTestRetriesEnabled,
|
|
58
|
-
isDiEnabled:
|
|
187
|
+
isDiEnabled: attributes.di_enabled === true && isFlakyTestRetriesEnabled,
|
|
59
188
|
isKnownTestsEnabled,
|
|
60
|
-
isTestManagementEnabled:
|
|
61
|
-
testManagementAttemptToFixRetries:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
isCoverageReportUploadEnabled: isCoverageReportUploadEnabled ?? false,
|
|
189
|
+
isTestManagementEnabled: testManagement.enabled,
|
|
190
|
+
testManagementAttemptToFixRetries: testManagement.attemptToFixRetries,
|
|
191
|
+
isImpactedTestsEnabled: attributes.impacted_tests_enabled === true,
|
|
192
|
+
isCoverageReportUploadEnabled: attributes.coverage_report_upload_enabled === true,
|
|
65
193
|
}
|
|
66
194
|
|
|
67
195
|
log.debug('Remote settings: %j', settings)
|
|
@@ -82,7 +210,7 @@ function parseLibraryConfigurationResponse (rawJson, config = getConfig(), optio
|
|
|
82
210
|
log.debug('Code coverage report upload was disabled by the environment variable')
|
|
83
211
|
}
|
|
84
212
|
|
|
85
|
-
return settings
|
|
213
|
+
return Object.freeze(settings)
|
|
86
214
|
}
|
|
87
215
|
|
|
88
216
|
function getLibraryConfiguration ({
|
|
@@ -42,7 +42,7 @@ function request (data, options, callback) {
|
|
|
42
42
|
if (url.protocol === 'unix:') {
|
|
43
43
|
opts.socketPath = url.pathname
|
|
44
44
|
} else {
|
|
45
|
-
opts.path
|
|
45
|
+
opts.path ??= url.path
|
|
46
46
|
opts.protocol = url.protocol
|
|
47
47
|
opts.hostname = url.hostname
|
|
48
48
|
opts.port = url.port
|
|
@@ -100,9 +100,9 @@ function request (data, options, callback) {
|
|
|
100
100
|
if (res.statusCode === 429 && !hasRetried) {
|
|
101
101
|
const resetHeader = res.headers['x-ratelimit-reset']
|
|
102
102
|
const resetTs = (resetHeader === null || resetHeader === undefined)
|
|
103
|
-
?
|
|
103
|
+
? NaN
|
|
104
104
|
: Number.parseInt(resetHeader, 10)
|
|
105
|
-
const waitMs = Number.isFinite(resetTs) ? Math.max(0, resetTs * 1000 - Date.now()) :
|
|
105
|
+
const waitMs = Number.isFinite(resetTs) ? Math.max(0, resetTs * 1000 - Date.now()) : NaN
|
|
106
106
|
|
|
107
107
|
if (Number.isFinite(waitMs) && waitMs <= RATE_LIMIT_MAX_WAIT_MS) {
|
|
108
108
|
hasRetried = true
|
|
@@ -26,11 +26,11 @@ const SETTINGS_BOOLEAN_KEYS = [
|
|
|
26
26
|
]
|
|
27
27
|
const EARLY_FLAKE_DETECTION_KEYS = ['enabled', 'faulty_session_threshold', 'slow_test_retries']
|
|
28
28
|
const TEST_MANAGEMENT_KEYS = ['attempt_to_fix_retries', 'enabled']
|
|
29
|
-
const RETRY_THRESHOLD_PATTERN = /^\d+(?:ms|
|
|
29
|
+
const RETRY_THRESHOLD_PATTERN = /^\d+(?:ms|[smh])$/
|
|
30
30
|
const MAX_VALIDATION_MODULES = 1000
|
|
31
31
|
const MAX_VALIDATION_SUITES = 10_000
|
|
32
32
|
const MAX_VALIDATION_TESTS = 100_000
|
|
33
|
-
const
|
|
33
|
+
const MAX_RETRIES = 100
|
|
34
34
|
const MAX_VALIDATION_STRING_BYTES = 4096
|
|
35
35
|
|
|
36
36
|
function isObject (value) {
|
|
@@ -75,7 +75,8 @@ function validateSettingsResponse (response, options = {}) {
|
|
|
75
75
|
assertBooleanFields(attributes.test_management, ['enabled'], 'settings test_management')
|
|
76
76
|
assertOptionalBoundedNumber(
|
|
77
77
|
attributes.early_flake_detection.faulty_session_threshold,
|
|
78
|
-
'settings early_flake_detection faulty_session_threshold'
|
|
78
|
+
'settings early_flake_detection faulty_session_threshold',
|
|
79
|
+
{ integer: true }
|
|
79
80
|
)
|
|
80
81
|
assertRetryMap(attributes.early_flake_detection.slow_test_retries)
|
|
81
82
|
assertOptionalBoundedNumber(
|
|
@@ -216,8 +217,8 @@ function assertBooleanFields (object, keys, endpoint) {
|
|
|
216
217
|
function assertOptionalBoundedNumber (value, endpoint, { integer = false } = {}) {
|
|
217
218
|
if (value === undefined) return
|
|
218
219
|
if (!Number.isFinite(value) || (integer && !Number.isInteger(value)) ||
|
|
219
|
-
value < 0 || value >
|
|
220
|
-
throw new TypeError(`Invalid ${endpoint}: value must be between 0 and ${
|
|
220
|
+
value < 0 || value > MAX_RETRIES) {
|
|
221
|
+
throw new TypeError(`Invalid ${endpoint}: value must be between 0 and ${MAX_RETRIES}`)
|
|
221
222
|
}
|
|
222
223
|
}
|
|
223
224
|
|
|
@@ -249,6 +250,7 @@ function assertValidationString (value, field) {
|
|
|
249
250
|
}
|
|
250
251
|
|
|
251
252
|
module.exports = {
|
|
253
|
+
MAX_RETRIES,
|
|
252
254
|
validateKnownTestsResponse,
|
|
253
255
|
validateSettingsResponse,
|
|
254
256
|
validateSkippableTestsResponse,
|
|
@@ -32,18 +32,26 @@ const parseErrors = new Map()
|
|
|
32
32
|
* @param {string} source - The source of the value.
|
|
33
33
|
* @param {string} baseMessage - The base message to use for the warning.
|
|
34
34
|
* @param {Error} [error] - An error that was thrown while parsing the value.
|
|
35
|
+
* @param {string} [outcome] - The outcome after the invalid value is rejected.
|
|
35
36
|
*/
|
|
36
|
-
function warnInvalidValue (value, optionName, source, baseMessage, error) {
|
|
37
|
-
const canonicalName =
|
|
37
|
+
function warnInvalidValue (value, optionName, source, baseMessage, error, outcome = 'picked default') {
|
|
38
|
+
const canonicalName = optionsTable[optionName]?.canonicalName ?? optionName
|
|
39
|
+
const telemetryKey = canonicalName + source
|
|
40
|
+
const telemetryEntry = configWithOrigin.get(telemetryKey)
|
|
38
41
|
// Lazy load log module to avoid circular dependency
|
|
39
|
-
if (!parseErrors.has(
|
|
40
|
-
// TODO:
|
|
41
|
-
let message = `${baseMessage}: ${util.inspect(value)} for ${optionName} (source: ${source})
|
|
42
|
+
if (!parseErrors.has(telemetryKey) && !telemetryEntry?.error) {
|
|
43
|
+
// TODO: Report the prior source when an invalid value does not use the default.
|
|
44
|
+
let message = `${baseMessage}: ${util.inspect(value)} for ${optionName} (source: ${source})`
|
|
45
|
+
if (outcome) message += `, ${outcome}`
|
|
42
46
|
if (error) {
|
|
43
47
|
error.stack = error.toString()
|
|
44
48
|
message += `\n\n${util.inspect(error)}`
|
|
45
49
|
}
|
|
46
|
-
|
|
50
|
+
if (telemetryEntry) {
|
|
51
|
+
telemetryEntry.error = { message }
|
|
52
|
+
} else {
|
|
53
|
+
parseErrors.set(telemetryKey, { message })
|
|
54
|
+
}
|
|
47
55
|
log ??= require('../log')
|
|
48
56
|
const logLevel = error ? 'error' : 'warn'
|
|
49
57
|
log[logLevel](message)
|
|
@@ -333,6 +333,7 @@ export interface GeneratedConfig {
|
|
|
333
333
|
DD_TRACE_NODE_SERIALIZE_ENABLED: boolean;
|
|
334
334
|
DD_TRACE_NYC_ENABLED: boolean;
|
|
335
335
|
DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP: string;
|
|
336
|
+
DD_TRACE_OPENAI_AGENTS_ENABLED: boolean;
|
|
336
337
|
DD_TRACE_OPENAI_ENABLED: boolean;
|
|
337
338
|
DD_TRACE_OPENSEARCH_ENABLED: boolean;
|
|
338
339
|
DD_TRACE_OPENSEARCH_PROJECT_OPENSEARCH_ENABLED: boolean;
|
|
@@ -433,7 +434,7 @@ export interface GeneratedConfig {
|
|
|
433
434
|
};
|
|
434
435
|
};
|
|
435
436
|
featureFlags: {
|
|
436
|
-
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE:
|
|
437
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE: string;
|
|
437
438
|
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_BASE_URL: string | undefined;
|
|
438
439
|
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_POLL_INTERVAL_SECONDS: number;
|
|
439
440
|
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_REQUEST_TIMEOUT_SECONDS: number;
|
|
@@ -699,7 +700,7 @@ export interface GeneratedEnvVarConfig {
|
|
|
699
700
|
DD_EXPERIMENTAL_TEST_OPT_VITEST_NO_WORKER_INIT: boolean | undefined;
|
|
700
701
|
DD_EXPERIMENTAL_TEST_REQUESTS_FS_CACHE: boolean;
|
|
701
702
|
DD_EXTERNAL_ENV: string | undefined;
|
|
702
|
-
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE:
|
|
703
|
+
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE: string;
|
|
703
704
|
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_BASE_URL: string | undefined;
|
|
704
705
|
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_POLL_INTERVAL_SECONDS: number;
|
|
705
706
|
DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_REQUEST_TIMEOUT_SECONDS: number;
|
|
@@ -1028,6 +1029,7 @@ export interface GeneratedEnvVarConfig {
|
|
|
1028
1029
|
DD_TRACE_NODE_SERIALIZE_ENABLED: boolean;
|
|
1029
1030
|
DD_TRACE_NYC_ENABLED: boolean;
|
|
1030
1031
|
DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP: string;
|
|
1032
|
+
DD_TRACE_OPENAI_AGENTS_ENABLED: boolean;
|
|
1031
1033
|
DD_TRACE_OPENAI_ENABLED: boolean;
|
|
1032
1034
|
DD_TRACE_OPENSEARCH_ENABLED: boolean;
|
|
1033
1035
|
DD_TRACE_OPENSEARCH_PROJECT_OPENSEARCH_ENABLED: boolean;
|
|
@@ -343,6 +343,21 @@ class Config extends ConfigBase {
|
|
|
343
343
|
}
|
|
344
344
|
}
|
|
345
345
|
|
|
346
|
+
const configurationSource = this.featureFlags.DD_FEATURE_FLAGS_CONFIGURATION_SOURCE
|
|
347
|
+
if (this.featureFlags.DD_FEATURE_FLAGS_ENABLED &&
|
|
348
|
+
configurationSource !== 'agentless' &&
|
|
349
|
+
configurationSource !== 'remote_config') {
|
|
350
|
+
warnInvalidValue(
|
|
351
|
+
configurationSource,
|
|
352
|
+
'DD_FEATURE_FLAGS_CONFIGURATION_SOURCE',
|
|
353
|
+
this.getOrigin('featureFlags.DD_FEATURE_FLAGS_CONFIGURATION_SOURCE'),
|
|
354
|
+
'Unsupported Feature Flagging configuration source',
|
|
355
|
+
undefined,
|
|
356
|
+
'provider disabled'
|
|
357
|
+
)
|
|
358
|
+
setAndTrack(this, 'featureFlags.DD_FEATURE_FLAGS_ENABLED', false)
|
|
359
|
+
}
|
|
360
|
+
|
|
346
361
|
if (this.url ||
|
|
347
362
|
os.type() !== 'Windows_NT' &&
|
|
348
363
|
!trackedConfigOrigins.has('hostname') &&
|
|
@@ -58,6 +58,17 @@ const transformers = {
|
|
|
58
58
|
toLowerCase (value) {
|
|
59
59
|
return toCase(value, 'toLowerCase')
|
|
60
60
|
},
|
|
61
|
+
/**
|
|
62
|
+
* Normalizes a Feature Flagging configuration source.
|
|
63
|
+
* A blank value is treated as unset so legacy configuration can still apply.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} value
|
|
66
|
+
* @returns {string | undefined}
|
|
67
|
+
*/
|
|
68
|
+
configurationSource (value) {
|
|
69
|
+
const normalized = value.trim().toLowerCase()
|
|
70
|
+
return normalized || undefined
|
|
71
|
+
},
|
|
61
72
|
toUpperCase (value) {
|
|
62
73
|
return toCase(value, 'toUpperCase')
|
|
63
74
|
},
|
|
@@ -161,7 +172,14 @@ const transformers = {
|
|
|
161
172
|
return transformers.stripColonWhitespace(item)
|
|
162
173
|
})
|
|
163
174
|
}
|
|
164
|
-
|
|
175
|
+
// Only whitespace adjacent to a colon is removed; the outer whitespace of the first and
|
|
176
|
+
// last segment stays.
|
|
177
|
+
const parts = value.split(':')
|
|
178
|
+
for (let i = 0; i < parts.length; i++) {
|
|
179
|
+
if (i !== 0) parts[i] = parts[i].trimStart()
|
|
180
|
+
if (i !== parts.length - 1) parts[i] = parts[i].trimEnd()
|
|
181
|
+
}
|
|
182
|
+
return parts.join(':')
|
|
165
183
|
},
|
|
166
184
|
/**
|
|
167
185
|
* @param {string} value
|
|
@@ -849,10 +849,9 @@
|
|
|
849
849
|
"implementation": "A",
|
|
850
850
|
"type": "string",
|
|
851
851
|
"default": "agentless",
|
|
852
|
-
"
|
|
853
|
-
"description": "Experimental: Select where Feature Flagging loads Universal Flag Configuration. Supported values are agentless and remote_config.",
|
|
852
|
+
"description": "Select where Feature Flagging loads Universal Flag Configuration. Supported values are agentless and remote_config; offline is reserved and currently unsupported.",
|
|
854
853
|
"namespace": "featureFlags",
|
|
855
|
-
"transform": "
|
|
854
|
+
"transform": "configurationSource"
|
|
856
855
|
}
|
|
857
856
|
],
|
|
858
857
|
"DD_FEATURE_FLAGS_CONFIGURATION_SOURCE_AGENTLESS_BASE_URL": [
|
|
@@ -860,7 +859,7 @@
|
|
|
860
859
|
"implementation": "A",
|
|
861
860
|
"type": "string",
|
|
862
861
|
"default": null,
|
|
863
|
-
"description": "
|
|
862
|
+
"description": "Override the agentless Feature Flagging UFC endpoint or base URL.",
|
|
864
863
|
"namespace": "featureFlags",
|
|
865
864
|
"sensitive": true
|
|
866
865
|
}
|
|
@@ -870,7 +869,7 @@
|
|
|
870
869
|
"implementation": "A",
|
|
871
870
|
"type": "int",
|
|
872
871
|
"default": "30",
|
|
873
|
-
"description": "
|
|
872
|
+
"description": "Set the agentless Feature Flagging UFC polling interval in seconds, capped at one hour.",
|
|
874
873
|
"allowed": "[1-9]\\d*",
|
|
875
874
|
"namespace": "featureFlags"
|
|
876
875
|
}
|
|
@@ -880,7 +879,7 @@
|
|
|
880
879
|
"implementation": "A",
|
|
881
880
|
"type": "int",
|
|
882
881
|
"default": "5",
|
|
883
|
-
"description": "
|
|
882
|
+
"description": "Set the agentless Feature Flagging UFC request timeout in seconds.",
|
|
884
883
|
"allowed": "[1-9]\\d*",
|
|
885
884
|
"namespace": "featureFlags"
|
|
886
885
|
}
|
|
@@ -3452,6 +3451,13 @@
|
|
|
3452
3451
|
"default": "true"
|
|
3453
3452
|
}
|
|
3454
3453
|
],
|
|
3454
|
+
"DD_TRACE_OPENAI_AGENTS_ENABLED": [
|
|
3455
|
+
{
|
|
3456
|
+
"implementation": "A",
|
|
3457
|
+
"type": "boolean",
|
|
3458
|
+
"default": "true"
|
|
3459
|
+
}
|
|
3460
|
+
],
|
|
3455
3461
|
"DD_TRACE_OPENSEARCH_ENABLED": [
|
|
3456
3462
|
{
|
|
3457
3463
|
"implementation": "A",
|
|
@@ -40,7 +40,7 @@ function encodeVarintInto (target, offset, value) {
|
|
|
40
40
|
let i = offset
|
|
41
41
|
const limit = offset + maxVarLen64 - 1
|
|
42
42
|
// if first byte is 1, the number is negative in javascript, but we want to interpret it as positive
|
|
43
|
-
while ((high !== 0 || low < 0 || low >
|
|
43
|
+
while ((high !== 0 || low < 0 || low > 0x7F) && i < limit) {
|
|
44
44
|
target[i] = (low & 0x7F) | 0x80
|
|
45
45
|
low >>>= 7
|
|
46
46
|
low |= (high & 0x7F) << 25
|
|
@@ -88,7 +88,7 @@ function decodeUvarint64 (
|
|
|
88
88
|
low |= n << s
|
|
89
89
|
}
|
|
90
90
|
if (s > 0) {
|
|
91
|
-
high |= s
|
|
91
|
+
high |= s > 32 ? n << (s - 32) : n >> (32 - s)
|
|
92
92
|
}
|
|
93
93
|
return [low, high, bytes]
|
|
94
94
|
}
|
|
@@ -96,8 +96,7 @@ function decodeUvarint64 (
|
|
|
96
96
|
low |= (n & 0x7F) << s
|
|
97
97
|
}
|
|
98
98
|
if (s > 0) {
|
|
99
|
-
high |=
|
|
100
|
-
s - 32 > 0 ? (n & 0x7F) << (s - 32) : (n & 0x7F) >> (32 - s)
|
|
99
|
+
high |= s > 32 ? (n & 0x7F) << (s - 32) : (n & 0x7F) >> (32 - s)
|
|
101
100
|
}
|
|
102
101
|
s += 7
|
|
103
102
|
}
|
|
@@ -20,11 +20,12 @@ const on = (level, ...args) => {
|
|
|
20
20
|
const off = () => {}
|
|
21
21
|
|
|
22
22
|
const threshold = LEVELS.indexOf(logLevel)
|
|
23
|
+
const isEnabled = debug && typeof logPort?.postMessage === 'function'
|
|
23
24
|
|
|
24
25
|
/** @type {Logger} */
|
|
25
26
|
module.exports = Object.fromEntries(
|
|
26
27
|
LEVELS.map(level => [
|
|
27
28
|
level,
|
|
28
|
-
|
|
29
|
+
isEnabled && threshold >= LEVELS.indexOf(level) ? on.bind(null, level) : off,
|
|
29
30
|
])
|
|
30
31
|
)
|
|
@@ -36,10 +36,7 @@ function getRemoveProbeExpression (id) {
|
|
|
36
36
|
* @returns {string}
|
|
37
37
|
*/
|
|
38
38
|
function compileBreakpointCondition (probes) {
|
|
39
|
-
const probeConditions =
|
|
40
|
-
for (const probe of probes) {
|
|
41
|
-
probeConditions.push(compileProbeCondition(probe))
|
|
42
|
-
}
|
|
39
|
+
const probeConditions = probes.map(compileProbeCondition)
|
|
43
40
|
|
|
44
41
|
// NOTE: $dd_sampler is read from the realm-local `globalThis` where it was installed (the main
|
|
45
42
|
// realm). A probe whose code runs in a different V8 realm (e.g. a `vm.createContext` script with a
|
|
@@ -67,14 +67,13 @@ function send (message, logger, dd, snapshot, processTags) {
|
|
|
67
67
|
|
|
68
68
|
if (pruned) {
|
|
69
69
|
json = pruned
|
|
70
|
-
size = Buffer.byteLength(json)
|
|
71
70
|
} else {
|
|
72
71
|
// Fallback if pruning fails
|
|
73
72
|
const line = Object.keys(snapshot.captures.lines)[0]
|
|
74
73
|
snapshot.captures.lines[line] = { pruned: true }
|
|
75
74
|
json = JSON.stringify(payload)
|
|
76
|
-
size = Buffer.byteLength(json)
|
|
77
75
|
}
|
|
76
|
+
size = Buffer.byteLength(json)
|
|
78
77
|
}
|
|
79
78
|
|
|
80
79
|
jsonBuffer.write(json, size)
|
|
@@ -61,7 +61,7 @@ async function getLocalStateForCallFrame (callFrame, limits, deadlineNs = BIGINT
|
|
|
61
61
|
// Delay calling `processRawState` so caller can resume the main thread before processing `rawState`
|
|
62
62
|
return {
|
|
63
63
|
processLocalState () {
|
|
64
|
-
processedState
|
|
64
|
+
processedState ??= processRawState(rawState, maxLength)
|
|
65
65
|
return processedState
|
|
66
66
|
},
|
|
67
67
|
fatalErrors: ctx.fatalErrors,
|
|
@@ -155,7 +155,7 @@ async function evaluateCaptureExpressions (callFrame, expressions, deadlineNs =
|
|
|
155
155
|
fatalErrors.push(...ctx.fatalErrors)
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
if (ctx.deadlineReached
|
|
158
|
+
if (ctx.deadlineReached) {
|
|
159
159
|
// Add the current expression (properties may be incomplete due to timeout)
|
|
160
160
|
rawResults.push({ name, remoteObject: result, maxLength })
|
|
161
161
|
// Add stub entries for remaining uncaptured expressions
|
|
@@ -97,10 +97,24 @@ const REDACTED_IDENTIFIERS = new Set(
|
|
|
97
97
|
'XSRF-TOKEN',
|
|
98
98
|
...config.dynamicInstrumentation.redactedIdentifiers,
|
|
99
99
|
]
|
|
100
|
-
.map(
|
|
101
|
-
.filter(
|
|
100
|
+
.map(normalizeIdentifier)
|
|
101
|
+
.filter(isIncludedIdentifier)
|
|
102
102
|
)
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* @param {string} name
|
|
106
|
+
*/
|
|
107
|
+
function normalizeIdentifier (name) {
|
|
108
|
+
return normalizeName(name)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {string} name
|
|
113
|
+
*/
|
|
114
|
+
function isIncludedIdentifier (name) {
|
|
115
|
+
return !excludedIdentifiers.has(name)
|
|
116
|
+
}
|
|
117
|
+
|
|
104
118
|
function normalizeName (name, isSymbol) {
|
|
105
119
|
if (isSymbol) name = name.slice(7, -1) // Remove `Symbol(` and `)`
|
|
106
120
|
return name.toLowerCase().replaceAll(/[-_@$.]/g, '')
|
|
@@ -31,7 +31,7 @@ class SpanStatsEncoder extends AgentEncoder {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
_encodeStat (bytes, stat) {
|
|
34
|
-
bytes.writeMapPrefix(
|
|
34
|
+
bytes.writeMapPrefix(17)
|
|
35
35
|
|
|
36
36
|
this._encodeString(bytes, 'Service')
|
|
37
37
|
const service = stat.Service || DEFAULT_SERVICE_NAME
|
|
@@ -79,6 +79,12 @@ class SpanStatsEncoder extends AgentEncoder {
|
|
|
79
79
|
|
|
80
80
|
this._encodeString(bytes, 'srv_src')
|
|
81
81
|
this._encodeString(bytes, stat.srv_src || '')
|
|
82
|
+
|
|
83
|
+
this._encodeString(bytes, 'SpanKind')
|
|
84
|
+
this._encodeString(bytes, stat.SpanKind || '')
|
|
85
|
+
|
|
86
|
+
this._encodeString(bytes, 'GRPCStatusCode')
|
|
87
|
+
this._encodeString(bytes, stat.GRPCStatusCode || '')
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
_encodeBucket (bytes, bucket) {
|
|
@@ -60,11 +60,11 @@ function eventTimeNano (event) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
function normalizeSpan (span) {
|
|
63
|
-
span.service
|
|
63
|
+
span.service ||= DEFAULT_SERVICE_NAME
|
|
64
64
|
if (span.service.length > MAX_SERVICE_LENGTH) {
|
|
65
65
|
span.service = span.service.slice(0, MAX_SERVICE_LENGTH)
|
|
66
66
|
}
|
|
67
|
-
span.name
|
|
67
|
+
span.name ||= DEFAULT_SPAN_NAME
|
|
68
68
|
if (span.name.length > MAX_NAME_LENGTH) {
|
|
69
69
|
span.name = span.name.slice(0, MAX_NAME_LENGTH)
|
|
70
70
|
}
|
|
@@ -4,6 +4,7 @@ const fs = require('fs')
|
|
|
4
4
|
const exporters = require('../../../ext/exporters')
|
|
5
5
|
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
|
|
6
6
|
const constants = require('./constants')
|
|
7
|
+
const { isTrue } = require('./util')
|
|
7
8
|
|
|
8
9
|
module.exports = function getExporter (name) {
|
|
9
10
|
switch (name) {
|
|
@@ -20,20 +21,26 @@ module.exports = function getExporter (name) {
|
|
|
20
21
|
case exporters.AGENT_PROXY:
|
|
21
22
|
return require('./ci-visibility/exporters/agent-proxy')
|
|
22
23
|
case exporters.CI_VALIDATION:
|
|
23
|
-
return require('./ci-visibility/exporters/ci-validation')
|
|
24
|
+
if (hasCiValidationEnvironment()) return require('./ci-visibility/exporters/ci-validation')
|
|
25
|
+
break
|
|
24
26
|
case exporters.JEST_WORKER:
|
|
25
27
|
case exporters.CUCUMBER_WORKER:
|
|
26
28
|
case exporters.MOCHA_WORKER:
|
|
27
29
|
case exporters.PLAYWRIGHT_WORKER:
|
|
28
30
|
case exporters.VITEST_WORKER:
|
|
29
31
|
return require('./ci-visibility/exporters/test-worker')
|
|
30
|
-
default: {
|
|
31
|
-
const inAWSLambda = getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') !== undefined
|
|
32
|
-
const usingAgent = inAWSLambda && (
|
|
33
|
-
fs.existsSync(constants.DATADOG_LAMBDA_EXTENSION_PATH) ||
|
|
34
|
-
fs.existsSync(constants.DATADOG_MINI_AGENT_PATH)
|
|
35
|
-
)
|
|
36
|
-
return inAWSLambda && !usingAgent ? require('./exporters/log') : require('./exporters/agent')
|
|
37
|
-
}
|
|
38
32
|
}
|
|
33
|
+
|
|
34
|
+
const inAWSLambda = getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') !== undefined
|
|
35
|
+
const usingAgent = inAWSLambda && (
|
|
36
|
+
fs.existsSync(constants.DATADOG_LAMBDA_EXTENSION_PATH) ||
|
|
37
|
+
fs.existsSync(constants.DATADOG_MINI_AGENT_PATH)
|
|
38
|
+
)
|
|
39
|
+
return inAWSLambda && !usingAgent ? require('./exporters/log') : require('./exporters/agent')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function hasCiValidationEnvironment () {
|
|
43
|
+
return isTrue(getEnvironmentVariable('_DD_TEST_OPTIMIZATION_VALIDATION_MODE')) &&
|
|
44
|
+
getEnvironmentVariable('_DD_TEST_OPTIMIZATION_VALIDATION_MANIFEST_FILE') &&
|
|
45
|
+
getEnvironmentVariable('_DD_TEST_OPTIMIZATION_VALIDATION_OUTPUT_DIR')
|
|
39
46
|
}
|