dd-trace 3.20.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/index.d.ts +8 -1
- package/package.json +6 -5
- package/packages/datadog-instrumentations/src/cucumber.js +13 -0
- package/packages/datadog-instrumentations/src/grpc/client.js +9 -5
- package/packages/datadog-instrumentations/src/grpc/server.js +8 -4
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +4 -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/jest.js +20 -17
- package/packages/datadog-instrumentations/src/next.js +6 -1
- 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-aws-sdk/src/base.js +3 -0
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +4 -2
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +4 -3
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +2 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +8 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +7 -1
- 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 -67
- package/packages/datadog-plugin-http2/src/client.js +50 -46
- package/packages/datadog-plugin-jest/src/index.js +5 -4
- package/packages/datadog-plugin-jest/src/util.js +10 -1
- 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/command-injection-analyzer.js +2 -1
- 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/ldap-injection-analyzer.js +2 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +26 -5
- 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 +65 -4
- 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/analyzers/weak-cipher-analyzer.js +2 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +2 -1
- package/packages/dd-trace/src/appsec/iast/index.js +1 -1
- package/packages/dd-trace/src/appsec/iast/path-line.js +16 -8
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +19 -4
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/range-utils.js +37 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +29 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +35 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +118 -0
- 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 +146 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +113 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +10 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -109
- 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 +86 -9
- package/packages/dd-trace/src/constants.js +3 -1
- 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/git_metadata_tagger.js +17 -0
- package/packages/dd-trace/src/git_properties.js +32 -0
- 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 +63 -8
- package/packages/dd-trace/src/plugins/util/tags.js +5 -1
- package/packages/dd-trace/src/profiling/config.js +4 -2
- package/packages/dd-trace/src/profiling/constants.js +0 -1
- package/packages/dd-trace/src/profiling/profilers/space.js +1 -3
- package/packages/dd-trace/src/proxy.js +4 -0
- package/packages/dd-trace/src/serverless.js +25 -0
- 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/span_processor.js +3 -0
- package/packages/dd-trace/src/tracer.js +3 -2
- package/version.js +9 -0
- package/packages/dd-trace/src/plugins/incoming.js +0 -7
|
@@ -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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const ClientPlugin = require('../../dd-trace/src/plugins/client')
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
5
|
const tags = require('../../../ext/tags')
|
|
6
6
|
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
@@ -9,96 +9,99 @@ const HTTP_HEADERS = formats.HTTP_HEADERS
|
|
|
9
9
|
const urlFilter = require('../../dd-trace/src/plugins/util/urlfilter')
|
|
10
10
|
const log = require('../../dd-trace/src/log')
|
|
11
11
|
const url = require('url')
|
|
12
|
-
const { COMPONENT, ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
|
|
12
|
+
const { CLIENT_PORT_KEY, COMPONENT, ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
|
|
13
13
|
|
|
14
14
|
const HTTP_STATUS_CODE = tags.HTTP_STATUS_CODE
|
|
15
15
|
const HTTP_REQUEST_HEADERS = tags.HTTP_REQUEST_HEADERS
|
|
16
16
|
const HTTP_RESPONSE_HEADERS = tags.HTTP_RESPONSE_HEADERS
|
|
17
17
|
|
|
18
|
-
class HttpClientPlugin extends
|
|
18
|
+
class HttpClientPlugin extends ClientPlugin {
|
|
19
19
|
static get id () {
|
|
20
20
|
return 'http'
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
this.addSub('apm:http:client:request:start', ({ args, http }) => {
|
|
27
|
-
const store = storage.getStore()
|
|
28
|
-
const options = args.options
|
|
29
|
-
const agent = options.agent || options._defaultAgent || http.globalAgent
|
|
30
|
-
const protocol = options.protocol || agent.protocol || 'http:'
|
|
31
|
-
const hostname = options.hostname || options.host || 'localhost'
|
|
32
|
-
const host = options.port ? `${hostname}:${options.port}` : hostname
|
|
33
|
-
const path = options.path ? options.path.split(/[?#]/)[0] : '/'
|
|
34
|
-
const uri = `${protocol}//${host}${path}`
|
|
35
|
-
const allowed = this.config.filter(uri)
|
|
36
|
-
|
|
37
|
-
const method = (options.method || 'GET').toUpperCase()
|
|
38
|
-
const childOf = store && allowed ? store.span : null
|
|
39
|
-
const span = this.tracer.startSpan('http.request', {
|
|
40
|
-
childOf,
|
|
41
|
-
tags: {
|
|
42
|
-
[COMPONENT]: this.constructor.id,
|
|
43
|
-
'span.kind': 'client',
|
|
44
|
-
'service.name': getServiceName(this.tracer, this.config, options),
|
|
45
|
-
'resource.name': method,
|
|
46
|
-
'span.type': 'http',
|
|
47
|
-
'http.method': method,
|
|
48
|
-
'http.url': uri
|
|
49
|
-
}
|
|
50
|
-
})
|
|
23
|
+
addTraceSub (eventName, handler) {
|
|
24
|
+
this.addSub(`apm:${this.constructor.id}:client:${this.operation}:${eventName}`, handler)
|
|
25
|
+
}
|
|
51
26
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
27
|
+
start ({ args, http }) {
|
|
28
|
+
const store = storage.getStore()
|
|
29
|
+
const options = args.options
|
|
30
|
+
const agent = options.agent || options._defaultAgent || http.globalAgent
|
|
31
|
+
const protocol = options.protocol || agent.protocol || 'http:'
|
|
32
|
+
const hostname = options.hostname || options.host || 'localhost'
|
|
33
|
+
const host = options.port ? `${hostname}:${options.port}` : hostname
|
|
34
|
+
const path = options.path ? options.path.split(/[?#]/)[0] : '/'
|
|
35
|
+
const uri = `${protocol}//${host}${path}`
|
|
36
|
+
const allowed = this.config.filter(uri)
|
|
37
|
+
|
|
38
|
+
const method = (options.method || 'GET').toUpperCase()
|
|
39
|
+
const childOf = store && allowed ? store.span : null
|
|
40
|
+
// TODO delegate to super.startspan
|
|
41
|
+
const span = this.startSpan('http.request', {
|
|
42
|
+
childOf,
|
|
43
|
+
meta: {
|
|
44
|
+
[COMPONENT]: this.constructor.id,
|
|
45
|
+
'span.kind': 'client',
|
|
46
|
+
'service.name': getServiceName(this.tracer, this.config, options),
|
|
47
|
+
'resource.name': method,
|
|
48
|
+
'span.type': 'http',
|
|
49
|
+
'http.method': method,
|
|
50
|
+
'http.url': uri,
|
|
51
|
+
'out.host': hostname
|
|
52
|
+
},
|
|
53
|
+
metrics: {
|
|
54
|
+
[CLIENT_PORT_KEY]: parseInt(options.port)
|
|
55
55
|
}
|
|
56
|
+
})
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
// TODO: Figure out a better way to do this for any span.
|
|
59
|
+
if (!allowed) {
|
|
60
|
+
span._spanContext._trace.record = false
|
|
61
|
+
}
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
this.
|
|
63
|
-
}
|
|
63
|
+
if (!(hasAmazonSignature(options) || !this.config.propagationFilter(uri))) {
|
|
64
|
+
this.tracer.inject(span, HTTP_HEADERS, options.headers)
|
|
65
|
+
}
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
span.setTag(HTTP_STATUS_CODE, res.statusCode)
|
|
67
|
+
analyticsSampler.sample(span, this.config.measured)
|
|
68
|
+
this.enter(span, store)
|
|
69
|
+
}
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
finish ({ req, res }) {
|
|
72
|
+
const span = storage.getStore().span
|
|
73
|
+
if (res) {
|
|
74
|
+
span.setTag(HTTP_STATUS_CODE, res.statusCode)
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
if (!this.config.validateStatus(res.statusCode)) {
|
|
77
|
+
span.setTag('error', 1)
|
|
75
78
|
}
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
addResponseHeaders(res, span, this.config)
|
|
81
|
+
}
|
|
78
82
|
|
|
79
|
-
|
|
80
|
-
span.finish()
|
|
81
|
-
})
|
|
83
|
+
addRequestHeaders(req, span, this.config)
|
|
82
84
|
|
|
83
|
-
this.
|
|
85
|
+
this.config.hooks.request(span, req, res)
|
|
86
|
+
span.finish()
|
|
84
87
|
}
|
|
85
88
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
}
|
|
89
|
+
error (err) {
|
|
90
|
+
const span = storage.getStore().span
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
if (err) {
|
|
93
|
+
span.addTags({
|
|
94
|
+
[ERROR_TYPE]: err.name,
|
|
95
|
+
[ERROR_MESSAGE]: err.message || err.code,
|
|
96
|
+
[ERROR_STACK]: err.stack
|
|
97
|
+
})
|
|
98
|
+
} else {
|
|
99
|
+
span.setTag('error', 1)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
93
102
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
[ERROR_TYPE]: err.name,
|
|
97
|
-
[ERROR_MESSAGE]: err.message || err.code,
|
|
98
|
-
[ERROR_STACK]: err.stack
|
|
99
|
-
})
|
|
100
|
-
} else {
|
|
101
|
-
span.setTag('error', 1)
|
|
103
|
+
configure (config) {
|
|
104
|
+
return super.configure(normalizeClientConfig(config))
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
107
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { storage } = require('../../datadog-core')
|
|
4
|
-
const
|
|
4
|
+
const ClientPlugin = require('../../dd-trace/src/plugins/client')
|
|
5
5
|
|
|
6
6
|
const URL = require('url').URL
|
|
7
7
|
const log = require('../../dd-trace/src/log')
|
|
@@ -24,7 +24,7 @@ const HTTP2_HEADER_PATH = ':path'
|
|
|
24
24
|
const HTTP2_HEADER_STATUS = ':status'
|
|
25
25
|
const HTTP2_METHOD_GET = 'GET'
|
|
26
26
|
|
|
27
|
-
class Http2ClientPlugin extends
|
|
27
|
+
class Http2ClientPlugin extends ClientPlugin {
|
|
28
28
|
static get id () {
|
|
29
29
|
return 'http2'
|
|
30
30
|
}
|
|
@@ -32,46 +32,6 @@ class Http2ClientPlugin extends Plugin {
|
|
|
32
32
|
constructor (...args) {
|
|
33
33
|
super(...args)
|
|
34
34
|
|
|
35
|
-
this.addSub('apm:http2:client:request:start', ({ authority, options, headers = {} }) => {
|
|
36
|
-
const sessionDetails = extractSessionDetails(authority, options)
|
|
37
|
-
const path = headers[HTTP2_HEADER_PATH] || '/'
|
|
38
|
-
const pathname = path.split(/[?#]/)[0]
|
|
39
|
-
const method = headers[HTTP2_HEADER_METHOD] || HTTP2_METHOD_GET
|
|
40
|
-
const uri = `${sessionDetails.protocol}//${sessionDetails.host}:${sessionDetails.port}${pathname}`
|
|
41
|
-
const allowed = this.config.filter(uri)
|
|
42
|
-
|
|
43
|
-
const store = storage.getStore()
|
|
44
|
-
const childOf = store && allowed ? store.span : null
|
|
45
|
-
const span = this.tracer.startSpan('http.request', {
|
|
46
|
-
childOf,
|
|
47
|
-
tags: {
|
|
48
|
-
[COMPONENT]: this.constructor.id,
|
|
49
|
-
[CLIENT_PORT_KEY]: parseInt(sessionDetails.port),
|
|
50
|
-
[SPAN_KIND]: CLIENT,
|
|
51
|
-
'service.name': getServiceName(this.tracer, this.config, sessionDetails),
|
|
52
|
-
'resource.name': method,
|
|
53
|
-
'span.type': 'http',
|
|
54
|
-
'http.method': method,
|
|
55
|
-
'http.url': uri
|
|
56
|
-
}
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
// TODO: Figure out a better way to do this for any span.
|
|
60
|
-
if (!allowed) {
|
|
61
|
-
span._spanContext._trace.record = false
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
addHeaderTags(span, headers, HTTP_REQUEST_HEADERS, this.config)
|
|
65
|
-
|
|
66
|
-
if (!hasAmazonSignature(headers, path)) {
|
|
67
|
-
this.tracer.inject(span, HTTP_HEADERS, headers)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
analyticsSampler.sample(span, this.config.measured)
|
|
71
|
-
|
|
72
|
-
this.enter(span, store)
|
|
73
|
-
})
|
|
74
|
-
|
|
75
35
|
this.addSub('apm:http2:client:response', (headers) => {
|
|
76
36
|
const span = storage.getStore().span
|
|
77
37
|
const status = headers && headers[HTTP2_HEADER_STATUS]
|
|
@@ -84,14 +44,58 @@ class Http2ClientPlugin extends Plugin {
|
|
|
84
44
|
|
|
85
45
|
addHeaderTags(span, headers, HTTP_RESPONSE_HEADERS, this.config)
|
|
86
46
|
})
|
|
47
|
+
}
|
|
87
48
|
|
|
88
|
-
|
|
89
|
-
|
|
49
|
+
addTraceSub (eventName, handler) {
|
|
50
|
+
this.addSub(`apm:${this.constructor.id}:client:${this.operation}:${eventName}`, handler)
|
|
51
|
+
}
|
|
90
52
|
|
|
91
|
-
|
|
53
|
+
start ({ authority, options, headers = {} }) {
|
|
54
|
+
const sessionDetails = extractSessionDetails(authority, options)
|
|
55
|
+
const path = headers[HTTP2_HEADER_PATH] || '/'
|
|
56
|
+
const pathname = path.split(/[?#]/)[0]
|
|
57
|
+
const method = headers[HTTP2_HEADER_METHOD] || HTTP2_METHOD_GET
|
|
58
|
+
const uri = `${sessionDetails.protocol}//${sessionDetails.host}:${sessionDetails.port}${pathname}`
|
|
59
|
+
const allowed = this.config.filter(uri)
|
|
60
|
+
|
|
61
|
+
const store = storage.getStore()
|
|
62
|
+
const childOf = store && allowed ? store.span : null
|
|
63
|
+
const span = this.startSpan('http.request', {
|
|
64
|
+
childOf,
|
|
65
|
+
meta: {
|
|
66
|
+
[COMPONENT]: this.constructor.id,
|
|
67
|
+
[SPAN_KIND]: CLIENT,
|
|
68
|
+
'service.name': getServiceName(this.tracer, this.config, sessionDetails),
|
|
69
|
+
'resource.name': method,
|
|
70
|
+
'span.type': 'http',
|
|
71
|
+
'http.method': method,
|
|
72
|
+
'http.url': uri,
|
|
73
|
+
'out.host': sessionDetails.host
|
|
74
|
+
},
|
|
75
|
+
metrics: {
|
|
76
|
+
[CLIENT_PORT_KEY]: parseInt(sessionDetails.port)
|
|
77
|
+
}
|
|
92
78
|
})
|
|
93
79
|
|
|
94
|
-
|
|
80
|
+
// TODO: Figure out a better way to do this for any span.
|
|
81
|
+
if (!allowed) {
|
|
82
|
+
span._spanContext._trace.record = false
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
addHeaderTags(span, headers, HTTP_REQUEST_HEADERS, this.config)
|
|
86
|
+
|
|
87
|
+
if (!hasAmazonSignature(headers, path)) {
|
|
88
|
+
this.tracer.inject(span, HTTP_HEADERS, headers)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
analyticsSampler.sample(span, this.config.measured)
|
|
92
|
+
|
|
93
|
+
this.enter(span, store)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
finish () {
|
|
97
|
+
const span = storage.getStore().span
|
|
98
|
+
span.finish()
|
|
95
99
|
}
|
|
96
100
|
|
|
97
101
|
configure (config) {
|
|
@@ -118,8 +118,8 @@ class JestPlugin extends CiPlugin {
|
|
|
118
118
|
|
|
119
119
|
this.addSub('ci:jest:worker-report:coverage', data => {
|
|
120
120
|
const formattedCoverages = JSON.parse(data).map(coverage => ({
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
sessionId: id(coverage.sessionId),
|
|
122
|
+
suiteId: id(coverage.suiteId),
|
|
123
123
|
files: coverage.files
|
|
124
124
|
}))
|
|
125
125
|
formattedCoverages.forEach(formattedCoverage => {
|
|
@@ -150,9 +150,10 @@ class JestPlugin extends CiPlugin {
|
|
|
150
150
|
* fetching the ITR config.
|
|
151
151
|
*/
|
|
152
152
|
this.addSub('ci:jest:test-suite:code-coverage', (coverageFiles) => {
|
|
153
|
+
const { _traceId, _spanId } = this.testSuiteSpan.context()
|
|
153
154
|
const formattedCoverage = {
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
sessionId: _traceId,
|
|
156
|
+
suiteId: _spanId,
|
|
156
157
|
files: coverageFiles
|
|
157
158
|
}
|
|
158
159
|
this.tracer._exporter.exportCoverage(formattedCoverage)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { getTestSuitePath } = require('../../dd-trace/src/plugins/util/test')
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* There are two ways to call `test.each` in `jest`:
|
|
3
5
|
* 1. With an array of arrays: https://jestjs.io/docs/api#1-testeachtablename-fn-timeout
|
|
@@ -45,4 +47,11 @@ function getJestTestName (test) {
|
|
|
45
47
|
return titles.join(' ')
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
function getJestSuitesToRun (skippableSuites, originalTests, rootDir) {
|
|
51
|
+
return originalTests.filter(({ path: testPath }) => {
|
|
52
|
+
const relativePath = getTestSuitePath(testPath, rootDir)
|
|
53
|
+
return !skippableSuites.includes(relativePath)
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = { getFormattedJestTestParameters, getJestTestName, getJestSuitesToRun }
|