dd-trace 2.25.1 → 2.26.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 +50 -0
- package/package.json +1 -1
- package/packages/datadog-instrumentations/src/fs.js +350 -4
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/jest.js +11 -1
- package/packages/datadog-instrumentations/src/mocha.js +3 -2
- package/packages/datadog-instrumentations/src/mysql.js +7 -1
- package/packages/datadog-instrumentations/src/mysql2.js +7 -1
- package/packages/datadog-instrumentations/src/playwright.js +236 -0
- package/packages/datadog-plugin-fs/src/index.js +37 -574
- package/packages/datadog-plugin-jest/src/index.js +45 -23
- package/packages/datadog-plugin-mocha/src/index.js +34 -6
- package/packages/datadog-plugin-mysql/src/index.js +8 -7
- package/packages/datadog-plugin-playwright/src/index.js +171 -0
- package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +60 -0
- package/packages/dd-trace/src/appsec/index.js +1 -1
- package/packages/dd-trace/src/appsec/recommended.json +247 -112
- package/packages/dd-trace/src/appsec/sdk/index.js +23 -0
- package/packages/dd-trace/src/appsec/sdk/noop.js +11 -0
- package/packages/dd-trace/src/appsec/sdk/track_event.js +74 -0
- package/packages/dd-trace/src/appsec/sdk/utils.js +10 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +1 -1
- package/packages/dd-trace/src/config.js +7 -0
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +44 -4
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +52 -37
- package/packages/dd-trace/src/log/channels.js +47 -0
- package/packages/dd-trace/src/log/index.js +79 -0
- package/packages/dd-trace/src/log/writer.js +108 -0
- package/packages/dd-trace/src/noop/proxy.js +3 -0
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +13 -21
- package/packages/dd-trace/src/{appsec → plugins/util}/ip_blocklist.js +0 -0
- package/packages/dd-trace/src/{appsec → plugins/util}/ip_extractor.js +1 -1
- package/packages/dd-trace/src/plugins/util/test.js +27 -10
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -7
- package/packages/dd-trace/src/plugins/util/web.js +11 -0
- package/packages/dd-trace/src/proxy.js +2 -0
- package/packages/dd-trace/src/startup-log.js +1 -1
- package/scripts/check-proposal-labels.js +71 -0
- package/packages/dd-trace/src/log.js +0 -143
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
2
|
+
const shimmer = require('../../datadog-shimmer')
|
|
3
|
+
|
|
4
|
+
const testStartCh = channel('ci:playwright:test:start')
|
|
5
|
+
const testFinishCh = channel('ci:playwright:test:finish')
|
|
6
|
+
|
|
7
|
+
const testSessionStartCh = channel('ci:playwright:session:start')
|
|
8
|
+
const testSessionFinishCh = channel('ci:playwright:session:finish')
|
|
9
|
+
|
|
10
|
+
const testSuiteStartCh = channel('ci:playwright:test-suite:start')
|
|
11
|
+
const testSuiteFinishCh = channel('ci:playwright:test-suite:finish')
|
|
12
|
+
|
|
13
|
+
const testToAr = new WeakMap()
|
|
14
|
+
const testSuiteToAr = new Map()
|
|
15
|
+
const testSuiteToTestStatuses = new Map()
|
|
16
|
+
|
|
17
|
+
let startedSuites = []
|
|
18
|
+
|
|
19
|
+
const STATUS_TO_TEST_STATUS = {
|
|
20
|
+
passed: 'pass',
|
|
21
|
+
failed: 'fail',
|
|
22
|
+
timedOut: 'fail',
|
|
23
|
+
skipped: 'skip'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let remainingTestsByFile = {}
|
|
27
|
+
|
|
28
|
+
function getTestsBySuiteFromTestsById (testsById) {
|
|
29
|
+
const testsByTestSuite = {}
|
|
30
|
+
for (const { test } of testsById.values()) {
|
|
31
|
+
const { _requireFile } = test
|
|
32
|
+
if (test._type === 'beforeAll' || test._type === 'afterAll') {
|
|
33
|
+
continue
|
|
34
|
+
}
|
|
35
|
+
if (testsByTestSuite[_requireFile]) {
|
|
36
|
+
testsByTestSuite[_requireFile].push(test)
|
|
37
|
+
} else {
|
|
38
|
+
testsByTestSuite[_requireFile] = [test]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return testsByTestSuite
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function getPlaywrightConfig (playwrightRunner) {
|
|
45
|
+
try {
|
|
46
|
+
return playwrightRunner._configLoader.fullConfig()
|
|
47
|
+
} catch (e) {
|
|
48
|
+
try {
|
|
49
|
+
return playwrightRunner._loader.fullConfig()
|
|
50
|
+
} catch (e) {
|
|
51
|
+
return {}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getRootDir (playwrightRunner) {
|
|
57
|
+
const config = getPlaywrightConfig(playwrightRunner)
|
|
58
|
+
if (config.rootDir) {
|
|
59
|
+
return config.rootDir
|
|
60
|
+
}
|
|
61
|
+
if (playwrightRunner._configDir) {
|
|
62
|
+
return playwrightRunner._configDir
|
|
63
|
+
}
|
|
64
|
+
return process.cwd()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function testBeginHandler (test) {
|
|
68
|
+
const { title: testName, location: { file: testSuiteAbsolutePath }, _type } = test
|
|
69
|
+
|
|
70
|
+
if (_type === 'beforeAll' || _type === 'afterAll') {
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const isNewTestSuite = !startedSuites.includes(testSuiteAbsolutePath)
|
|
75
|
+
|
|
76
|
+
if (isNewTestSuite) {
|
|
77
|
+
startedSuites.push(testSuiteAbsolutePath)
|
|
78
|
+
const testSuiteAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
79
|
+
testSuiteToAr.set(testSuiteAbsolutePath, testSuiteAsyncResource)
|
|
80
|
+
testSuiteAsyncResource.runInAsyncScope(() => {
|
|
81
|
+
testSuiteStartCh.publish(testSuiteAbsolutePath)
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const testAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
86
|
+
testToAr.set(test, testAsyncResource)
|
|
87
|
+
testAsyncResource.runInAsyncScope(() => {
|
|
88
|
+
testStartCh.publish({ testName, testSuiteAbsolutePath })
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function testEndHandler (test, testStatus, error) {
|
|
93
|
+
const { location: { file: testSuiteAbsolutePath }, results, _type } = test
|
|
94
|
+
|
|
95
|
+
if (_type === 'beforeAll' || _type === 'afterAll') {
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const testResult = results[results.length - 1]
|
|
100
|
+
const testAsyncResource = testToAr.get(test)
|
|
101
|
+
testAsyncResource.runInAsyncScope(() => {
|
|
102
|
+
testFinishCh.publish({ testStatus, steps: testResult.steps, error })
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
if (!testSuiteToTestStatuses.has(testSuiteAbsolutePath)) {
|
|
106
|
+
testSuiteToTestStatuses.set(testSuiteAbsolutePath, [testStatus])
|
|
107
|
+
} else {
|
|
108
|
+
testSuiteToTestStatuses.get(testSuiteAbsolutePath).push(testStatus)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
remainingTestsByFile[testSuiteAbsolutePath] = remainingTestsByFile[testSuiteAbsolutePath]
|
|
112
|
+
.filter(currentTest => currentTest !== test)
|
|
113
|
+
|
|
114
|
+
if (!remainingTestsByFile[testSuiteAbsolutePath].length) {
|
|
115
|
+
const testStatuses = testSuiteToTestStatuses.get(testSuiteAbsolutePath)
|
|
116
|
+
|
|
117
|
+
let testSuiteStatus = 'pass'
|
|
118
|
+
if (testStatuses.some(status => status === 'fail')) {
|
|
119
|
+
testSuiteStatus = 'fail'
|
|
120
|
+
} else if (testStatuses.every(status => status === 'skip')) {
|
|
121
|
+
testSuiteStatus = 'skip'
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const testSuiteAsyncResource = testSuiteToAr.get(testSuiteAbsolutePath)
|
|
125
|
+
testSuiteAsyncResource.runInAsyncScope(() => {
|
|
126
|
+
testSuiteFinishCh.publish(testSuiteStatus)
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function dispatcherRunWrapper (run) {
|
|
132
|
+
return function () {
|
|
133
|
+
remainingTestsByFile = getTestsBySuiteFromTestsById(this._testById)
|
|
134
|
+
return run.apply(this, arguments)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function dispatcherHook (dispatcherExport) {
|
|
139
|
+
shimmer.wrap(dispatcherExport.Dispatcher.prototype, 'run', dispatcherRunWrapper)
|
|
140
|
+
shimmer.wrap(dispatcherExport.Dispatcher.prototype, '_createWorker', createWorker => function () {
|
|
141
|
+
const dispatcher = this
|
|
142
|
+
const worker = createWorker.apply(this, arguments)
|
|
143
|
+
|
|
144
|
+
worker.process.on('message', ({ method, params }) => {
|
|
145
|
+
if (method === 'testBegin') {
|
|
146
|
+
const { test } = dispatcher._testById.get(params.testId)
|
|
147
|
+
testBeginHandler(test)
|
|
148
|
+
} else if (method === 'testEnd') {
|
|
149
|
+
const { test } = dispatcher._testById.get(params.testId)
|
|
150
|
+
|
|
151
|
+
const { results } = test
|
|
152
|
+
const testResult = results[results.length - 1]
|
|
153
|
+
|
|
154
|
+
testEndHandler(test, STATUS_TO_TEST_STATUS[testResult.status], testResult.error)
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
return worker
|
|
159
|
+
})
|
|
160
|
+
return dispatcherExport
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function dispatcherHookNew (dispatcherExport) {
|
|
164
|
+
shimmer.wrap(dispatcherExport.Dispatcher.prototype, 'run', dispatcherRunWrapper)
|
|
165
|
+
shimmer.wrap(dispatcherExport.Dispatcher.prototype, '_createWorker', createWorker => function () {
|
|
166
|
+
const dispatcher = this
|
|
167
|
+
const worker = createWorker.apply(this, arguments)
|
|
168
|
+
|
|
169
|
+
worker.on('testBegin', ({ testId }) => {
|
|
170
|
+
const { test } = dispatcher._testById.get(testId)
|
|
171
|
+
testBeginHandler(test)
|
|
172
|
+
})
|
|
173
|
+
worker.on('testEnd', ({ testId, status, errors }) => {
|
|
174
|
+
const { test } = dispatcher._testById.get(testId)
|
|
175
|
+
|
|
176
|
+
testEndHandler(test, STATUS_TO_TEST_STATUS[status], errors && errors[0])
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
return worker
|
|
180
|
+
})
|
|
181
|
+
return dispatcherExport
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function runnerHook (runnerExport) {
|
|
185
|
+
shimmer.wrap(runnerExport.Runner.prototype, 'runAllTests', runAllTests => async function () {
|
|
186
|
+
const testSessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
187
|
+
const { version: frameworkVersion } = getPlaywrightConfig(this)
|
|
188
|
+
|
|
189
|
+
const rootDir = getRootDir(this)
|
|
190
|
+
|
|
191
|
+
const processArgv = process.argv.slice(2).join(' ')
|
|
192
|
+
const command = `playwright ${processArgv}`
|
|
193
|
+
testSessionAsyncResource.runInAsyncScope(() => {
|
|
194
|
+
testSessionStartCh.publish({ command, frameworkVersion, rootDir })
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
const res = await runAllTests.apply(this, arguments)
|
|
198
|
+
const sessionStatus = STATUS_TO_TEST_STATUS[res.status]
|
|
199
|
+
|
|
200
|
+
let onDone
|
|
201
|
+
|
|
202
|
+
const flushWait = new Promise(resolve => {
|
|
203
|
+
onDone = resolve
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
testSessionAsyncResource.runInAsyncScope(() => {
|
|
207
|
+
testSessionFinishCh.publish({ status: sessionStatus, onDone })
|
|
208
|
+
})
|
|
209
|
+
await flushWait
|
|
210
|
+
|
|
211
|
+
startedSuites = []
|
|
212
|
+
remainingTestsByFile = {}
|
|
213
|
+
|
|
214
|
+
return res
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
return runnerExport
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
addHook({
|
|
221
|
+
name: '@playwright/test',
|
|
222
|
+
file: 'lib/runner.js',
|
|
223
|
+
versions: ['>=1.18.0']
|
|
224
|
+
}, runnerHook)
|
|
225
|
+
|
|
226
|
+
addHook({
|
|
227
|
+
name: '@playwright/test',
|
|
228
|
+
file: 'lib/dispatcher.js',
|
|
229
|
+
versions: ['>=1.18.0 <1.30.0']
|
|
230
|
+
}, dispatcherHook)
|
|
231
|
+
|
|
232
|
+
addHook({
|
|
233
|
+
name: '@playwright/test',
|
|
234
|
+
file: 'lib/dispatcher.js',
|
|
235
|
+
versions: ['>=1.30.0']
|
|
236
|
+
}, dispatcherHookNew)
|