dd-trace 6.8.0 → 6.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ci/diagnose.js +27 -25
- package/ci/init.js +6 -6
- package/ci/runbook.md +114 -20
- package/ci/test-optimization-validation/approval-artifacts.js +36 -3
- package/ci/test-optimization-validation/approval.js +78 -22
- package/ci/test-optimization-validation/blocker-category.js +24 -0
- package/ci/test-optimization-validation/ci-discovery.js +23 -17
- package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
- package/ci/test-optimization-validation/ci-remediation.js +1 -1
- package/ci/test-optimization-validation/cli.js +280 -52
- package/ci/test-optimization-validation/command-blocker.js +159 -20
- package/ci/test-optimization-validation/command-output-policy.js +9 -3
- package/ci/test-optimization-validation/command-runner.js +9 -7
- package/ci/test-optimization-validation/environment.js +4 -2
- package/ci/test-optimization-validation/executable.js +15 -13
- package/ci/test-optimization-validation/execution-lock.js +70 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
- package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
- package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
- package/ci/test-optimization-validation/generated-files.js +38 -28
- package/ci/test-optimization-validation/generated-test-contract.js +8 -4
- package/ci/test-optimization-validation/generated-verifier.js +24 -17
- package/ci/test-optimization-validation/literal-glob.js +52 -0
- package/ci/test-optimization-validation/manifest-loader.js +3 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +300 -50
- package/ci/test-optimization-validation/manifest-schema.js +80 -17
- package/ci/test-optimization-validation/offline-fixtures.js +13 -4
- package/ci/test-optimization-validation/package-check.js +94 -0
- package/ci/test-optimization-validation/plan-writer.js +183 -10
- package/ci/test-optimization-validation/preflight-runner.js +110 -31
- package/ci/test-optimization-validation/project-build-artifact.js +31 -0
- package/ci/test-optimization-validation/redaction.js +18 -27
- package/ci/test-optimization-validation/report-writer.js +182 -48
- package/ci/test-optimization-validation/result-semantics.js +20 -3
- package/ci/test-optimization-validation/runner-command.js +40 -20
- package/ci/test-optimization-validation/runner-contract.js +79 -43
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +59 -5
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
- package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
- package/ci/test-optimization-validation/static-diagnosis.js +10 -3
- package/ci/test-optimization-validation/test-output.js +2 -1
- package/ci/test-optimization-validation/validation-blocker.js +21 -0
- package/ci/vitest-no-worker-init-setup.mjs +140 -42
- package/index.d.ts +140 -1
- package/init.js +1 -17
- package/initialize.mjs +11 -0
- package/loader-hook.mjs +6 -4
- package/package.json +8 -5
- package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
- package/packages/datadog-esbuild/src/utils.js +16 -1
- package/packages/datadog-instrumentations/src/ai.js +61 -34
- package/packages/datadog-instrumentations/src/bluebird.js +6 -6
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +81 -5
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +111 -6
- package/packages/datadog-instrumentations/src/cucumber.js +124 -47
- package/packages/datadog-instrumentations/src/dns.js +21 -2
- package/packages/datadog-instrumentations/src/electron.js +1 -0
- package/packages/datadog-instrumentations/src/fastify.js +3 -1
- package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +629 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +34 -9
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +199 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +62 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +83 -1
- package/packages/datadog-instrumentations/src/helpers/router-helper.js +37 -6
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +980 -234
- package/packages/datadog-instrumentations/src/mocha/main.js +108 -10
- package/packages/datadog-instrumentations/src/mocha/utils.js +66 -50
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +25 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +12 -18
- package/packages/datadog-instrumentations/src/mysql.js +46 -16
- package/packages/datadog-instrumentations/src/mysql2.js +119 -18
- package/packages/datadog-instrumentations/src/next.js +155 -23
- package/packages/datadog-instrumentations/src/openai.js +14 -0
- package/packages/datadog-instrumentations/src/path-to-regexp.js +67 -1
- package/packages/datadog-instrumentations/src/pg.js +209 -11
- package/packages/datadog-instrumentations/src/playwright.js +173 -79
- package/packages/datadog-instrumentations/src/promise-js.js +4 -4
- package/packages/datadog-instrumentations/src/promise.js +3 -3
- package/packages/datadog-instrumentations/src/router.js +195 -19
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +85 -13
- package/packages/datadog-instrumentations/src/vitest-main.js +528 -72
- package/packages/datadog-instrumentations/src/vitest-util.js +106 -12
- package/packages/datadog-instrumentations/src/vitest-worker.js +382 -40
- package/packages/datadog-instrumentations/src/webdriverio.js +212 -22
- package/packages/datadog-instrumentations/src/when.js +3 -3
- package/packages/datadog-instrumentations/src/ws.js +5 -1
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +12 -6
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -5
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -5
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -3
- package/packages/datadog-plugin-cucumber/src/index.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +51 -47
- package/packages/datadog-plugin-cypress/src/support.js +7 -4
- package/packages/datadog-plugin-electron/src/net.js +10 -4
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +31 -17
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +6 -22
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +5 -3
- package/packages/datadog-plugin-kafkajs/src/utils.js +65 -7
- package/packages/datadog-plugin-mocha/src/index.js +832 -4
- package/packages/datadog-plugin-mysql/src/index.js +37 -0
- package/packages/datadog-plugin-next/src/index.js +51 -21
- package/packages/datadog-plugin-openai/src/tracing.js +4 -0
- package/packages/datadog-plugin-openai-agents/src/integration.js +278 -69
- package/packages/datadog-plugin-openai-agents/src/processor.js +16 -4
- package/packages/datadog-plugin-pg/src/index.js +66 -1
- package/packages/datadog-plugin-playwright/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +103 -27
- package/packages/datadog-plugin-ws/src/util.js +2 -1
- package/packages/datadog-shimmer/src/shimmer.js +6 -2
- package/packages/dd-trace/src/aiguard/sdk.js +3 -0
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +453 -0
- package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
- package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +228 -0
- package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
- package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
- package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +48 -476
- package/packages/dd-trace/src/appsec/sdk/track_event.js +9 -0
- package/packages/dd-trace/src/carrier.js +356 -0
- package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
- package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +27 -13
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +17 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +21 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +1 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
- package/packages/dd-trace/src/config/generated-config-types.d.ts +5 -0
- package/packages/dd-trace/src/config/helper.js +2 -0
- package/packages/dd-trace/src/config/index.js +16 -5
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +18 -0
- package/packages/dd-trace/src/datastreams/context.js +6 -1
- package/packages/dd-trace/src/datastreams/manager.js +5 -1
- package/packages/dd-trace/src/datastreams/pathway.js +23 -22
- package/packages/dd-trace/src/datastreams/processor.js +3 -2
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
- package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
- package/packages/dd-trace/src/guardrails/log.js +1 -10
- package/packages/dd-trace/src/llmobs/constants/tags.js +5 -0
- package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
- package/packages/dd-trace/src/llmobs/experiments/index.js +33 -25
- package/packages/dd-trace/src/llmobs/experiments/util.js +4 -2
- package/packages/dd-trace/src/llmobs/index.js +34 -2
- package/packages/dd-trace/src/llmobs/noop.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +149 -68
- package/packages/dd-trace/src/llmobs/span_processor.js +16 -0
- package/packages/dd-trace/src/llmobs/tagger.js +96 -0
- package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
- package/packages/dd-trace/src/llmobs/util.js +78 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
- package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
- package/packages/dd-trace/src/log/channels.js +1 -9
- package/packages/dd-trace/src/log/levels.js +12 -0
- package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -1
- package/packages/dd-trace/src/opentelemetry/span.js +4 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +126 -120
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +4 -8
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +21 -5
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +6 -0
- package/packages/dd-trace/src/plugins/util/git.js +6 -4
- package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +2 -2
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
- package/packages/{datadog-plugin-jest/src/util.js → dd-trace/src/plugins/util/jest.js} +3 -62
- package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
- package/packages/dd-trace/src/plugins/util/test.js +397 -74
- package/packages/dd-trace/src/plugins/util/url.js +1 -1
- package/packages/dd-trace/src/plugins/util/web.js +76 -3
- package/packages/dd-trace/src/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
- package/packages/dd-trace/src/proxy.js +1 -0
- package/packages/dd-trace/src/ritm.js +5 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
- package/packages/dd-trace/src/sampling_rule.js +4 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
- package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
- package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
- package/vendor/dist/pprof-format/index.js +1 -1
- package/version.js +10 -8
- /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
|
@@ -5,12 +5,17 @@ const {
|
|
|
5
5
|
JEST_WORKER_TRACE_PAYLOAD_CODE,
|
|
6
6
|
JEST_WORKER_TELEMETRY_PAYLOAD_CODE,
|
|
7
7
|
CUCUMBER_WORKER_TRACE_PAYLOAD_CODE,
|
|
8
|
+
CUCUMBER_WORKER_TELEMETRY_PAYLOAD_CODE,
|
|
8
9
|
MOCHA_WORKER_LOGS_PAYLOAD_CODE,
|
|
10
|
+
MOCHA_WORKER_TELEMETRY_PAYLOAD_CODE,
|
|
9
11
|
MOCHA_WORKER_TRACE_PAYLOAD_CODE,
|
|
10
12
|
JEST_WORKER_LOGS_PAYLOAD_CODE,
|
|
13
|
+
PLAYWRIGHT_WORKER_TELEMETRY_PAYLOAD_CODE,
|
|
11
14
|
PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE,
|
|
12
15
|
VITEST_WORKER_TRACE_PAYLOAD_CODE,
|
|
16
|
+
VITEST_WORKER_COVERAGE_PAYLOAD_CODE,
|
|
13
17
|
VITEST_WORKER_LOGS_PAYLOAD_CODE,
|
|
18
|
+
VITEST_WORKER_TELEMETRY_PAYLOAD_CODE,
|
|
14
19
|
} = require('../../../plugins/util/test')
|
|
15
20
|
const getConfig = require('../../../config')
|
|
16
21
|
const { getEnvironmentVariable } = require('../../../config/helper')
|
|
@@ -44,6 +49,9 @@ function getInterprocessCoverageCode () {
|
|
|
44
49
|
if (getEnvironmentVariable('JEST_WORKER_ID')) {
|
|
45
50
|
return JEST_WORKER_COVERAGE_PAYLOAD_CODE
|
|
46
51
|
}
|
|
52
|
+
if (getEnvironmentVariable('TINYPOOL_WORKER_ID') || getConfig().DD_VITEST_WORKER) {
|
|
53
|
+
return VITEST_WORKER_COVERAGE_PAYLOAD_CODE
|
|
54
|
+
}
|
|
47
55
|
return null
|
|
48
56
|
}
|
|
49
57
|
|
|
@@ -67,6 +75,19 @@ function getInterprocessTelemetryCode () {
|
|
|
67
75
|
if (getEnvironmentVariable('JEST_WORKER_ID')) {
|
|
68
76
|
return JEST_WORKER_TELEMETRY_PAYLOAD_CODE
|
|
69
77
|
}
|
|
78
|
+
if (getEnvironmentVariable('CUCUMBER_WORKER_ID')) {
|
|
79
|
+
return CUCUMBER_WORKER_TELEMETRY_PAYLOAD_CODE
|
|
80
|
+
}
|
|
81
|
+
if (getEnvironmentVariable('MOCHA_WORKER_ID')) {
|
|
82
|
+
return MOCHA_WORKER_TELEMETRY_PAYLOAD_CODE
|
|
83
|
+
}
|
|
84
|
+
const { DD_PLAYWRIGHT_WORKER, DD_VITEST_WORKER } = getConfig()
|
|
85
|
+
if (DD_PLAYWRIGHT_WORKER) {
|
|
86
|
+
return PLAYWRIGHT_WORKER_TELEMETRY_PAYLOAD_CODE
|
|
87
|
+
}
|
|
88
|
+
if (getEnvironmentVariable('TINYPOOL_WORKER_ID') || DD_VITEST_WORKER) {
|
|
89
|
+
return VITEST_WORKER_TELEMETRY_PAYLOAD_CODE
|
|
90
|
+
}
|
|
70
91
|
return null
|
|
71
92
|
}
|
|
72
93
|
|
|
@@ -85,7 +106,6 @@ class TestWorkerCiVisibilityExporter {
|
|
|
85
106
|
this._writer = new Writer(interprocessTraceCode)
|
|
86
107
|
this._coverageWriter = new Writer(interprocessCoverageCode)
|
|
87
108
|
this._logsWriter = new Writer(interprocessLogsCode)
|
|
88
|
-
// TODO: add support for test workers other than Jest
|
|
89
109
|
if (interprocessTelemetryCode) {
|
|
90
110
|
this._telemetryWriter = new Writer(interprocessTelemetryCode)
|
|
91
111
|
this.exportTelemetry = function (telemetryEvent) {
|
|
@@ -25,6 +25,7 @@ function parseSkippableSuitesResponse (
|
|
|
25
25
|
{
|
|
26
26
|
testLevel = 'suite',
|
|
27
27
|
isCoverageReportUploadEnabled = false,
|
|
28
|
+
isLineCoverageSupported = true,
|
|
28
29
|
validateRequiredFields = false,
|
|
29
30
|
validationMode = false,
|
|
30
31
|
} = {}
|
|
@@ -34,8 +35,11 @@ function parseSkippableSuitesResponse (
|
|
|
34
35
|
validateSkippableTestsResponse(parsedResponse, { validationMode })
|
|
35
36
|
}
|
|
36
37
|
const coverage = {}
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
const coverageByFilename = parsedResponse.meta?.coverage
|
|
39
|
+
if (coverageByFilename) {
|
|
40
|
+
for (const [filename, bitmap] of Object.entries(coverageByFilename)) {
|
|
41
|
+
coverage[filename.replaceAll('\\', '/')] = bitmap
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
const skippableItems = parsedResponse
|
|
@@ -51,7 +55,7 @@ function parseSkippableSuitesResponse (
|
|
|
51
55
|
},
|
|
52
56
|
} of skippableItems) {
|
|
53
57
|
// Only reject candidates without backend line coverage when we need that coverage to backfill reports.
|
|
54
|
-
if (isCoverageReportUploadEnabled && isMissingLineCodeCoverage) {
|
|
58
|
+
if (isCoverageReportUploadEnabled && isLineCoverageSupported && isMissingLineCodeCoverage) {
|
|
55
59
|
numExcludedByMissingLineCoverage++
|
|
56
60
|
continue
|
|
57
61
|
}
|
|
@@ -78,10 +82,11 @@ function parseSkippableSuitesResponse (
|
|
|
78
82
|
* numExcludedByMissingLineCoverage?: number
|
|
79
83
|
* }} result - Parsed skippable response.
|
|
80
84
|
* @param {'suite'|'test'} testLevel - Test optimization skipping level.
|
|
85
|
+
* @param {boolean} shouldConsiderLineCoverage - Whether line coverage can affect suite skipping.
|
|
81
86
|
* @returns {void}
|
|
82
87
|
*/
|
|
83
|
-
function logSkippableSuitesResponse (result, testLevel) {
|
|
84
|
-
if (result.numReceivedSkippableItems === undefined) {
|
|
88
|
+
function logSkippableSuitesResponse (result, testLevel, shouldConsiderLineCoverage) {
|
|
89
|
+
if (!shouldConsiderLineCoverage || result.numReceivedSkippableItems === undefined) {
|
|
85
90
|
log.debug('Number of received skippable %ss: %d', testLevel, result.skippableSuites.length)
|
|
86
91
|
return
|
|
87
92
|
}
|
|
@@ -122,10 +127,12 @@ function getSkippableSuites ({
|
|
|
122
127
|
custom,
|
|
123
128
|
testLevel = 'suite',
|
|
124
129
|
isCoverageReportUploadEnabled = false,
|
|
130
|
+
isLineCoverageSupported = true,
|
|
125
131
|
}, done) {
|
|
132
|
+
const shouldConsiderLineCoverage = isCoverageReportUploadEnabled && isLineCoverageSupported
|
|
126
133
|
const cacheKey = buildCacheKey('skippable', [
|
|
127
134
|
sha, service, env, repositoryUrl, osPlatform, osVersion, osArchitecture,
|
|
128
|
-
runtimeName, runtimeVersion, testLevel, custom,
|
|
135
|
+
runtimeName, runtimeVersion, testLevel, custom, shouldConsiderLineCoverage,
|
|
129
136
|
])
|
|
130
137
|
|
|
131
138
|
withCache(cacheKey, (activeCacheKey, cb) => {
|
|
@@ -146,11 +153,16 @@ function getSkippableSuites ({
|
|
|
146
153
|
custom,
|
|
147
154
|
testLevel,
|
|
148
155
|
isCoverageReportUploadEnabled,
|
|
156
|
+
isLineCoverageSupported,
|
|
149
157
|
cacheKey: activeCacheKey,
|
|
150
158
|
}, cb)
|
|
151
159
|
}, (err, data) => {
|
|
152
160
|
if (err) return done(err)
|
|
153
|
-
logSkippableSuitesResponse(
|
|
161
|
+
logSkippableSuitesResponse(
|
|
162
|
+
data,
|
|
163
|
+
testLevel,
|
|
164
|
+
shouldConsiderLineCoverage
|
|
165
|
+
)
|
|
154
166
|
done(null, data.skippableSuites, data.correlationId, data.coverage)
|
|
155
167
|
})
|
|
156
168
|
}
|
|
@@ -175,6 +187,7 @@ function getSkippableSuites ({
|
|
|
175
187
|
* @param {object} [params.custom]
|
|
176
188
|
* @param {string} [params.testLevel]
|
|
177
189
|
* @param {boolean} [params.isCoverageReportUploadEnabled]
|
|
190
|
+
* @param {boolean} [params.isLineCoverageSupported]
|
|
178
191
|
* @param {string | null} params.cacheKey
|
|
179
192
|
* @param {Function} done
|
|
180
193
|
*/
|
|
@@ -195,6 +208,7 @@ function fetchFromApi ({
|
|
|
195
208
|
custom,
|
|
196
209
|
testLevel,
|
|
197
210
|
isCoverageReportUploadEnabled,
|
|
211
|
+
isLineCoverageSupported,
|
|
198
212
|
cacheKey,
|
|
199
213
|
}, done) {
|
|
200
214
|
const options = {
|
|
@@ -258,6 +272,7 @@ function fetchFromApi ({
|
|
|
258
272
|
const result = parseSkippableSuitesResponse(parsedResponse, {
|
|
259
273
|
testLevel,
|
|
260
274
|
isCoverageReportUploadEnabled,
|
|
275
|
+
isLineCoverageSupported,
|
|
261
276
|
validateRequiredFields: true,
|
|
262
277
|
})
|
|
263
278
|
const skippableItems = parsedResponse.data.filter(({ type }) => type === testLevel)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const getConfig = require('../../config')
|
|
4
4
|
const id = require('../../id')
|
|
5
5
|
const log = require('../../log')
|
|
6
|
+
const { EARLY_FLAKE_DETECTION_RETRY_BUCKETS, createEfdRetryPolicy } = require('../efd-retry-policy')
|
|
6
7
|
const {
|
|
7
8
|
incrementCountMetric,
|
|
8
9
|
distributionMetric,
|
|
@@ -15,21 +16,20 @@ const { writeSettingsToCache } = require('../test-optimization-cache')
|
|
|
15
16
|
const { MAX_RETRIES, validateSettingsResponse } = require('../test-optimization-http-cache-schema')
|
|
16
17
|
const request = require('./request')
|
|
17
18
|
|
|
18
|
-
const DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES = 2
|
|
19
19
|
const DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES = Object.freeze({
|
|
20
20
|
'5s': 10,
|
|
21
21
|
'10s': 5,
|
|
22
22
|
'30s': 3,
|
|
23
23
|
'5m': 2,
|
|
24
24
|
})
|
|
25
|
+
const DEFAULT_EARLY_FLAKE_DETECTION_RETRY_POLICY =
|
|
26
|
+
createEfdRetryPolicy(DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES)
|
|
25
27
|
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
|
|
|
28
29
|
/**
|
|
29
30
|
* @typedef {object} EarlyFlakeDetectionSettings
|
|
30
31
|
* @property {boolean} enabled
|
|
31
|
-
* @property {
|
|
32
|
-
* @property {Readonly<Record<string, number>>} slowTestRetries
|
|
32
|
+
* @property {import('../efd-retry-policy').EfdRetryPolicy} retryPolicy
|
|
33
33
|
* @property {number} faultyThreshold
|
|
34
34
|
*/
|
|
35
35
|
|
|
@@ -90,20 +90,17 @@ function parseEarlyFlakeDetectionSettings (value, isKnownTestsEnabled) {
|
|
|
90
90
|
if (!isRecord(value) || value.enabled !== true) {
|
|
91
91
|
return {
|
|
92
92
|
enabled: false,
|
|
93
|
-
|
|
94
|
-
slowTestRetries: DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES,
|
|
93
|
+
retryPolicy: DEFAULT_EARLY_FLAKE_DETECTION_RETRY_POLICY,
|
|
95
94
|
faultyThreshold: DEFAULT_EARLY_FLAKE_DETECTION_ERROR_THRESHOLD,
|
|
96
95
|
}
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
let isValid = true
|
|
100
|
-
let
|
|
101
|
-
let slowTestRetries = DEFAULT_EARLY_FLAKE_DETECTION_SLOW_TEST_RETRIES
|
|
99
|
+
let retryPolicy = DEFAULT_EARLY_FLAKE_DETECTION_RETRY_POLICY
|
|
102
100
|
if (Object.hasOwn(value, 'slow_test_retries')) {
|
|
103
101
|
const parsedSlowTestRetries = parseSlowTestRetries(value.slow_test_retries)
|
|
104
102
|
if (parsedSlowTestRetries) {
|
|
105
|
-
|
|
106
|
-
numRetries = parsedSlowTestRetries['5s'] ?? DEFAULT_EARLY_FLAKE_DETECTION_NUM_RETRIES
|
|
103
|
+
retryPolicy = createEfdRetryPolicy(parsedSlowTestRetries)
|
|
107
104
|
} else {
|
|
108
105
|
isValid = false
|
|
109
106
|
}
|
|
@@ -120,8 +117,7 @@ function parseEarlyFlakeDetectionSettings (value, isKnownTestsEnabled) {
|
|
|
120
117
|
|
|
121
118
|
return {
|
|
122
119
|
enabled: isKnownTestsEnabled && isValid,
|
|
123
|
-
|
|
124
|
-
slowTestRetries,
|
|
120
|
+
retryPolicy,
|
|
125
121
|
faultyThreshold,
|
|
126
122
|
}
|
|
127
123
|
}
|
|
@@ -180,8 +176,7 @@ function parseLibraryConfigurationResponse (rawJson, config = getConfig(), optio
|
|
|
180
176
|
isItrEnabled: attributes.itr_enabled === true,
|
|
181
177
|
requireGit: attributes.require_git === true,
|
|
182
178
|
isEarlyFlakeDetectionEnabled: earlyFlakeDetection.enabled,
|
|
183
|
-
|
|
184
|
-
earlyFlakeDetectionSlowTestRetries: earlyFlakeDetection.slowTestRetries,
|
|
179
|
+
earlyFlakeDetectionRetryPolicy: earlyFlakeDetection.retryPolicy,
|
|
185
180
|
earlyFlakeDetectionFaultyThreshold: earlyFlakeDetection.faultyThreshold,
|
|
186
181
|
isFlakyTestRetriesEnabled,
|
|
187
182
|
isDiEnabled: attributes.di_enabled === true && isFlakyTestRetriesEnabled,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { readFileSync } = require('node:fs')
|
|
3
|
+
const { closeSync, constants, fstatSync, openSync, readFileSync } = require('node:fs')
|
|
4
4
|
const { gzipSync } = require('node:zlib')
|
|
5
5
|
|
|
6
6
|
const getConfig = require('../../config')
|
|
@@ -17,12 +17,18 @@ const {
|
|
|
17
17
|
} = require('../telemetry')
|
|
18
18
|
|
|
19
19
|
const UPLOAD_TIMEOUT_MS = 30_000
|
|
20
|
+
const COVERAGE_FILE_OPEN_FLAGS = constants.O_RDONLY |
|
|
21
|
+
(constants.O_NOFOLLOW || 0) |
|
|
22
|
+
constants.O_NONBLOCK
|
|
23
|
+
const BIGINT_STAT_OPTIONS = { bigint: true }
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* Uploads a single coverage report to the Datadog CI intake.
|
|
23
27
|
* One file per request with field names 'coverage' and 'event'.
|
|
24
28
|
* @param {object} options - Upload options
|
|
25
29
|
* @param {string} options.filePath - Path to the coverage report file
|
|
30
|
+
* @param {bigint} options.fileDevice - Device containing the discovered report
|
|
31
|
+
* @param {bigint} options.fileInode - Inode of the discovered report
|
|
26
32
|
* @param {string} options.format - Format of the coverage report (e.g., 'lcov', 'cobertura')
|
|
27
33
|
* @param {string[]} [options.flags] - Optional coverage report grouping flags
|
|
28
34
|
* @param {object} options.testEnvironmentMetadata - Test environment metadata containing git/CI tags
|
|
@@ -32,7 +38,7 @@ const UPLOAD_TIMEOUT_MS = 30_000
|
|
|
32
38
|
* @param {(error: Error|null) => void} callback - Callback function
|
|
33
39
|
*/
|
|
34
40
|
function uploadCoverageReport (
|
|
35
|
-
{ filePath, format, flags, testEnvironmentMetadata, url, isEvpProxy, evpProxyPrefix },
|
|
41
|
+
{ filePath, fileDevice, fileInode, format, flags, testEnvironmentMetadata, url, isEvpProxy, evpProxyPrefix },
|
|
36
42
|
callback
|
|
37
43
|
) {
|
|
38
44
|
const { DD_API_KEY } = getConfig()
|
|
@@ -43,10 +49,20 @@ function uploadCoverageReport (
|
|
|
43
49
|
|
|
44
50
|
let compressedCoverage
|
|
45
51
|
try {
|
|
46
|
-
const
|
|
52
|
+
const fileDescriptor = openSync(filePath, COVERAGE_FILE_OPEN_FLAGS)
|
|
53
|
+
let coverageContent
|
|
54
|
+
try {
|
|
55
|
+
const fileStats = fstatSync(fileDescriptor, BIGINT_STAT_OPTIONS)
|
|
56
|
+
if (!fileStats.isFile() || fileStats.dev !== fileDevice || fileStats.ino !== fileInode) {
|
|
57
|
+
throw new Error('Coverage report changed after discovery')
|
|
58
|
+
}
|
|
59
|
+
coverageContent = readFileSync(fileDescriptor)
|
|
60
|
+
} finally {
|
|
61
|
+
closeSync(fileDescriptor)
|
|
62
|
+
}
|
|
47
63
|
compressedCoverage = gzipSync(coverageContent)
|
|
48
|
-
} catch (
|
|
49
|
-
return callback(new Error(`Failed to read coverage report at ${filePath}: ${
|
|
64
|
+
} catch (error) {
|
|
65
|
+
return callback(new Error(`Failed to read coverage report at ${filePath}: ${error.message}`))
|
|
50
66
|
}
|
|
51
67
|
|
|
52
68
|
// Build the event payload with format, type, and all tags from test environment metadata
|
|
@@ -137,7 +137,7 @@ function validateSkippableTestsResponse (response, options = {}) {
|
|
|
137
137
|
if (response.meta !== undefined) {
|
|
138
138
|
assertObject(response.meta, 'Invalid skippable tests response: meta must be an object')
|
|
139
139
|
}
|
|
140
|
-
if (response.meta?.coverage !== undefined) {
|
|
140
|
+
if (response.meta?.coverage !== undefined && response.meta.coverage !== null) {
|
|
141
141
|
assertObject(response.meta.coverage, 'Invalid skippable tests response: meta.coverage must be an object')
|
|
142
142
|
}
|
|
143
143
|
if (response.meta?.correlation_id !== undefined && typeof response.meta.correlation_id !== 'string') {
|
|
@@ -145,7 +145,11 @@ class TestOptimizationHttpCache {
|
|
|
145
145
|
validationMode: Boolean(this._validationManifestPath),
|
|
146
146
|
})
|
|
147
147
|
const testLevel = options.testLevel || 'suite'
|
|
148
|
-
logSkippableSuitesResponse(
|
|
148
|
+
logSkippableSuitesResponse(
|
|
149
|
+
result,
|
|
150
|
+
testLevel,
|
|
151
|
+
options.isCoverageReportUploadEnabled && options.isLineCoverageSupported !== false
|
|
152
|
+
)
|
|
149
153
|
const skippableItems = parsedResponse.data.filter(({ type }) => type === testLevel)
|
|
150
154
|
incrementCountMetric(
|
|
151
155
|
testLevel === 'test'
|
|
@@ -272,6 +272,7 @@ export interface GeneratedConfig {
|
|
|
272
272
|
DD_TRACE_HAPI_HAPI_ENABLED: boolean;
|
|
273
273
|
DD_TRACE_HONO_ENABLED: boolean;
|
|
274
274
|
DD_TRACE_HTTP_ENABLED: boolean;
|
|
275
|
+
DD_TRACE_HTTP_SERVER_ERROR_STATUSES: string;
|
|
275
276
|
DD_TRACE_HTTP2_ENABLED: boolean;
|
|
276
277
|
DD_TRACE_HTTPS_ENABLED: boolean;
|
|
277
278
|
DD_TRACE_IOREDIS_ENABLED: boolean;
|
|
@@ -579,6 +580,7 @@ export interface GeneratedConfig {
|
|
|
579
580
|
DD_TEST_LOCAL_CONFIG_PATH: string | undefined;
|
|
580
581
|
DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES: number;
|
|
581
582
|
DD_TEST_MANAGEMENT_ENABLED: boolean;
|
|
583
|
+
DD_TEST_MANAGEMENT_REPORT_ENABLED: boolean | undefined;
|
|
582
584
|
};
|
|
583
585
|
traceId128BitGenerationEnabled: boolean;
|
|
584
586
|
traceId128BitLoggingEnabled: boolean;
|
|
@@ -726,6 +728,7 @@ export interface GeneratedEnvVarConfig {
|
|
|
726
728
|
DD_HEAP_SNAPSHOT_COUNT: number;
|
|
727
729
|
DD_HEAP_SNAPSHOT_DESTINATION: string;
|
|
728
730
|
DD_HEAP_SNAPSHOT_INTERVAL: number;
|
|
731
|
+
DD_HTTP_SERVER_ERROR_STATUSES: string;
|
|
729
732
|
DD_IAST_DB_ROWS_TO_TAINT: number;
|
|
730
733
|
DD_IAST_DEDUPLICATION_ENABLED: boolean;
|
|
731
734
|
DD_IAST_ENABLED: boolean;
|
|
@@ -821,6 +824,7 @@ export interface GeneratedEnvVarConfig {
|
|
|
821
824
|
DD_TEST_LOCAL_CONFIG_PATH: string | undefined;
|
|
822
825
|
DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES: number;
|
|
823
826
|
DD_TEST_MANAGEMENT_ENABLED: boolean;
|
|
827
|
+
DD_TEST_MANAGEMENT_REPORT_ENABLED: boolean | undefined;
|
|
824
828
|
DD_TEST_SESSION_NAME: string | undefined;
|
|
825
829
|
DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED: boolean;
|
|
826
830
|
DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED: boolean;
|
|
@@ -964,6 +968,7 @@ export interface GeneratedEnvVarConfig {
|
|
|
964
968
|
DD_TRACE_HEADER_TAGS: string[];
|
|
965
969
|
DD_TRACE_HONO_ENABLED: boolean;
|
|
966
970
|
DD_TRACE_HTTP_ENABLED: boolean;
|
|
971
|
+
DD_TRACE_HTTP_SERVER_ERROR_STATUSES: string;
|
|
967
972
|
DD_TRACE_HTTP2_ENABLED: boolean;
|
|
968
973
|
DD_TRACE_HTTPS_ENABLED: boolean;
|
|
969
974
|
DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED: boolean;
|
|
@@ -307,6 +307,8 @@ module.exports = {
|
|
|
307
307
|
*
|
|
308
308
|
* This should only be called once in config.js to avoid copying the object frequently.
|
|
309
309
|
*
|
|
310
|
+
* @param {typeof process.env} [source] The environment to read from
|
|
311
|
+
* @param {boolean} [internalOnly] Only return configurations marked as internal
|
|
310
312
|
* @returns {TracerEnv} The environment variables
|
|
311
313
|
*/
|
|
312
314
|
getEnvironmentVariables (source = process.env, internalOnly = false) {
|
|
@@ -4,6 +4,7 @@ const fs = require('node:fs')
|
|
|
4
4
|
const os = require('node:os')
|
|
5
5
|
const { URL, format } = require('node:url')
|
|
6
6
|
|
|
7
|
+
const exporters = require('../../../../ext/exporters')
|
|
7
8
|
const rfdc = require('../../../../vendor/dist/rfdc')({ proto: false, circles: false })
|
|
8
9
|
const uuid = require('../../../../vendor/dist/crypto-randomuuid') // we need to keep the old uuid dep because of cypress
|
|
9
10
|
const set = require('../../../datadog-core/src/utils/src/set')
|
|
@@ -41,6 +42,13 @@ const { normalizeService } = require('./normalize-service')
|
|
|
41
42
|
const { programmaticTypeCoercions, transformers } = require('./parsers')
|
|
42
43
|
|
|
43
44
|
const RUNTIME_ID = uuid()
|
|
45
|
+
const TEST_OPTIMIZATION_WORKER_EXPORTERS = new Set([
|
|
46
|
+
exporters.CUCUMBER_WORKER,
|
|
47
|
+
exporters.JEST_WORKER,
|
|
48
|
+
exporters.MOCHA_WORKER,
|
|
49
|
+
exporters.PLAYWRIGHT_WORKER,
|
|
50
|
+
exporters.VITEST_WORKER,
|
|
51
|
+
])
|
|
44
52
|
|
|
45
53
|
const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
|
|
46
54
|
|
|
@@ -194,8 +202,11 @@ class Config extends ConfigBase {
|
|
|
194
202
|
this.debug = log.configure(options)
|
|
195
203
|
|
|
196
204
|
// Process stable config warnings, if any
|
|
197
|
-
|
|
198
|
-
|
|
205
|
+
const stableConfigWarnings = this.stableConfig?.warnings
|
|
206
|
+
if (stableConfigWarnings) {
|
|
207
|
+
for (const warning of stableConfigWarnings) {
|
|
208
|
+
log.warn(warning)
|
|
209
|
+
}
|
|
199
210
|
}
|
|
200
211
|
|
|
201
212
|
this.#applyDefaults()
|
|
@@ -593,9 +604,9 @@ class Config extends ConfigBase {
|
|
|
593
604
|
setAndTrack(this, 'remoteConfig.DD_REMOTE_CONFIGURATION_ENABLED', false)
|
|
594
605
|
}
|
|
595
606
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
607
|
+
const isTestOptimizationWorker = this.isCiVisibility &&
|
|
608
|
+
TEST_OPTIMIZATION_WORKER_EXPORTERS.has(this.experimental.exporter)
|
|
609
|
+
if (isTestOptimizationWorker) {
|
|
599
610
|
setAndTrack(this, 'telemetry.DD_INSTRUMENTATION_TELEMETRY_ENABLED', false)
|
|
600
611
|
}
|
|
601
612
|
|
|
@@ -236,7 +236,7 @@ const optionLookupTable = {
|
|
|
236
236
|
|
|
237
237
|
const transformers = {
|
|
238
238
|
tracing_sampling_rules (samplingRules) {
|
|
239
|
-
for (const rule of
|
|
239
|
+
for (const rule of samplingRules) {
|
|
240
240
|
if (rule.tags) {
|
|
241
241
|
const reformattedTags = {}
|
|
242
242
|
for (const tag of rule.tags) {
|
|
@@ -1941,6 +1941,14 @@
|
|
|
1941
1941
|
"namespace": "testOptimization"
|
|
1942
1942
|
}
|
|
1943
1943
|
],
|
|
1944
|
+
"DD_TEST_MANAGEMENT_REPORT_ENABLED": [
|
|
1945
|
+
{
|
|
1946
|
+
"implementation": "A",
|
|
1947
|
+
"type": "boolean",
|
|
1948
|
+
"default": null,
|
|
1949
|
+
"namespace": "testOptimization"
|
|
1950
|
+
}
|
|
1951
|
+
],
|
|
1944
1952
|
"DD_TEST_SESSION_NAME": [
|
|
1945
1953
|
{
|
|
1946
1954
|
"implementation": "A",
|
|
@@ -2991,6 +2999,16 @@
|
|
|
2991
2999
|
"default": "true"
|
|
2992
3000
|
}
|
|
2993
3001
|
],
|
|
3002
|
+
"DD_TRACE_HTTP_SERVER_ERROR_STATUSES": [
|
|
3003
|
+
{
|
|
3004
|
+
"implementation": "A",
|
|
3005
|
+
"type": "string",
|
|
3006
|
+
"default": "500-599",
|
|
3007
|
+
"aliases": [
|
|
3008
|
+
"DD_HTTP_SERVER_ERROR_STATUSES"
|
|
3009
|
+
]
|
|
3010
|
+
}
|
|
3011
|
+
],
|
|
2994
3012
|
"DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED": [
|
|
2995
3013
|
{
|
|
2996
3014
|
"implementation": "A",
|
|
@@ -13,7 +13,12 @@ function getDataStreamsContext () {
|
|
|
13
13
|
function setDataStreamsContext (dataStreamsContext) {
|
|
14
14
|
log.debug('Setting new DSM Context: %j.', dataStreamsContext)
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// `undefined` clears: a message that carries no context must not inherit the previous message's.
|
|
17
|
+
// The identity check keeps the common no-context case from allocating a store per message.
|
|
18
|
+
const store = legacyStorage.getStore()
|
|
19
|
+
if (store?.dataStreamsContext !== dataStreamsContext) {
|
|
20
|
+
legacyStorage.enterWith({ ...store, dataStreamsContext })
|
|
21
|
+
}
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
module.exports = {
|
|
@@ -16,9 +16,13 @@ class DataStreamsManager {
|
|
|
16
16
|
return ctx
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @param {Record<string, string>|undefined} carrier Pass every message's carrier, including the
|
|
21
|
+
* ones without a context: that is what starts a new pathway instead of extending the previous
|
|
22
|
+
* message's.
|
|
23
|
+
*/
|
|
19
24
|
decodeDataStreamsContext (carrier) {
|
|
20
25
|
const ctx = DsmPathwayCodec.decode(carrier)
|
|
21
|
-
// we erase the previous context everytime we decode a new one
|
|
22
26
|
DataStreamsContext.setDataStreamsContext(ctx)
|
|
23
27
|
return ctx
|
|
24
28
|
}
|
|
@@ -5,23 +5,25 @@
|
|
|
5
5
|
// this inconsistency is ok because hashes do not need to be consistent across services
|
|
6
6
|
const crypto = require('crypto')
|
|
7
7
|
const { LRUCache } = require('../../../../vendor/dist/lru-cache')
|
|
8
|
+
const {
|
|
9
|
+
hasDsmBase64,
|
|
10
|
+
hasDsmBinary,
|
|
11
|
+
pickDsm,
|
|
12
|
+
readDsmBase64,
|
|
13
|
+
readDsmBinary,
|
|
14
|
+
writeDsmBase64,
|
|
15
|
+
} = require('../carrier')
|
|
8
16
|
const log = require('../log')
|
|
9
|
-
const pick = require('../../../datadog-core/src/utils/src/pick')
|
|
10
17
|
const { encodeVarintInto, decodeVarint } = require('./encoding')
|
|
11
18
|
|
|
12
19
|
const cache = new LRUCache({ max: 500 })
|
|
13
20
|
|
|
14
|
-
const CONTEXT_PROPAGATION_KEY = 'dd-pathway-ctx'
|
|
15
|
-
const CONTEXT_PROPAGATION_KEY_BASE64 = 'dd-pathway-ctx-base64'
|
|
16
|
-
|
|
17
21
|
const PATHWAY_CONTEXT_BYTES = 20
|
|
18
22
|
|
|
19
23
|
// Reused across `encodePathwayContext` calls; the buffer is fully rewritten before each
|
|
20
24
|
// `Buffer.from(...)` copy-out so callers never observe mutation between checkpoints.
|
|
21
25
|
const pathwayScratch = Buffer.allocUnsafe(PATHWAY_CONTEXT_BYTES)
|
|
22
26
|
|
|
23
|
-
const logKeys = [CONTEXT_PROPAGATION_KEY, CONTEXT_PROPAGATION_KEY_BASE64]
|
|
24
|
-
|
|
25
27
|
function shaHash (checkpointString) {
|
|
26
28
|
// Copy out of the 32-byte digest so the LRU cache doesn't retain it.
|
|
27
29
|
return Buffer.from(crypto.createHash('sha256').update(checkpointString).digest().subarray(0, 8))
|
|
@@ -114,7 +116,7 @@ function decodePathwayContext (pathwayContext) {
|
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
/**
|
|
117
|
-
* @param {string} pathwayContext
|
|
119
|
+
* @param {string | Buffer} pathwayContext
|
|
118
120
|
* @returns {ReturnType<typeof decodePathwayContext>|undefined}
|
|
119
121
|
*/
|
|
120
122
|
function decodePathwayContextBase64 (pathwayContext) {
|
|
@@ -142,10 +144,10 @@ const DsmPathwayCodec = {
|
|
|
142
144
|
encode (dataStreamsContext, carrier) {
|
|
143
145
|
if (!dataStreamsContext || !dataStreamsContext.hash) return
|
|
144
146
|
carrier ??= {}
|
|
145
|
-
carrier
|
|
147
|
+
writeDsmBase64(carrier, encodePathwayContextBase64(dataStreamsContext))
|
|
146
148
|
|
|
147
149
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
148
|
-
log.debug(() => `Injected into DSM carrier: ${JSON.stringify(
|
|
150
|
+
log.debug(() => `Injected into DSM carrier: ${JSON.stringify(pickDsm(carrier))}.`)
|
|
149
151
|
|
|
150
152
|
return carrier
|
|
151
153
|
},
|
|
@@ -155,25 +157,25 @@ const DsmPathwayCodec = {
|
|
|
155
157
|
* @returns {ReturnType<typeof decodePathwayContext>|undefined}
|
|
156
158
|
*/
|
|
157
159
|
decode (carrier) {
|
|
158
|
-
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
159
|
-
log.debug(() => `Attempting extract from DSM carrier: ${JSON.stringify(pick(carrier, logKeys))}.`)
|
|
160
|
-
|
|
161
160
|
if (carrier == null) return
|
|
162
161
|
|
|
162
|
+
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
163
|
+
log.debug(() => `Attempting extract from DSM carrier: ${JSON.stringify(pickDsm(carrier))}.`)
|
|
164
|
+
|
|
163
165
|
let ctx
|
|
164
|
-
if (
|
|
166
|
+
if (hasDsmBase64(carrier)) {
|
|
165
167
|
// decode v2 encoding of base64
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
const encoded = readDsmBase64(carrier)
|
|
169
|
+
if (encoded !== undefined) ctx = decodePathwayContextBase64(encoded)
|
|
170
|
+
} else if (hasDsmBinary(carrier)) {
|
|
171
|
+
const encoded = readDsmBinary(carrier)
|
|
172
|
+
if (Buffer.isBuffer(encoded)) {
|
|
169
173
|
// decode v1 encoding
|
|
170
|
-
ctx = decodePathwayContext(
|
|
171
|
-
} catch {
|
|
172
|
-
// pass
|
|
174
|
+
ctx = decodePathwayContext(encoded)
|
|
173
175
|
}
|
|
174
176
|
// cover case where base64 context was received under wrong key
|
|
175
|
-
if (!ctx &&
|
|
176
|
-
ctx = decodePathwayContextBase64(
|
|
177
|
+
if (!ctx && encoded !== undefined) {
|
|
178
|
+
ctx = decodePathwayContextBase64(encoded)
|
|
177
179
|
}
|
|
178
180
|
}
|
|
179
181
|
|
|
@@ -182,7 +184,6 @@ const DsmPathwayCodec = {
|
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
module.exports = {
|
|
185
|
-
CONTEXT_PROPAGATION_KEY_BASE64,
|
|
186
187
|
computePathwayHash: computeHash,
|
|
187
188
|
encodePathwayContext,
|
|
188
189
|
decodePathwayContext,
|
|
@@ -5,10 +5,11 @@ const pkg = require('../../../../package.json')
|
|
|
5
5
|
|
|
6
6
|
const { LogCollapsingLowestDenseDDSketch } = require('../../../../vendor/dist/@datadog/sketches-js')
|
|
7
7
|
const { PATHWAY_HASH, DSM_TRANSACTION_ID, DSM_TRANSACTION_CHECKPOINT } = require('../../../../ext/tags')
|
|
8
|
+
const { dsmBase64NameLength } = require('../carrier')
|
|
8
9
|
const log = require('../log')
|
|
9
10
|
const processTags = require('../process-tags')
|
|
10
11
|
const propagationHash = require('../propagation-hash')
|
|
11
|
-
const {
|
|
12
|
+
const { computePathwayHash } = require('./pathway')
|
|
12
13
|
const { DataStreamsWriter } = require('./writer')
|
|
13
14
|
const { getAmqpMessageSize, getHeadersSize, getMessageSize, getSizeOrZero } = require('./size')
|
|
14
15
|
const { SchemaBuilder } = require('./schemas/schema_builder')
|
|
@@ -21,7 +22,7 @@ const ENTRY_PARENT_HASH = Buffer.from('0000000000000000', 'hex')
|
|
|
21
22
|
// bytes, encoded as 28 base64 chars; together with the header key and
|
|
22
23
|
// JSON framing (matching the prior `JSON.stringify({key: value})` byte
|
|
23
24
|
// count minus 1), this is a fixed value.
|
|
24
|
-
const PATHWAY_HEADER_BYTES =
|
|
25
|
+
const PATHWAY_HEADER_BYTES = dsmBase64NameLength + 28 + 6
|
|
25
26
|
|
|
26
27
|
class StatsPoint {
|
|
27
28
|
constructor (hash, parentHash, edgeTags) {
|
|
@@ -32,7 +32,7 @@ const STATUSES = {
|
|
|
32
32
|
INSTALLED: 'INSTALLED',
|
|
33
33
|
EMITTING: 'EMITTING',
|
|
34
34
|
ERROR: 'ERROR',
|
|
35
|
-
|
|
35
|
+
// TODO: Add BLOCKED once support for allow list, deny list or max probe limit has been added
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function ackReceived ({ id: probeId, version }) {
|
|
@@ -110,7 +110,6 @@ class CoverageCIVisibilityEncoder extends AgentEncoder {
|
|
|
110
110
|
_encodePayloadStart (bytes) {
|
|
111
111
|
const payload = {
|
|
112
112
|
version: COVERAGE_PAYLOAD_VERSION,
|
|
113
|
-
coverages: [],
|
|
114
113
|
}
|
|
115
114
|
bytes.writeMapPrefix(COVERAGE_KEYS_LENGTH)
|
|
116
115
|
this._encodeString(bytes, 'version')
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// In PM2 cluster mode, per-app env vars arrive as a `pm2_env`
|
|
4
|
+
// JSON string after preloads have run, so extract them first.
|
|
5
|
+
var pm2EnvStr = process.env.pm2_env
|
|
6
|
+
if (typeof pm2EnvStr === 'string') {
|
|
7
|
+
try {
|
|
8
|
+
var pm2Config = JSON.parse(pm2EnvStr)
|
|
9
|
+
var pm2Keys = Object.keys(pm2Config)
|
|
10
|
+
for (var i = 0; i < pm2Keys.length; i++) {
|
|
11
|
+
var key = pm2Keys[i]
|
|
12
|
+
var value = pm2Config[key]
|
|
13
|
+
process.env[key] = String(value)
|
|
14
|
+
}
|
|
15
|
+
} catch (error) {}
|
|
16
|
+
}
|
|
@@ -2,21 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
/* eslint-disable no-console */
|
|
4
4
|
|
|
5
|
+
var logLevels = require('../log/levels')
|
|
5
6
|
var isTrue = require('./util').isTrue
|
|
6
7
|
|
|
7
8
|
var DD_TRACE_DEBUG = process.env.DD_TRACE_DEBUG
|
|
8
9
|
var DD_TRACE_LOG_LEVEL = process.env.DD_TRACE_LOG_LEVEL
|
|
9
10
|
|
|
10
|
-
var logLevels = {
|
|
11
|
-
trace: 20,
|
|
12
|
-
debug: 20,
|
|
13
|
-
info: 30,
|
|
14
|
-
warn: 40,
|
|
15
|
-
error: 50,
|
|
16
|
-
critical: 50,
|
|
17
|
-
off: 100
|
|
18
|
-
}
|
|
19
|
-
|
|
20
11
|
var logLevel = isTrue(DD_TRACE_DEBUG)
|
|
21
12
|
? Number(DD_TRACE_LOG_LEVEL) || logLevels.debug
|
|
22
13
|
: logLevels.off
|