dd-trace 3.42.0 → 3.44.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 +5 -0
- package/package.json +4 -4
- package/packages/datadog-instrumentations/src/apollo-server-core.js +41 -0
- package/packages/datadog-instrumentations/src/apollo-server.js +83 -0
- 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/graphql.js +18 -4
- package/packages/datadog-instrumentations/src/helpers/hooks.js +9 -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 +4 -16
- 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 +1 -1
- package/packages/datadog-instrumentations/src/net.js +10 -2
- package/packages/datadog-instrumentations/src/next.js +15 -5
- package/packages/datadog-instrumentations/src/rhea.js +15 -9
- package/packages/datadog-plugin-cucumber/src/index.js +34 -2
- package/packages/datadog-plugin-cypress/src/plugin.js +60 -8
- package/packages/datadog-plugin-graphql/src/resolve.js +26 -18
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +38 -4
- package/packages/datadog-plugin-mocha/src/index.js +32 -1
- package/packages/datadog-plugin-next/src/index.js +32 -6
- package/packages/datadog-plugin-playwright/src/index.js +17 -1
- package/packages/dd-trace/src/appsec/activation.js +29 -0
- package/packages/dd-trace/src/appsec/addresses.js +1 -0
- package/packages/dd-trace/src/appsec/api_security_sampler.js +48 -0
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -1
- package/packages/dd-trace/src/appsec/blocking.js +95 -43
- package/packages/dd-trace/src/appsec/channels.js +4 -1
- package/packages/dd-trace/src/appsec/graphql.js +146 -0
- package/packages/dd-trace/src/appsec/index.js +29 -40
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +6 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +40 -15
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +25 -13
- 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 +104 -58
- 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/plugins/util/user-provided-git.js +3 -2
- package/packages/dd-trace/src/priority_sampler.js +30 -38
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -0
- package/packages/dd-trace/src/profiling/profiler.js +7 -6
- package/packages/dd-trace/src/profiling/profilers/events.js +18 -13
- package/packages/dd-trace/src/profiling/profilers/shared.js +34 -4
- package/packages/dd-trace/src/profiling/profilers/space.js +2 -1
- package/packages/dd-trace/src/profiling/profilers/wall.js +17 -12
- package/packages/dd-trace/src/proxy.js +4 -0
- 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
|
@@ -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) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
|
|
4
|
+
const dc = require('dc-polyfill')
|
|
4
5
|
|
|
5
6
|
const collapsedPathSym = Symbol('collapsedPaths')
|
|
6
7
|
|
|
@@ -14,8 +15,6 @@ class GraphQLResolvePlugin extends TracingPlugin {
|
|
|
14
15
|
if (!shouldInstrument(this.config, path)) return
|
|
15
16
|
const computedPathString = path.join('.')
|
|
16
17
|
|
|
17
|
-
addResolver(context, info, args)
|
|
18
|
-
|
|
19
18
|
if (this.config.collapse) {
|
|
20
19
|
if (!context[collapsedPathSym]) {
|
|
21
20
|
context[collapsedPathSym] = {}
|
|
@@ -55,6 +54,10 @@ class GraphQLResolvePlugin extends TracingPlugin {
|
|
|
55
54
|
span.setTag(`graphql.variables.${name}`, variables[name])
|
|
56
55
|
})
|
|
57
56
|
}
|
|
57
|
+
|
|
58
|
+
if (this.resolverStartCh.hasSubscribers) {
|
|
59
|
+
this.resolverStartCh.publish({ context, resolverInfo: getResolverInfo(info, args) })
|
|
60
|
+
}
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
constructor (...args) {
|
|
@@ -69,6 +72,8 @@ class GraphQLResolvePlugin extends TracingPlugin {
|
|
|
69
72
|
field.finishTime = span._getTime ? span._getTime() : 0
|
|
70
73
|
field.error = field.error || err
|
|
71
74
|
})
|
|
75
|
+
|
|
76
|
+
this.resolverStartCh = dc.channel('datadog:graphql:resolver:start')
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
configure (config) {
|
|
@@ -109,28 +114,31 @@ function withCollapse (responsePathAsArray) {
|
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
|
|
112
|
-
function
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
117
|
+
function getResolverInfo (info, args) {
|
|
118
|
+
let resolverInfo = null
|
|
119
|
+
const resolverVars = {}
|
|
116
120
|
|
|
117
|
-
if (
|
|
118
|
-
|
|
121
|
+
if (args && Object.keys(args).length) {
|
|
122
|
+
Object.assign(resolverVars, args)
|
|
119
123
|
}
|
|
120
124
|
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
} else {
|
|
127
|
-
resolvers[info.fieldName] = []
|
|
125
|
+
const directives = info.fieldNodes[0].directives
|
|
126
|
+
for (const directive of directives) {
|
|
127
|
+
const argList = {}
|
|
128
|
+
for (const argument of directive['arguments']) {
|
|
129
|
+
argList[argument.name.value] = argument.value.value
|
|
128
130
|
}
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
|
|
131
|
+
|
|
132
|
+
if (Object.keys(argList).length) {
|
|
133
|
+
resolverVars[directive.name.value] = argList
|
|
132
134
|
}
|
|
133
135
|
}
|
|
136
|
+
|
|
137
|
+
if (Object.keys(resolverVars).length) {
|
|
138
|
+
resolverInfo = { [info.fieldName]: resolverVars }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return resolverInfo
|
|
134
142
|
}
|
|
135
143
|
|
|
136
144
|
module.exports = GraphQLResolvePlugin
|
|
@@ -121,7 +121,7 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
121
121
|
} else {
|
|
122
122
|
// conditions for no error:
|
|
123
123
|
// 1. not using a custom agent instance with custom timeout specified
|
|
124
|
-
// 2. no invocation of `req.setTimeout`
|
|
124
|
+
// 2. no invocation of `req.setTimeout`
|
|
125
125
|
if (!args.options.agent?.options.timeout && !customRequestTimeout) return
|
|
126
126
|
|
|
127
127
|
span.setTag('error', 1)
|
|
@@ -12,10 +12,21 @@ const {
|
|
|
12
12
|
TEST_FRAMEWORK_VERSION,
|
|
13
13
|
TEST_SOURCE_START,
|
|
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 { COMPONENT } = require('../../dd-trace/src/constants')
|
|
18
19
|
const id = require('../../dd-trace/src/id')
|
|
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
|
const isJestWorker = !!process.env.JEST_WORKER_ID
|
|
21
32
|
|
|
@@ -81,7 +92,9 @@ class JestPlugin extends CiPlugin {
|
|
|
81
92
|
)
|
|
82
93
|
|
|
83
94
|
this.testModuleSpan.finish()
|
|
95
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
84
96
|
this.testSessionSpan.finish()
|
|
97
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
85
98
|
finishAllTraceSpans(this.testSessionSpan)
|
|
86
99
|
this.tracer._exporter.flush()
|
|
87
100
|
})
|
|
@@ -103,7 +116,8 @@ class JestPlugin extends CiPlugin {
|
|
|
103
116
|
_ddTestCommand: testCommand,
|
|
104
117
|
_ddTestModuleId: testModuleId,
|
|
105
118
|
_ddForcedToRun,
|
|
106
|
-
_ddUnskippable
|
|
119
|
+
_ddUnskippable,
|
|
120
|
+
_ddTestCodeCoverageEnabled
|
|
107
121
|
} = testEnvironmentOptions
|
|
108
122
|
|
|
109
123
|
const testSessionSpanContext = this.tracer.extract('text_map', {
|
|
@@ -114,8 +128,10 @@ class JestPlugin extends CiPlugin {
|
|
|
114
128
|
const testSuiteMetadata = getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, 'jest')
|
|
115
129
|
|
|
116
130
|
if (_ddUnskippable) {
|
|
131
|
+
this.telemetry.count(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
|
|
117
132
|
testSuiteMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
|
|
118
133
|
if (_ddForcedToRun) {
|
|
134
|
+
this.telemetry.count(TELEMETRY_ITR_FORCED_TO_RUN, { testLevel: 'suite' })
|
|
119
135
|
testSuiteMetadata[TEST_ITR_FORCED_RUN] = 'true'
|
|
120
136
|
}
|
|
121
137
|
}
|
|
@@ -128,6 +144,10 @@ class JestPlugin extends CiPlugin {
|
|
|
128
144
|
...testSuiteMetadata
|
|
129
145
|
}
|
|
130
146
|
})
|
|
147
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
148
|
+
if (_ddTestCodeCoverageEnabled) {
|
|
149
|
+
this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_STARTED, 'suite', { library: 'istanbul' })
|
|
150
|
+
}
|
|
131
151
|
})
|
|
132
152
|
|
|
133
153
|
this.addSub('ci:jest:worker-report:trace', traces => {
|
|
@@ -164,6 +184,7 @@ class JestPlugin extends CiPlugin {
|
|
|
164
184
|
this.testSuiteSpan.setTag('error', new Error(errorMessage))
|
|
165
185
|
}
|
|
166
186
|
this.testSuiteSpan.finish()
|
|
187
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
167
188
|
// Suites potentially run in a different process than the session,
|
|
168
189
|
// so calling finishAllTraceSpans on the session span is not enough
|
|
169
190
|
finishAllTraceSpans(this.testSuiteSpan)
|
|
@@ -180,14 +201,22 @@ class JestPlugin extends CiPlugin {
|
|
|
180
201
|
* because this subscription happens in a different process from the one
|
|
181
202
|
* fetching the ITR config.
|
|
182
203
|
*/
|
|
183
|
-
this.addSub('ci:jest:test-suite:code-coverage', (coverageFiles) => {
|
|
204
|
+
this.addSub('ci:jest:test-suite:code-coverage', ({ coverageFiles, testSuite }) => {
|
|
205
|
+
if (!coverageFiles.length) {
|
|
206
|
+
this.telemetry.count(TELEMETRY_CODE_COVERAGE_EMPTY)
|
|
207
|
+
}
|
|
208
|
+
const files = [...coverageFiles, testSuite]
|
|
209
|
+
|
|
184
210
|
const { _traceId, _spanId } = this.testSuiteSpan.context()
|
|
185
211
|
const formattedCoverage = {
|
|
186
212
|
sessionId: _traceId,
|
|
187
213
|
suiteId: _spanId,
|
|
188
|
-
files
|
|
214
|
+
files
|
|
189
215
|
}
|
|
216
|
+
|
|
190
217
|
this.tracer._exporter.exportCoverage(formattedCoverage)
|
|
218
|
+
this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_FINISHED, 'suite', { library: 'istanbul' })
|
|
219
|
+
this.telemetry.distribution(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, files.length)
|
|
191
220
|
})
|
|
192
221
|
|
|
193
222
|
this.addSub('ci:jest:test:start', (test) => {
|
|
@@ -204,6 +233,11 @@ class JestPlugin extends CiPlugin {
|
|
|
204
233
|
span.setTag(TEST_SOURCE_START, testStartLine)
|
|
205
234
|
}
|
|
206
235
|
span.finish()
|
|
236
|
+
this.telemetry.ciVisEvent(
|
|
237
|
+
TELEMETRY_EVENT_FINISHED,
|
|
238
|
+
'test',
|
|
239
|
+
{ hasCodeOwners: !!span.context()._tags[TEST_CODE_OWNERS] }
|
|
240
|
+
)
|
|
207
241
|
finishAllTraceSpans(span)
|
|
208
242
|
})
|
|
209
243
|
|
|
@@ -13,9 +13,20 @@ const {
|
|
|
13
13
|
addIntelligentTestRunnerSpanTags,
|
|
14
14
|
TEST_SOURCE_START,
|
|
15
15
|
TEST_ITR_UNSKIPPABLE,
|
|
16
|
-
TEST_ITR_FORCED_RUN
|
|
16
|
+
TEST_ITR_FORCED_RUN,
|
|
17
|
+
TEST_CODE_OWNERS
|
|
17
18
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
18
19
|
const { COMPONENT } = 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 MochaPlugin extends CiPlugin {
|
|
21
32
|
static get id () {
|
|
@@ -35,6 +46,10 @@ class MochaPlugin extends CiPlugin {
|
|
|
35
46
|
}
|
|
36
47
|
const testSuiteSpan = this._testSuites.get(suiteFile)
|
|
37
48
|
|
|
49
|
+
if (!coverageFiles.length) {
|
|
50
|
+
this.telemetry.count(TELEMETRY_CODE_COVERAGE_EMPTY)
|
|
51
|
+
}
|
|
52
|
+
|
|
38
53
|
const relativeCoverageFiles = [...coverageFiles, suiteFile]
|
|
39
54
|
.map(filename => getTestSuitePath(filename, this.sourceRoot))
|
|
40
55
|
|
|
@@ -47,6 +62,8 @@ class MochaPlugin extends CiPlugin {
|
|
|
47
62
|
}
|
|
48
63
|
|
|
49
64
|
this.tracer._exporter.exportCoverage(formattedCoverage)
|
|
65
|
+
this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_FINISHED, 'suite', { library: 'istanbul' })
|
|
66
|
+
this.telemetry.distribution(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
|
|
50
67
|
})
|
|
51
68
|
|
|
52
69
|
this.addSub('ci:mocha:test-suite:start', ({ testSuite, isUnskippable, isForcedToRun }) => {
|
|
@@ -59,9 +76,11 @@ class MochaPlugin extends CiPlugin {
|
|
|
59
76
|
)
|
|
60
77
|
if (isUnskippable) {
|
|
61
78
|
testSuiteMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
|
|
79
|
+
this.telemetry.count(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
|
|
62
80
|
}
|
|
63
81
|
if (isForcedToRun) {
|
|
64
82
|
testSuiteMetadata[TEST_ITR_FORCED_RUN] = 'true'
|
|
83
|
+
this.telemetry.count(TELEMETRY_ITR_FORCED_TO_RUN, { testLevel: 'suite' })
|
|
65
84
|
}
|
|
66
85
|
|
|
67
86
|
const testSuiteSpan = this.tracer.startSpan('mocha.test_suite', {
|
|
@@ -72,6 +91,10 @@ class MochaPlugin extends CiPlugin {
|
|
|
72
91
|
...testSuiteMetadata
|
|
73
92
|
}
|
|
74
93
|
})
|
|
94
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
95
|
+
if (this.itrConfig?.isCodeCoverageEnabled) {
|
|
96
|
+
this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_STARTED, 'suite', { library: 'istanbul' })
|
|
97
|
+
}
|
|
75
98
|
this.enter(testSuiteSpan, store)
|
|
76
99
|
this._testSuites.set(testSuite, testSuiteSpan)
|
|
77
100
|
})
|
|
@@ -85,6 +108,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
85
108
|
span.setTag(TEST_STATUS, status)
|
|
86
109
|
}
|
|
87
110
|
span.finish()
|
|
111
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
88
112
|
}
|
|
89
113
|
})
|
|
90
114
|
|
|
@@ -113,6 +137,11 @@ class MochaPlugin extends CiPlugin {
|
|
|
113
137
|
span.setTag(TEST_STATUS, status)
|
|
114
138
|
|
|
115
139
|
span.finish()
|
|
140
|
+
this.telemetry.ciVisEvent(
|
|
141
|
+
TELEMETRY_EVENT_FINISHED,
|
|
142
|
+
'test',
|
|
143
|
+
{ hasCodeOwners: !!span.context()._tags[TEST_CODE_OWNERS] }
|
|
144
|
+
)
|
|
116
145
|
finishAllTraceSpans(span)
|
|
117
146
|
}
|
|
118
147
|
})
|
|
@@ -179,7 +208,9 @@ class MochaPlugin extends CiPlugin {
|
|
|
179
208
|
)
|
|
180
209
|
|
|
181
210
|
this.testModuleSpan.finish()
|
|
211
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
182
212
|
this.testSessionSpan.finish()
|
|
213
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
183
214
|
finishAllTraceSpans(this.testSessionSpan)
|
|
184
215
|
}
|
|
185
216
|
this.itrConfig = null
|
|
@@ -6,6 +6,8 @@ const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
|
6
6
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
7
7
|
const web = require('../../dd-trace/src/plugins/util/web')
|
|
8
8
|
|
|
9
|
+
const errorPages = ['/404', '/500', '/_error', '/_not-found']
|
|
10
|
+
|
|
9
11
|
class NextPlugin extends ServerPlugin {
|
|
10
12
|
static get id () {
|
|
11
13
|
return 'next'
|
|
@@ -40,6 +42,13 @@ class NextPlugin extends ServerPlugin {
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
error ({ span, error }) {
|
|
45
|
+
if (!span) {
|
|
46
|
+
const store = storage.getStore()
|
|
47
|
+
if (!store) return
|
|
48
|
+
|
|
49
|
+
span = store.span
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
this.addError(error, span)
|
|
44
53
|
}
|
|
45
54
|
|
|
@@ -50,10 +59,20 @@ class NextPlugin extends ServerPlugin {
|
|
|
50
59
|
|
|
51
60
|
const span = store.span
|
|
52
61
|
const error = span.context()._tags['error']
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
const requestError = req.error || nextRequest.error
|
|
63
|
+
|
|
64
|
+
if (requestError) {
|
|
65
|
+
// prioritize user-set errors from API routes
|
|
66
|
+
span.setTag('error', requestError)
|
|
67
|
+
web.addError(req, requestError)
|
|
68
|
+
} else if (error) {
|
|
69
|
+
// general error handling
|
|
70
|
+
span.setTag('error', error)
|
|
71
|
+
web.addError(req, requestError || error)
|
|
72
|
+
} else if (!this.config.validateStatus(res.statusCode)) {
|
|
73
|
+
// where there's no error, we still need to validate status
|
|
74
|
+
span.setTag('error', true)
|
|
75
|
+
web.addError(req, true)
|
|
57
76
|
}
|
|
58
77
|
|
|
59
78
|
span.addTags({
|
|
@@ -73,14 +92,21 @@ class NextPlugin extends ServerPlugin {
|
|
|
73
92
|
const span = store.span
|
|
74
93
|
const req = this._requests.get(span)
|
|
75
94
|
|
|
95
|
+
// safeguard against missing req in complicated timeout scenarios
|
|
96
|
+
if (!req) return
|
|
97
|
+
|
|
76
98
|
// Only use error page names if there's not already a name
|
|
77
99
|
const current = span.context()._tags['next.page']
|
|
78
|
-
|
|
100
|
+
const isErrorPage = errorPages.includes(page)
|
|
101
|
+
|
|
102
|
+
if (current && isErrorPage) {
|
|
79
103
|
return
|
|
80
104
|
}
|
|
81
105
|
|
|
82
106
|
// remove ending /route or /page for appDir projects
|
|
83
|
-
if
|
|
107
|
+
// need to check if not an error page too, as those are marked as app directory
|
|
108
|
+
// in newer versions
|
|
109
|
+
if (isAppPath && !isErrorPage) page = page.substring(0, page.lastIndexOf('/'))
|
|
84
110
|
|
|
85
111
|
// handle static resource
|
|
86
112
|
if (isStatic) {
|
|
@@ -8,10 +8,15 @@ const {
|
|
|
8
8
|
finishAllTraceSpans,
|
|
9
9
|
getTestSuitePath,
|
|
10
10
|
getTestSuiteCommonTags,
|
|
11
|
-
TEST_SOURCE_START
|
|
11
|
+
TEST_SOURCE_START,
|
|
12
|
+
TEST_CODE_OWNERS
|
|
12
13
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
13
14
|
const { RESOURCE_NAME } = require('../../../ext/tags')
|
|
14
15
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
16
|
+
const {
|
|
17
|
+
TELEMETRY_EVENT_CREATED,
|
|
18
|
+
TELEMETRY_EVENT_FINISHED
|
|
19
|
+
} = require('../../dd-trace/src/ci-visibility/telemetry')
|
|
15
20
|
|
|
16
21
|
class PlaywrightPlugin extends CiPlugin {
|
|
17
22
|
static get id () {
|
|
@@ -28,7 +33,9 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
28
33
|
this.testSessionSpan.setTag(TEST_STATUS, status)
|
|
29
34
|
|
|
30
35
|
this.testModuleSpan.finish()
|
|
36
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
|
|
31
37
|
this.testSessionSpan.finish()
|
|
38
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
|
|
32
39
|
finishAllTraceSpans(this.testSessionSpan)
|
|
33
40
|
this.tracer._exporter.flush(onDone)
|
|
34
41
|
})
|
|
@@ -52,6 +59,7 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
52
59
|
...testSuiteMetadata
|
|
53
60
|
}
|
|
54
61
|
})
|
|
62
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
|
|
55
63
|
this.enter(testSuiteSpan, store)
|
|
56
64
|
|
|
57
65
|
this._testSuites.set(testSuite, testSuiteSpan)
|
|
@@ -63,6 +71,7 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
63
71
|
if (!span) return
|
|
64
72
|
span.setTag(TEST_STATUS, status)
|
|
65
73
|
span.finish()
|
|
74
|
+
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
|
|
66
75
|
})
|
|
67
76
|
|
|
68
77
|
this.addSub('ci:playwright:test:start', ({ testName, testSuiteAbsolutePath, testSourceLine }) => {
|
|
@@ -104,6 +113,13 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
104
113
|
})
|
|
105
114
|
|
|
106
115
|
span.finish()
|
|
116
|
+
|
|
117
|
+
this.telemetry.ciVisEvent(
|
|
118
|
+
TELEMETRY_EVENT_FINISHED,
|
|
119
|
+
'test',
|
|
120
|
+
{ hasCodeOwners: !!span.context()._tags[TEST_CODE_OWNERS] }
|
|
121
|
+
)
|
|
122
|
+
|
|
107
123
|
finishAllTraceSpans(span)
|
|
108
124
|
})
|
|
109
125
|
}
|