dd-trace 6.10.0 → 6.12.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 +5 -0
- package/README.md +0 -17
- package/index.d.ts +128 -6
- package/initialize.mjs +28 -17
- package/openfeature.js +2 -2
- package/package.json +27 -23
- package/packages/datadog-esbuild/index.js +0 -34
- package/packages/datadog-instrumentations/src/anthropic.js +210 -15
- package/packages/datadog-instrumentations/src/aws-sdk.js +9 -1
- package/packages/datadog-instrumentations/src/browser-bunyan.js +11 -0
- package/packages/datadog-instrumentations/src/bunyan.js +3 -16
- package/packages/datadog-instrumentations/src/cucumber.js +30 -15
- package/packages/datadog-instrumentations/src/cypress-config.js +182 -16
- package/packages/datadog-instrumentations/src/cypress-legacy-finalizers.js +30 -0
- package/packages/datadog-instrumentations/src/cypress.js +2 -0
- package/packages/datadog-instrumentations/src/fastify.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/bunyan.js +22 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +9 -4
- package/packages/datadog-instrumentations/src/helpers/register.js +10 -8
- package/packages/datadog-instrumentations/src/jest.js +25 -17
- package/packages/datadog-instrumentations/src/mariadb.js +278 -21
- package/packages/datadog-instrumentations/src/mocha/main.js +539 -55
- package/packages/datadog-instrumentations/src/mocha/utils.js +135 -19
- package/packages/datadog-instrumentations/src/playwright-reporter.js +247 -0
- package/packages/datadog-instrumentations/src/playwright.js +182 -35
- package/packages/datadog-instrumentations/src/router.js +2 -0
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +6 -8
- package/packages/datadog-instrumentations/src/vitest-main.js +11 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +163 -44
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -8
- package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
- package/packages/datadog-plugin-browser-bunyan/src/index.js +9 -0
- package/packages/datadog-plugin-bunyan/src/index.js +5 -8
- package/packages/datadog-plugin-cucumber/src/index.js +11 -0
- package/packages/datadog-plugin-cypress/src/after-run.js +5 -1
- package/packages/datadog-plugin-cypress/src/after-spec.js +5 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +81 -29
- package/packages/datadog-plugin-cypress/src/finalization.js +76 -0
- package/packages/datadog-plugin-cypress/src/index.js +12 -6
- package/packages/datadog-plugin-cypress/src/plugin.js +16 -3
- package/packages/datadog-plugin-dd-trace-api/src/index.js +4 -0
- package/packages/datadog-plugin-electron/src/index.js +2 -0
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +6 -0
- package/packages/datadog-plugin-mocha/src/index.js +56 -1
- package/packages/datadog-plugin-nats/src/index.js +1 -1
- package/packages/datadog-plugin-openai/src/tracing.js +41 -30
- package/packages/datadog-plugin-openai-agents/src/integration.js +1 -0
- package/packages/datadog-plugin-playwright/src/index.js +46 -13
- package/packages/datadog-plugin-vitest/src/index.js +6 -0
- package/packages/datadog-webpack/index.js +0 -11
- package/packages/dd-trace/index.js +0 -1
- package/packages/dd-trace/src/agent/info.js +6 -5
- package/packages/dd-trace/src/aiguard/client.js +100 -1
- package/packages/dd-trace/src/aiguard/errors.js +41 -0
- package/packages/dd-trace/src/aiguard/evaluation.js +357 -0
- package/packages/dd-trace/src/aiguard/integrations/anthropic.js +70 -0
- package/packages/dd-trace/src/aiguard/integrations/index.js +4 -0
- package/packages/dd-trace/src/aiguard/messages/anthropic.js +423 -0
- package/packages/dd-trace/src/aiguard/messages/openai.js +1 -24
- package/packages/dd-trace/src/aiguard/messages/utils.js +28 -0
- package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +1 -11
- package/packages/dd-trace/src/aiguard/sdk.js +22 -278
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +9 -12
- package/packages/dd-trace/src/appsec/reporter.js +2 -0
- package/packages/dd-trace/src/appsec/telemetry/index.js +13 -0
- package/packages/dd-trace/src/appsec/telemetry/rasp.js +16 -0
- package/packages/dd-trace/src/appsec/telemetry/waf.js +24 -0
- package/packages/dd-trace/src/carrier.js +107 -48
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +1 -0
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +5 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +29 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +27 -9
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +21 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +164 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +26 -8
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +365 -32
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -4
- package/packages/dd-trace/src/ci-visibility/exporters/request.js +201 -0
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +5 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +9 -5
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +7 -4
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -2
- package/packages/dd-trace/src/ci-visibility/requests/rate-limit.js +39 -0
- package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -6
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +4 -2
- package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +10 -4
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +5 -5
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -0
- package/packages/dd-trace/src/config/index.js +13 -2
- package/packages/dd-trace/src/config/major-overrides.js +7 -0
- package/packages/dd-trace/src/config/supported-configurations.json +14 -0
- package/packages/dd-trace/src/datastreams/index.js +2 -0
- package/packages/dd-trace/src/datastreams/manager.js +9 -2
- package/packages/dd-trace/src/datastreams/processor.js +15 -13
- package/packages/dd-trace/src/datastreams/size.js +5 -0
- package/packages/dd-trace/src/debugger/constants.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/index.js +5 -11
- package/packages/dd-trace/src/debugger/index.js +4 -2
- package/packages/dd-trace/src/debugger/inspect-segment.js +154 -0
- package/packages/dd-trace/src/evp_proxy/constants.js +8 -0
- package/packages/dd-trace/src/evp_proxy/direct.js +64 -0
- package/packages/dd-trace/src/evp_proxy/discovery.js +133 -0
- package/packages/dd-trace/src/evp_proxy/path.js +22 -0
- package/packages/dd-trace/src/exporters/agent/writer.js +49 -9
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +6 -4
- package/packages/dd-trace/src/exporters/common/request.js +5 -2
- package/packages/dd-trace/src/exporters/common/writer.js +11 -6
- package/packages/dd-trace/src/llmobs/experiments/client.js +167 -5
- package/packages/dd-trace/src/llmobs/experiments/dataset.js +484 -92
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +302 -29
- package/packages/dd-trace/src/llmobs/experiments/index.js +75 -64
- package/packages/dd-trace/src/llmobs/experiments/noop.js +135 -7
- package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
- package/packages/dd-trace/src/llmobs/experiments/util.js +101 -9
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +12 -3
- package/packages/dd-trace/src/llmobs/plugins/base.js +4 -2
- package/packages/dd-trace/src/noop/proxy.js +3 -4
- package/packages/dd-trace/src/openfeature/constants/constants.js +0 -18
- package/packages/dd-trace/src/openfeature/flagging_provider.js +18 -2
- package/packages/dd-trace/src/openfeature/index.js +7 -4
- package/packages/dd-trace/src/openfeature/remote_config.js +1 -1
- package/packages/dd-trace/src/openfeature/writers/base.js +153 -11
- package/packages/dd-trace/src/openfeature/writers/exposures.js +62 -14
- package/packages/dd-trace/src/openfeature/writers/util.js +97 -15
- package/packages/dd-trace/src/opentelemetry/context_manager.js +7 -7
- package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +2 -1
- package/packages/dd-trace/src/opentelemetry/logs/logger.js +67 -11
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +14 -3
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +25 -12
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +2 -5
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +96 -43
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +22 -13
- package/packages/dd-trace/src/opentracing/tracer.js +5 -2
- package/packages/dd-trace/src/otel-thread-ctx.js +387 -0
- package/packages/dd-trace/src/plugin_manager.js +3 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/jest.js +4 -3
- package/packages/dd-trace/src/plugins/util/test.js +9 -9
- package/packages/dd-trace/src/plugins/util/web.js +3 -0
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/space.js +1 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +37 -90
- package/packages/dd-trace/src/profiling/webspan-utils.js +45 -0
- package/packages/dd-trace/src/proxy.js +38 -29
- package/packages/dd-trace/src/ritm.js +9 -2
- package/packages/dd-trace/src/serverless.js +37 -0
- package/packages/dd-trace/src/span_format.js +1 -0
- package/packages/dd-trace/src/span_stats.js +30 -3
- package/packages/dd-trace/src/storage-channels.js +86 -0
- package/packages/dd-trace/src/telemetry/metrics.js +62 -8
- package/packages/dd-trace/src/telemetry/send-data.js +1 -0
- package/packages/dd-trace/src/tracer.js +9 -2
- package/packages/dd-trace/src/tracer_metadata.js +14 -1
- package/packages/dd-trace/src/web-tags-cache.js +132 -0
- package/vendor/dist/@datadog/openfeature-node-server/LICENSE +201 -0
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -0
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/https-proxy-agent/LICENSE +22 -0
- package/vendor/dist/https-proxy-agent/index.js +4 -0
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/proxy-from-env/LICENSE +20 -0
- package/vendor/dist/proxy-from-env/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/optional-peer-bundler.js +0 -65
- package/packages/datadog-webpack/src/optional-peer-loader.js +0 -17
- package/packages/dd-trace/src/feature-registry.js +0 -29
- package/packages/dd-trace/src/openfeature/register.js +0 -35
- package/packages/dd-trace/src/openfeature/require-provider.js +0 -18
|
@@ -9,6 +9,23 @@ const FIELD_HAS = 4
|
|
|
9
9
|
const FIELD_DELETE = 8
|
|
10
10
|
const FIELD_NAME_LENGTH = 16
|
|
11
11
|
|
|
12
|
+
const b3FlagsHeader = 'x-b3-flags'
|
|
13
|
+
const b3Header = 'b3'
|
|
14
|
+
const b3SampledHeader = 'x-b3-sampled'
|
|
15
|
+
const b3SpanIdHeader = 'x-b3-spanid'
|
|
16
|
+
const b3TraceIdHeader = 'x-b3-traceid'
|
|
17
|
+
const baggageHeader = 'baggage'
|
|
18
|
+
const datadogOriginHeader = 'x-datadog-origin'
|
|
19
|
+
const datadogParentIdHeader = 'x-datadog-parent-id'
|
|
20
|
+
const datadogSamplingPriorityHeader = 'x-datadog-sampling-priority'
|
|
21
|
+
const datadogTagsHeader = 'x-datadog-tags'
|
|
22
|
+
const datadogTraceIdHeader = 'x-datadog-trace-id'
|
|
23
|
+
const dsmBase64Header = 'dd-pathway-ctx-base64'
|
|
24
|
+
const dsmBinaryHeader = 'dd-pathway-ctx'
|
|
25
|
+
const sqsdHeader = 'x-aws-sqsd-attr-_datadog'
|
|
26
|
+
const traceparentHeader = 'traceparent'
|
|
27
|
+
const tracestateHeader = 'tracestate'
|
|
28
|
+
|
|
12
29
|
/** @type {Record<string, unknown>} */
|
|
13
30
|
const carrierOperations = {}
|
|
14
31
|
|
|
@@ -24,7 +41,7 @@ const carrierOperations = {}
|
|
|
24
41
|
/**
|
|
25
42
|
* @template Value
|
|
26
43
|
* @typedef {object} CarrierField
|
|
27
|
-
* @property {(carrier: Carrier) => Value | undefined} read
|
|
44
|
+
* @property {((carrier: Carrier) => Value | undefined) | undefined} read
|
|
28
45
|
* @property {(carrier: Carrier, value: Value) => void} write
|
|
29
46
|
* @property {(carrier: Carrier) => boolean} has
|
|
30
47
|
* @property {(carrier: Carrier) => void} delete
|
|
@@ -53,19 +70,13 @@ function defineCapability (name, operations, capability) {
|
|
|
53
70
|
* @template Value
|
|
54
71
|
* @param {string} fieldName
|
|
55
72
|
* @param {string} headerName
|
|
56
|
-
* @param {(
|
|
73
|
+
* @param {((carrier: Carrier) => Value | undefined) | undefined} read
|
|
57
74
|
* @param {number} operations
|
|
58
75
|
* @returns {CarrierField<Value>}
|
|
59
76
|
*/
|
|
60
|
-
function defineField (fieldName, headerName,
|
|
77
|
+
function defineField (fieldName, headerName, read, operations) {
|
|
61
78
|
return defineCapability(fieldName, operations, {
|
|
62
|
-
|
|
63
|
-
* @param {Carrier} carrier
|
|
64
|
-
* @returns {Value | undefined}
|
|
65
|
-
*/
|
|
66
|
-
read (carrier) {
|
|
67
|
-
return resolve(carrier[headerName])
|
|
68
|
-
},
|
|
79
|
+
read,
|
|
69
80
|
|
|
70
81
|
/**
|
|
71
82
|
* @param {Carrier} carrier
|
|
@@ -183,48 +194,96 @@ function readLastPathway (value) {
|
|
|
183
194
|
return result
|
|
184
195
|
}
|
|
185
196
|
|
|
197
|
+
/** @param {Carrier} carrier */
|
|
198
|
+
function readB3Flags (carrier) { return readLastText(carrier[b3FlagsHeader]) }
|
|
199
|
+
|
|
200
|
+
/** @param {Carrier} carrier */
|
|
201
|
+
function readB3 (carrier) { return readLastText(carrier[b3Header]) }
|
|
202
|
+
|
|
203
|
+
/** @param {Carrier} carrier */
|
|
204
|
+
function readB3Sampled (carrier) { return readLastText(carrier[b3SampledHeader]) }
|
|
205
|
+
|
|
206
|
+
/** @param {Carrier} carrier */
|
|
207
|
+
function readB3SpanId (carrier) { return readLastText(carrier[b3SpanIdHeader]) }
|
|
208
|
+
|
|
209
|
+
/** @param {Carrier} carrier */
|
|
210
|
+
function readB3TraceId (carrier) { return readLastText(carrier[b3TraceIdHeader]) }
|
|
211
|
+
|
|
212
|
+
/** @param {Carrier} carrier */
|
|
213
|
+
function readBaggage (carrier) { return readListText(carrier[baggageHeader]) }
|
|
214
|
+
|
|
215
|
+
/** @param {Carrier} carrier */
|
|
216
|
+
function readDatadogOrigin (carrier) { return readLastText(carrier[datadogOriginHeader]) }
|
|
217
|
+
|
|
218
|
+
/** @param {Carrier} carrier */
|
|
219
|
+
function readDatadogParentId (carrier) { return readLastText(carrier[datadogParentIdHeader]) }
|
|
220
|
+
|
|
221
|
+
/** @param {Carrier} carrier */
|
|
222
|
+
function readDatadogSamplingPriority (carrier) { return readLastText(carrier[datadogSamplingPriorityHeader]) }
|
|
223
|
+
|
|
224
|
+
/** @param {Carrier} carrier */
|
|
225
|
+
function readDatadogTags (carrier) { return readListText(carrier[datadogTagsHeader]) }
|
|
226
|
+
|
|
227
|
+
/** @param {Carrier} carrier */
|
|
228
|
+
function readDatadogTraceId (carrier) { return readLastText(carrier[datadogTraceIdHeader]) }
|
|
229
|
+
|
|
230
|
+
/** @param {Carrier} carrier */
|
|
231
|
+
function readDsmBase64 (carrier) { return readLastPathway(carrier[dsmBase64Header]) }
|
|
232
|
+
|
|
233
|
+
/** @param {Carrier} carrier */
|
|
234
|
+
function readDsmBinary (carrier) { return readLastPathway(carrier[dsmBinaryHeader]) }
|
|
235
|
+
|
|
236
|
+
/** @param {Carrier} carrier */
|
|
237
|
+
function readSqsd (carrier) { return readLastText(carrier[sqsdHeader]) }
|
|
238
|
+
|
|
239
|
+
/** @param {Carrier} carrier */
|
|
240
|
+
function readTraceparent (carrier) { return readUniqueText(carrier[traceparentHeader]) }
|
|
241
|
+
|
|
242
|
+
/** @param {Carrier} carrier */
|
|
243
|
+
function readTracestate (carrier) { return readListText(carrier[tracestateHeader]) }
|
|
244
|
+
|
|
186
245
|
const datadogTraceId = defineField(
|
|
187
246
|
'datadogTraceId',
|
|
188
|
-
|
|
189
|
-
|
|
247
|
+
datadogTraceIdHeader,
|
|
248
|
+
readDatadogTraceId,
|
|
190
249
|
FIELD_READ | FIELD_WRITE
|
|
191
250
|
)
|
|
192
251
|
const datadogParentId = defineField(
|
|
193
252
|
'datadogParentId',
|
|
194
|
-
|
|
195
|
-
|
|
253
|
+
datadogParentIdHeader,
|
|
254
|
+
readDatadogParentId,
|
|
196
255
|
FIELD_READ | FIELD_WRITE | FIELD_DELETE
|
|
197
256
|
)
|
|
198
257
|
const datadogOrigin = defineField(
|
|
199
258
|
'datadogOrigin',
|
|
200
|
-
|
|
201
|
-
|
|
259
|
+
datadogOriginHeader,
|
|
260
|
+
readDatadogOrigin,
|
|
202
261
|
FIELD_READ | FIELD_WRITE
|
|
203
262
|
)
|
|
204
263
|
const datadogSamplingPriority = defineField(
|
|
205
264
|
'datadogSamplingPriority',
|
|
206
|
-
|
|
207
|
-
|
|
265
|
+
datadogSamplingPriorityHeader,
|
|
266
|
+
readDatadogSamplingPriority,
|
|
208
267
|
FIELD_READ | FIELD_WRITE
|
|
209
268
|
)
|
|
210
|
-
defineField('datadogTags',
|
|
211
|
-
defineField('baggage',
|
|
212
|
-
const b3TraceId = defineField('b3TraceId',
|
|
213
|
-
const b3SpanId = defineField('b3SpanId',
|
|
214
|
-
const b3ParentId = defineField('b3ParentId', 'x-b3-parentspanid',
|
|
215
|
-
const b3Sampled = defineField('b3Sampled',
|
|
216
|
-
const b3Flags = defineField('b3Flags',
|
|
217
|
-
const b3 = defineField('b3',
|
|
218
|
-
defineField('sqsd',
|
|
219
|
-
const traceparent = defineField('traceparent',
|
|
220
|
-
const tracestate = defineField('tracestate',
|
|
269
|
+
defineField('datadogTags', datadogTagsHeader, readDatadogTags, FIELD_READ | FIELD_WRITE)
|
|
270
|
+
defineField('baggage', baggageHeader, readBaggage, FIELD_READ | FIELD_WRITE)
|
|
271
|
+
const b3TraceId = defineField('b3TraceId', b3TraceIdHeader, readB3TraceId, FIELD_READ | FIELD_WRITE)
|
|
272
|
+
const b3SpanId = defineField('b3SpanId', b3SpanIdHeader, readB3SpanId, FIELD_READ | FIELD_WRITE)
|
|
273
|
+
const b3ParentId = defineField('b3ParentId', 'x-b3-parentspanid', undefined, FIELD_WRITE)
|
|
274
|
+
const b3Sampled = defineField('b3Sampled', b3SampledHeader, readB3Sampled, FIELD_READ | FIELD_WRITE)
|
|
275
|
+
const b3Flags = defineField('b3Flags', b3FlagsHeader, readB3Flags, FIELD_READ | FIELD_WRITE)
|
|
276
|
+
const b3 = defineField('b3', b3Header, readB3, FIELD_READ | FIELD_WRITE)
|
|
277
|
+
defineField('sqsd', sqsdHeader, readSqsd, FIELD_READ)
|
|
278
|
+
const traceparent = defineField('traceparent', traceparentHeader, readTraceparent, FIELD_READ | FIELD_WRITE)
|
|
279
|
+
const tracestate = defineField('tracestate', tracestateHeader, readTracestate, FIELD_READ | FIELD_WRITE)
|
|
221
280
|
const dsmBase64 = defineField(
|
|
222
281
|
'dsmBase64',
|
|
223
|
-
|
|
224
|
-
|
|
282
|
+
dsmBase64Header,
|
|
283
|
+
readDsmBase64,
|
|
225
284
|
FIELD_READ | FIELD_WRITE | FIELD_HAS | FIELD_NAME_LENGTH
|
|
226
285
|
)
|
|
227
|
-
const dsmBinary = defineField('dsmBinary',
|
|
286
|
+
const dsmBinary = defineField('dsmBinary', dsmBinaryHeader, readDsmBinary, FIELD_READ | FIELD_HAS)
|
|
228
287
|
|
|
229
288
|
const legacyBaggagePrefix = 'ot-baggage-'
|
|
230
289
|
// RFC 7230 `token`, compatible with Node.js header-name validation.
|
|
@@ -314,23 +373,23 @@ function pickDsm (carrier) {
|
|
|
314
373
|
* @property {typeof dsmBinary.has} hasDsmBinary
|
|
315
374
|
* @property {typeof pickDsm} pickDsm
|
|
316
375
|
* @property {typeof pickTextMap} pickTextMap
|
|
317
|
-
* @property {
|
|
318
|
-
* @property {typeof
|
|
319
|
-
* @property {typeof
|
|
320
|
-
* @property {typeof
|
|
321
|
-
* @property {typeof
|
|
322
|
-
* @property {typeof
|
|
323
|
-
* @property {typeof
|
|
324
|
-
* @property {typeof
|
|
325
|
-
* @property {typeof
|
|
326
|
-
* @property {
|
|
327
|
-
* @property {typeof
|
|
328
|
-
* @property {typeof
|
|
329
|
-
* @property {typeof
|
|
376
|
+
* @property {typeof readBaggage} readBaggage
|
|
377
|
+
* @property {typeof readB3} readB3
|
|
378
|
+
* @property {typeof readB3Flags} readB3Flags
|
|
379
|
+
* @property {typeof readB3Sampled} readB3Sampled
|
|
380
|
+
* @property {typeof readB3SpanId} readB3SpanId
|
|
381
|
+
* @property {typeof readB3TraceId} readB3TraceId
|
|
382
|
+
* @property {typeof readDatadogOrigin} readDatadogOrigin
|
|
383
|
+
* @property {typeof readDatadogParentId} readDatadogParentId
|
|
384
|
+
* @property {typeof readDatadogSamplingPriority} readDatadogSamplingPriority
|
|
385
|
+
* @property {typeof readDatadogTags} readDatadogTags
|
|
386
|
+
* @property {typeof readDatadogTraceId} readDatadogTraceId
|
|
387
|
+
* @property {typeof readDsmBase64} readDsmBase64
|
|
388
|
+
* @property {typeof readDsmBinary} readDsmBinary
|
|
330
389
|
* @property {(carrier: Carrier, target: Record<string, string>) => void} readLegacyBaggage
|
|
331
|
-
* @property {
|
|
332
|
-
* @property {typeof
|
|
333
|
-
* @property {typeof
|
|
390
|
+
* @property {typeof readSqsd} readSqsd
|
|
391
|
+
* @property {typeof readTraceparent} readTraceparent
|
|
392
|
+
* @property {typeof readTracestate} readTracestate
|
|
334
393
|
* @property {(carrier: Carrier, value: string) => void} writeBaggage
|
|
335
394
|
* @property {typeof b3.write} writeB3
|
|
336
395
|
* @property {typeof b3Flags.write} writeB3Flags
|
|
@@ -92,6 +92,7 @@ function removeEmptyCaptureProperties (value) {
|
|
|
92
92
|
if (current.fields === null || (
|
|
93
93
|
current.fields &&
|
|
94
94
|
typeof current.fields === 'object' &&
|
|
95
|
+
// eslint-disable-next-line no-restricted-syntax -- snapshot field names are user variables; no key to probe
|
|
95
96
|
Object.keys(current.fields).length === 0
|
|
96
97
|
)) {
|
|
97
98
|
delete current.fields
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const getConfig = require('../../config')
|
|
4
|
-
const
|
|
4
|
+
const { EVP_SUBDOMAIN_HEADER_NAME } = require('../../evp_proxy/constants')
|
|
5
|
+
const { joinEVPProxyPath } = require('../../evp_proxy/path')
|
|
5
6
|
const id = require('../../id')
|
|
6
7
|
const log = require('../../log')
|
|
7
|
-
|
|
8
8
|
const {
|
|
9
9
|
incrementCountMetric,
|
|
10
10
|
distributionMetric,
|
|
@@ -14,8 +14,8 @@ const {
|
|
|
14
14
|
TELEMETRY_KNOWN_TESTS_RESPONSE_TESTS,
|
|
15
15
|
TELEMETRY_KNOWN_TESTS_RESPONSE_BYTES,
|
|
16
16
|
} = require('../../ci-visibility/telemetry')
|
|
17
|
-
|
|
18
17
|
const { getNumFromKnownTests } = require('../../plugins/util/test')
|
|
18
|
+
const request = require('../requests/request')
|
|
19
19
|
const { buildCacheKey, writeToCache, withCache } = require('../requests/fs-cache')
|
|
20
20
|
const { validateKnownTestsResponse } = require('../test-optimization-http-cache-schema')
|
|
21
21
|
|
|
@@ -162,8 +162,8 @@ function fetchFromApi ({
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
if (isEvpProxy) {
|
|
165
|
-
options.path =
|
|
166
|
-
options.headers[
|
|
165
|
+
options.path = joinEVPProxyPath(evpProxyPrefix, '/api/v2/ci/libraries/tests')
|
|
166
|
+
options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'api'
|
|
167
167
|
} else {
|
|
168
168
|
const { DD_API_KEY } = getConfig()
|
|
169
169
|
if (!DD_API_KEY) {
|
|
@@ -4,9 +4,12 @@ const AgentWriter = require('../../../exporters/agent/writer')
|
|
|
4
4
|
const AgentlessWriter = require('../agentless/writer')
|
|
5
5
|
const CoverageWriter = require('../agentless/coverage-writer')
|
|
6
6
|
const CiVisibilityExporter = require('../ci-visibility-exporter')
|
|
7
|
+
const request = require('../request')
|
|
7
8
|
const { fetchAgentInfo } = require('../../../agent/info')
|
|
8
9
|
const { DEBUGGER_INPUT_V1 } = require('../../../debugger/constants')
|
|
9
10
|
|
|
11
|
+
// Product-specific discovery: newest advertised version, skip v3 (citestcycle), gzip if >= v4.
|
|
12
|
+
// Shared `evp_proxy` discovery is an explicit path allowlist and does not cover this contract.
|
|
10
13
|
const AGENT_EVP_PROXY_PATH_PREFIX = '/evp_proxy/v'
|
|
11
14
|
const AGENT_EVP_PROXY_PATH_REGEX = /\/evp_proxy\/v(\d+)\/?/
|
|
12
15
|
|
|
@@ -43,9 +46,21 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
43
46
|
testOptimization,
|
|
44
47
|
} = config
|
|
45
48
|
|
|
49
|
+
const initializationController = new AbortController()
|
|
50
|
+
const initializationOptions = { signal: initializationController.signal }
|
|
51
|
+
this._initializationRequest = {
|
|
52
|
+
controller: initializationController,
|
|
53
|
+
options: initializationOptions,
|
|
54
|
+
}
|
|
55
|
+
|
|
46
56
|
fetchAgentInfo(this._url, (err, agentInfo) => {
|
|
57
|
+
const initializationFinalFlush = this._initializationRequest?.finalFlush
|
|
58
|
+
this._initializationRequest = undefined
|
|
59
|
+
const initializationAborted = initializationController.signal.aborted
|
|
60
|
+
const agentInfoError = err || (initializationAborted ? initializationController.signal.reason : undefined)
|
|
61
|
+
|
|
47
62
|
this._isInitialized = true
|
|
48
|
-
let latestEvpProxyVersion = getLatestEvpProxyVersion(
|
|
63
|
+
let latestEvpProxyVersion = getLatestEvpProxyVersion(agentInfoError, agentInfo)
|
|
49
64
|
const isEvpCompatible = latestEvpProxyVersion >= 2
|
|
50
65
|
this._isGzipCompatible = latestEvpProxyVersion >= 4
|
|
51
66
|
|
|
@@ -72,7 +87,7 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
72
87
|
// path with evpProxyPrefix and sets X-Datadog-EVP-Subdomain: api (see uploadTestScreenshot).
|
|
73
88
|
this._testScreenshotUploadUrl = this._url
|
|
74
89
|
if (testOptimization.DD_TEST_FAILED_TEST_REPLAY_ENABLED) {
|
|
75
|
-
const canFowardLogs = getCanForwardDebuggerLogs(
|
|
90
|
+
const canFowardLogs = getCanForwardDebuggerLogs(agentInfoError, agentInfo)
|
|
76
91
|
if (canFowardLogs) {
|
|
77
92
|
const DynamicInstrumentationLogsWriter = require('../agentless/di-logs-writer')
|
|
78
93
|
this._logsWriter = new DynamicInstrumentationLogsWriter({
|
|
@@ -89,14 +104,25 @@ class AgentProxyCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
89
104
|
lookup,
|
|
90
105
|
protocolVersion,
|
|
91
106
|
headers,
|
|
107
|
+
isTestOptimization: true,
|
|
92
108
|
})
|
|
93
109
|
// coverages will never be used, so we discard them
|
|
94
110
|
this._coverageBuffer = []
|
|
95
111
|
}
|
|
96
112
|
this._resolveCanUseCiVisProtocol(isEvpCompatible)
|
|
113
|
+
if (initializationAborted) {
|
|
114
|
+
this.resetUncodedTraces()
|
|
115
|
+
this.resetDeferredTestSuiteSpans()
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
if (isEvpCompatible) {
|
|
119
|
+
if (initializationFinalFlush) this.exportDeferredTestSuiteSpans()
|
|
120
|
+
} else {
|
|
121
|
+
this.resetDeferredTestSuiteSpans()
|
|
122
|
+
}
|
|
97
123
|
this.exportUncodedTraces()
|
|
98
124
|
this.exportUncodedCoverages()
|
|
99
|
-
})
|
|
125
|
+
}, initializationOptions, request)
|
|
100
126
|
}
|
|
101
127
|
|
|
102
128
|
setUrl (url, coverageUrl) {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const getConfig = require('../../../config')
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const { EVP_SUBDOMAIN_HEADER_NAME } = require('../../../evp_proxy/constants')
|
|
4
|
+
const { joinEVPProxyPath } = require('../../../evp_proxy/path')
|
|
5
5
|
const { safeJSONStringify } = require('../../../exporters/common/util')
|
|
6
|
+
const log = require('../../../log')
|
|
6
7
|
|
|
7
|
-
const { CoverageCIVisibilityEncoder } = require('../../../encode/coverage-ci-visibility')
|
|
8
|
-
const BaseWriter = require('../../../exporters/common/writer')
|
|
9
8
|
const {
|
|
10
9
|
incrementCountMetric,
|
|
11
10
|
distributionMetric,
|
|
@@ -15,16 +14,34 @@ const {
|
|
|
15
14
|
TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_ERRORS,
|
|
16
15
|
TELEMETRY_ENDPOINT_PAYLOAD_DROPPED,
|
|
17
16
|
} = require('../../../ci-visibility/telemetry')
|
|
17
|
+
const { CoverageCIVisibilityEncoder } = require('../../../encode/coverage-ci-visibility')
|
|
18
|
+
const BaseWriter = require('../../../exporters/common/writer')
|
|
19
|
+
const request = require('../request')
|
|
20
|
+
const TestOptimizationRequestTracker = require('./request-tracker')
|
|
18
21
|
|
|
19
22
|
class Writer extends BaseWriter {
|
|
23
|
+
#requestTracker
|
|
24
|
+
|
|
20
25
|
constructor ({ url, evpProxyPrefix = '' }) {
|
|
21
26
|
super(...arguments)
|
|
27
|
+
this.#requestTracker = new TestOptimizationRequestTracker(this)
|
|
22
28
|
this._url = url
|
|
23
29
|
this._encoder = new CoverageCIVisibilityEncoder(this)
|
|
24
30
|
this._evpProxyPrefix = evpProxyPrefix
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Flushes buffered coverage, waiting for tracked requests during finalization.
|
|
35
|
+
*
|
|
36
|
+
* @param {(error?: Error) => void} [done]
|
|
37
|
+
* @param {{ deadline?: number }} [options]
|
|
38
|
+
* @returns {void}
|
|
39
|
+
*/
|
|
40
|
+
flush (done, options) {
|
|
41
|
+
this.#requestTracker.flush(done, options)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
_sendPayload (form, _, done, flushOptions) {
|
|
28
45
|
const options = {
|
|
29
46
|
path: '/api/v2/citestcov',
|
|
30
47
|
method: 'POST',
|
|
@@ -34,12 +51,13 @@ class Writer extends BaseWriter {
|
|
|
34
51
|
},
|
|
35
52
|
timeout: 15_000,
|
|
36
53
|
url: this._url,
|
|
54
|
+
deadline: flushOptions?.deadline,
|
|
37
55
|
}
|
|
38
56
|
|
|
39
57
|
if (this._evpProxyPrefix) {
|
|
40
|
-
options.path =
|
|
58
|
+
options.path = joinEVPProxyPath(this._evpProxyPrefix, '/api/v2/citestcov')
|
|
41
59
|
delete options.headers['dd-api-key']
|
|
42
|
-
options.headers[
|
|
60
|
+
options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'citestcov-intake'
|
|
43
61
|
}
|
|
44
62
|
|
|
45
63
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
@@ -50,7 +68,7 @@ class Writer extends BaseWriter {
|
|
|
50
68
|
incrementCountMetric(TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS, { endpoint: 'code_coverage' })
|
|
51
69
|
distributionMetric(TELEMETRY_ENDPOINT_PAYLOAD_BYTES, { endpoint: 'code_coverage' }, form.size())
|
|
52
70
|
|
|
53
|
-
request
|
|
71
|
+
this.#requestTracker.send(request, form, options, (err, res, statusCode) => {
|
|
54
72
|
distributionMetric(
|
|
55
73
|
TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_MS,
|
|
56
74
|
{ endpoint: 'code_coverage' },
|
|
@@ -66,7 +84,7 @@ class Writer extends BaseWriter {
|
|
|
66
84
|
{ endpoint: 'code_coverage' }
|
|
67
85
|
)
|
|
68
86
|
log.error('Error sending CI coverage payload', err)
|
|
69
|
-
done()
|
|
87
|
+
done(err)
|
|
70
88
|
return
|
|
71
89
|
}
|
|
72
90
|
log.debug('Response from the intake:', res)
|
|
@@ -1,27 +1,42 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const getConfig = require('../../../config')
|
|
3
|
-
const request = require('../../../exporters/common/request')
|
|
4
3
|
const log = require('../../../log')
|
|
5
4
|
const { safeJSONStringify } = require('../../../exporters/common/util')
|
|
6
5
|
const { JSONEncoder } = require('../../encode/json-encoder')
|
|
7
6
|
const { DEBUGGER_INPUT_V1 } = require('../../../debugger/constants')
|
|
8
|
-
|
|
9
7
|
const BaseWriter = require('../../../exporters/common/writer')
|
|
10
8
|
|
|
9
|
+
const request = require('../request')
|
|
10
|
+
const TestOptimizationRequestTracker = require('./request-tracker')
|
|
11
|
+
|
|
11
12
|
// Writer used by the integration between Dynamic Instrumentation and Test Visibility
|
|
12
13
|
// It is used to encode and send logs to both the logs intake directly and the
|
|
13
14
|
// `/debugger/v1/input` endpoint in the agent, which is a proxy to the logs intake.
|
|
14
15
|
class DynamicInstrumentationLogsWriter extends BaseWriter {
|
|
16
|
+
#requestTracker
|
|
17
|
+
|
|
15
18
|
// TODO: what's a good value for timeout for the logs intake?
|
|
16
19
|
constructor ({ url, timeout = 15_000, isAgentProxy = false }) {
|
|
17
20
|
super(...arguments)
|
|
21
|
+
this.#requestTracker = new TestOptimizationRequestTracker(this)
|
|
18
22
|
this._url = url
|
|
19
23
|
this._encoder = new JSONEncoder()
|
|
20
24
|
this._isAgentProxy = isAgentProxy
|
|
21
25
|
this.timeout = timeout
|
|
22
26
|
}
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Flushes buffered logs, waiting for tracked requests during finalization.
|
|
30
|
+
*
|
|
31
|
+
* @param {(error?: Error) => void} [done]
|
|
32
|
+
* @param {{ deadline?: number }} [options]
|
|
33
|
+
* @returns {void}
|
|
34
|
+
*/
|
|
35
|
+
flush (done, options) {
|
|
36
|
+
this.#requestTracker.flush(done, options)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
_sendPayload (data, _, done, flushOptions) {
|
|
25
40
|
const options = {
|
|
26
41
|
path: '/api/v2/logs',
|
|
27
42
|
method: 'POST',
|
|
@@ -31,6 +46,7 @@ class DynamicInstrumentationLogsWriter extends BaseWriter {
|
|
|
31
46
|
},
|
|
32
47
|
timeout: this.timeout,
|
|
33
48
|
url: this._url,
|
|
49
|
+
deadline: flushOptions?.deadline,
|
|
34
50
|
}
|
|
35
51
|
|
|
36
52
|
if (this._isAgentProxy) {
|
|
@@ -41,10 +57,10 @@ class DynamicInstrumentationLogsWriter extends BaseWriter {
|
|
|
41
57
|
// eslint-disable-next-line eslint-rules/eslint-log-printf-style
|
|
42
58
|
log.debug(() => `Request to the logs intake: ${safeJSONStringify(options)}`)
|
|
43
59
|
|
|
44
|
-
request
|
|
60
|
+
this.#requestTracker.send(request, data, options, (err, res) => {
|
|
45
61
|
if (err) {
|
|
46
62
|
log.error('Error sending DI logs payload', err)
|
|
47
|
-
done()
|
|
63
|
+
done(err)
|
|
48
64
|
return
|
|
49
65
|
}
|
|
50
66
|
log.debug('Response from the logs intake:', res)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const BaseWriter = require('../../../exporters/common/writer')
|
|
4
|
+
|
|
5
|
+
const FINAL_FLUSH_TIMEOUT_CODE = 'ERR_DD_TEST_OPTIMIZATION_FLUSH_TIMEOUT'
|
|
6
|
+
|
|
7
|
+
class TestOptimizationRequestTracker {
|
|
8
|
+
#writer
|
|
9
|
+
#pendingRequests = new Set()
|
|
10
|
+
#finalFlushes = new Set()
|
|
11
|
+
#activeFinalFlush
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates request tracking for a Test Optimization writer.
|
|
15
|
+
*
|
|
16
|
+
* @param {BaseWriter} writer
|
|
17
|
+
*/
|
|
18
|
+
constructor (writer) {
|
|
19
|
+
this.#writer = writer
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Flushes queued payloads and, for a final flush, waits for requests that were
|
|
24
|
+
* already in flight. The absolute deadline prevents Test Optimization from
|
|
25
|
+
* keeping the test process alive indefinitely.
|
|
26
|
+
*
|
|
27
|
+
* @param {(error?: Error) => void} [done]
|
|
28
|
+
* @param {{ deadline?: number }} [options]
|
|
29
|
+
* @returns {void}
|
|
30
|
+
*/
|
|
31
|
+
flush (done, options) {
|
|
32
|
+
if (options?.deadline === undefined) {
|
|
33
|
+
BaseWriter.prototype.flush.call(this.#writer, done, options)
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const finalFlush = {
|
|
38
|
+
deadline: options.deadline,
|
|
39
|
+
done: done || (() => {}),
|
|
40
|
+
error: undefined,
|
|
41
|
+
requests: new Set(),
|
|
42
|
+
timeoutId: undefined,
|
|
43
|
+
writerDone: false,
|
|
44
|
+
}
|
|
45
|
+
this.#finalFlushes.add(finalFlush)
|
|
46
|
+
|
|
47
|
+
for (const pendingRequest of this.#pendingRequests) {
|
|
48
|
+
this.#attachRequest(finalFlush, pendingRequest)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const remaining = Math.max(0, options.deadline - Date.now())
|
|
52
|
+
finalFlush.timeoutId = setTimeout(() => {
|
|
53
|
+
const error = new Error('Timed out flushing Test Optimization data')
|
|
54
|
+
error.code = FINAL_FLUSH_TIMEOUT_CODE
|
|
55
|
+
|
|
56
|
+
finalFlush.error ||= error
|
|
57
|
+
finalFlush.writerDone = true
|
|
58
|
+
|
|
59
|
+
for (const pendingRequest of finalFlush.requests) {
|
|
60
|
+
pendingRequest.finalFlushes.delete(finalFlush)
|
|
61
|
+
if (pendingRequest.finalFlushes.size === 0) {
|
|
62
|
+
pendingRequest.controller.abort(error)
|
|
63
|
+
this.#pendingRequests.delete(pendingRequest)
|
|
64
|
+
} else {
|
|
65
|
+
this.#updateRequestDeadline(pendingRequest)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
finalFlush.requests.clear()
|
|
69
|
+
this.#finishFinalFlush(finalFlush)
|
|
70
|
+
}, remaining)
|
|
71
|
+
|
|
72
|
+
const previousFinalFlush = this.#activeFinalFlush
|
|
73
|
+
this.#activeFinalFlush = finalFlush
|
|
74
|
+
try {
|
|
75
|
+
BaseWriter.prototype.flush.call(this.#writer, (error) => {
|
|
76
|
+
finalFlush.error ||= error
|
|
77
|
+
finalFlush.writerDone = true
|
|
78
|
+
this.#finishFinalFlush(finalFlush)
|
|
79
|
+
}, options)
|
|
80
|
+
} finally {
|
|
81
|
+
this.#activeFinalFlush = previousFinalFlush
|
|
82
|
+
}
|
|
83
|
+
this.#finishFinalFlush(finalFlush)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Sends and tracks a request so a later final flush can wait for or abort it.
|
|
88
|
+
*
|
|
89
|
+
* @param {Function} request
|
|
90
|
+
* @param {Buffer|string|object} data
|
|
91
|
+
* @param {object} options
|
|
92
|
+
* @param {(error: Error|null, result?: string|null, statusCode?: number,
|
|
93
|
+
* headers?: import('node:http').IncomingHttpHeaders) => void} callback
|
|
94
|
+
* @returns {void}
|
|
95
|
+
*/
|
|
96
|
+
send (request, data, options, callback) {
|
|
97
|
+
const controller = new AbortController()
|
|
98
|
+
const requestOptions = { ...options, signal: controller.signal }
|
|
99
|
+
const pendingRequest = { controller, finalFlushes: new Set(), options: requestOptions }
|
|
100
|
+
this.#pendingRequests.add(pendingRequest)
|
|
101
|
+
if (this.#activeFinalFlush) this.#attachRequest(this.#activeFinalFlush, pendingRequest)
|
|
102
|
+
|
|
103
|
+
request(data, requestOptions, (error, result, statusCode, headers) => {
|
|
104
|
+
if (error) {
|
|
105
|
+
for (const finalFlush of pendingRequest.finalFlushes) finalFlush.error ||= error
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
callback(error, result, statusCode, headers)
|
|
110
|
+
} finally {
|
|
111
|
+
this.#pendingRequests.delete(pendingRequest)
|
|
112
|
+
for (const finalFlush of pendingRequest.finalFlushes) {
|
|
113
|
+
finalFlush.requests.delete(pendingRequest)
|
|
114
|
+
this.#finishFinalFlush(finalFlush)
|
|
115
|
+
}
|
|
116
|
+
pendingRequest.finalFlushes.clear()
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Associates a request with the final flush boundary that must wait for it.
|
|
123
|
+
*
|
|
124
|
+
* @param {object} finalFlush
|
|
125
|
+
* @param {object} pendingRequest
|
|
126
|
+
* @returns {void}
|
|
127
|
+
*/
|
|
128
|
+
#attachRequest (finalFlush, pendingRequest) {
|
|
129
|
+
finalFlush.requests.add(pendingRequest)
|
|
130
|
+
pendingRequest.finalFlushes.add(finalFlush)
|
|
131
|
+
this.#updateRequestDeadline(pendingRequest)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Gives a shared request the latest deadline of the flushes waiting for it.
|
|
136
|
+
*
|
|
137
|
+
* @param {object} pendingRequest
|
|
138
|
+
* @returns {void}
|
|
139
|
+
*/
|
|
140
|
+
#updateRequestDeadline (pendingRequest) {
|
|
141
|
+
let deadline = 0
|
|
142
|
+
for (const finalFlush of pendingRequest.finalFlushes) {
|
|
143
|
+
deadline = Math.max(deadline, finalFlush.deadline)
|
|
144
|
+
}
|
|
145
|
+
pendingRequest.options.deadline = deadline
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Completes a final flush callback once its writer and associated requests
|
|
150
|
+
* have settled.
|
|
151
|
+
*
|
|
152
|
+
* @param {object} finalFlush
|
|
153
|
+
* @returns {void}
|
|
154
|
+
*/
|
|
155
|
+
#finishFinalFlush (finalFlush) {
|
|
156
|
+
if (!this.#finalFlushes.has(finalFlush) || !finalFlush.writerDone || finalFlush.requests.size !== 0) return
|
|
157
|
+
|
|
158
|
+
this.#finalFlushes.delete(finalFlush)
|
|
159
|
+
clearTimeout(finalFlush.timeoutId)
|
|
160
|
+
finalFlush.done(finalFlush.error)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = TestOptimizationRequestTracker
|