dd-trace 6.11.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.
Files changed (55) hide show
  1. package/LICENSE-3rdparty.csv +5 -0
  2. package/index.d.ts +20 -3
  3. package/package.json +18 -17
  4. package/packages/datadog-instrumentations/src/cucumber.js +4 -4
  5. package/packages/datadog-instrumentations/src/mocha/utils.js +5 -2
  6. package/packages/datadog-instrumentations/src/playwright-reporter.js +149 -1
  7. package/packages/datadog-instrumentations/src/playwright.js +33 -33
  8. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +6 -8
  9. package/packages/datadog-plugin-playwright/src/index.js +4 -0
  10. package/packages/dd-trace/src/appsec/reporter.js +2 -0
  11. package/packages/dd-trace/src/appsec/telemetry/index.js +13 -0
  12. package/packages/dd-trace/src/appsec/telemetry/rasp.js +16 -0
  13. package/packages/dd-trace/src/appsec/telemetry/waf.js +24 -0
  14. package/packages/dd-trace/src/carrier.js +107 -48
  15. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +5 -5
  16. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +2 -0
  17. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +5 -3
  18. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +4 -2
  19. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -4
  20. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +5 -3
  21. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -2
  22. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +4 -2
  23. package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +4 -2
  24. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +5 -5
  25. package/packages/dd-trace/src/debugger/constants.js +1 -0
  26. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
  27. package/packages/dd-trace/src/debugger/devtools_client/index.js +3 -10
  28. package/packages/dd-trace/src/debugger/index.js +4 -2
  29. package/packages/dd-trace/src/debugger/inspect-segment.js +154 -0
  30. package/packages/dd-trace/src/evp_proxy/constants.js +8 -0
  31. package/packages/dd-trace/src/evp_proxy/direct.js +64 -0
  32. package/packages/dd-trace/src/evp_proxy/discovery.js +133 -0
  33. package/packages/dd-trace/src/evp_proxy/path.js +22 -0
  34. package/packages/dd-trace/src/exporters/common/request.js +5 -2
  35. package/packages/dd-trace/src/llmobs/experiments/client.js +6 -2
  36. package/packages/dd-trace/src/llmobs/experiments/dataset.js +249 -11
  37. package/packages/dd-trace/src/llmobs/experiments/experiment.js +23 -10
  38. package/packages/dd-trace/src/llmobs/experiments/index.js +18 -6
  39. package/packages/dd-trace/src/llmobs/experiments/noop.js +64 -4
  40. package/packages/dd-trace/src/llmobs/experiments/util.js +60 -4
  41. package/packages/dd-trace/src/openfeature/constants/constants.js +0 -18
  42. package/packages/dd-trace/src/openfeature/index.js +7 -4
  43. package/packages/dd-trace/src/openfeature/writers/base.js +153 -11
  44. package/packages/dd-trace/src/openfeature/writers/exposures.js +62 -14
  45. package/packages/dd-trace/src/openfeature/writers/util.js +97 -15
  46. package/packages/dd-trace/src/opentracing/propagation/text_map.js +22 -13
  47. package/packages/dd-trace/src/telemetry/metrics.js +62 -8
  48. package/packages/dd-trace/src/telemetry/send-data.js +1 -0
  49. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  50. package/vendor/dist/https-proxy-agent/LICENSE +22 -0
  51. package/vendor/dist/https-proxy-agent/index.js +4 -0
  52. package/vendor/dist/protobufjs/index.js +1 -1
  53. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  54. package/vendor/dist/proxy-from-env/LICENSE +20 -0
  55. package/vendor/dist/proxy-from-env/index.js +1 -0
