dd-trace 6.9.0 → 6.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ci/vitest-no-worker-init-setup.mjs +112 -10
- package/index.d.ts +42 -0
- package/package.json +4 -3
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +111 -6
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +629 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +81 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +83 -1
- package/packages/datadog-instrumentations/src/jest.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -8
- package/packages/datadog-instrumentations/src/mysql.js +45 -15
- package/packages/datadog-instrumentations/src/mysql2.js +119 -18
- package/packages/datadog-instrumentations/src/path-to-regexp.js +67 -1
- package/packages/datadog-instrumentations/src/pg.js +116 -92
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +43 -4
- package/packages/datadog-instrumentations/src/vitest-main.js +169 -17
- package/packages/datadog-instrumentations/src/vitest-util.js +64 -5
- package/packages/datadog-instrumentations/src/vitest-worker.js +150 -25
- package/packages/datadog-instrumentations/src/webdriverio.js +31 -17
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +12 -6
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -5
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -5
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +31 -17
- package/packages/datadog-plugin-jest/src/index.js +5 -4
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -2
- package/packages/datadog-plugin-kafkajs/src/utils.js +65 -7
- package/packages/datadog-plugin-mocha/src/index.js +550 -39
- package/packages/datadog-plugin-mysql/src/index.js +37 -0
- package/packages/datadog-plugin-next/src/index.js +1 -19
- package/packages/datadog-plugin-openai-agents/src/integration.js +278 -69
- package/packages/datadog-plugin-openai-agents/src/processor.js +16 -4
- package/packages/datadog-plugin-pg/src/index.js +1 -0
- package/packages/datadog-plugin-vitest/src/index.js +8 -20
- package/packages/datadog-plugin-ws/src/util.js +2 -1
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +453 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +13 -0
- package/packages/dd-trace/src/carrier.js +356 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +3 -0
- package/packages/dd-trace/src/config/supported-configurations.json +10 -0
- package/packages/dd-trace/src/datastreams/context.js +6 -1
- package/packages/dd-trace/src/datastreams/manager.js +5 -1
- package/packages/dd-trace/src/datastreams/pathway.js +23 -22
- package/packages/dd-trace/src/datastreams/processor.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +5 -0
- package/packages/dd-trace/src/llmobs/index.js +34 -2
- package/packages/dd-trace/src/llmobs/span_processor.js +16 -0
- package/packages/dd-trace/src/llmobs/tagger.js +96 -0
- package/packages/dd-trace/src/llmobs/util.js +78 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +126 -120
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +4 -8
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/{datadog-plugin-jest/src/util.js → dd-trace/src/plugins/util/jest.js} +1 -62
- package/packages/dd-trace/src/plugins/util/test.js +84 -5
- package/packages/dd-trace/src/plugins/util/web.js +53 -2
|
@@ -8,17 +8,18 @@ const { getLageTestSessionName } = require('../../ci-visibility/lage')
|
|
|
8
8
|
const log = require('../../log')
|
|
9
9
|
const { getEnvironmentVariable, getValueFromEnvSources } = require('../../config/helper')
|
|
10
10
|
const { getSegment } = require('../../util')
|
|
11
|
+
const { parse } = require('../../../../../vendor/dist/jest-docblock')
|
|
11
12
|
const satisfies = require('../../../../../vendor/dist/semifies')
|
|
12
13
|
|
|
13
14
|
const istanbul = require('../../../../../vendor/dist/istanbul-lib-coverage')
|
|
14
15
|
|
|
16
|
+
const { writeDatadogParentId, writeDatadogTraceId } = require('../../carrier')
|
|
15
17
|
const id = require('../../id')
|
|
16
18
|
const {
|
|
17
19
|
incrementCountMetric,
|
|
18
20
|
TELEMETRY_GIT_COMMIT_SHA_DISCREPANCY,
|
|
19
21
|
TELEMETRY_GIT_SHA_MATCH,
|
|
20
22
|
} = require('../../ci-visibility/telemetry')
|
|
21
|
-
|
|
22
23
|
const { SPAN_TYPE, RESOURCE_NAME, SAMPLING_PRIORITY } = require('../../../../../ext/tags')
|
|
23
24
|
const { SAMPLING_RULE_DECISION } = require('../../constants')
|
|
24
25
|
const { AUTO_KEEP } = require('../../../../../ext/priority')
|
|
@@ -195,6 +196,8 @@ const VITEST_WORKER_TRACE_PAYLOAD_CODE = 100
|
|
|
195
196
|
const VITEST_WORKER_COVERAGE_PAYLOAD_CODE = 101
|
|
196
197
|
const VITEST_WORKER_LOGS_PAYLOAD_CODE = 102
|
|
197
198
|
const VITEST_WORKER_TELEMETRY_PAYLOAD_CODE = 103
|
|
199
|
+
const VITEST_WORKER_EFD_SUITE_ADMISSION_REQUEST_CODE = 104
|
|
200
|
+
const VITEST_WORKER_EFD_SUITE_ADMISSION_RESPONSE_CODE = 105
|
|
198
201
|
|
|
199
202
|
const TEST_IS_TEST_FRAMEWORK_WORKER = 'test.is_test_framework_worker'
|
|
200
203
|
|
|
@@ -489,6 +492,8 @@ module.exports = {
|
|
|
489
492
|
VITEST_WORKER_COVERAGE_PAYLOAD_CODE,
|
|
490
493
|
VITEST_WORKER_LOGS_PAYLOAD_CODE,
|
|
491
494
|
VITEST_WORKER_TELEMETRY_PAYLOAD_CODE,
|
|
495
|
+
VITEST_WORKER_EFD_SUITE_ADMISSION_REQUEST_CODE,
|
|
496
|
+
VITEST_WORKER_EFD_SUITE_ADMISSION_RESPONSE_CODE,
|
|
492
497
|
TEST_IS_TEST_FRAMEWORK_WORKER,
|
|
493
498
|
TEST_SOURCE_START,
|
|
494
499
|
TEST_SKIPPED_BY_ITR,
|
|
@@ -504,6 +509,7 @@ module.exports = {
|
|
|
504
509
|
getTestParametersString,
|
|
505
510
|
finishAllTraceSpans,
|
|
506
511
|
getTestParentSpan,
|
|
512
|
+
isMarkedAsUnskippable,
|
|
507
513
|
getTestSuitePath,
|
|
508
514
|
getCodeOwnersFileEntries,
|
|
509
515
|
getCodeOwnersForFilename,
|
|
@@ -544,6 +550,7 @@ module.exports = {
|
|
|
544
550
|
removeInvalidMetadata,
|
|
545
551
|
parseAnnotations,
|
|
546
552
|
getIsFaultyEarlyFlakeDetection,
|
|
553
|
+
getFailedTestReplayPromise,
|
|
547
554
|
TEST_BROWSER_DRIVER,
|
|
548
555
|
TEST_BROWSER_DRIVER_VERSION,
|
|
549
556
|
TEST_BROWSER_NAME,
|
|
@@ -901,10 +908,10 @@ function setRumTestCorrelation (context, activeSpan) {
|
|
|
901
908
|
* @returns {import('../../opentracing/span_context')}
|
|
902
909
|
*/
|
|
903
910
|
function getTestParentSpan (tracer, testExecutionId) {
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
911
|
+
const carrier = /** @type {Record<string, unknown>} */ ({})
|
|
912
|
+
writeDatadogTraceId(carrier, testExecutionId || id().toString(10))
|
|
913
|
+
writeDatadogParentId(carrier, '0000000000000000')
|
|
914
|
+
return tracer.extract('text_map', carrier)
|
|
908
915
|
}
|
|
909
916
|
|
|
910
917
|
function getTestCommonTags (name, suite, version, testFramework) {
|
|
@@ -941,6 +948,62 @@ function getTestSuitePath (testSuiteAbsolutePath, sourceRoot) {
|
|
|
941
948
|
return testSuitePath.replaceAll(path.sep, '/')
|
|
942
949
|
}
|
|
943
950
|
|
|
951
|
+
const globalDocblockRegExp = /^\s*(\/\*\*?(.|\r?\n)*?\*\/)/
|
|
952
|
+
const MAX_COMMENTS_CHECKED = 10
|
|
953
|
+
|
|
954
|
+
function isMarkedAsUnskippable (test) {
|
|
955
|
+
let testSource
|
|
956
|
+
|
|
957
|
+
try {
|
|
958
|
+
testSource = fs.readFileSync(test.path, 'utf8')
|
|
959
|
+
} catch {
|
|
960
|
+
return false
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
const re = globalDocblockRegExp
|
|
964
|
+
re.lastIndex = 0
|
|
965
|
+
let commentsChecked = 0
|
|
966
|
+
|
|
967
|
+
while (testSource.length) {
|
|
968
|
+
const match = re.exec(testSource)
|
|
969
|
+
if (!match) break
|
|
970
|
+
const comment = match[1]
|
|
971
|
+
|
|
972
|
+
let docblocks
|
|
973
|
+
try {
|
|
974
|
+
docblocks = parse(comment)
|
|
975
|
+
} catch {
|
|
976
|
+
// Skip unparsable comment and continue scanning
|
|
977
|
+
if (commentsChecked++ >= MAX_COMMENTS_CHECKED) {
|
|
978
|
+
return false
|
|
979
|
+
}
|
|
980
|
+
continue
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
if (docblocks?.datadog) {
|
|
984
|
+
try {
|
|
985
|
+
// @ts-expect-error The datadog type is defined by us and may only be a string.
|
|
986
|
+
return JSON.parse(docblocks.datadog).unskippable
|
|
987
|
+
} catch {
|
|
988
|
+
// If the @datadog block comment is present but malformed, we'll run the suite
|
|
989
|
+
log.warn('@datadog block comment is malformed.')
|
|
990
|
+
return true
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
if (commentsChecked++ >= MAX_COMMENTS_CHECKED) {
|
|
995
|
+
return false
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
// To stop as soon as no doc blocks are found, slice the source. That way the
|
|
999
|
+
// regexp works by using the `^` anchor. Without it, it would continue
|
|
1000
|
+
// scanning the rest of the file.
|
|
1001
|
+
testSource = testSource.slice(match[0].length)
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
return false
|
|
1005
|
+
}
|
|
1006
|
+
|
|
944
1007
|
const POSSIBLE_CODEOWNERS_LOCATIONS = [
|
|
945
1008
|
'CODEOWNERS',
|
|
946
1009
|
'.github/CODEOWNERS',
|
|
@@ -1542,6 +1605,22 @@ function parseAnnotations (annotations) {
|
|
|
1542
1605
|
}, {})
|
|
1543
1606
|
}
|
|
1544
1607
|
|
|
1608
|
+
/**
|
|
1609
|
+
* Combines the optional Failed Test Replay operations that must settle before a retry.
|
|
1610
|
+
*
|
|
1611
|
+
* @param {{setProbePromise?: Promise<void>, finishTestPromise?: Promise<void>}} promises
|
|
1612
|
+
* @returns {Promise<void>|undefined}
|
|
1613
|
+
*/
|
|
1614
|
+
function getFailedTestReplayPromise (promises) {
|
|
1615
|
+
if (promises.setProbePromise && promises.finishTestPromise) {
|
|
1616
|
+
return Promise.all([
|
|
1617
|
+
promises.setProbePromise,
|
|
1618
|
+
promises.finishTestPromise,
|
|
1619
|
+
]).then(() => {})
|
|
1620
|
+
}
|
|
1621
|
+
return promises.setProbePromise || promises.finishTestPromise
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1545
1624
|
function getIsFaultyEarlyFlakeDetection (projectSuites, testsBySuiteName, faultyThresholdPercentage) {
|
|
1546
1625
|
let newSuites = 0
|
|
1547
1626
|
for (const suite of projectSuites) {
|
|
@@ -35,6 +35,11 @@ const MANUAL_DROP = tags.MANUAL_DROP
|
|
|
35
35
|
|
|
36
36
|
const contexts = new WeakMap()
|
|
37
37
|
const requests = new WeakMap()
|
|
38
|
+
const statusCodeRangesPattern = /^[1-5]\d{2}(?:-[1-5]\d{2})?(?:,[1-5]\d{2}(?:-[1-5]\d{2})?)*$/
|
|
39
|
+
const whitespacePattern = /\s/g
|
|
40
|
+
const MAX_HTTP_STATUS_CODE = 599
|
|
41
|
+
|
|
42
|
+
/** @typedef {(code: number) => boolean} StatusValidator */
|
|
38
43
|
|
|
39
44
|
// TODO: change this to no longer rely on creating a dummy plugin to be able to access startSpan
|
|
40
45
|
function createWebPlugin (tracer, config = {}) {
|
|
@@ -559,13 +564,59 @@ function isNot500ErrorCode (code) {
|
|
|
559
564
|
return code < 500
|
|
560
565
|
}
|
|
561
566
|
|
|
567
|
+
/**
|
|
568
|
+
* @param {{ validateStatus?: unknown, DD_TRACE_HTTP_SERVER_ERROR_STATUSES?: unknown }} config
|
|
569
|
+
* @returns {StatusValidator}
|
|
570
|
+
*/
|
|
562
571
|
function getStatusValidator (config) {
|
|
563
572
|
if (typeof config.validateStatus === 'function') {
|
|
564
|
-
return config.validateStatus
|
|
573
|
+
return /** @type {StatusValidator} */ (config.validateStatus)
|
|
565
574
|
} else if (config.hasOwnProperty('validateStatus')) {
|
|
566
575
|
log.error('Expected `validateStatus` to be a function.')
|
|
567
576
|
}
|
|
568
|
-
|
|
577
|
+
|
|
578
|
+
const { DD_TRACE_HTTP_SERVER_ERROR_STATUSES } = config
|
|
579
|
+
if (DD_TRACE_HTTP_SERVER_ERROR_STATUSES === undefined) return isNot500ErrorCode
|
|
580
|
+
if (typeof DD_TRACE_HTTP_SERVER_ERROR_STATUSES !== 'string') {
|
|
581
|
+
log.error('Expected `DD_TRACE_HTTP_SERVER_ERROR_STATUSES` to be a string.')
|
|
582
|
+
return isNot500ErrorCode
|
|
583
|
+
}
|
|
584
|
+
if (DD_TRACE_HTTP_SERVER_ERROR_STATUSES === '500-599') return isNot500ErrorCode
|
|
585
|
+
|
|
586
|
+
const normalized = DD_TRACE_HTTP_SERVER_ERROR_STATUSES.replaceAll(whitespacePattern, '')
|
|
587
|
+
if (normalized === '500-599') return isNot500ErrorCode
|
|
588
|
+
if (!statusCodeRangesPattern.test(normalized)) {
|
|
589
|
+
log.error(
|
|
590
|
+
'`DD_TRACE_HTTP_SERVER_ERROR_STATUSES` must contain comma-separated status codes or ranges from 100 to 599.'
|
|
591
|
+
)
|
|
592
|
+
return isNot500ErrorCode
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const errorStatusCodes = new Uint8Array(MAX_HTTP_STATUS_CODE + 1)
|
|
596
|
+
const ranges = normalized.split(',')
|
|
597
|
+
for (const range of ranges) {
|
|
598
|
+
const separator = range.indexOf('-')
|
|
599
|
+
if (separator === -1) {
|
|
600
|
+
errorStatusCodes[Number(range)] = 1
|
|
601
|
+
continue
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const first = Number(range.slice(0, separator))
|
|
605
|
+
const second = Number(range.slice(separator + 1))
|
|
606
|
+
const start = Math.min(first, second)
|
|
607
|
+
const end = Math.max(first, second)
|
|
608
|
+
errorStatusCodes.fill(1, start, end + 1)
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* @param {number} code
|
|
613
|
+
* @returns {boolean}
|
|
614
|
+
*/
|
|
615
|
+
function isValidStatusCode (code) {
|
|
616
|
+
return errorStatusCodes[code] !== 1
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
return isValidStatusCode
|
|
569
620
|
}
|
|
570
621
|
|
|
571
622
|
const noop = () => {}
|