dd-trace 3.21.0 → 3.22.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 +2 -2
- package/packages/datadog-instrumentations/src/cucumber.js +13 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/http/client.js +2 -1
- package/packages/datadog-instrumentations/src/http/server.js +14 -0
- package/packages/datadog-instrumentations/src/http2/client.js +4 -0
- package/packages/datadog-instrumentations/src/playwright.js +1 -1
- package/packages/datadog-instrumentations/src/sequelize.js +51 -0
- package/packages/datadog-plugin-amqp10/src/consumer.js +1 -3
- package/packages/datadog-plugin-amqp10/src/producer.js +1 -3
- package/packages/datadog-plugin-amqplib/src/client.js +4 -3
- package/packages/datadog-plugin-amqplib/src/consumer.js +1 -3
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -3
- package/packages/datadog-plugin-cucumber/src/index.js +2 -2
- package/packages/datadog-plugin-cypress/src/plugin.js +150 -30
- package/packages/datadog-plugin-cypress/src/support.js +6 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -3
- package/packages/datadog-plugin-http/src/client.js +70 -68
- package/packages/datadog-plugin-http2/src/client.js +50 -47
- package/packages/datadog-plugin-jest/src/index.js +5 -4
- package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -4
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -3
- package/packages/datadog-plugin-memcached/src/index.js +2 -3
- package/packages/datadog-plugin-mocha/src/index.js +4 -2
- package/packages/datadog-plugin-pg/src/index.js +1 -1
- package/packages/datadog-plugin-redis/src/index.js +2 -13
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -3
- package/packages/datadog-plugin-rhea/src/producer.js +1 -5
- package/packages/dd-trace/src/appsec/blocked_templates.js +2 -101
- package/packages/dd-trace/src/appsec/blocking.js +60 -11
- package/packages/dd-trace/src/appsec/channels.js +3 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +7 -5
- package/packages/dd-trace/src/appsec/iast/analyzers/index.js +3 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/insecure-cookie-analyzer.js +31 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +47 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +30 -5
- package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +26 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +35 -3
- package/packages/dd-trace/src/appsec/iast/path-line.js +14 -7
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +19 -4
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +25 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +49 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +7 -5
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +0 -33
- package/packages/dd-trace/src/appsec/recommended.json +45 -46
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +3 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +4 -0
- package/packages/dd-trace/src/appsec/rule_manager.js +49 -6
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -7
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -6
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +10 -4
- package/packages/dd-trace/src/config.js +29 -2
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +11 -3
- package/packages/dd-trace/src/exporters/common/util.js +9 -0
- package/packages/dd-trace/src/exporters/common/writer.js +3 -2
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/cache.js +7 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +2 -0
- package/packages/dd-trace/src/plugins/client.js +3 -2
- package/packages/dd-trace/src/plugins/consumer.js +14 -2
- package/packages/dd-trace/src/plugins/database.js +2 -2
- package/packages/dd-trace/src/plugins/inbound.js +7 -0
- package/packages/dd-trace/src/plugins/{outgoing.js → outbound.js} +2 -2
- package/packages/dd-trace/src/plugins/producer.js +19 -2
- package/packages/dd-trace/src/plugins/server.js +2 -2
- package/packages/dd-trace/src/plugins/storage.js +2 -0
- package/packages/dd-trace/src/plugins/tracing.js +11 -0
- package/packages/dd-trace/src/plugins/util/ci.js +1 -1
- package/packages/dd-trace/src/profiling/config.js +4 -2
- package/packages/dd-trace/src/service-naming/index.js +30 -0
- package/packages/dd-trace/src/service-naming/schemas/definition.js +24 -0
- package/packages/dd-trace/src/service-naming/schemas/index.js +6 -0
- package/packages/dd-trace/src/service-naming/schemas/util.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/index.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +64 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +33 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/index.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +52 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +21 -0
- package/packages/dd-trace/src/plugins/incoming.js +0 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.22.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"node": ">=14"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@datadog/native-appsec": "^3.
|
|
69
|
+
"@datadog/native-appsec": "^3.2.0",
|
|
70
70
|
"@datadog/native-iast-rewriter": "2.0.1",
|
|
71
71
|
"@datadog/native-iast-taint-tracking": "^1.4.1",
|
|
72
72
|
"@datadog/native-metrics": "^2.0.0",
|
|
@@ -3,6 +3,7 @@ const { createCoverageMap } = require('istanbul-lib-coverage')
|
|
|
3
3
|
|
|
4
4
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
5
5
|
const shimmer = require('../../datadog-shimmer')
|
|
6
|
+
const log = require('../../dd-trace/src/log')
|
|
6
7
|
|
|
7
8
|
const testStartCh = channel('ci:cucumber:test:start')
|
|
8
9
|
const testFinishCh = channel('ci:cucumber:test:finish') // used for test steps too
|
|
@@ -175,6 +176,12 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
175
176
|
}
|
|
176
177
|
|
|
177
178
|
function pickleHook (PickleRunner) {
|
|
179
|
+
if (process.env.CUCUMBER_WORKER_ID) {
|
|
180
|
+
// Parallel mode is not supported
|
|
181
|
+
log.warn('Unable to initialize CI Visibility because Cucumber is running in parallel mode.')
|
|
182
|
+
return PickleRunner
|
|
183
|
+
}
|
|
184
|
+
|
|
178
185
|
const pl = PickleRunner.default
|
|
179
186
|
|
|
180
187
|
wrapRun(pl, false)
|
|
@@ -183,6 +190,12 @@ function pickleHook (PickleRunner) {
|
|
|
183
190
|
}
|
|
184
191
|
|
|
185
192
|
function testCaseHook (TestCaseRunner) {
|
|
193
|
+
if (process.env.CUCUMBER_WORKER_ID) {
|
|
194
|
+
// Parallel mode is not supported
|
|
195
|
+
log.warn('Unable to initialize CI Visibility because Cucumber is running in parallel mode.')
|
|
196
|
+
return TestCaseRunner
|
|
197
|
+
}
|
|
198
|
+
|
|
186
199
|
const pl = TestCaseRunner.default
|
|
187
200
|
|
|
188
201
|
wrapRun(pl, true)
|
|
@@ -80,6 +80,7 @@ module.exports = {
|
|
|
80
80
|
'rhea': () => require('../rhea'),
|
|
81
81
|
'router': () => require('../router'),
|
|
82
82
|
'sharedb': () => require('../sharedb'),
|
|
83
|
+
'sequelize': () => require('../sequelize'),
|
|
83
84
|
'tedious': () => require('../tedious'),
|
|
84
85
|
'when': () => require('../when'),
|
|
85
86
|
'winston': () => require('../winston')
|
|
@@ -101,6 +101,7 @@ function patch (http, methodName) {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
function normalizeArgs (inputURL, inputOptions, cb) {
|
|
104
|
+
const originalUrl = inputURL
|
|
104
105
|
inputURL = normalizeOptions(inputURL)
|
|
105
106
|
|
|
106
107
|
const [callback, inputOptionsNormalized] = normalizeCallback(inputOptions, cb, inputURL)
|
|
@@ -108,7 +109,7 @@ function patch (http, methodName) {
|
|
|
108
109
|
normalizeHeaders(options)
|
|
109
110
|
const uri = url.format(options)
|
|
110
111
|
|
|
111
|
-
return { uri, options, callback }
|
|
112
|
+
return { uri, options, callback, originalUrl }
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
function combineOptions (inputURL, inputOptions) {
|
|
@@ -11,6 +11,7 @@ const startServerCh = channel('apm:http:server:request:start')
|
|
|
11
11
|
const exitServerCh = channel('apm:http:server:request:exit')
|
|
12
12
|
const errorServerCh = channel('apm:http:server:request:error')
|
|
13
13
|
const finishServerCh = channel('apm:http:server:request:finish')
|
|
14
|
+
const finishSetHeaderCh = channel('datadog:http:server:response:set-header:finish')
|
|
14
15
|
|
|
15
16
|
const requestFinishedSet = new WeakSet()
|
|
16
17
|
|
|
@@ -58,6 +59,9 @@ function wrapEmit (emit) {
|
|
|
58
59
|
// TODO: should this always return true ?
|
|
59
60
|
return this.listenerCount(eventName) > 0
|
|
60
61
|
}
|
|
62
|
+
if (finishSetHeaderCh.hasSubscribers) {
|
|
63
|
+
wrapSetHeader(res)
|
|
64
|
+
}
|
|
61
65
|
return emit.apply(this, arguments)
|
|
62
66
|
} catch (err) {
|
|
63
67
|
errorServerCh.publish(err)
|
|
@@ -70,3 +74,13 @@ function wrapEmit (emit) {
|
|
|
70
74
|
return emit.apply(this, arguments)
|
|
71
75
|
}
|
|
72
76
|
}
|
|
77
|
+
|
|
78
|
+
function wrapSetHeader (res) {
|
|
79
|
+
shimmer.wrap(res, 'setHeader', setHeader => {
|
|
80
|
+
return function (name, value) {
|
|
81
|
+
const setHeaderResult = setHeader.apply(this, arguments)
|
|
82
|
+
finishSetHeaderCh.publish({ name, value, res })
|
|
83
|
+
return setHeaderResult
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const shimmer = require('../../../datadog-shimmer')
|
|
4
4
|
const { addHook, channel, AsyncResource } = require('../helpers/instrument')
|
|
5
5
|
|
|
6
|
+
const connectChannel = channel('apm:http2:client:connect:start')
|
|
6
7
|
const startChannel = channel('apm:http2:client:request:start')
|
|
7
8
|
const finishChannel = channel('apm:http2:client:request:finish')
|
|
8
9
|
const errorChannel = channel('apm:http2:client:request:error')
|
|
@@ -52,6 +53,9 @@ function createWrapRequest (authority, options) {
|
|
|
52
53
|
|
|
53
54
|
function wrapConnect (connect) {
|
|
54
55
|
return function (authority, options) {
|
|
56
|
+
if (connectChannel.hasSubscribers) {
|
|
57
|
+
connectChannel.publish({ authority })
|
|
58
|
+
}
|
|
55
59
|
const session = connect.apply(this, arguments)
|
|
56
60
|
|
|
57
61
|
shimmer.wrap(session, 'request', createWrapRequest(authority, options))
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
|
|
9
|
+
const shimmer = require('../../datadog-shimmer')
|
|
10
|
+
|
|
11
|
+
addHook({ name: 'sequelize', versions: ['>=4'] }, Sequelize => {
|
|
12
|
+
const startCh = channel('datadog:sequelize:query:start')
|
|
13
|
+
const finishCh = channel('datadog:sequelize:query:finish')
|
|
14
|
+
|
|
15
|
+
shimmer.wrap(Sequelize.prototype, 'query', query => {
|
|
16
|
+
return function (sql) {
|
|
17
|
+
if (!startCh.hasSubscribers) {
|
|
18
|
+
return query.apply(this, arguments)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
22
|
+
|
|
23
|
+
let dialect
|
|
24
|
+
if (this.options && this.options.dialect) {
|
|
25
|
+
dialect = this.options.dialect
|
|
26
|
+
} else if (this.dialect && this.dialect.name) {
|
|
27
|
+
dialect = this.dialect.name
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function onFinish () {
|
|
31
|
+
asyncResource.bind(function () {
|
|
32
|
+
finishCh.publish()
|
|
33
|
+
}, this).apply(this)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return asyncResource.bind(function () {
|
|
37
|
+
startCh.publish({
|
|
38
|
+
sql,
|
|
39
|
+
dialect
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const promise = query.apply(this, arguments)
|
|
43
|
+
promise.then(onFinish, onFinish)
|
|
44
|
+
|
|
45
|
+
return promise
|
|
46
|
+
}, this).apply(this, arguments)
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
return Sequelize
|
|
51
|
+
})
|
|
@@ -11,11 +11,9 @@ class Amqp10ConsumerPlugin extends ConsumerPlugin {
|
|
|
11
11
|
const source = getShortName(link)
|
|
12
12
|
const address = getAddress(link)
|
|
13
13
|
|
|
14
|
-
this.startSpan(
|
|
15
|
-
service: this.config.service || `${this.tracer._service}-amqp`,
|
|
14
|
+
this.startSpan({
|
|
16
15
|
resource: ['receive', source].filter(v => v).join(' '),
|
|
17
16
|
type: 'worker',
|
|
18
|
-
kind: 'consumer',
|
|
19
17
|
meta: {
|
|
20
18
|
'amqp.link.source.address': source,
|
|
21
19
|
'amqp.link.role': 'receiver',
|
|
@@ -13,10 +13,8 @@ class Amqp10ProducerPlugin extends ProducerPlugin {
|
|
|
13
13
|
const address = getAddress(link)
|
|
14
14
|
const target = getShortName(link)
|
|
15
15
|
|
|
16
|
-
this.startSpan(
|
|
17
|
-
service: this.config.service || `${this.tracer._service}-amqp`,
|
|
16
|
+
this.startSpan({
|
|
18
17
|
resource: ['send', target].filter(v => v).join(' '),
|
|
19
|
-
kind: 'producer',
|
|
20
18
|
meta: {
|
|
21
19
|
'amqp.link.target.address': target,
|
|
22
20
|
'amqp.link.role': 'sender',
|
|
@@ -7,6 +7,7 @@ const { getResourceName } = require('./util')
|
|
|
7
7
|
|
|
8
8
|
class AmqplibClientPlugin extends ClientPlugin {
|
|
9
9
|
static get id () { return 'amqplib' }
|
|
10
|
+
static get type () { return 'messaging' }
|
|
10
11
|
static get operation () { return 'command' }
|
|
11
12
|
|
|
12
13
|
start ({ channel = {}, method, fields }) {
|
|
@@ -14,10 +15,10 @@ class AmqplibClientPlugin extends ClientPlugin {
|
|
|
14
15
|
if (method === 'basic.publish') return
|
|
15
16
|
|
|
16
17
|
const stream = (channel.connection && channel.connection.stream) || {}
|
|
17
|
-
const span = this.startSpan(
|
|
18
|
-
service: this.config.service ||
|
|
18
|
+
const span = this.startSpan(this.operationName(), {
|
|
19
|
+
service: this.config.service || this.serviceName(),
|
|
19
20
|
resource: getResourceName(method, fields),
|
|
20
|
-
kind:
|
|
21
|
+
kind: this.constructor.kind,
|
|
21
22
|
meta: {
|
|
22
23
|
'out.host': stream._host,
|
|
23
24
|
[CLIENT_PORT_KEY]: stream.remotePort,
|
|
@@ -13,11 +13,9 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
|
|
|
13
13
|
|
|
14
14
|
const childOf = extract(this.tracer, message)
|
|
15
15
|
|
|
16
|
-
this.startSpan(
|
|
16
|
+
this.startSpan({
|
|
17
17
|
childOf,
|
|
18
|
-
service: this.config.service || `${this.tracer._service}-amqp`,
|
|
19
18
|
resource: getResourceName(method, fields),
|
|
20
|
-
kind: 'consumer',
|
|
21
19
|
type: 'worker',
|
|
22
20
|
meta: {
|
|
23
21
|
'amqp.queue': fields.queue,
|
|
@@ -13,10 +13,8 @@ class AmqplibProducerPlugin extends ProducerPlugin {
|
|
|
13
13
|
if (method !== 'basic.publish') return
|
|
14
14
|
|
|
15
15
|
const stream = (channel.connection && channel.connection.stream) || {}
|
|
16
|
-
const span = this.startSpan(
|
|
17
|
-
service: this.config.service || `${this.tracer._service}-amqp`,
|
|
16
|
+
const span = this.startSpan({
|
|
18
17
|
resource: getResourceName(method, fields),
|
|
19
|
-
kind: 'producer',
|
|
20
18
|
meta: {
|
|
21
19
|
'out.host': stream._host,
|
|
22
20
|
[CLIENT_PORT_KEY]: stream.remotePort,
|
|
@@ -73,8 +73,8 @@ class CucumberPlugin extends CiPlugin {
|
|
|
73
73
|
.map(filename => getTestSuitePath(filename, this.sourceRoot))
|
|
74
74
|
|
|
75
75
|
const formattedCoverage = {
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
sessionId: this.testSuiteSpan.context()._traceId,
|
|
77
|
+
suiteId: this.testSuiteSpan.context()._spanId,
|
|
78
78
|
files: relativeCoverageFiles
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -17,13 +17,16 @@ const {
|
|
|
17
17
|
TEST_COMMAND,
|
|
18
18
|
TEST_MODULE,
|
|
19
19
|
TEST_SOURCE_START,
|
|
20
|
-
finishAllTraceSpans
|
|
20
|
+
finishAllTraceSpans,
|
|
21
|
+
getCoveredFilenamesFromCoverage,
|
|
22
|
+
getTestSuitePath,
|
|
23
|
+
addIntelligentTestRunnerSpanTags
|
|
21
24
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
25
|
+
const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
|
|
26
|
+
const log = require('../../dd-trace/src/log')
|
|
22
27
|
|
|
23
28
|
const TEST_FRAMEWORK_NAME = 'cypress'
|
|
24
29
|
|
|
25
|
-
const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
|
|
26
|
-
|
|
27
30
|
const CYPRESS_STATUS_TO_TEST_STATUS = {
|
|
28
31
|
passed: 'pass',
|
|
29
32
|
failed: 'fail',
|
|
@@ -52,6 +55,13 @@ function getCypressVersion (details) {
|
|
|
52
55
|
return ''
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
function getRootDir (details) {
|
|
59
|
+
if (details && details.config) {
|
|
60
|
+
return details.config.projectRoot || details.config.repoRoot || process.cwd()
|
|
61
|
+
}
|
|
62
|
+
return process.cwd()
|
|
63
|
+
}
|
|
64
|
+
|
|
55
65
|
function getCypressCommand (details) {
|
|
56
66
|
if (!details) {
|
|
57
67
|
return TEST_FRAMEWORK_NAME
|
|
@@ -79,10 +89,62 @@ function getSuiteStatus (suiteStats) {
|
|
|
79
89
|
return 'pass'
|
|
80
90
|
}
|
|
81
91
|
|
|
92
|
+
function getItrConfig (tracer, testConfiguration) {
|
|
93
|
+
return new Promise(resolve => {
|
|
94
|
+
if (!tracer._tracer._exporter || !tracer._tracer._exporter.getItrConfiguration) {
|
|
95
|
+
return resolve({ err: new Error('CI Visibility was not initialized correctly') })
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
tracer._tracer._exporter.getItrConfiguration(testConfiguration, (err, itrConfig) => {
|
|
99
|
+
resolve({ err, itrConfig })
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function getSkippableTests (isSuitesSkippingEnabled, tracer, testConfiguration) {
|
|
105
|
+
if (!isSuitesSkippingEnabled) {
|
|
106
|
+
return Promise.resolve({ skippableTests: [] })
|
|
107
|
+
}
|
|
108
|
+
return new Promise(resolve => {
|
|
109
|
+
if (!tracer._tracer._exporter || !tracer._tracer._exporter.getItrConfiguration) {
|
|
110
|
+
return resolve({ err: new Error('CI Visibility was not initialized correctly') })
|
|
111
|
+
}
|
|
112
|
+
tracer._tracer._exporter.getSkippableSuites(testConfiguration, (err, skippableTests) => {
|
|
113
|
+
resolve({
|
|
114
|
+
err,
|
|
115
|
+
skippableTests
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
82
121
|
module.exports = (on, config) => {
|
|
83
122
|
const tracer = require('../../dd-trace')
|
|
84
123
|
const testEnvironmentMetadata = getTestEnvironmentMetadata(TEST_FRAMEWORK_NAME)
|
|
85
124
|
|
|
125
|
+
const {
|
|
126
|
+
'git.repository_url': repositoryUrl,
|
|
127
|
+
'git.commit.sha': sha,
|
|
128
|
+
'os.version': osVersion,
|
|
129
|
+
'os.platform': osPlatform,
|
|
130
|
+
'os.architecture': osArchitecture,
|
|
131
|
+
'runtime.name': runtimeName,
|
|
132
|
+
'runtime.version': runtimeVersion,
|
|
133
|
+
'git.branch': branch
|
|
134
|
+
} = testEnvironmentMetadata
|
|
135
|
+
|
|
136
|
+
const testConfiguration = {
|
|
137
|
+
repositoryUrl,
|
|
138
|
+
sha,
|
|
139
|
+
osVersion,
|
|
140
|
+
osPlatform,
|
|
141
|
+
osArchitecture,
|
|
142
|
+
runtimeName,
|
|
143
|
+
runtimeVersion,
|
|
144
|
+
branch,
|
|
145
|
+
testLevel: 'test'
|
|
146
|
+
}
|
|
147
|
+
|
|
86
148
|
const codeOwnersEntries = getCodeOwnersFileEntries()
|
|
87
149
|
|
|
88
150
|
let activeSpan = null
|
|
@@ -91,31 +153,54 @@ module.exports = (on, config) => {
|
|
|
91
153
|
let testSuiteSpan = null
|
|
92
154
|
let command = null
|
|
93
155
|
let frameworkVersion
|
|
156
|
+
let rootDir
|
|
157
|
+
let isSuitesSkippingEnabled = false
|
|
158
|
+
let isCodeCoverageEnabled = false
|
|
159
|
+
let testsToSkip = []
|
|
94
160
|
|
|
95
161
|
on('before:run', (details) => {
|
|
96
|
-
|
|
162
|
+
return getItrConfig(tracer, testConfiguration).then(({ err, itrConfig }) => {
|
|
163
|
+
if (err) {
|
|
164
|
+
log.error(err)
|
|
165
|
+
} else {
|
|
166
|
+
isSuitesSkippingEnabled = itrConfig.isSuitesSkippingEnabled
|
|
167
|
+
isCodeCoverageEnabled = itrConfig.isCodeCoverageEnabled
|
|
168
|
+
}
|
|
97
169
|
|
|
98
|
-
|
|
99
|
-
|
|
170
|
+
getSkippableTests(isSuitesSkippingEnabled, tracer, testConfiguration).then(({ err, skippableTests }) => {
|
|
171
|
+
if (err) {
|
|
172
|
+
log.error(err)
|
|
173
|
+
} else {
|
|
174
|
+
testsToSkip = skippableTests || []
|
|
175
|
+
}
|
|
100
176
|
|
|
101
|
-
|
|
102
|
-
|
|
177
|
+
const childOf = getTestParentSpan(tracer)
|
|
178
|
+
rootDir = getRootDir(details)
|
|
103
179
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
180
|
+
command = getCypressCommand(details)
|
|
181
|
+
frameworkVersion = getCypressVersion(details)
|
|
182
|
+
|
|
183
|
+
const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion, TEST_FRAMEWORK_NAME)
|
|
184
|
+
const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion, TEST_FRAMEWORK_NAME)
|
|
185
|
+
|
|
186
|
+
testSessionSpan = tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_session`, {
|
|
187
|
+
childOf,
|
|
188
|
+
tags: {
|
|
189
|
+
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
190
|
+
...testEnvironmentMetadata,
|
|
191
|
+
...testSessionSpanMetadata
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
testModuleSpan = tracer.startSpan(`${TEST_FRAMEWORK_NAME}.test_module`, {
|
|
195
|
+
childOf: testSessionSpan,
|
|
196
|
+
tags: {
|
|
197
|
+
[COMPONENT]: TEST_FRAMEWORK_NAME,
|
|
198
|
+
...testEnvironmentMetadata,
|
|
199
|
+
...testModuleSpanMetadata
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
return details
|
|
203
|
+
})
|
|
119
204
|
})
|
|
120
205
|
})
|
|
121
206
|
|
|
@@ -125,6 +210,16 @@ module.exports = (on, config) => {
|
|
|
125
210
|
testModuleSpan.setTag(TEST_STATUS, testStatus)
|
|
126
211
|
testSessionSpan.setTag(TEST_STATUS, testStatus)
|
|
127
212
|
|
|
213
|
+
addIntelligentTestRunnerSpanTags(
|
|
214
|
+
testSessionSpan,
|
|
215
|
+
testModuleSpan,
|
|
216
|
+
{
|
|
217
|
+
isSuitesSkipped: !!testsToSkip.length,
|
|
218
|
+
isSuitesSkippingEnabled,
|
|
219
|
+
isCodeCoverageEnabled
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
|
|
128
223
|
testModuleSpan.finish()
|
|
129
224
|
testSessionSpan.finish()
|
|
130
225
|
|
|
@@ -132,9 +227,15 @@ module.exports = (on, config) => {
|
|
|
132
227
|
}
|
|
133
228
|
|
|
134
229
|
return new Promise(resolve => {
|
|
135
|
-
tracer._tracer._exporter.
|
|
136
|
-
|
|
137
|
-
|
|
230
|
+
if (tracer._tracer._exporter.flush) {
|
|
231
|
+
tracer._tracer._exporter.flush(() => {
|
|
232
|
+
resolve(null)
|
|
233
|
+
})
|
|
234
|
+
} else {
|
|
235
|
+
tracer._tracer._exporter._writer.flush(() => {
|
|
236
|
+
resolve(null)
|
|
237
|
+
})
|
|
238
|
+
}
|
|
138
239
|
})
|
|
139
240
|
})
|
|
140
241
|
on('task', {
|
|
@@ -153,9 +254,9 @@ module.exports = (on, config) => {
|
|
|
153
254
|
})
|
|
154
255
|
return null
|
|
155
256
|
},
|
|
156
|
-
'dd:testSuiteFinish': (
|
|
257
|
+
'dd:testSuiteFinish': (stats) => {
|
|
157
258
|
if (testSuiteSpan) {
|
|
158
|
-
const status = getSuiteStatus(
|
|
259
|
+
const status = getSuiteStatus(stats)
|
|
159
260
|
testSuiteSpan.setTag(TEST_STATUS, status)
|
|
160
261
|
testSuiteSpan.finish()
|
|
161
262
|
testSuiteSpan = null
|
|
@@ -164,6 +265,12 @@ module.exports = (on, config) => {
|
|
|
164
265
|
},
|
|
165
266
|
'dd:beforeEach': (test) => {
|
|
166
267
|
const { testName, testSuite } = test
|
|
268
|
+
// skip test
|
|
269
|
+
if (testsToSkip.find(test => {
|
|
270
|
+
return testName === test.name && testSuite === test.suite
|
|
271
|
+
})) {
|
|
272
|
+
return { shouldSkip: true }
|
|
273
|
+
}
|
|
167
274
|
|
|
168
275
|
const testSuiteTags = {
|
|
169
276
|
[TEST_COMMAND]: command,
|
|
@@ -202,11 +309,24 @@ module.exports = (on, config) => {
|
|
|
202
309
|
}
|
|
203
310
|
})
|
|
204
311
|
}
|
|
205
|
-
return activeSpan ? activeSpan.context().toTraceId() :
|
|
312
|
+
return activeSpan ? { traceId: activeSpan.context().toTraceId() } : {}
|
|
206
313
|
},
|
|
207
|
-
'dd:afterEach': (test) => {
|
|
314
|
+
'dd:afterEach': ({ test, coverage }) => {
|
|
208
315
|
const { state, error, isRUMActive, testSourceLine } = test
|
|
209
316
|
if (activeSpan) {
|
|
317
|
+
if (coverage && tracer._tracer._exporter.exportCoverage && isCodeCoverageEnabled) {
|
|
318
|
+
const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
|
|
319
|
+
const relativeCoverageFiles = coverageFiles.map(file => getTestSuitePath(file, rootDir))
|
|
320
|
+
const { _traceId, _spanId } = testSuiteSpan.context()
|
|
321
|
+
const formattedCoverage = {
|
|
322
|
+
sessionId: _traceId,
|
|
323
|
+
suiteId: _spanId,
|
|
324
|
+
testId: activeSpan.context()._spanId,
|
|
325
|
+
files: relativeCoverageFiles
|
|
326
|
+
}
|
|
327
|
+
tracer._tracer._exporter.exportCoverage(formattedCoverage)
|
|
328
|
+
}
|
|
329
|
+
|
|
210
330
|
activeSpan.setTag(TEST_STATUS, CYPRESS_STATUS_TO_TEST_STATUS[state])
|
|
211
331
|
if (error) {
|
|
212
332
|
activeSpan.setTag('error', error)
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
beforeEach(()
|
|
2
|
+
beforeEach(function () {
|
|
3
3
|
cy.task('dd:beforeEach', {
|
|
4
4
|
testName: Cypress.mocha.getRunner().suite.ctx.currentTest.fullTitle(),
|
|
5
5
|
testSuite: Cypress.mocha.getRootSuite().file
|
|
6
|
-
}).then(traceId => {
|
|
6
|
+
}).then(({ traceId, shouldSkip }) => {
|
|
7
7
|
Cypress.env('traceId', traceId)
|
|
8
|
+
if (shouldSkip) {
|
|
9
|
+
this.skip()
|
|
10
|
+
}
|
|
8
11
|
})
|
|
9
12
|
})
|
|
10
13
|
|
|
@@ -36,6 +39,6 @@ afterEach(() => {
|
|
|
36
39
|
if (win.DD_RUM) {
|
|
37
40
|
testInfo.isRUMActive = true
|
|
38
41
|
}
|
|
39
|
-
cy.task('dd:afterEach', testInfo)
|
|
42
|
+
cy.task('dd:afterEach', { test: testInfo, coverage: win.__coverage__ })
|
|
40
43
|
})
|
|
41
44
|
})
|
|
@@ -4,15 +4,16 @@ const ClientPlugin = require('../../dd-trace/src/plugins/client')
|
|
|
4
4
|
|
|
5
5
|
class GoogleCloudPubsubClientPlugin extends ClientPlugin {
|
|
6
6
|
static get id () { return 'google-cloud-pubsub' }
|
|
7
|
+
static get type () { return 'messaging' }
|
|
7
8
|
static get operation () { return 'request' }
|
|
8
9
|
|
|
9
10
|
start ({ request, api, projectId }) {
|
|
10
11
|
if (api === 'publish') return
|
|
11
12
|
|
|
12
|
-
this.startSpan(
|
|
13
|
-
service: this.config.service ||
|
|
13
|
+
this.startSpan(this.operationName(), {
|
|
14
|
+
service: this.config.service || this.serviceName(),
|
|
14
15
|
resource: [api, request.name].filter(x => x).join(' '),
|
|
15
|
-
kind:
|
|
16
|
+
kind: this.constructor.kind,
|
|
16
17
|
meta: {
|
|
17
18
|
'pubsub.method': api,
|
|
18
19
|
'gcloud.project_id': projectId
|
|
@@ -11,11 +11,9 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
|
|
|
11
11
|
const topic = subscription.metadata && subscription.metadata.topic
|
|
12
12
|
const childOf = this.tracer.extract('text_map', message.attributes) || null
|
|
13
13
|
|
|
14
|
-
this.startSpan(
|
|
14
|
+
this.startSpan({
|
|
15
15
|
childOf,
|
|
16
|
-
service: this.config.service,
|
|
17
16
|
resource: topic,
|
|
18
|
-
kind: 'consumer',
|
|
19
17
|
type: 'worker',
|
|
20
18
|
meta: {
|
|
21
19
|
'gcloud.project_id': subscription.pubsub.projectId,
|
|
@@ -11,10 +11,8 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
|
|
|
11
11
|
|
|
12
12
|
const messages = request.messages || []
|
|
13
13
|
const topic = request.topic
|
|
14
|
-
const span = this.startSpan(
|
|
15
|
-
service: this.config.service || `${this.tracer._service}-pubsub`,
|
|
14
|
+
const span = this.startSpan({ // TODO: rename
|
|
16
15
|
resource: `${api} ${topic}`,
|
|
17
|
-
kind: 'producer',
|
|
18
16
|
meta: {
|
|
19
17
|
'gcloud.project_id': projectId,
|
|
20
18
|
'pubsub.method': api, // TODO: remove
|