dd-trace 4.22.0 → 4.24.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/package.json +4 -4
- package/packages/datadog-instrumentations/src/child-process.js +4 -5
- package/packages/datadog-instrumentations/src/couchbase.js +5 -4
- package/packages/datadog-instrumentations/src/crypto.js +2 -1
- package/packages/datadog-instrumentations/src/dns.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +7 -2
- package/packages/datadog-instrumentations/src/helpers/instrument.js +8 -3
- package/packages/datadog-instrumentations/src/helpers/register.js +18 -2
- package/packages/datadog-instrumentations/src/http/client.js +2 -2
- package/packages/datadog-instrumentations/src/http/server.js +7 -4
- package/packages/datadog-instrumentations/src/http2/client.js +3 -1
- package/packages/datadog-instrumentations/src/http2/server.js +3 -1
- package/packages/datadog-instrumentations/src/jest.js +3 -1
- package/packages/datadog-instrumentations/src/net.js +10 -2
- package/packages/datadog-plugin-cucumber/src/index.js +34 -2
- package/packages/datadog-plugin-cypress/src/plugin.js +60 -8
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -0
- package/packages/datadog-plugin-jest/src/index.js +60 -6
- package/packages/datadog-plugin-jest/src/util.js +38 -16
- package/packages/datadog-plugin-mocha/src/index.js +32 -1
- package/packages/datadog-plugin-playwright/src/index.js +17 -1
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +5 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +4 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +30 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +30 -1
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +36 -4
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +18 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +26 -1
- package/packages/dd-trace/src/ci-visibility/telemetry.js +130 -0
- package/packages/dd-trace/src/config.js +100 -59
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +14 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +14 -0
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +4 -0
- package/packages/dd-trace/src/exporters/common/form-data.js +4 -0
- package/packages/dd-trace/src/opentracing/tracer.js +2 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +44 -8
- package/packages/dd-trace/src/plugins/index.js +5 -0
- package/packages/dd-trace/src/plugins/util/exec.js +23 -2
- package/packages/dd-trace/src/plugins/util/git.js +94 -19
- package/packages/dd-trace/src/priority_sampler.js +30 -38
- package/packages/dd-trace/src/profiling/config.js +17 -2
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -0
- package/packages/dd-trace/src/profiling/exporters/file.js +2 -1
- package/packages/dd-trace/src/profiling/profiler.js +18 -14
- package/packages/dd-trace/src/profiling/profilers/events.js +11 -5
- package/packages/dd-trace/src/profiling/profilers/shared.js +7 -1
- package/packages/dd-trace/src/profiling/profilers/space.js +17 -2
- package/packages/dd-trace/src/profiling/profilers/wall.js +34 -21
- package/packages/dd-trace/src/sampling_rule.js +130 -0
- package/packages/dd-trace/src/span_sampler.js +6 -64
- package/packages/dd-trace/src/telemetry/index.js +43 -5
- package/packages/dd-trace/src/telemetry/send-data.js +35 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.24.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -72,20 +72,20 @@
|
|
|
72
72
|
"@datadog/native-iast-rewriter": "2.2.2",
|
|
73
73
|
"@datadog/native-iast-taint-tracking": "1.6.4",
|
|
74
74
|
"@datadog/native-metrics": "^2.0.0",
|
|
75
|
-
"@datadog/pprof": "
|
|
75
|
+
"@datadog/pprof": "5.0.0",
|
|
76
76
|
"@datadog/sketches-js": "^2.1.0",
|
|
77
77
|
"@opentelemetry/api": "^1.0.0",
|
|
78
78
|
"@opentelemetry/core": "^1.14.0",
|
|
79
79
|
"crypto-randomuuid": "^1.0.0",
|
|
80
80
|
"dc-polyfill": "^0.1.2",
|
|
81
81
|
"ignore": "^5.2.4",
|
|
82
|
-
"import-in-the-middle": "^1.
|
|
82
|
+
"import-in-the-middle": "^1.7.1",
|
|
83
83
|
"int64-buffer": "^0.1.9",
|
|
84
84
|
"ipaddr.js": "^2.1.0",
|
|
85
85
|
"istanbul-lib-coverage": "3.2.0",
|
|
86
86
|
"jest-docblock": "^29.7.0",
|
|
87
87
|
"koalas": "^1.0.2",
|
|
88
|
-
"limiter": "
|
|
88
|
+
"limiter": "1.1.5",
|
|
89
89
|
"lodash.kebabcase": "^4.1.1",
|
|
90
90
|
"lodash.pick": "^4.4.0",
|
|
91
91
|
"lodash.sortby": "^4.7.0",
|
|
@@ -9,11 +9,10 @@ const shimmer = require('../../datadog-shimmer')
|
|
|
9
9
|
const childProcessChannel = channel('datadog:child_process:execution:start')
|
|
10
10
|
const execMethods = ['exec', 'execFile', 'fork', 'spawn', 'execFileSync', 'execSync', 'spawnSync']
|
|
11
11
|
const names = ['child_process', 'node:child_process']
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
})
|
|
12
|
+
|
|
13
|
+
addHook({ name: names }, childProcess => {
|
|
14
|
+
shimmer.massWrap(childProcess, execMethods, wrapChildProcessMethod())
|
|
15
|
+
return childProcess
|
|
17
16
|
})
|
|
18
17
|
|
|
19
18
|
function wrapChildProcessMethod () {
|
|
@@ -252,9 +252,10 @@ addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^3.0.7', '^3.1.
|
|
|
252
252
|
return Cluster
|
|
253
253
|
})
|
|
254
254
|
|
|
255
|
-
// semver >=3.2.
|
|
255
|
+
// semver >=3.2.2
|
|
256
|
+
// NOTE: <3.2.2 segfaults on cluster.close() https://issues.couchbase.com/browse/JSCBC-936
|
|
256
257
|
|
|
257
|
-
addHook({ name: 'couchbase', file: 'dist/collection.js', versions: ['>=3.2.
|
|
258
|
+
addHook({ name: 'couchbase', file: 'dist/collection.js', versions: ['>=3.2.2'] }, collection => {
|
|
258
259
|
const Collection = collection.Collection
|
|
259
260
|
|
|
260
261
|
wrapAllNames(['upsert', 'insert', 'replace'], name => {
|
|
@@ -264,7 +265,7 @@ addHook({ name: 'couchbase', file: 'dist/collection.js', versions: ['>=3.2.0'] }
|
|
|
264
265
|
return collection
|
|
265
266
|
})
|
|
266
267
|
|
|
267
|
-
addHook({ name: 'couchbase', file: 'dist/bucket.js', versions: ['>=3.2.
|
|
268
|
+
addHook({ name: 'couchbase', file: 'dist/bucket.js', versions: ['>=3.2.2'] }, bucket => {
|
|
268
269
|
const Bucket = bucket.Bucket
|
|
269
270
|
shimmer.wrap(Bucket.prototype, 'collection', getCollection => {
|
|
270
271
|
return function () {
|
|
@@ -278,7 +279,7 @@ addHook({ name: 'couchbase', file: 'dist/bucket.js', versions: ['>=3.2.0'] }, bu
|
|
|
278
279
|
return bucket
|
|
279
280
|
})
|
|
280
281
|
|
|
281
|
-
addHook({ name: 'couchbase', file: 'dist/cluster.js', versions: ['
|
|
282
|
+
addHook({ name: 'couchbase', file: 'dist/cluster.js', versions: ['>=3.2.2'] }, (cluster) => {
|
|
282
283
|
const Cluster = cluster.Cluster
|
|
283
284
|
|
|
284
285
|
shimmer.wrap(Cluster.prototype, 'query', wrapV3Query)
|
|
@@ -11,8 +11,9 @@ const cryptoCipherCh = channel('datadog:crypto:cipher:start')
|
|
|
11
11
|
|
|
12
12
|
const hashMethods = ['createHash', 'createHmac', 'createSign', 'createVerify', 'sign', 'verify']
|
|
13
13
|
const cipherMethods = ['createCipheriv', 'createDecipheriv']
|
|
14
|
+
const names = ['crypto', 'node:crypto']
|
|
14
15
|
|
|
15
|
-
addHook({ name:
|
|
16
|
+
addHook({ name: names }, crypto => {
|
|
16
17
|
shimmer.massWrap(crypto, hashMethods, wrapCryptoMethod(cryptoHashCh))
|
|
17
18
|
shimmer.massWrap(crypto, cipherMethods, wrapCryptoMethod(cryptoCipherCh))
|
|
18
19
|
return crypto
|
|
@@ -18,8 +18,9 @@ const rrtypes = {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const rrtypeMap = new WeakMap()
|
|
21
|
+
const names = ['dns', 'node:dns']
|
|
21
22
|
|
|
22
|
-
addHook({ name:
|
|
23
|
+
addHook({ name: names }, dns => {
|
|
23
24
|
dns.lookup = wrap('apm:dns:lookup', dns.lookup, 2)
|
|
24
25
|
dns.lookupService = wrap('apm:dns:lookup_service', dns.lookupService, 3)
|
|
25
26
|
dns.resolve = wrap('apm:dns:resolve', dns.resolve, 2)
|
|
@@ -31,7 +31,6 @@ module.exports = {
|
|
|
31
31
|
'bunyan': () => require('../bunyan'),
|
|
32
32
|
'cassandra-driver': () => require('../cassandra-driver'),
|
|
33
33
|
'child_process': () => require('../child-process'),
|
|
34
|
-
'node:child_process': () => require('../child-process'),
|
|
35
34
|
'connect': () => require('../connect'),
|
|
36
35
|
'cookie': () => require('../cookie'),
|
|
37
36
|
'cookie-parser': () => require('../cookie-parser'),
|
|
@@ -45,7 +44,6 @@ module.exports = {
|
|
|
45
44
|
'fastify': () => require('../fastify'),
|
|
46
45
|
'find-my-way': () => require('../find-my-way'),
|
|
47
46
|
'fs': () => require('../fs'),
|
|
48
|
-
'node:fs': () => require('../fs'),
|
|
49
47
|
'generic-pool': () => require('../generic-pool'),
|
|
50
48
|
'graphql': () => require('../graphql'),
|
|
51
49
|
'grpc': () => require('../grpc'),
|
|
@@ -79,6 +77,13 @@ module.exports = {
|
|
|
79
77
|
'mysql2': () => require('../mysql2'),
|
|
80
78
|
'net': () => require('../net'),
|
|
81
79
|
'next': () => require('../next'),
|
|
80
|
+
'node:child_process': () => require('../child-process'),
|
|
81
|
+
'node:crypto': () => require('../crypto'),
|
|
82
|
+
'node:dns': () => require('../dns'),
|
|
83
|
+
'node:http': () => require('../http'),
|
|
84
|
+
'node:http2': () => require('../http2'),
|
|
85
|
+
'node:https': () => require('../http'),
|
|
86
|
+
'node:net': () => require('../net'),
|
|
82
87
|
'oracledb': () => require('../oracledb'),
|
|
83
88
|
'openai': () => require('../openai'),
|
|
84
89
|
'paperplane': () => require('../paperplane'),
|
|
@@ -21,11 +21,16 @@ exports.channel = function (name) {
|
|
|
21
21
|
* @param Function hook
|
|
22
22
|
*/
|
|
23
23
|
exports.addHook = function addHook ({ name, versions, file }, hook) {
|
|
24
|
-
if (
|
|
25
|
-
|
|
24
|
+
if (typeof name === 'string') {
|
|
25
|
+
name = [name]
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
for (const val of name) {
|
|
29
|
+
if (!instrumentations[val]) {
|
|
30
|
+
instrumentations[val] = []
|
|
31
|
+
}
|
|
32
|
+
instrumentations[val].push({ name: val, versions, file, hook })
|
|
33
|
+
}
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
// AsyncResource.bind exists and binds `this` properly only from 17.8.0 and up.
|
|
@@ -24,6 +24,7 @@ if (!disabledInstrumentations.has('fetch')) {
|
|
|
24
24
|
require('../fetch')
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
const HOOK_SYMBOL = Symbol('hookExportsMap')
|
|
27
28
|
// TODO: make this more efficient
|
|
28
29
|
|
|
29
30
|
for (const packageName of names) {
|
|
@@ -42,14 +43,29 @@ for (const packageName of names) {
|
|
|
42
43
|
for (const { name, file, versions, hook } of instrumentations[packageName]) {
|
|
43
44
|
const fullFilename = filename(name, file)
|
|
44
45
|
|
|
46
|
+
// Create a WeakMap associated with the hook function so that patches on the same moduleExport only happens once
|
|
47
|
+
// for example by instrumenting both dns and node:dns double the spans would be created
|
|
48
|
+
// since they both patch the same moduleExport, this WeakMap is used to mitigate that
|
|
49
|
+
if (!hook[HOOK_SYMBOL]) {
|
|
50
|
+
hook[HOOK_SYMBOL] = new WeakMap()
|
|
51
|
+
}
|
|
52
|
+
|
|
45
53
|
if (moduleName === fullFilename) {
|
|
46
54
|
const version = moduleVersion || getVersion(moduleBaseDir)
|
|
47
55
|
|
|
48
56
|
if (matchVersion(version, versions)) {
|
|
57
|
+
// Check if the hook already has a set moduleExport
|
|
58
|
+
if (hook[HOOK_SYMBOL].has(moduleExports)) {
|
|
59
|
+
return moduleExports
|
|
60
|
+
}
|
|
61
|
+
|
|
49
62
|
try {
|
|
50
63
|
loadChannel.publish({ name, version, file })
|
|
51
|
-
|
|
52
|
-
|
|
64
|
+
// Send the name and version of the module back to the callback because now addHook
|
|
65
|
+
// takes in an array of names so by passing the name the callback will know which module name is being used
|
|
66
|
+
moduleExports = hook(moduleExports, version, name)
|
|
67
|
+
// Set the moduleExports in the hooks weakmap
|
|
68
|
+
hook[HOOK_SYMBOL].set(moduleExports, name)
|
|
53
69
|
} catch (e) {
|
|
54
70
|
log.error(e)
|
|
55
71
|
}
|
|
@@ -14,9 +14,9 @@ const endChannel = channel('apm:http:client:request:end')
|
|
|
14
14
|
const asyncStartChannel = channel('apm:http:client:request:asyncStart')
|
|
15
15
|
const errorChannel = channel('apm:http:client:request:error')
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const names = ['http', 'https', 'node:http', 'node:https']
|
|
18
18
|
|
|
19
|
-
addHook({ name:
|
|
19
|
+
addHook({ name: names }, hookFn)
|
|
20
20
|
|
|
21
21
|
function hookFn (http) {
|
|
22
22
|
patch(http, 'request')
|
|
@@ -15,14 +15,17 @@ const finishSetHeaderCh = channel('datadog:http:server:response:set-header:finis
|
|
|
15
15
|
|
|
16
16
|
const requestFinishedSet = new WeakSet()
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const httpNames = ['http', 'node:http']
|
|
19
|
+
const httpsNames = ['https', 'node:https']
|
|
20
|
+
|
|
21
|
+
addHook({ name: httpNames }, http => {
|
|
22
|
+
shimmer.wrap(http.ServerResponse.prototype, 'emit', wrapResponseEmit)
|
|
20
23
|
shimmer.wrap(http.Server.prototype, 'emit', wrapEmit)
|
|
21
24
|
return http
|
|
22
25
|
})
|
|
23
26
|
|
|
24
|
-
addHook({ name:
|
|
25
|
-
|
|
27
|
+
addHook({ name: httpsNames }, http => {
|
|
28
|
+
// http.ServerResponse not present on https
|
|
26
29
|
shimmer.wrap(http.Server.prototype, 'emit', wrapEmit)
|
|
27
30
|
return http
|
|
28
31
|
})
|
|
@@ -10,6 +10,8 @@ const asyncStartChannel = channel('apm:http2:client:request:asyncStart')
|
|
|
10
10
|
const asyncEndChannel = channel('apm:http2:client:request:asyncEnd')
|
|
11
11
|
const errorChannel = channel('apm:http2:client:request:error')
|
|
12
12
|
|
|
13
|
+
const names = ['http2', 'node:http2']
|
|
14
|
+
|
|
13
15
|
function createWrapEmit (ctx) {
|
|
14
16
|
return function wrapEmit (emit) {
|
|
15
17
|
return function (event, arg1) {
|
|
@@ -66,7 +68,7 @@ function wrapConnect (connect) {
|
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
addHook({ name:
|
|
71
|
+
addHook({ name: names }, http2 => {
|
|
70
72
|
shimmer.wrap(http2, 'connect', wrapConnect)
|
|
71
73
|
|
|
72
74
|
return http2
|
|
@@ -14,7 +14,9 @@ const startServerCh = channel('apm:http2:server:request:start')
|
|
|
14
14
|
const errorServerCh = channel('apm:http2:server:request:error')
|
|
15
15
|
const finishServerCh = channel('apm:http2:server:request:finish')
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const names = ['http2', 'node:http2']
|
|
18
|
+
|
|
19
|
+
addHook({ name: names }, http2 => {
|
|
18
20
|
shimmer.wrap(http2, 'createSecureServer', wrapCreateServer)
|
|
19
21
|
shimmer.wrap(http2, 'createServer', wrapCreateServer)
|
|
20
22
|
return http2
|
|
@@ -403,7 +403,7 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
|
|
|
403
403
|
const coverageFiles = getCoveredFilenamesFromCoverage(environment.global.__coverage__)
|
|
404
404
|
.map(filename => getTestSuitePath(filename, environment.rootDir))
|
|
405
405
|
asyncResource.runInAsyncScope(() => {
|
|
406
|
-
testSuiteCodeCoverageCh.publish(
|
|
406
|
+
testSuiteCodeCoverageCh.publish({ coverageFiles, testSuite: environment.testSuite })
|
|
407
407
|
})
|
|
408
408
|
}
|
|
409
409
|
testSuiteFinishCh.publish({ status, errorMessage })
|
|
@@ -495,6 +495,8 @@ addHook({
|
|
|
495
495
|
_ddTestModuleId,
|
|
496
496
|
_ddTestSessionId,
|
|
497
497
|
_ddTestCommand,
|
|
498
|
+
_ddForcedToRun,
|
|
499
|
+
_ddUnskippable,
|
|
498
500
|
...restOfTestEnvironmentOptions
|
|
499
501
|
} = testEnvironmentOptions
|
|
500
502
|
|
|
@@ -17,8 +17,16 @@ const errorTCPCh = channel('apm:net:tcp:error')
|
|
|
17
17
|
|
|
18
18
|
const connectionCh = channel(`apm:net:tcp:connection`)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const names = ['net', 'node:net']
|
|
21
|
+
|
|
22
|
+
addHook({ name: names }, (net, version, name) => {
|
|
23
|
+
// explicitly require dns so that net gets an instrumented instance
|
|
24
|
+
// so that we don't miss the dns calls
|
|
25
|
+
if (name === 'net') {
|
|
26
|
+
require('dns')
|
|
27
|
+
} else {
|
|
28
|
+
require('node:dns')
|
|
29
|
+
}
|
|
22
30
|
|
|
23
31
|
shimmer.wrap(net.Socket.prototype, 'connect', connect => function () {
|
|
24
32
|
if (!startICPCh.hasSubscribers || !startTCPCh.hasSubscribers) {
|
|
@@ -12,10 +12,21 @@ const {
|
|
|
12
12
|
getTestSuiteCommonTags,
|
|
13
13
|
addIntelligentTestRunnerSpanTags,
|
|
14
14
|
TEST_ITR_UNSKIPPABLE,
|
|
15
|
-
TEST_ITR_FORCED_RUN
|
|
15
|
+
TEST_ITR_FORCED_RUN,
|
|
16
|
+
TEST_CODE_OWNERS
|
|
16
17
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
17
18
|
const { RESOURCE_NAME } = require('../../../ext/tags')
|
|
18
19
|
const { COMPONENT, ERROR_MESSAGE } = require('../../dd-trace/src/constants')
|
|
20
|
+
const {
|
|
21
|
+
TELEMETRY_EVENT_CREATED,
|
|
22
|
+
TELEMETRY_EVENT_FINISHED,
|
|
23
|
+
TELEMETRY_CODE_COVERAGE_STARTED,
|
|
24
|
+
TELEMETRY_CODE_COVERAGE_FINISHED,
|
|
25
|
+
TELEMETRY_ITR_FORCED_TO_RUN,
|
|
26
|
+
TELEMETRY_CODE_COVERAGE_EMPTY,
|
|
27
|
+
TELEMETRY_ITR_UNSKIPPABLE,
|
|
28
|
+
TELEMETRY_CODE_COVERAGE_NUM_FILES
|
|
29
|
+
} = require('../../dd-trace/src/ci-visibility/telemetry')
|
|
19
30
|
|
|
20
31
|
class CucumberPlugin extends CiPlugin {
|
|
21
32
|
static get id () {
|
|
@@ -54,7 +65,9 @@ class CucumberPlugin extends CiPlugin {
|
|
|
54
65
|
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
55
66
|
this.testModuleSpan.setTag(TEST_STATUS, status)
|
|
56
67
|
this.testModuleSpan.finish()
|
|
68
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
57
69
|
this.testSessionSpan.finish()
|
|
70
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
58
71
|
finishAllTraceSpans(this.testSessionSpan)
|
|
59
72
|
|
|
60
73
|
this.itrConfig = null
|
|
@@ -69,9 +82,11 @@ class CucumberPlugin extends CiPlugin {
|
|
|
69
82
|
'cucumber'
|
|
70
83
|
)
|
|
71
84
|
if (isUnskippable) {
|
|
85
|
+
this.telemetry.count(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
|
|
72
86
|
testSuiteMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
|
|
73
87
|
}
|
|
74
88
|
if (isForcedToRun) {
|
|
89
|
+
this.telemetry.count(TELEMETRY_ITR_FORCED_TO_RUN, { testLevel: 'suite' })
|
|
75
90
|
testSuiteMetadata[TEST_ITR_FORCED_RUN] = 'true'
|
|
76
91
|
}
|
|
77
92
|
this.testSuiteSpan = this.tracer.startSpan('cucumber.test_suite', {
|
|
@@ -82,20 +97,31 @@ class CucumberPlugin extends CiPlugin {
|
|
|
82
97
|
...testSuiteMetadata
|
|
83
98
|
}
|
|
84
99
|
})
|
|
100
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
101
|
+
if (this.itrConfig?.isCodeCoverageEnabled) {
|
|
102
|
+
this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_STARTED, 'suite', { library: 'istanbul' })
|
|
103
|
+
}
|
|
85
104
|
})
|
|
86
105
|
|
|
87
106
|
this.addSub('ci:cucumber:test-suite:finish', status => {
|
|
88
107
|
this.testSuiteSpan.setTag(TEST_STATUS, status)
|
|
89
108
|
this.testSuiteSpan.finish()
|
|
109
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
90
110
|
})
|
|
91
111
|
|
|
92
112
|
this.addSub('ci:cucumber:test-suite:code-coverage', ({ coverageFiles, suiteFile }) => {
|
|
93
|
-
if (!this.itrConfig
|
|
113
|
+
if (!this.itrConfig?.isCodeCoverageEnabled) {
|
|
94
114
|
return
|
|
95
115
|
}
|
|
116
|
+
if (!coverageFiles.length) {
|
|
117
|
+
this.telemetry.count(TELEMETRY_CODE_COVERAGE_EMPTY)
|
|
118
|
+
}
|
|
119
|
+
|
|
96
120
|
const relativeCoverageFiles = [...coverageFiles, suiteFile]
|
|
97
121
|
.map(filename => getTestSuitePath(filename, this.sourceRoot))
|
|
98
122
|
|
|
123
|
+
this.telemetry.distribution(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
|
|
124
|
+
|
|
99
125
|
const formattedCoverage = {
|
|
100
126
|
sessionId: this.testSuiteSpan.context()._traceId,
|
|
101
127
|
suiteId: this.testSuiteSpan.context()._spanId,
|
|
@@ -103,6 +129,7 @@ class CucumberPlugin extends CiPlugin {
|
|
|
103
129
|
}
|
|
104
130
|
|
|
105
131
|
this.tracer._exporter.exportCoverage(formattedCoverage)
|
|
132
|
+
this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_FINISHED, 'suite', { library: 'istanbul' })
|
|
106
133
|
})
|
|
107
134
|
|
|
108
135
|
this.addSub('ci:cucumber:test:start', ({ testName, fullTestSuite, testSourceLine }) => {
|
|
@@ -142,6 +169,11 @@ class CucumberPlugin extends CiPlugin {
|
|
|
142
169
|
}
|
|
143
170
|
|
|
144
171
|
span.finish()
|
|
172
|
+
this.telemetry.ciVisEvent(
|
|
173
|
+
TELEMETRY_EVENT_FINISHED,
|
|
174
|
+
'test',
|
|
175
|
+
{ hasCodeOwners: !!span.context()._tags[TEST_CODE_OWNERS] }
|
|
176
|
+
)
|
|
145
177
|
if (!isStep) {
|
|
146
178
|
finishAllTraceSpans(span)
|
|
147
179
|
}
|
|
@@ -29,6 +29,29 @@ const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
|
|
|
29
29
|
const log = require('../../dd-trace/src/log')
|
|
30
30
|
const NoopTracer = require('../../dd-trace/src/noop/tracer')
|
|
31
31
|
const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')
|
|
32
|
+
const {
|
|
33
|
+
TELEMETRY_EVENT_CREATED,
|
|
34
|
+
TELEMETRY_EVENT_FINISHED,
|
|
35
|
+
TELEMETRY_ITR_FORCED_TO_RUN,
|
|
36
|
+
TELEMETRY_CODE_COVERAGE_EMPTY,
|
|
37
|
+
TELEMETRY_ITR_UNSKIPPABLE,
|
|
38
|
+
TELEMETRY_CODE_COVERAGE_NUM_FILES,
|
|
39
|
+
incrementCountMetric,
|
|
40
|
+
distributionMetric
|
|
41
|
+
} = require('../../dd-trace/src/ci-visibility/telemetry')
|
|
42
|
+
const {
|
|
43
|
+
GIT_REPOSITORY_URL,
|
|
44
|
+
GIT_COMMIT_SHA,
|
|
45
|
+
GIT_BRANCH,
|
|
46
|
+
CI_PROVIDER_NAME
|
|
47
|
+
} = require('../../dd-trace/src/plugins/util/tags')
|
|
48
|
+
const {
|
|
49
|
+
OS_VERSION,
|
|
50
|
+
OS_PLATFORM,
|
|
51
|
+
OS_ARCHITECTURE,
|
|
52
|
+
RUNTIME_NAME,
|
|
53
|
+
RUNTIME_VERSION
|
|
54
|
+
} = require('../../dd-trace/src/plugins/util/env')
|
|
32
55
|
|
|
33
56
|
const TEST_FRAMEWORK_NAME = 'cypress'
|
|
34
57
|
|
|
@@ -152,16 +175,19 @@ module.exports = (on, config) => {
|
|
|
152
175
|
const testEnvironmentMetadata = getTestEnvironmentMetadata(TEST_FRAMEWORK_NAME)
|
|
153
176
|
|
|
154
177
|
const {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
178
|
+
[GIT_REPOSITORY_URL]: repositoryUrl,
|
|
179
|
+
[GIT_COMMIT_SHA]: sha,
|
|
180
|
+
[OS_VERSION]: osVersion,
|
|
181
|
+
[OS_PLATFORM]: osPlatform,
|
|
182
|
+
[OS_ARCHITECTURE]: osArchitecture,
|
|
183
|
+
[RUNTIME_NAME]: runtimeName,
|
|
184
|
+
[RUNTIME_VERSION]: runtimeVersion,
|
|
185
|
+
[GIT_BRANCH]: branch,
|
|
186
|
+
[CI_PROVIDER_NAME]: ciProviderName
|
|
163
187
|
} = testEnvironmentMetadata
|
|
164
188
|
|
|
189
|
+
const isUnsupportedCIProvider = !ciProviderName
|
|
190
|
+
|
|
165
191
|
const finishedTestsByFile = {}
|
|
166
192
|
|
|
167
193
|
const testConfiguration = {
|
|
@@ -192,6 +218,15 @@ module.exports = (on, config) => {
|
|
|
192
218
|
let hasForcedToRunSuites = false
|
|
193
219
|
let hasUnskippableSuites = false
|
|
194
220
|
|
|
221
|
+
function ciVisEvent (name, testLevel, tags = {}) {
|
|
222
|
+
incrementCountMetric(name, {
|
|
223
|
+
testLevel,
|
|
224
|
+
testFramework: 'cypress',
|
|
225
|
+
isUnsupportedCIProvider,
|
|
226
|
+
...tags
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
|
|
195
230
|
function getTestSpan (testName, testSuite, isUnskippable, isForcedToRun) {
|
|
196
231
|
const testSuiteTags = {
|
|
197
232
|
[TEST_COMMAND]: command,
|
|
@@ -220,14 +255,18 @@ module.exports = (on, config) => {
|
|
|
220
255
|
|
|
221
256
|
if (isUnskippable) {
|
|
222
257
|
hasUnskippableSuites = true
|
|
258
|
+
incrementCountMetric(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
|
|
223
259
|
testSpanMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
|
|
224
260
|
}
|
|
225
261
|
|
|
226
262
|
if (isForcedToRun) {
|
|
227
263
|
hasForcedToRunSuites = true
|
|
264
|
+
incrementCountMetric(TELEMETRY_ITR_FORCED_TO_RUN, { testLevel: 'suite' })
|
|
228
265
|
testSpanMetadata[TEST_ITR_FORCED_RUN] = 'true'
|
|
229
266
|
}
|
|
230
267
|
|
|
268
|
+
ciVisEvent(TELEMETRY_EVENT_CREATED, 'test', { hasCodeOwners: !!codeOwners })
|
|
269
|
+
|
|
231
270
|
return tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test`, {
|
|
232
271
|
childOf,
|
|
233
272
|
tags: {
|
|
@@ -281,6 +320,8 @@ module.exports = (on, config) => {
|
|
|
281
320
|
...testSessionSpanMetadata
|
|
282
321
|
}
|
|
283
322
|
})
|
|
323
|
+
ciVisEvent(TELEMETRY_EVENT_CREATED, 'session')
|
|
324
|
+
|
|
284
325
|
testModuleSpan = tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_module`, {
|
|
285
326
|
childOf: testSessionSpan,
|
|
286
327
|
tags: {
|
|
@@ -289,6 +330,8 @@ module.exports = (on, config) => {
|
|
|
289
330
|
...testModuleSpanMetadata
|
|
290
331
|
}
|
|
291
332
|
})
|
|
333
|
+
ciVisEvent(TELEMETRY_EVENT_CREATED, 'module')
|
|
334
|
+
|
|
292
335
|
return details
|
|
293
336
|
})
|
|
294
337
|
})
|
|
@@ -347,6 +390,7 @@ module.exports = (on, config) => {
|
|
|
347
390
|
}
|
|
348
391
|
testSuiteSpan.finish()
|
|
349
392
|
testSuiteSpan = null
|
|
393
|
+
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
350
394
|
}
|
|
351
395
|
})
|
|
352
396
|
|
|
@@ -371,7 +415,9 @@ module.exports = (on, config) => {
|
|
|
371
415
|
)
|
|
372
416
|
|
|
373
417
|
testModuleSpan.finish()
|
|
418
|
+
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
374
419
|
testSessionSpan.finish()
|
|
420
|
+
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
375
421
|
|
|
376
422
|
finishAllTraceSpans(testSessionSpan)
|
|
377
423
|
}
|
|
@@ -406,6 +452,7 @@ module.exports = (on, config) => {
|
|
|
406
452
|
...testSuiteSpanMetadata
|
|
407
453
|
}
|
|
408
454
|
})
|
|
455
|
+
ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
409
456
|
return null
|
|
410
457
|
},
|
|
411
458
|
'dd:beforeEach': (test) => {
|
|
@@ -435,6 +482,10 @@ module.exports = (on, config) => {
|
|
|
435
482
|
if (coverage && isCodeCoverageEnabled && tracer._tracer._exporter && tracer._tracer._exporter.exportCoverage) {
|
|
436
483
|
const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
|
|
437
484
|
const relativeCoverageFiles = coverageFiles.map(file => getTestSuitePath(file, rootDir))
|
|
485
|
+
if (!relativeCoverageFiles.length) {
|
|
486
|
+
incrementCountMetric(TELEMETRY_CODE_COVERAGE_EMPTY)
|
|
487
|
+
}
|
|
488
|
+
distributionMetric(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
|
|
438
489
|
const { _traceId, _spanId } = testSuiteSpan.context()
|
|
439
490
|
const formattedCoverage = {
|
|
440
491
|
sessionId: _traceId,
|
|
@@ -470,6 +521,7 @@ module.exports = (on, config) => {
|
|
|
470
521
|
// test spans are finished at after:spec
|
|
471
522
|
}
|
|
472
523
|
activeSpan = null
|
|
524
|
+
ciVisEvent(TELEMETRY_EVENT_FINISHED, 'test')
|
|
473
525
|
return null
|
|
474
526
|
},
|
|
475
527
|
'dd:addTags': (tags) => {
|