@@ -1058,7 +1058,7 @@ function getRepeatedTestReport (task, testName, testSuiteAbsolutePath, testPrope
1058
1058
  const errors = browserEnvironment
1059
1059
  ? normalizeVitestBrowserErrors(result?.errors)
1060
1060
  : result?.errors || []
1061
- const finalAttemptStatus = finalStatus(statuses)
1061
+ const finalAttemptStatus = finalStatus(statuses, testProperties)
1062
1062
  const hasFailure = finalAttemptStatus === 'fail'
1063
1063
  const attempts = []
1064
1064
  const attemptCount = getRepeatedAttemptCount(task, statuses)
@@ -1095,8 +1095,7 @@ function getRepeatedTestReport (task, testName, testSuiteAbsolutePath, testPrope
1095
1095
  testProperties,
1096
1096
  type,
1097
1097
  statuses,
1098
- isFinalAttempt,
1099
- hasFailure
1098
+ isFinalAttempt
1100
1099
  ),
1101
1100
  isRetry: index > 0,
1102
1101
  status: attemptStatus,
@@ -1136,11 +1135,10 @@ function getRepeatedTestReport (task, testName, testSuiteAbsolutePath, testPrope
1136
1135
  * @param {'attempt_to_fix'|'early_flake_detection'|'external'} type
1137
1136
  * @param {string[]} statuses
1138
1137
  * @param {boolean} isFinalAttempt
1139
- * @param {boolean} hasFailure
1140
1138
  * @returns {boolean}
1141
1139
  */
1142
- function hasFailedAllManagedRetries (task, testProperties, type, statuses, isFinalAttempt, hasFailure) {
1143
- if (!isFinalAttempt || !hasFailure || statuses.length === 0 || !statuses.every(status => status === 'fail')) {
1140
+ function hasFailedAllManagedRetries (task, testProperties, type, statuses, isFinalAttempt) {
1141
+ if (!isFinalAttempt || statuses.length === 0 || !statuses.every(status => status === 'fail')) {
1144
1142
  return false
1145
1143
  }
1146
1144
 
@@ -1165,7 +1163,8 @@ function getAttemptToFixFinalStatus (statuses) {
1165
1163
  return statuses.includes('fail') ? 'fail' : 'pass'
1166
1164
  }
1167
1165
 
1168
- function getEarlyFlakeDetectionFinalStatus (statuses) {
1166
+ function getEarlyFlakeDetectionFinalStatus (statuses, testProperties) {
1167
+ if (testProperties.isDisabled || testProperties.isQuarantined) return 'skip'
1169
1168
  return statuses.includes('pass') ? 'pass' : 'fail'
1170
1169
  }
1171
1170
 
@@ -1274,7 +1273,6 @@ function reportFinalTestAttempt (testReport) {
1274
1273
  testProperties,
1275
1274
  'external',
1276
1275
  ['fail'],
1277
- true,
1278
1276
  true
1279
1277
  ),
1280
1278
  isRetry: (result?.retryCount || 0) > 0 || (result?.repeatCount || 0) > 0,
@@ -534,6 +534,7 @@ class PlaywrightPlugin extends CiPlugin {
534
534
  testSourceLine,
535
535
  browserName,
536
536
  isNew,
537
+ isAttemptToFix,
537
538
  isDisabled,
538
539
  isModified,
539
540
  isQuarantined,
@@ -559,6 +560,9 @@ class PlaywrightPlugin extends CiPlugin {
559
560
  if (isNew) {
560
561
  span.setTag(TEST_IS_NEW, 'true')
561
562
  }
563
+ if (isAttemptToFix) {
564
+ span.setTag(TEST_MANAGEMENT_IS_ATTEMPT_TO_FIX, 'true')
565
+ }
562
566
  if (isDisabled) {
563
567
  span.setTag(TEST_MANAGEMENT_IS_DISABLED, 'true')
564
568
  }
@@ -15,6 +15,7 @@ const {
15
15
  incrementWafUpdatesMetric,
16
16
  incrementWafConfigErrorsMetric,
17
17
  incrementWafRequestsMetric,
18
+ incrementRequestDurationMetrics,
18
19
  updateWafRequestsMetricTags,
19
20
  updateRaspRequestsMetricTags,
20
21
  updateRaspRuleSkippedMetricTags,
@@ -608,6 +609,7 @@ function finishRequest (req, res, storedResponseHeaders, requestBody, rootSpan)
608
609
 
609
610
  if (!req) return
610
611
 
612
+ incrementRequestDurationMetrics(req)
611
613
  incrementWafRequestsMetric(req)
612
614
 
613
615
  const tags = rootSpan.context().getTags()
@@ -12,6 +12,7 @@ const {
12
12
  trackRaspMetrics,
13
13
  trackRaspRuleMatch,
14
14
  trackRaspRuleSkipped,
15
+ incrementRaspDurationMetrics,
15
16
  } = require('./rasp')
16
17
  const {
17
18
  addWafRequestMetrics,
@@ -20,6 +21,7 @@ const {
20
21
  incrementWafUpdates,
21
22
  incrementWafConfigErrors,
22
23
  incrementWafRequests,
24
+ incrementWafDurationMetrics,
23
25
  } = require('./waf')
24
26
 
25
27
  const metricsStoreMap = new WeakMap()
@@ -142,6 +144,16 @@ function incrementWafRequestsMetric (req) {
142
144
  metricsStoreMap.delete(req)
143
145
  }
144
146
 
147
+ function incrementRequestDurationMetrics (req) {
148
+ if (!req || !enabled) return
149
+
150
+ const store = getStore(req)
151
+ const requestMetrics = store[DD_TELEMETRY_REQUEST_METRICS]
152
+
153
+ incrementWafDurationMetrics(requestMetrics)
154
+ incrementRaspDurationMetrics(requestMetrics)
155
+ }
156
+
145
157
  function incrementMissingUserLoginMetric (framework, eventType) {
146
158
  if (!enabled) return
147
159
 
@@ -199,6 +211,7 @@ module.exports = {
199
211
  incrementWafUpdatesMetric,
200
212
  incrementWafConfigErrorsMetric,
201
213
  incrementWafRequestsMetric,
214
+ incrementRequestDurationMetrics,
202
215
  incrementMissingUserLoginMetric,
203
216
  incrementMissingUserIdMetric,
204
217
  incrementSdkEventMetric,
@@ -77,6 +77,21 @@ function trackRaspRuleMatch (store, raspRule, blockTriggered, blocked) {
77
77
  appsecMetrics.count('rasp.rule.match', tags).inc(1)
78
78
  }
79
79
 
80
+ function incrementRaspDurationMetrics (requestMetrics) {
81
+ const { raspDuration, raspDurationExt, wafVersion, rulesVersion } = requestMetrics
82
+ if (!raspDuration && !raspDurationExt) return
83
+
84
+ const versionsTags = getVersionsTags(wafVersion, rulesVersion)
85
+
86
+ if (raspDuration) {
87
+ appsecMetrics.distribution('rasp.duration', versionsTags).track(raspDuration)
88
+ }
89
+
90
+ if (raspDurationExt) {
91
+ appsecMetrics.distribution('rasp.duration_ext', versionsTags).track(raspDurationExt)
92
+ }
93
+ }
94
+
80
95
  function trackRaspRuleSkipped (raspRule, reason) {
81
96
  const tags = { reason, rule_type: raspRule.type }
82
97
 
@@ -100,4 +115,5 @@ module.exports = {
100
115
  trackRaspMetrics,
101
116
  trackRaspRuleMatch,
102
117
  trackRaspRuleSkipped,
118
+ incrementRaspDurationMetrics,
103
119
  }
@@ -34,6 +34,14 @@ function addWafRequestMetrics (store, { duration, durationExt, wafTimeout, error
34
34
  function trackWafMetrics (store, metrics) {
35
35
  const versionsTags = getVersionsTags(metrics.wafVersion, metrics.rulesVersion)
36
36
 
37
+ const requestMetrics = store[DD_TELEMETRY_REQUEST_METRICS]
38
+ if (metrics.wafVersion) {
39
+ requestMetrics.wafVersion = metrics.wafVersion
40
+ }
41
+ if (metrics.rulesVersion) {
42
+ requestMetrics.rulesVersion = metrics.rulesVersion
43
+ }
44
+
37
45
  const metricTags = getOrCreateMetricTags(store, versionsTags)
38
46
 
39
47
  if (metrics.blockFailed) {
@@ -118,6 +126,21 @@ function incrementWafRequests (store) {
118
126
  }
119
127
  }
120
128
 
129
+ function incrementWafDurationMetrics (requestMetrics) {
130
+ const { duration, durationExt, wafVersion, rulesVersion } = requestMetrics
131
+ if (!duration && !durationExt) return
132
+
133
+ const versionsTags = getVersionsTags(wafVersion, rulesVersion)
134
+
135
+ if (duration) {
136
+ appsecMetrics.distribution('waf.duration', versionsTags).track(duration)
137
+ }
138
+
139
+ if (durationExt) {
140
+ appsecMetrics.distribution('waf.duration_ext', versionsTags).track(durationExt)
141
+ }
142
+ }
143
+
121
144
  function incrementTruncatedMetrics (metrics, truncationReason) {
122
145
  const truncationTags = { truncation_reason: truncationReason }
123
146
  appsecMetrics.count('waf.input_truncated', truncationTags).inc(1)
@@ -140,4 +163,5 @@ module.exports = {
140
163
  incrementWafUpdates,
141
164
  incrementWafConfigErrors,
142
165
  incrementWafRequests,
166
+ incrementWafDurationMetrics,
143
167
  }
@@ -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 {(value: unknown) => Value | undefined} resolve
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, resolve, operations) {
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
- 'x-datadog-trace-id',
189
- readLastText,
247
+ datadogTraceIdHeader,
248
+ readDatadogTraceId,
190
249
  FIELD_READ | FIELD_WRITE
191
250
  )
192
251
  const datadogParentId = defineField(
193
252
  'datadogParentId',
194
- 'x-datadog-parent-id',
195
- readLastText,
253
+ datadogParentIdHeader,
254
+ readDatadogParentId,
196
255
  FIELD_READ | FIELD_WRITE | FIELD_DELETE
197
256
  )
198
257
  const datadogOrigin = defineField(
199
258
  'datadogOrigin',
200
- 'x-datadog-origin',
201
- readLastText,
259
+ datadogOriginHeader,
260
+ readDatadogOrigin,
202
261
  FIELD_READ | FIELD_WRITE
203
262
  )
204
263
  const datadogSamplingPriority = defineField(
205
264
  'datadogSamplingPriority',
206
- 'x-datadog-sampling-priority',
207
- readLastText,
265
+ datadogSamplingPriorityHeader,
266
+ readDatadogSamplingPriority,
208
267
  FIELD_READ | FIELD_WRITE
209
268
  )
210
- defineField('datadogTags', 'x-datadog-tags', readListText, FIELD_READ | FIELD_WRITE)
211
- defineField('baggage', 'baggage', readListText, FIELD_READ | FIELD_WRITE)
212
- const b3TraceId = defineField('b3TraceId', 'x-b3-traceid', readLastText, FIELD_READ | FIELD_WRITE)
213
- const b3SpanId = defineField('b3SpanId', 'x-b3-spanid', readLastText, FIELD_READ | FIELD_WRITE)
214
- const b3ParentId = defineField('b3ParentId', 'x-b3-parentspanid', readLastText, FIELD_WRITE)
215
- const b3Sampled = defineField('b3Sampled', 'x-b3-sampled', readLastText, FIELD_READ | FIELD_WRITE)
216
- const b3Flags = defineField('b3Flags', 'x-b3-flags', readLastText, FIELD_READ | FIELD_WRITE)
217
- const b3 = defineField('b3', 'b3', readLastText, FIELD_READ | FIELD_WRITE)
218
- defineField('sqsd', 'x-aws-sqsd-attr-_datadog', readLastText, FIELD_READ)
219
- const traceparent = defineField('traceparent', 'traceparent', readUniqueText, FIELD_READ | FIELD_WRITE)
220
- const tracestate = defineField('tracestate', 'tracestate', readListText, FIELD_READ | FIELD_WRITE)
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
- 'dd-pathway-ctx-base64',
224
- readLastPathway,
282
+ dsmBase64Header,
283
+ readDsmBase64,
225
284
  FIELD_READ | FIELD_WRITE | FIELD_HAS | FIELD_NAME_LENGTH
226
285
  )
227
- const dsmBinary = defineField('dsmBinary', 'dd-pathway-ctx', readLastPathway, FIELD_READ | FIELD_HAS)
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 {(carrier: Carrier) => string | undefined} readBaggage
318
- * @property {typeof b3.read} readB3
319
- * @property {typeof b3Flags.read} readB3Flags
320
- * @property {typeof b3Sampled.read} readB3Sampled
321
- * @property {typeof b3SpanId.read} readB3SpanId
322
- * @property {typeof b3TraceId.read} readB3TraceId
323
- * @property {typeof datadogOrigin.read} readDatadogOrigin
324
- * @property {typeof datadogParentId.read} readDatadogParentId
325
- * @property {typeof datadogSamplingPriority.read} readDatadogSamplingPriority
326
- * @property {(carrier: Carrier) => string | undefined} readDatadogTags
327
- * @property {typeof datadogTraceId.read} readDatadogTraceId
328
- * @property {typeof dsmBase64.read} readDsmBase64
329
- * @property {typeof dsmBinary.read} readDsmBinary
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 {(carrier: Carrier) => string | undefined} readSqsd
332
- * @property {typeof traceparent.read} readTraceparent
333
- * @property {typeof tracestate.read} readTracestate
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
@@ -1,10 +1,10 @@
1
1
  'use strict'
2
2
 
3
3
  const getConfig = require('../../config')
4
- const request = require('../requests/request')
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 = `${evpProxyPrefix}/api/v2/ci/libraries/tests`
166
- options.headers['X-Datadog-EVP-Subdomain'] = 'api'
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) {
@@ -8,6 +8,8 @@ const request = require('../request')
8
8
  const { fetchAgentInfo } = require('../../../agent/info')
9
9
  const { DEBUGGER_INPUT_V1 } = require('../../../debugger/constants')
10
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.
11
13
  const AGENT_EVP_PROXY_PATH_PREFIX = '/evp_proxy/v'
12
14
  const AGENT_EVP_PROXY_PATH_REGEX = /\/evp_proxy\/v(\d+)\/?/
13
15
 
@@ -1,7 +1,9 @@
1
1
  'use strict'
2
2
  const getConfig = require('../../../config')
3
- const log = require('../../../log')
3
+ const { EVP_SUBDOMAIN_HEADER_NAME } = require('../../../evp_proxy/constants')
4
+ const { joinEVPProxyPath } = require('../../../evp_proxy/path')
4
5
  const { safeJSONStringify } = require('../../../exporters/common/util')
6
+ const log = require('../../../log')
5
7
 
6
8
  const {
7
9
  incrementCountMetric,
@@ -53,9 +55,9 @@ class Writer extends BaseWriter {
53
55
  }
54
56
 
55
57
  if (this._evpProxyPrefix) {
56
- options.path = `${this._evpProxyPrefix}/api/v2/citestcov`
58
+ options.path = joinEVPProxyPath(this._evpProxyPrefix, '/api/v2/citestcov')
57
59
  delete options.headers['dd-api-key']
58
- options.headers['X-Datadog-EVP-Subdomain'] = 'citestcov-intake'
60
+ options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'citestcov-intake'
59
61
  }
60
62
 
61
63
  // eslint-disable-next-line eslint-rules/eslint-log-printf-style
@@ -1,5 +1,7 @@
1
1
  'use strict'
2
2
  const getConfig = require('../../../config')
3
+ const { EVP_SUBDOMAIN_HEADER_NAME } = require('../../../evp_proxy/constants')
4
+ const { joinEVPProxyPath } = require('../../../evp_proxy/path')
3
5
  const { safeJSONStringify } = require('../../../exporters/common/util')
4
6
  const log = require('../../../log')
5
7
 
@@ -54,9 +56,9 @@ class Writer extends BaseWriter {
54
56
  }
55
57
 
56
58
  if (this._evpProxyPrefix) {
57
- options.path = `${this._evpProxyPrefix}/api/v2/citestcycle`
59
+ options.path = joinEVPProxyPath(this._evpProxyPrefix, '/api/v2/citestcycle')
58
60
  delete options.headers['dd-api-key']
59
- options.headers['X-Datadog-EVP-Subdomain'] = 'citestcycle-intake'
61
+ options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'citestcycle-intake'
60
62
  }
61
63
 
62
64
  // eslint-disable-next-line eslint-rules/eslint-log-printf-style
@@ -4,6 +4,8 @@ const fs = require('fs')
4
4
  const path = require('path')
5
5
 
6
6
  const getConfig = require('../../../config')
7
+ const { EVP_SUBDOMAIN_HEADER_NAME } = require('../../../evp_proxy/constants')
8
+ const { joinEVPProxyPath } = require('../../../evp_proxy/path')
7
9
  const FormData = require('../../../exporters/common/form-data')
8
10
  const request = require('../../../exporters/common/request')
9
11
 
@@ -83,8 +85,8 @@ function getCommitsToUpload ({ url, repositoryUrl, latestCommits, isEvpProxy, ev
83
85
  }
84
86
 
85
87
  if (isEvpProxy) {
86
- options.path = `${evpProxyPrefix}/api/v2/git/repository/search_commits`
87
- options.headers['X-Datadog-EVP-Subdomain'] = 'api'
88
+ options.path = joinEVPProxyPath(evpProxyPrefix, '/api/v2/git/repository/search_commits')
89
+ options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'api'
88
90
  delete options.headers['dd-api-key']
89
91
  }
90
92
 
@@ -179,8 +181,8 @@ function uploadPackFile ({ url, isEvpProxy, evpProxyPrefix, packFileToUpload, re
179
181
  }
180
182
 
181
183
  if (isEvpProxy) {
182
- options.path = `${evpProxyPrefix}/api/v2/git/repository/packfile`
183
- options.headers['X-Datadog-EVP-Subdomain'] = 'api'
184
+ options.path = joinEVPProxyPath(evpProxyPrefix, '/api/v2/git/repository/packfile')
185
+ options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'api'
184
186
  delete options.headers['dd-api-key']
185
187
  }
186
188
 
@@ -1,7 +1,8 @@
1
1
  'use strict'
2
2
 
3
3
  const getConfig = require('../../config')
4
- const request = require('../requests/request')
4
+ const { EVP_SUBDOMAIN_HEADER_NAME } = require('../../evp_proxy/constants')
5
+ const { joinEVPProxyPath } = require('../../evp_proxy/path')
5
6
  const log = require('../../log')
6
7
  const {
7
8
  incrementCountMetric,
@@ -13,6 +14,7 @@ const {
13
14
  TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_TESTS,
14
15
  TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_BYTES,
15
16
  } = require('../../ci-visibility/telemetry')
17
+ const request = require('../requests/request')
16
18
  const { buildCacheKey, writeToCache, withCache } = require('../requests/fs-cache')
17
19
  const { validateSkippableTestsResponse } = require('../test-optimization-http-cache-schema')
18
20
 
@@ -227,8 +229,8 @@ function fetchFromApi ({
227
229
  }
228
230
 
229
231
  if (isEvpProxy) {
230
- options.path = `${evpProxyPrefix}/api/v2/ci/tests/skippable`
231
- options.headers['X-Datadog-EVP-Subdomain'] = 'api'
232
+ options.path = joinEVPProxyPath(evpProxyPrefix, '/api/v2/ci/tests/skippable')
233
+ options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'api'
232
234
  } else {
233
235
  const { DD_API_KEY } = getConfig()
234
236
  if (!DD_API_KEY) {
@@ -1,6 +1,8 @@
1
1
  'use strict'
2
2
 
3
3
  const getConfig = require('../../config')
4
+ const { EVP_SUBDOMAIN_HEADER_NAME } = require('../../evp_proxy/constants')
5
+ const { joinEVPProxyPath } = require('../../evp_proxy/path')
4
6
  const id = require('../../id')
5
7
  const log = require('../../log')
6
8
  const { EARLY_FLAKE_DETECTION_RETRY_BUCKETS, createEfdRetryPolicy } = require('../efd-retry-policy')
@@ -238,8 +240,8 @@ function getLibraryConfiguration ({
238
240
  }
239
241
 
240
242
  if (isEvpProxy) {
241
- options.path = `${evpProxyPrefix}/api/v2/libraries/tests/services/setting`
242
- options.headers['X-Datadog-EVP-Subdomain'] = 'api'
243
+ options.path = joinEVPProxyPath(evpProxyPrefix, '/api/v2/libraries/tests/services/setting')
244
+ options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'api'
243
245
  } else {
244
246
  if (!config.DD_API_KEY) {
245
247
  return done(new Error('Request to settings endpoint was not done because Datadog API key is not defined.'))
@@ -4,6 +4,8 @@ const { closeSync, constants, fstatSync, openSync, readFileSync } = require('nod
4
4
  const { gzipSync } = require('node:zlib')
5
5
 
6
6
  const getConfig = require('../../config')
7
+ const { EVP_SUBDOMAIN_HEADER_NAME } = require('../../evp_proxy/constants')
8
+ const { joinEVPProxyPath } = require('../../evp_proxy/path')
7
9
  const FormData = require('../../exporters/common/form-data')
8
10
  const request = require('../../exporters/common/request')
9
11
  const log = require('../../log')
@@ -98,8 +100,8 @@ function uploadCoverageReport (
98
100
  }
99
101
 
100
102
  if (isEvpProxy) {
101
- options.path = `${evpProxyPrefix}/api/v2/cicovreprt`
102
- options.headers['X-Datadog-EVP-Subdomain'] = 'ci-intake'
103
+ options.path = joinEVPProxyPath(evpProxyPrefix, '/api/v2/cicovreprt')
104
+ options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'ci-intake'
103
105
  } else {
104
106
  options.path = '/api/v2/cicovreprt'
105
107
  options.headers['dd-api-key'] = DD_API_KEY
@@ -4,6 +4,8 @@ const { readFileSync } = require('node:fs')
4
4
  const { extname } = require('node:path')
5
5
 
6
6
  const getConfig = require('../../config')
7
+ const { EVP_SUBDOMAIN_HEADER_NAME } = require('../../evp_proxy/constants')
8
+ const { joinEVPProxyPath } = require('../../evp_proxy/path')
7
9
  const log = require('../../log')
8
10
  const request = require('../exporters/request')
9
11
 
@@ -134,8 +136,8 @@ function uploadTestScreenshot (
134
136
  if (isEvpProxy) {
135
137
  // Agent mode: prefix the evp_proxy path, tell the proxy which subdomain to forward to, and
136
138
  // drop the API key — the Agent injects it. The query params survive the proxy.
137
- options.path = `${evpProxyPrefix}${basePath}?${query}`
138
- options.headers['X-Datadog-EVP-Subdomain'] = 'api'
139
+ options.path = `${joinEVPProxyPath(evpProxyPrefix, basePath)}?${query}`
140
+ options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'api'
139
141
  } else {
140
142
  options.headers['DD-API-KEY'] = DD_API_KEY
141
143
  }
@@ -1,10 +1,10 @@
1
1
  'use strict'
2
2
 
3
3
  const getConfig = require('../../config')
4
- const request = require('../requests/request')
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,7 +14,7 @@ const {
14
14
  TELEMETRY_TEST_MANAGEMENT_TESTS_RESPONSE_TESTS,
15
15
  TELEMETRY_TEST_MANAGEMENT_TESTS_RESPONSE_BYTES,
16
16
  } = require('../telemetry')
17
-
17
+ const request = require('../requests/request')
18
18
  const { buildCacheKey, writeToCache, withCache } = require('../requests/fs-cache')
19
19
  const { validateTestManagementTestsResponse } = require('../test-optimization-http-cache-schema')
20
20
 
@@ -132,8 +132,8 @@ function fetchFromApi ({
132
132
  }
133
133
 
134
134
  if (isEvpProxy) {
135
- options.path = `${evpProxyPrefix}/api/v2/test/libraries/test-management/tests`
136
- options.headers['X-Datadog-EVP-Subdomain'] = 'api'
135
+ options.path = joinEVPProxyPath(evpProxyPrefix, '/api/v2/test/libraries/test-management/tests')
136
+ options.headers[EVP_SUBDOMAIN_HEADER_NAME] = 'api'
137
137
  } else {
138
138
  const { DD_API_KEY } = getConfig()
139
139
  if (!DD_API_KEY) {