dd-trace 5.110.0 → 5.112.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/LICENSE-3rdparty.csv +1 -2
- package/README.md +13 -8
- package/ci/init.js +21 -2
- package/ci/vitest-no-worker-init-setup.mjs +430 -0
- package/ext/tags.js +2 -0
- package/index.d.ts +34 -1
- package/initialize.mjs +5 -6
- package/loader-hook.mjs +76 -55
- package/package.json +37 -34
- package/packages/datadog-instrumentations/src/ai.js +45 -0
- package/packages/datadog-instrumentations/src/apollo-server.js +5 -13
- package/packages/datadog-instrumentations/src/child_process.js +3 -3
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +587 -0
- package/packages/datadog-instrumentations/src/cucumber.js +102 -43
- package/packages/datadog-instrumentations/src/cypress-config.js +11 -3
- package/packages/datadog-instrumentations/src/fastify.js +27 -8
- package/packages/datadog-instrumentations/src/fs.js +8 -6
- package/packages/datadog-instrumentations/src/graphql.js +26 -495
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +7 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +6 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/claude-agent-sdk.js +17 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +201 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
- package/packages/datadog-instrumentations/src/jest.js +713 -63
- package/packages/datadog-instrumentations/src/mocha/main.js +24 -3
- package/packages/datadog-instrumentations/src/mocha/utils.js +128 -22
- package/packages/datadog-instrumentations/src/mocha/worker.js +13 -0
- package/packages/datadog-instrumentations/src/mongodb.js +74 -0
- package/packages/datadog-instrumentations/src/mongoose.js +13 -2
- package/packages/datadog-instrumentations/src/playwright.js +13 -9
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +1297 -0
- package/packages/datadog-instrumentations/src/vitest-main.js +1594 -0
- package/packages/datadog-instrumentations/src/vitest-util.js +254 -0
- package/packages/datadog-instrumentations/src/vitest-worker.js +823 -0
- package/packages/datadog-instrumentations/src/vitest.js +11 -1855
- package/packages/datadog-plugin-ai/src/index.js +1 -1
- package/packages/datadog-plugin-ai/src/tracing.js +66 -3
- package/packages/datadog-plugin-ai/src/utils.js +17 -4
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/client.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +19 -10
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/handler.js +1 -0
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +47 -11
- package/packages/datadog-plugin-child_process/src/index.js +13 -2
- package/packages/datadog-plugin-claude-agent-sdk/src/index.js +31 -0
- package/packages/datadog-plugin-claude-agent-sdk/src/tracing.js +107 -0
- package/packages/datadog-plugin-claude-agent-sdk/src/util.js +15 -0
- package/packages/datadog-plugin-cucumber/src/index.js +15 -24
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +360 -14
- package/packages/datadog-plugin-cypress/src/index.js +47 -2
- package/packages/datadog-plugin-cypress/src/plugin.js +1 -0
- package/packages/datadog-plugin-cypress/src/support.js +45 -1
- package/packages/datadog-plugin-express/src/code_origin.js +1 -1
- package/packages/datadog-plugin-fastify/src/code_origin.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +639 -12
- package/packages/datadog-plugin-graphql/src/index.js +37 -9
- package/packages/datadog-plugin-graphql/src/parse.js +24 -4
- package/packages/datadog-plugin-graphql/src/utils.js +9 -2
- package/packages/datadog-plugin-graphql/src/validate.js +17 -6
- package/packages/datadog-plugin-http/src/index.js +6 -8
- package/packages/datadog-plugin-jest/src/index.js +31 -15
- package/packages/datadog-plugin-mocha/src/index.js +40 -15
- package/packages/datadog-plugin-mongodb-core/src/bulk-write.js +43 -0
- package/packages/datadog-plugin-mongodb-core/src/index.js +8 -443
- package/packages/datadog-plugin-mongodb-core/src/query.js +452 -0
- package/packages/datadog-plugin-openai/src/services.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +4 -3
- package/packages/datadog-plugin-vitest/src/index.js +120 -72
- package/packages/datadog-shimmer/src/shimmer.js +37 -16
- package/packages/dd-trace/src/aiguard/index.js +9 -14
- package/packages/dd-trace/src/aiguard/integrations/index.js +34 -0
- package/packages/dd-trace/src/aiguard/integrations/openai.js +47 -33
- package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +42 -28
- package/packages/dd-trace/src/aiguard/sdk.js +2 -2
- package/packages/dd-trace/src/appsec/api_security/sampler.js +3 -3
- package/packages/dd-trace/src/appsec/channels.js +3 -1
- package/packages/dd-trace/src/appsec/downstream_requests.js +4 -4
- package/packages/dd-trace/src/appsec/graphql.js +14 -11
- package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +23 -23
- package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/index.js +2 -1
- package/packages/dd-trace/src/appsec/index.js +10 -1
- package/packages/dd-trace/src/appsec/lambda.js +135 -0
- package/packages/dd-trace/src/appsec/reporter.js +49 -10
- package/packages/dd-trace/src/appsec/telemetry/index.js +1 -1
- package/packages/dd-trace/src/appsec/waf/index.js +16 -4
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +4 -4
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +26 -1
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +115 -24
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +21 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +5 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +6 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +130 -20
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +17 -0
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +47 -26
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +2 -2
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +64 -53
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +3 -3
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +156 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +23 -5
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +128 -0
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +287 -0
- package/packages/dd-trace/src/config/defaults.js +3 -2
- package/packages/dd-trace/src/config/generated-config-types.d.ts +71 -57
- package/packages/dd-trace/src/config/helper.js +1 -0
- package/packages/dd-trace/src/config/index.js +35 -22
- package/packages/dd-trace/src/config/major-overrides.js +4 -2
- package/packages/dd-trace/src/config/remote_config.js +1 -1
- package/packages/dd-trace/src/config/supported-configurations.json +127 -56
- package/packages/dd-trace/src/constants.js +7 -0
- package/packages/dd-trace/src/crashtracking/crashtracker.js +2 -2
- package/packages/dd-trace/src/datastreams/processor.js +11 -3
- package/packages/dd-trace/src/exporters/agent/index.js +1 -1
- package/packages/dd-trace/src/exporters/agentless/writer.js +4 -4
- package/packages/dd-trace/src/llmobs/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +403 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +8 -395
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +27 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +363 -0
- package/packages/dd-trace/src/llmobs/plugins/base.js +4 -4
- package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +270 -0
- package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/utils.js +10 -0
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +3 -3
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +3 -3
- package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +54 -5
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +40 -0
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +169 -0
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +38 -39
- package/packages/dd-trace/src/opentelemetry/span.js +5 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +4 -0
- package/packages/dd-trace/src/opentelemetry/tracer_provider.js +1 -1
- package/packages/dd-trace/src/opentracing/tracer.js +6 -1
- package/packages/dd-trace/src/plugin_manager.js +23 -7
- package/packages/dd-trace/src/plugins/ci_plugin.js +159 -10
- package/packages/dd-trace/src/plugins/index.js +2 -0
- package/packages/dd-trace/src/plugins/util/llm.js +6 -1
- package/packages/dd-trace/src/plugins/util/test.js +15 -9
- package/packages/dd-trace/src/profiling/exporter_cli.js +2 -2
- package/packages/dd-trace/src/profiling/exporters/agent.js +28 -3
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +3 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
- package/packages/dd-trace/src/proxy.js +8 -8
- package/packages/dd-trace/src/span_processor.js +5 -6
- package/packages/dd-trace/src/span_stats.js +96 -78
- package/packages/dd-trace/src/startup-log.js +2 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
- package/packages/dd-trace/src/telemetry/endpoints.js +6 -4
- package/packages/dd-trace/src/telemetry/index.js +2 -2
- package/packages/dd-trace/src/telemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/telemetry/send-data.js +8 -8
- package/packages/dd-trace/src/telemetry/session-propagation.js +1 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +9 -9
- 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-plugin-graphql/src/resolve.js +0 -170
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const REQUIRED_SETTINGS_KEYS = [
|
|
4
|
+
'code_coverage',
|
|
5
|
+
'tests_skipping',
|
|
6
|
+
'itr_enabled',
|
|
7
|
+
'require_git',
|
|
8
|
+
'early_flake_detection',
|
|
9
|
+
'flaky_test_retries_enabled',
|
|
10
|
+
'di_enabled',
|
|
11
|
+
'known_tests_enabled',
|
|
12
|
+
'test_management',
|
|
13
|
+
'impacted_tests_enabled',
|
|
14
|
+
'coverage_report_upload_enabled',
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
function isObject (value) {
|
|
18
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function assertObject (value, message) {
|
|
22
|
+
if (!isObject(value)) {
|
|
23
|
+
throw new Error(message)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function assertHasKeys (value, keys, endpoint) {
|
|
28
|
+
for (const key of keys) {
|
|
29
|
+
if (!Object.hasOwn(value, key)) {
|
|
30
|
+
throw new Error(`Invalid ${endpoint} response: missing ${key}`)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getAttributes (response, endpoint) {
|
|
36
|
+
const attributes = response?.data?.attributes
|
|
37
|
+
assertObject(attributes, `Invalid ${endpoint} response: attributes must be an object`)
|
|
38
|
+
return attributes
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function validateSettingsResponse (response) {
|
|
42
|
+
const attributes = response?.data?.attributes ?? response
|
|
43
|
+
assertObject(attributes, 'Invalid settings response: attributes must be an object')
|
|
44
|
+
assertHasKeys(attributes, REQUIRED_SETTINGS_KEYS, 'settings')
|
|
45
|
+
assertObject(attributes.early_flake_detection, 'Invalid settings response: early_flake_detection must be an object')
|
|
46
|
+
assertObject(attributes.test_management, 'Invalid settings response: test_management must be an object')
|
|
47
|
+
assertHasKeys(attributes.early_flake_detection, ['enabled'], 'settings early_flake_detection')
|
|
48
|
+
assertHasKeys(attributes.test_management, ['enabled'], 'settings test_management')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function validateKnownTestsResponse (response) {
|
|
52
|
+
const attributes = getAttributes(response, 'known tests')
|
|
53
|
+
assertHasKeys(attributes, ['tests'], 'known tests')
|
|
54
|
+
|
|
55
|
+
const { tests } = attributes
|
|
56
|
+
if (tests === null) return
|
|
57
|
+
assertObject(tests, 'Invalid known tests response: tests must be an object or null')
|
|
58
|
+
|
|
59
|
+
for (const suites of Object.values(tests)) {
|
|
60
|
+
assertObject(suites, 'Invalid known tests response: module suites must be objects')
|
|
61
|
+
for (const testNames of Object.values(suites)) {
|
|
62
|
+
if (!Array.isArray(testNames)) {
|
|
63
|
+
throw new TypeError('Invalid known tests response: suite tests must be arrays')
|
|
64
|
+
}
|
|
65
|
+
for (const testName of testNames) {
|
|
66
|
+
if (typeof testName !== 'string') {
|
|
67
|
+
throw new TypeError('Invalid known tests response: test names must be strings')
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function validateSkippableTestsResponse (response) {
|
|
75
|
+
assertObject(response, 'Invalid skippable tests response: response must be an object')
|
|
76
|
+
if (!Array.isArray(response.data)) {
|
|
77
|
+
throw new TypeError('Invalid skippable tests response: data must be an array')
|
|
78
|
+
}
|
|
79
|
+
if (response.meta !== undefined) {
|
|
80
|
+
assertObject(response.meta, 'Invalid skippable tests response: meta must be an object')
|
|
81
|
+
}
|
|
82
|
+
if (response.meta?.coverage !== undefined) {
|
|
83
|
+
assertObject(response.meta.coverage, 'Invalid skippable tests response: meta.coverage must be an object')
|
|
84
|
+
}
|
|
85
|
+
if (response.meta?.correlation_id !== undefined && typeof response.meta.correlation_id !== 'string') {
|
|
86
|
+
throw new Error('Invalid skippable tests response: meta.correlation_id must be a string')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
for (const item of response.data) {
|
|
90
|
+
assertObject(item, 'Invalid skippable tests response: data entries must be objects')
|
|
91
|
+
if (typeof item.type !== 'string') {
|
|
92
|
+
throw new TypeError('Invalid skippable tests response: data entry type must be a string')
|
|
93
|
+
}
|
|
94
|
+
assertObject(item.attributes, 'Invalid skippable tests response: data entry attributes must be an object')
|
|
95
|
+
if ((item.type === 'suite' || item.type === 'test') && typeof item.attributes.suite !== 'string') {
|
|
96
|
+
throw new Error('Invalid skippable tests response: data entry suite must be a string')
|
|
97
|
+
}
|
|
98
|
+
if (item.type === 'test' && typeof item.attributes.name !== 'string') {
|
|
99
|
+
throw new Error('Invalid skippable tests response: data entry name must be a string')
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function validateTestManagementTestsResponse (response) {
|
|
105
|
+
const attributes = getAttributes(response, 'test management tests')
|
|
106
|
+
assertHasKeys(attributes, ['modules'], 'test management tests')
|
|
107
|
+
assertObject(attributes.modules, 'Invalid test management tests response: modules must be an object')
|
|
108
|
+
|
|
109
|
+
for (const testModule of Object.values(attributes.modules)) {
|
|
110
|
+
assertObject(testModule, 'Invalid test management tests response: modules entries must be objects')
|
|
111
|
+
assertObject(testModule.suites, 'Invalid test management tests response: module suites must be objects')
|
|
112
|
+
for (const suite of Object.values(testModule.suites)) {
|
|
113
|
+
assertObject(suite, 'Invalid test management tests response: suites entries must be objects')
|
|
114
|
+
assertObject(suite.tests, 'Invalid test management tests response: suite tests must be objects')
|
|
115
|
+
for (const test of Object.values(suite.tests)) {
|
|
116
|
+
assertObject(test, 'Invalid test management tests response: tests entries must be objects')
|
|
117
|
+
assertObject(test.properties, 'Invalid test management tests response: test properties must be objects')
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
module.exports = {
|
|
124
|
+
validateKnownTestsResponse,
|
|
125
|
+
validateSettingsResponse,
|
|
126
|
+
validateSkippableTestsResponse,
|
|
127
|
+
validateTestManagementTestsResponse,
|
|
128
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs')
|
|
4
|
+
const path = require('node:path')
|
|
5
|
+
|
|
6
|
+
const log = require('../log')
|
|
7
|
+
const { getNumFromKnownTests } = require('../plugins/util/test')
|
|
8
|
+
const { parseKnownTestsResponse } = require('./early-flake-detection/get-known-tests')
|
|
9
|
+
const { parseSkippableSuitesResponse } = require('./intelligent-test-runner/get-skippable-suites')
|
|
10
|
+
const { parseLibraryConfigurationResponse } = require('./requests/get-library-configuration')
|
|
11
|
+
const {
|
|
12
|
+
getNumFromTestManagementTests,
|
|
13
|
+
parseTestManagementTestsResponse,
|
|
14
|
+
} = require('./test-management/get-test-management-tests')
|
|
15
|
+
const {
|
|
16
|
+
incrementCountMetric,
|
|
17
|
+
distributionMetric,
|
|
18
|
+
TELEMETRY_GIT_REQUESTS_SETTINGS_RESPONSE,
|
|
19
|
+
TELEMETRY_KNOWN_TESTS_RESPONSE_TESTS,
|
|
20
|
+
TELEMETRY_KNOWN_TESTS_RESPONSE_BYTES,
|
|
21
|
+
TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_SUITES,
|
|
22
|
+
TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_TESTS,
|
|
23
|
+
TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_BYTES,
|
|
24
|
+
TELEMETRY_TEST_MANAGEMENT_TESTS_RESPONSE_TESTS,
|
|
25
|
+
TELEMETRY_TEST_MANAGEMENT_TESTS_RESPONSE_BYTES,
|
|
26
|
+
} = require('./telemetry')
|
|
27
|
+
|
|
28
|
+
const CACHE_MISS = Symbol('test optimization http cache miss')
|
|
29
|
+
|
|
30
|
+
const PLAN_FOLDER = '.testoptimization'
|
|
31
|
+
const MANIFEST_FILE_NAME = 'manifest.txt'
|
|
32
|
+
const SUPPORTED_MANIFEST_VERSION = '1'
|
|
33
|
+
const CACHE_FOLDER_NAME = 'cache'
|
|
34
|
+
const HTTP_CACHE_FOLDER_NAME = 'http'
|
|
35
|
+
|
|
36
|
+
const ENV_MANIFEST_FILE = 'TEST_OPTIMIZATION_MANIFEST_FILE'
|
|
37
|
+
const ENV_MANIFEST_FILE_ALIAS = 'DD_TEST_OPTIMIZATION_MANIFEST_FILE'
|
|
38
|
+
const ENV_RUNFILES_DIR = 'RUNFILES_DIR'
|
|
39
|
+
const ENV_RUNFILES_MANIFEST_FILE = 'RUNFILES_MANIFEST_FILE'
|
|
40
|
+
const ENV_TEST_SRCDIR = 'TEST_SRCDIR'
|
|
41
|
+
|
|
42
|
+
const SETTINGS_FILE_NAME = 'settings.json'
|
|
43
|
+
const KNOWN_TESTS_FILE_NAME = 'known_tests.json'
|
|
44
|
+
const SKIPPABLE_TESTS_FILE_NAME = 'skippable_tests.json'
|
|
45
|
+
const TEST_MANAGEMENT_FILE_NAME = 'test_management.json'
|
|
46
|
+
|
|
47
|
+
const RUNFILES_MANIFEST_SEPARATOR = ' '
|
|
48
|
+
|
|
49
|
+
function parseManifestVersion (content) {
|
|
50
|
+
// Supported just the number version or 'version=x'
|
|
51
|
+
const version = content.replace(/^\uFEFF/, '').trim()
|
|
52
|
+
const match = version.match(/^version=(.+)$/)
|
|
53
|
+
return match ? match[1].trim() : version
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class TestOptimizationHttpCache {
|
|
57
|
+
constructor ({ cwd = process.cwd(), env } = {}) {
|
|
58
|
+
this._cwd = cwd
|
|
59
|
+
// This cache intentionally consumes env vars that are not tracer config keys. (??)
|
|
60
|
+
// eslint-disable-next-line eslint-rules/eslint-process-env
|
|
61
|
+
this._env = env ?? process.env
|
|
62
|
+
this._manifestPath = this._resolveManifestPath()
|
|
63
|
+
this._testOptimizationPath = undefined
|
|
64
|
+
this._httpCachePath = undefined
|
|
65
|
+
this._available = false
|
|
66
|
+
|
|
67
|
+
this._buildReader()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
isAvailable () {
|
|
71
|
+
return this._available
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
readSettings () {
|
|
75
|
+
const payload = this._readFile(SETTINGS_FILE_NAME)
|
|
76
|
+
if (payload === CACHE_MISS) {
|
|
77
|
+
this._disable()
|
|
78
|
+
return CACHE_MISS
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const settings = parseLibraryConfigurationResponse(payload, undefined, { validateRequiredFields: true })
|
|
83
|
+
incrementCountMetric(TELEMETRY_GIT_REQUESTS_SETTINGS_RESPONSE, settings)
|
|
84
|
+
return settings
|
|
85
|
+
} catch (err) {
|
|
86
|
+
this._logInvalidCacheFile(SETTINGS_FILE_NAME, err)
|
|
87
|
+
this._disable()
|
|
88
|
+
return CACHE_MISS
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
readKnownTests () {
|
|
93
|
+
const payload = this._readFile(KNOWN_TESTS_FILE_NAME)
|
|
94
|
+
if (payload === CACHE_MISS) return CACHE_MISS
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const knownTests = parseKnownTestsResponse(payload, { validateRequiredFields: true })
|
|
98
|
+
distributionMetric(TELEMETRY_KNOWN_TESTS_RESPONSE_TESTS, {}, getNumFromKnownTests(knownTests))
|
|
99
|
+
distributionMetric(TELEMETRY_KNOWN_TESTS_RESPONSE_BYTES, {}, payload.length)
|
|
100
|
+
return knownTests
|
|
101
|
+
} catch (err) {
|
|
102
|
+
this._logInvalidCacheFile(KNOWN_TESTS_FILE_NAME, err)
|
|
103
|
+
return CACHE_MISS
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
readSkippableSuites (options = {}) {
|
|
108
|
+
const payload = this._readFile(SKIPPABLE_TESTS_FILE_NAME)
|
|
109
|
+
if (payload === CACHE_MISS) return CACHE_MISS
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const parsedResponse = JSON.parse(payload)
|
|
113
|
+
const result = parseSkippableSuitesResponse(parsedResponse, { ...options, validateRequiredFields: true })
|
|
114
|
+
const testLevel = options.testLevel || 'suite'
|
|
115
|
+
const skippableItems = parsedResponse.data.filter(({ type }) => type === testLevel)
|
|
116
|
+
incrementCountMetric(
|
|
117
|
+
testLevel === 'test'
|
|
118
|
+
? TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_TESTS
|
|
119
|
+
: TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_SUITES,
|
|
120
|
+
{},
|
|
121
|
+
skippableItems.length
|
|
122
|
+
)
|
|
123
|
+
distributionMetric(TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_BYTES, {}, payload.length)
|
|
124
|
+
return result
|
|
125
|
+
} catch (err) {
|
|
126
|
+
this._logInvalidCacheFile(SKIPPABLE_TESTS_FILE_NAME, err)
|
|
127
|
+
return CACHE_MISS
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
hasValidSkippableSuites (options = {}) {
|
|
132
|
+
const payload = this._readFile(SKIPPABLE_TESTS_FILE_NAME)
|
|
133
|
+
if (payload === CACHE_MISS) return false
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
parseSkippableSuitesResponse(JSON.parse(payload), { ...options, validateRequiredFields: true })
|
|
137
|
+
return true
|
|
138
|
+
} catch {
|
|
139
|
+
return false
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
readTestManagementTests () {
|
|
144
|
+
const payload = this._readFile(TEST_MANAGEMENT_FILE_NAME)
|
|
145
|
+
if (payload === CACHE_MISS) return CACHE_MISS
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const testManagementTests = parseTestManagementTestsResponse(payload, { validateRequiredFields: true })
|
|
149
|
+
distributionMetric(
|
|
150
|
+
TELEMETRY_TEST_MANAGEMENT_TESTS_RESPONSE_TESTS,
|
|
151
|
+
{},
|
|
152
|
+
getNumFromTestManagementTests(testManagementTests)
|
|
153
|
+
)
|
|
154
|
+
distributionMetric(TELEMETRY_TEST_MANAGEMENT_TESTS_RESPONSE_BYTES, {}, payload.length)
|
|
155
|
+
return testManagementTests
|
|
156
|
+
} catch (err) {
|
|
157
|
+
this._logInvalidCacheFile(TEST_MANAGEMENT_FILE_NAME, err)
|
|
158
|
+
return CACHE_MISS
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
_buildReader () {
|
|
163
|
+
if (!this._manifestPath) {
|
|
164
|
+
log.debug('Test Optimization HTTP cache manifest not found')
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const version = this._readManifestVersion(this._manifestPath)
|
|
169
|
+
if (version !== SUPPORTED_MANIFEST_VERSION) {
|
|
170
|
+
log.debug('Unsupported Test Optimization HTTP cache manifest version %j at %s', version, this._manifestPath)
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this._testOptimizationPath = path.dirname(this._manifestPath)
|
|
175
|
+
this._httpCachePath = path.join(
|
|
176
|
+
this._testOptimizationPath,
|
|
177
|
+
CACHE_FOLDER_NAME,
|
|
178
|
+
HTTP_CACHE_FOLDER_NAME
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
const settingsPath = path.join(this._httpCachePath, SETTINGS_FILE_NAME)
|
|
182
|
+
if (!fs.existsSync(settingsPath)) {
|
|
183
|
+
log.debug('Test Optimization HTTP cache settings file not found at %s', settingsPath)
|
|
184
|
+
return
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
log.debug('Test Optimization HTTP cache found at %s', this._httpCachePath)
|
|
188
|
+
this._available = true
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
_resolveManifestPath () {
|
|
192
|
+
const localManifest = path.join(this._cwd, PLAN_FOLDER, MANIFEST_FILE_NAME)
|
|
193
|
+
if (fs.existsSync(localManifest)) {
|
|
194
|
+
return localManifest
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const manifestFile = this._env[ENV_MANIFEST_FILE] || this._env[ENV_MANIFEST_FILE_ALIAS]
|
|
198
|
+
if (!manifestFile) return
|
|
199
|
+
|
|
200
|
+
const resolvedManifestPath = this._resolveRunfilePath(manifestFile)
|
|
201
|
+
if (fs.existsSync(resolvedManifestPath)) {
|
|
202
|
+
return resolvedManifestPath
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
_resolveRunfilePath (manifestFile) {
|
|
207
|
+
if (fs.existsSync(manifestFile)) {
|
|
208
|
+
return manifestFile
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const runfilesDir = this._env[ENV_RUNFILES_DIR]
|
|
212
|
+
if (runfilesDir) {
|
|
213
|
+
const candidate = path.join(runfilesDir, manifestFile)
|
|
214
|
+
if (fs.existsSync(candidate)) {
|
|
215
|
+
return candidate
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const runfilesManifestCandidate = this._resolveRunfilePathFromManifest(manifestFile)
|
|
220
|
+
if (runfilesManifestCandidate) {
|
|
221
|
+
return runfilesManifestCandidate
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const testSrcdir = this._env[ENV_TEST_SRCDIR]
|
|
225
|
+
if (testSrcdir) {
|
|
226
|
+
const candidate = path.join(testSrcdir, manifestFile)
|
|
227
|
+
if (fs.existsSync(candidate)) {
|
|
228
|
+
return candidate
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return manifestFile
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
_resolveRunfilePathFromManifest (manifestFile) {
|
|
236
|
+
const runfilesManifest = this._env[ENV_RUNFILES_MANIFEST_FILE]
|
|
237
|
+
if (!runfilesManifest || !fs.existsSync(runfilesManifest)) return
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
const lines = fs.readFileSync(runfilesManifest, 'utf8').split('\n')
|
|
241
|
+
for (const line of lines) {
|
|
242
|
+
const separatorIndex = line.indexOf(RUNFILES_MANIFEST_SEPARATOR)
|
|
243
|
+
if (separatorIndex <= 0) continue
|
|
244
|
+
if (line.slice(0, separatorIndex) !== manifestFile) continue
|
|
245
|
+
|
|
246
|
+
const resolvedPath = line.slice(separatorIndex + 1).trim()
|
|
247
|
+
if (resolvedPath) return resolvedPath
|
|
248
|
+
}
|
|
249
|
+
} catch (err) {
|
|
250
|
+
log.debug('Failed to resolve Test Optimization HTTP cache manifest from %s: %s', runfilesManifest, err.message)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
_readManifestVersion (manifestPath) {
|
|
255
|
+
try {
|
|
256
|
+
return parseManifestVersion(fs.readFileSync(manifestPath, 'utf8'))
|
|
257
|
+
} catch (err) {
|
|
258
|
+
log.debug('Failed to read Test Optimization HTTP cache manifest %s: %s', manifestPath, err.message)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
_readFile (fileName) {
|
|
263
|
+
if (!this.isAvailable()) return CACHE_MISS
|
|
264
|
+
|
|
265
|
+
const filePath = path.join(this._httpCachePath, fileName)
|
|
266
|
+
try {
|
|
267
|
+
log.debug('Reading Test Optimization HTTP cache file %s', filePath)
|
|
268
|
+
return fs.readFileSync(filePath, 'utf8')
|
|
269
|
+
} catch (err) {
|
|
270
|
+
log.debug('Test Optimization HTTP cache file %s could not be read: %s', filePath, err.message)
|
|
271
|
+
return CACHE_MISS
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
_logInvalidCacheFile (fileName, err) {
|
|
276
|
+
log.debug('Test Optimization HTTP cache file %s could not be parsed: %s', fileName, err.message)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
_disable () {
|
|
280
|
+
this._available = false
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
module.exports = {
|
|
285
|
+
CACHE_MISS,
|
|
286
|
+
TestOptimizationHttpCache,
|
|
287
|
+
}
|
|
@@ -227,8 +227,9 @@ for (const [canonicalName, entries] of Object.entries(supportedConfigurations))
|
|
|
227
227
|
if (entry.sensitive) {
|
|
228
228
|
sensitiveConfigurations.add(canonicalName)
|
|
229
229
|
}
|
|
230
|
-
const
|
|
231
|
-
|
|
230
|
+
const fullPropertyName = entry.namespace
|
|
231
|
+
? `${entry.namespace}.${canonicalName}`
|
|
232
|
+
: (entry.internalPropertyName ?? entry.configurationNames?.[0] ?? canonicalName)
|
|
232
233
|
const type = entry.type.toUpperCase()
|
|
233
234
|
|
|
234
235
|
let transformer = transformers[entry.transform]
|