dd-trace 6.4.0 → 6.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.electron.md +7 -0
- package/README.md +17 -0
- package/ci/diagnose.js +2100 -0
- package/ci/init.js +23 -2
- package/ci/runbook.md +198 -0
- package/ci/test-optimization-validation/approval-artifacts.js +143 -0
- package/ci/test-optimization-validation/approval.js +299 -0
- package/ci/test-optimization-validation/artifact-id.js +20 -0
- package/ci/test-optimization-validation/bounded-json.js +121 -0
- package/ci/test-optimization-validation/ci-command-candidate.js +83 -0
- package/ci/test-optimization-validation/ci-discovery.js +181 -0
- package/ci/test-optimization-validation/ci-remediation.js +210 -0
- package/ci/test-optimization-validation/cli.js +903 -0
- package/ci/test-optimization-validation/command-blocker.js +81 -0
- package/ci/test-optimization-validation/command-output-policy.js +206 -0
- package/ci/test-optimization-validation/command-runner.js +707 -0
- package/ci/test-optimization-validation/command-suitability.js +471 -0
- package/ci/test-optimization-validation/executable-approval.js +48 -0
- package/ci/test-optimization-validation/executable.js +480 -0
- package/ci/test-optimization-validation/generated-file-policy.js +63 -0
- package/ci/test-optimization-validation/generated-files.js +351 -0
- package/ci/test-optimization-validation/generated-verifier.js +196 -0
- package/ci/test-optimization-validation/init-probe-preload.js +163 -0
- package/ci/test-optimization-validation/init-probe.js +246 -0
- package/ci/test-optimization-validation/late-initialization.js +63 -0
- package/ci/test-optimization-validation/local-command.js +163 -0
- package/ci/test-optimization-validation/manifest-loader.js +133 -0
- package/ci/test-optimization-validation/manifest-scaffold.js +738 -0
- package/ci/test-optimization-validation/manifest-schema.js +862 -0
- package/ci/test-optimization-validation/offline-fixtures.js +327 -0
- package/ci/test-optimization-validation/offline-output.js +406 -0
- package/ci/test-optimization-validation/payload-normalizer.js +72 -0
- package/ci/test-optimization-validation/plan-writer.js +1120 -0
- package/ci/test-optimization-validation/preflight-runner.js +114 -0
- package/ci/test-optimization-validation/redaction.js +331 -0
- package/ci/test-optimization-validation/report-writer.js +1508 -0
- package/ci/test-optimization-validation/safe-files.js +203 -0
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +159 -0
- package/ci/test-optimization-validation/scenarios/basic-reporting.js +657 -0
- package/ci/test-optimization-validation/scenarios/ci-wiring.js +780 -0
- package/ci/test-optimization-validation/scenarios/early-flake-detection.js +141 -0
- package/ci/test-optimization-validation/scenarios/helpers.js +539 -0
- package/ci/test-optimization-validation/scenarios/test-management.js +218 -0
- package/ci/test-optimization-validation/setup-runner.js +97 -0
- package/ci/test-optimization-validation/static-diagnosis.js +159 -0
- package/ci/test-optimization-validation/test-output.js +129 -0
- package/ci/test-optimization-validation-manifest.schema.json +1 -0
- package/ci/validate-test-optimization.js +3 -0
- package/ext/exporters.js +1 -0
- package/index.d.ts +121 -8
- package/init.js +18 -0
- package/initialize.mjs +1 -1
- package/loader-hook.mjs +28 -18
- package/openfeature.d.ts +1 -0
- package/openfeature.js +4 -0
- package/package.json +10 -7
- package/packages/datadog-instrumentations/src/ai.js +8 -2
- package/packages/datadog-instrumentations/src/child_process.js +1 -1
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber-worker-threads.js +9 -3
- package/packages/datadog-instrumentations/src/cucumber.js +20 -7
- package/packages/datadog-instrumentations/src/cypress-config.js +398 -52
- package/packages/datadog-instrumentations/src/fastify.js +7 -11
- package/packages/datadog-instrumentations/src/helpers/hook.js +27 -6
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +8 -8
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +28 -2
- package/packages/datadog-instrumentations/src/jest.js +26 -0
- package/packages/datadog-instrumentations/src/mariadb.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +0 -2
- package/packages/datadog-instrumentations/src/mocha/utils.js +0 -4
- package/packages/datadog-instrumentations/src/mongodb.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +3 -3
- package/packages/datadog-instrumentations/src/mquery.js +2 -2
- package/packages/datadog-instrumentations/src/mysql.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +24 -0
- package/packages/datadog-instrumentations/src/nyc.js +0 -2
- package/packages/datadog-instrumentations/src/oracledb.js +2 -2
- package/packages/datadog-instrumentations/src/pg.js +2 -2
- package/packages/datadog-instrumentations/src/playwright.js +159 -22
- package/packages/datadog-instrumentations/src/process.js +3 -0
- package/packages/datadog-instrumentations/src/router.js +18 -8
- package/packages/datadog-instrumentations/src/selenium.js +52 -26
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +2 -2
- package/packages/datadog-instrumentations/src/vitest-main.js +0 -2
- package/packages/datadog-instrumentations/src/ws.js +2 -1
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +2 -2
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
- package/packages/datadog-plugin-cucumber/src/index.js +1 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +19 -57
- package/packages/datadog-plugin-cypress/src/index.js +6 -1
- package/packages/datadog-plugin-cypress/src/support.js +92 -26
- package/packages/datadog-plugin-electron/src/ipc.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +87 -45
- package/packages/datadog-plugin-graphql/src/validate.js +2 -2
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-langchain/src/handlers/embedding.js +2 -1
- package/packages/datadog-plugin-langchain/src/handlers/language_models.js +2 -1
- package/packages/datadog-plugin-langchain/src/tokens.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +177 -64
- package/packages/datadog-plugin-router/src/index.js +11 -2
- package/packages/datadog-plugin-selenium/src/index.js +5 -36
- package/packages/datadog-plugin-ws/src/close.js +2 -1
- package/packages/datadog-plugin-ws/src/producer.js +2 -1
- package/packages/datadog-plugin-ws/src/receiver.js +2 -1
- package/packages/datadog-plugin-ws/src/server.js +2 -1
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +3 -1
- package/packages/dd-trace/src/azure_metadata.js +2 -1
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +93 -28
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +160 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +288 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/payload-projection.js +84 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +369 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +60 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +41 -3
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +7 -2
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +1 -1
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +6 -2
- package/packages/dd-trace/src/ci-visibility/rum.js +7 -0
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +1 -1
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +137 -9
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +168 -8
- package/packages/dd-trace/src/ci-visibility/test-screenshot.js +90 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +16 -0
- package/packages/dd-trace/src/config/helper.js +1 -0
- package/packages/dd-trace/src/config/index.js +10 -0
- package/packages/dd-trace/src/config/supported-configurations.json +66 -0
- package/packages/dd-trace/src/exporter.js +2 -0
- package/packages/dd-trace/src/exporters/common/client-library-headers.js +21 -0
- package/packages/dd-trace/src/exporters/common/request.js +59 -30
- package/packages/dd-trace/src/exporters/common/url.js +15 -1
- package/packages/dd-trace/src/feature-registry.js +10 -3
- package/packages/dd-trace/src/llmobs/experiments/client.js +113 -0
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +154 -0
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +283 -0
- package/packages/dd-trace/src/llmobs/experiments/index.js +152 -0
- package/packages/dd-trace/src/llmobs/experiments/noop.js +30 -0
- package/packages/dd-trace/src/llmobs/experiments/result.js +34 -0
- package/packages/dd-trace/src/llmobs/noop.js +6 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +20 -3
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +8 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +48 -14
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +43 -0
- package/packages/dd-trace/src/llmobs/sdk.js +17 -0
- package/packages/dd-trace/src/llmobs/tagger.js +68 -0
- package/packages/dd-trace/src/llmobs/telemetry.js +2 -1
- package/packages/dd-trace/src/llmobs/util.js +32 -0
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +322 -0
- package/packages/dd-trace/src/openfeature/configuration_source.js +90 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +14 -23
- package/packages/dd-trace/src/openfeature/index.js +0 -2
- package/packages/dd-trace/src/openfeature/noop.js +1 -28
- package/packages/dd-trace/src/openfeature/register.js +16 -27
- package/packages/dd-trace/src/openfeature/remote_config.js +15 -18
- package/packages/dd-trace/src/openfeature/require-provider.js +18 -0
- package/packages/dd-trace/src/opentelemetry/span-ending-hook.js +10 -0
- package/packages/dd-trace/src/opentelemetry/span.js +5 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +20 -6
- package/packages/dd-trace/src/plugins/util/git.js +3 -2
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +29 -5
- package/packages/dd-trace/src/plugins/util/test.js +56 -4
- package/packages/dd-trace/src/proxy.js +84 -7
- package/packages/dd-trace/src/span_processor.js +5 -0
- package/packages/dd-trace/src/standalone/index.js +0 -14
- package/packages/dd-trace/src/telemetry/send-data.js +2 -2
- package/packages/dd-trace/src/util.js +26 -0
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +1 -1
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/require-optional-peer.js +0 -17
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const MAX_COLLECTION_ENTRIES = 100_000
|
|
4
|
+
const MAX_INPUT_BYTES = 16 * 1024 * 1024
|
|
5
|
+
const MAX_NESTING_DEPTH = 128
|
|
6
|
+
const MAX_OUTPUT_BYTES = 16 * 1024 * 1024
|
|
7
|
+
const MAX_STRING_BYTES = 64 * 1024
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Converts one bounded MessagePack value to JSON without losing 64-bit integer precision.
|
|
11
|
+
*
|
|
12
|
+
* @param {Buffer} input encoded MessagePack payload
|
|
13
|
+
* @returns {Buffer} JSON payload
|
|
14
|
+
*/
|
|
15
|
+
function msgpackToJson (input) {
|
|
16
|
+
if (!Buffer.isBuffer(input) || input.length === 0) {
|
|
17
|
+
throw new Error('MessagePack validation payload must be a non-empty Buffer.')
|
|
18
|
+
}
|
|
19
|
+
if (input.length > MAX_INPUT_BYTES) {
|
|
20
|
+
throw new Error(`MessagePack validation payload exceeds ${MAX_INPUT_BYTES} bytes.`)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const writer = new BoundedJsonWriter()
|
|
24
|
+
const converter = new MsgpackJsonConverter(input, writer)
|
|
25
|
+
converter.convert()
|
|
26
|
+
return writer.toBuffer()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
class BoundedJsonWriter {
|
|
30
|
+
#bytes = 0
|
|
31
|
+
#chunks = []
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Appends one JSON fragment while enforcing the aggregate output limit.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} fragment JSON fragment
|
|
37
|
+
*/
|
|
38
|
+
write (fragment) {
|
|
39
|
+
const bytes = Buffer.byteLength(fragment)
|
|
40
|
+
if (this.#bytes + bytes > MAX_OUTPUT_BYTES) {
|
|
41
|
+
throw new Error(`JSON validation payload exceeds ${MAX_OUTPUT_BYTES} bytes.`)
|
|
42
|
+
}
|
|
43
|
+
this.#bytes += bytes
|
|
44
|
+
this.#chunks.push(fragment)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Materializes the completed bounded JSON payload.
|
|
49
|
+
*
|
|
50
|
+
* @returns {Buffer} JSON payload
|
|
51
|
+
*/
|
|
52
|
+
toBuffer () {
|
|
53
|
+
return Buffer.from(this.#chunks.join(''))
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class MsgpackJsonConverter {
|
|
58
|
+
#collectionEntries = 0
|
|
59
|
+
#input
|
|
60
|
+
#offset = 0
|
|
61
|
+
#writer
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Creates a converter for one MessagePack payload.
|
|
65
|
+
*
|
|
66
|
+
* @param {Buffer} input encoded MessagePack payload
|
|
67
|
+
* @param {BoundedJsonWriter} writer bounded JSON writer
|
|
68
|
+
*/
|
|
69
|
+
constructor (input, writer) {
|
|
70
|
+
this.#input = input
|
|
71
|
+
this.#writer = writer
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Converts exactly one top-level value and rejects trailing data.
|
|
76
|
+
*/
|
|
77
|
+
convert () {
|
|
78
|
+
this.#writeValue(0)
|
|
79
|
+
if (this.#offset !== this.#input.length) {
|
|
80
|
+
throw new Error('MessagePack validation payload contains trailing data.')
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Writes one MessagePack value as JSON.
|
|
86
|
+
*
|
|
87
|
+
* @param {number} depth current nesting depth
|
|
88
|
+
*/
|
|
89
|
+
#writeValue (depth) {
|
|
90
|
+
if (depth > MAX_NESTING_DEPTH) {
|
|
91
|
+
throw new Error('MessagePack nesting exceeds validation payload limit.')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const prefix = this.#readUInt8()
|
|
95
|
+
if (prefix <= 0x7F) return this.#writer.write(String(prefix))
|
|
96
|
+
if (prefix >= 0xE0) return this.#writer.write(String(prefix - 0x01_00))
|
|
97
|
+
if ((prefix & 0xE0) === 0xA0) return this.#writeString(prefix & 0x1F)
|
|
98
|
+
if ((prefix & 0xF0) === 0x90) return this.#writeArray(prefix & 0x0F, depth)
|
|
99
|
+
if ((prefix & 0xF0) === 0x80) return this.#writeMap(prefix & 0x0F, depth)
|
|
100
|
+
|
|
101
|
+
switch (prefix) {
|
|
102
|
+
case 0xC0: return this.#writer.write('null')
|
|
103
|
+
case 0xC2: return this.#writer.write('false')
|
|
104
|
+
case 0xC3: return this.#writer.write('true')
|
|
105
|
+
case 0xC4: return this.#writeBinary(this.#readUInt8())
|
|
106
|
+
case 0xC5: return this.#writeBinary(this.#read('readUInt16BE', 2))
|
|
107
|
+
case 0xC6: return this.#writeBinary(this.#read('readUInt32BE', 4))
|
|
108
|
+
case 0xCA: return this.#writeFloat(this.#read('readFloatBE', 4))
|
|
109
|
+
case 0xCB: return this.#writeFloat(this.#read('readDoubleBE', 8))
|
|
110
|
+
case 0xCC: return this.#writer.write(String(this.#readUInt8()))
|
|
111
|
+
case 0xCD: return this.#writer.write(String(this.#read('readUInt16BE', 2)))
|
|
112
|
+
case 0xCE: return this.#writer.write(String(this.#read('readUInt32BE', 4)))
|
|
113
|
+
case 0xCF: return this.#writer.write(this.#read('readBigUInt64BE', 8).toString())
|
|
114
|
+
case 0xD0: return this.#writer.write(String(this.#read('readInt8', 1)))
|
|
115
|
+
case 0xD1: return this.#writer.write(String(this.#read('readInt16BE', 2)))
|
|
116
|
+
case 0xD2: return this.#writer.write(String(this.#read('readInt32BE', 4)))
|
|
117
|
+
case 0xD3: return this.#writer.write(this.#read('readBigInt64BE', 8).toString())
|
|
118
|
+
case 0xD9: return this.#writeString(this.#readUInt8())
|
|
119
|
+
case 0xDA: return this.#writeString(this.#read('readUInt16BE', 2))
|
|
120
|
+
case 0xDB: return this.#writeString(this.#read('readUInt32BE', 4))
|
|
121
|
+
case 0xDC: return this.#writeArray(this.#read('readUInt16BE', 2), depth)
|
|
122
|
+
case 0xDD: return this.#writeArray(this.#read('readUInt32BE', 4), depth)
|
|
123
|
+
case 0xDE: return this.#writeMap(this.#read('readUInt16BE', 2), depth)
|
|
124
|
+
case 0xDF: return this.#writeMap(this.#read('readUInt32BE', 4), depth)
|
|
125
|
+
default:
|
|
126
|
+
throw new Error(`Unsupported MessagePack byte 0x${prefix.toString(16)} at offset ${this.#offset - 1}.`)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Writes one MessagePack array.
|
|
132
|
+
*
|
|
133
|
+
* @param {number} length array length
|
|
134
|
+
* @param {number} depth current nesting depth
|
|
135
|
+
*/
|
|
136
|
+
#writeArray (length, depth) {
|
|
137
|
+
this.#assertCollectionLength(length)
|
|
138
|
+
this.#writer.write('[')
|
|
139
|
+
for (let index = 0; index < length; index++) {
|
|
140
|
+
if (index > 0) this.#writer.write(',')
|
|
141
|
+
this.#writeValue(depth + 1)
|
|
142
|
+
}
|
|
143
|
+
this.#writer.write(']')
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Writes one MessagePack map with JSON-compatible keys.
|
|
148
|
+
*
|
|
149
|
+
* @param {number} length map entry count
|
|
150
|
+
* @param {number} depth current nesting depth
|
|
151
|
+
*/
|
|
152
|
+
#writeMap (length, depth) {
|
|
153
|
+
this.#assertCollectionLength(length)
|
|
154
|
+
this.#writer.write('{')
|
|
155
|
+
for (let index = 0; index < length; index++) {
|
|
156
|
+
if (index > 0) this.#writer.write(',')
|
|
157
|
+
this.#writeMapKey()
|
|
158
|
+
this.#writer.write(':')
|
|
159
|
+
this.#writeValue(depth + 1)
|
|
160
|
+
}
|
|
161
|
+
this.#writer.write('}')
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Writes a string or integer MessagePack map key as a JSON string.
|
|
166
|
+
*/
|
|
167
|
+
#writeMapKey () {
|
|
168
|
+
const prefix = this.#readUInt8()
|
|
169
|
+
if (prefix <= 0x7F) return this.#writer.write(JSON.stringify(String(prefix)))
|
|
170
|
+
if (prefix >= 0xE0) return this.#writer.write(JSON.stringify(String(prefix - 0x01_00)))
|
|
171
|
+
if ((prefix & 0xE0) === 0xA0) return this.#writeString(prefix & 0x1F)
|
|
172
|
+
|
|
173
|
+
let value
|
|
174
|
+
switch (prefix) {
|
|
175
|
+
case 0xCC: value = this.#readUInt8(); break
|
|
176
|
+
case 0xCD: value = this.#read('readUInt16BE', 2); break
|
|
177
|
+
case 0xCE: value = this.#read('readUInt32BE', 4); break
|
|
178
|
+
case 0xCF: value = this.#read('readBigUInt64BE', 8); break
|
|
179
|
+
case 0xD0: value = this.#read('readInt8', 1); break
|
|
180
|
+
case 0xD1: value = this.#read('readInt16BE', 2); break
|
|
181
|
+
case 0xD2: value = this.#read('readInt32BE', 4); break
|
|
182
|
+
case 0xD3: value = this.#read('readBigInt64BE', 8); break
|
|
183
|
+
case 0xD9: return this.#writeString(this.#readUInt8())
|
|
184
|
+
case 0xDA: return this.#writeString(this.#read('readUInt16BE', 2))
|
|
185
|
+
case 0xDB: return this.#writeString(this.#read('readUInt32BE', 4))
|
|
186
|
+
default:
|
|
187
|
+
throw new Error(`Unsupported MessagePack map key byte 0x${prefix.toString(16)}.`)
|
|
188
|
+
}
|
|
189
|
+
this.#writer.write(JSON.stringify(String(value)))
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Writes one UTF-8 MessagePack string.
|
|
194
|
+
*
|
|
195
|
+
* @param {number} length encoded byte length
|
|
196
|
+
*/
|
|
197
|
+
#writeString (length) {
|
|
198
|
+
if (length > MAX_STRING_BYTES) {
|
|
199
|
+
throw new Error('MessagePack string exceeds validation payload limit.')
|
|
200
|
+
}
|
|
201
|
+
this.#assertAvailable(length)
|
|
202
|
+
const end = this.#offset + length
|
|
203
|
+
const value = this.#input.toString('utf8', this.#offset, end)
|
|
204
|
+
this.#offset = end
|
|
205
|
+
this.#writer.write(JSON.stringify(value))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Writes one binary MessagePack value as a base64 JSON string.
|
|
210
|
+
*
|
|
211
|
+
* @param {number} length encoded byte length
|
|
212
|
+
*/
|
|
213
|
+
#writeBinary (length) {
|
|
214
|
+
this.#assertAvailable(length)
|
|
215
|
+
const end = this.#offset + length
|
|
216
|
+
const value = this.#input.subarray(this.#offset, end).toString('base64')
|
|
217
|
+
this.#offset = end
|
|
218
|
+
this.#writer.write(JSON.stringify(value))
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Writes one finite floating-point value.
|
|
223
|
+
*
|
|
224
|
+
* @param {number} value decoded floating-point value
|
|
225
|
+
*/
|
|
226
|
+
#writeFloat (value) {
|
|
227
|
+
if (!Number.isFinite(value)) throw new Error('MessagePack validation payload contains a non-finite number.')
|
|
228
|
+
this.#writer.write(Object.is(value, -0) ? '-0' : String(value))
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Enforces per-collection and aggregate collection-entry limits.
|
|
233
|
+
*
|
|
234
|
+
* @param {number} length collection length
|
|
235
|
+
*/
|
|
236
|
+
#assertCollectionLength (length) {
|
|
237
|
+
if (length > MAX_COLLECTION_ENTRIES) {
|
|
238
|
+
throw new Error(`MessagePack collection length ${length} exceeds validation entry limit.`)
|
|
239
|
+
}
|
|
240
|
+
this.#collectionEntries += length
|
|
241
|
+
if (this.#collectionEntries > MAX_COLLECTION_ENTRIES) {
|
|
242
|
+
throw new Error('MessagePack aggregate collection entries exceed validation limit.')
|
|
243
|
+
}
|
|
244
|
+
if (length > this.#input.length - this.#offset) {
|
|
245
|
+
throw new Error(`MessagePack collection length ${length} exceeds remaining payload bytes.`)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Ensures the requested bytes remain in the input.
|
|
251
|
+
*
|
|
252
|
+
* @param {number} length byte count
|
|
253
|
+
*/
|
|
254
|
+
#assertAvailable (length) {
|
|
255
|
+
if (length < 0 || this.#offset + length > this.#input.length) {
|
|
256
|
+
throw new Error('Unexpected end of MessagePack validation payload.')
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** @returns {number} unsigned 8-bit integer */
|
|
261
|
+
#readUInt8 () {
|
|
262
|
+
this.#assertAvailable(1)
|
|
263
|
+
return this.#input[this.#offset++]
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Reads one fixed-width numeric value.
|
|
268
|
+
*
|
|
269
|
+
* @param {keyof Buffer} method Buffer reader method
|
|
270
|
+
* @param {number} bytes encoded width
|
|
271
|
+
* @returns {number|bigint} decoded value
|
|
272
|
+
*/
|
|
273
|
+
#read (method, bytes) {
|
|
274
|
+
this.#assertAvailable(bytes)
|
|
275
|
+
const value = this.#input[method](this.#offset)
|
|
276
|
+
this.#offset += bytes
|
|
277
|
+
return value
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
module.exports = {
|
|
282
|
+
MAX_COLLECTION_ENTRIES,
|
|
283
|
+
MAX_INPUT_BYTES,
|
|
284
|
+
MAX_NESTING_DEPTH,
|
|
285
|
+
MAX_OUTPUT_BYTES,
|
|
286
|
+
MAX_STRING_BYTES,
|
|
287
|
+
msgpackToJson,
|
|
288
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const EVENT_TYPES = new Set(['test', 'test_module_end', 'test_session_end', 'test_suite_end'])
|
|
4
|
+
const META_FIELDS = new Set([
|
|
5
|
+
'test.command',
|
|
6
|
+
'test.early_flake.enabled',
|
|
7
|
+
'test.final_status',
|
|
8
|
+
'test.is_new',
|
|
9
|
+
'test.is_retry',
|
|
10
|
+
'test.module',
|
|
11
|
+
'test.name',
|
|
12
|
+
'test.retry_reason',
|
|
13
|
+
'test.source.file',
|
|
14
|
+
'test.status',
|
|
15
|
+
'test.suite',
|
|
16
|
+
'test.test_management.attempt_to_fix_passed',
|
|
17
|
+
'test.test_management.enabled',
|
|
18
|
+
'test.test_management.is_attempt_to_fix',
|
|
19
|
+
'test.test_management.is_quarantined',
|
|
20
|
+
'test.test_management.is_test_disabled',
|
|
21
|
+
])
|
|
22
|
+
const METRIC_FIELDS = new Set(['test.is_new', 'test.is_retry'])
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Projects a decoded Test Optimization payload into the fixed validation-only event schema.
|
|
26
|
+
*
|
|
27
|
+
* @param {unknown} payload decoded Test Optimization payload
|
|
28
|
+
* @returns {{events: object[], version: 1}} allowlisted payload
|
|
29
|
+
*/
|
|
30
|
+
function projectTestCyclePayload (payload) {
|
|
31
|
+
if (!isObject(payload) || payload.version !== 1 || !Array.isArray(payload.events)) {
|
|
32
|
+
throw new Error('Test Optimization validation payload has an unsupported envelope.')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const events = []
|
|
36
|
+
for (const event of payload.events) {
|
|
37
|
+
if (isNonTestSpan(event)) continue
|
|
38
|
+
events.push(projectEvent(event))
|
|
39
|
+
}
|
|
40
|
+
return { version: 1, events }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function projectEvent (event) {
|
|
44
|
+
if (!isObject(event) || !EVENT_TYPES.has(event.type) || !isObject(event.content)) {
|
|
45
|
+
throw new Error('Test Optimization validation payload contains an unsupported event shape.')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
type: event.type,
|
|
50
|
+
content: {
|
|
51
|
+
meta: projectFields(event.content.meta, META_FIELDS),
|
|
52
|
+
metrics: projectFields(event.content.metrics, METRIC_FIELDS),
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function isNonTestSpan (event) {
|
|
58
|
+
if (!isObject(event) || event.type !== 'span') return false
|
|
59
|
+
if (!isObject(event.content)) {
|
|
60
|
+
throw new Error('Test Optimization validation payload contains an unsupported span shape.')
|
|
61
|
+
}
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function projectFields (source, allowed) {
|
|
66
|
+
const projected = {}
|
|
67
|
+
if (!isObject(source)) return projected
|
|
68
|
+
for (const name of allowed) copyScalar(projected, source, name)
|
|
69
|
+
return projected
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function copyScalar (target, source, name) {
|
|
73
|
+
const value = source[name]
|
|
74
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') target[name] = value
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isObject (value) {
|
|
78
|
+
return Boolean(value && typeof value === 'object' && !Array.isArray(value))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = {
|
|
82
|
+
EVENT_TYPES,
|
|
83
|
+
projectTestCyclePayload,
|
|
84
|
+
}
|