dd-trace 4.30.0 → 4.31.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.
Files changed (36) hide show
  1. package/index.d.ts +4 -0
  2. package/package.json +2 -2
  3. package/packages/datadog-plugin-cucumber/src/index.js +2 -2
  4. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -2
  5. package/packages/datadog-plugin-jest/src/index.js +2 -2
  6. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  7. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +23 -12
  8. package/packages/dd-trace/src/appsec/iast/path-line.js +9 -6
  9. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +1 -1
  10. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +6 -2
  11. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +1 -1
  12. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +6 -7
  13. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
  14. package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +34 -27
  15. package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +39 -11
  16. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +7 -6
  17. package/packages/dd-trace/src/appsec/reporter.js +24 -11
  18. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +6 -1
  19. package/packages/dd-trace/src/lambda/runtime/ritm.js +1 -1
  20. package/packages/dd-trace/src/opentracing/propagation/text_map.js +21 -2
  21. package/packages/dd-trace/src/opentracing/span.js +2 -0
  22. package/packages/dd-trace/src/opentracing/span_context.js +1 -0
  23. package/packages/dd-trace/src/plugins/util/test.js +2 -2
  24. package/packages/dd-trace/src/priority_sampler.js +11 -6
  25. package/packages/dd-trace/src/telemetry/index.js +15 -4
  26. package/CONTRIBUTING.md +0 -171
  27. package/MIGRATING.md +0 -224
  28. package/packages/dd-trace/src/external-logger/test/index.spec.js +0 -147
  29. package/scripts/check-proposal-labels.js +0 -71
  30. package/scripts/check_licenses.js +0 -69
  31. package/scripts/helpers/color.js +0 -8
  32. package/scripts/helpers/exec.js +0 -22
  33. package/scripts/helpers/title.js +0 -15
  34. package/scripts/install_plugin_modules.js +0 -248
  35. package/scripts/publish_docs.js +0 -21
  36. package/scripts/st.js +0 -105
@@ -1,147 +0,0 @@
1
- 'use strict'
2
-
3
- require('../../../../dd-trace/test/setup/tap')
4
- const proxyquire = require('proxyquire')
5
- const { expect } = require('chai')
6
- const nock = require('nock')
7
-
8
- const tracerLogger = require('../../log')
9
-
10
- describe('External Logger', () => {
11
- let externalLogger
12
- let interceptor
13
- let errorLog
14
-
15
- beforeEach(() => {
16
- errorLog = sinon.spy(tracerLogger, 'error')
17
-
18
- const { ExternalLogger } = proxyquire('../src', {
19
- '../../log': {
20
- error: errorLog
21
- }
22
- })
23
-
24
- externalLogger = new ExternalLogger({
25
- ddsource: 'logging_from_space',
26
- hostname: 'mac_desktop',
27
- apiKey: 'API_KEY_PLACEHOLDER',
28
- interval: 10000,
29
- timeout: 5000,
30
- limit: 10
31
- })
32
- })
33
-
34
- afterEach(() => {
35
- interceptor.done()
36
- errorLog.restore()
37
- })
38
-
39
- it('should properly encode the log message', (done) => {
40
- let request
41
- const currentTime = Date.now()
42
-
43
- interceptor = nock('https://http-intake.logs.datadoghq.com:443')
44
- .post('/api/v2/logs')
45
- .reply((_uri, req, cb) => {
46
- request = req
47
- cb(null, [202, '{}', { 'Content-Type': 'application/json' }])
48
- })
49
-
50
- const span = {
51
- service: 'openAi',
52
- trace_id: '000001000',
53
- span_id: '9999991999'
54
- }
55
- const tags = {
56
- env: 'external_logger',
57
- version: '1.2.3',
58
- service: 'external'
59
- }
60
- externalLogger.log({
61
- message: 'oh no, something is up',
62
- custom: 'field',
63
- attribute: 'funky',
64
- service: 'outer_space',
65
- level: 'info'
66
- }, span, tags)
67
-
68
- externalLogger.flush((err) => {
69
- try {
70
- expect(request[0]).to.have.property('message', 'oh no, something is up')
71
- expect(request[0]).to.have.property('custom', 'field')
72
- expect(request[0]).to.have.property('attribute', 'funky')
73
- expect(request[0]).to.have.property('service', 'outer_space')
74
- expect(request[0]).to.have.property('level', 'info')
75
- expect(request[0]).to.have.property('dd.trace_id', '000001000')
76
- expect(request[0]).to.have.property('dd.span_id', '9999991999')
77
- expect(request[0].timestamp).to.be.greaterThanOrEqual(currentTime)
78
- expect(request[0]).to.have.property('ddsource', 'logging_from_space')
79
- expect(request[0]).to.have.property('ddtags', 'env:external_logger,version:1.2.3,service:external')
80
- } catch (e) {
81
- done(e)
82
- return
83
- }
84
-
85
- done(err)
86
- })
87
- })
88
-
89
- it('should empty the log queue when calling flush', (done) => {
90
- interceptor = nock('https://http-intake.logs.datadoghq.com:443')
91
- .post('/api/v2/logs')
92
- .reply(202, {})
93
-
94
- externalLogger.enqueue({})
95
- expect(externalLogger.queue.length).to.equal(1)
96
-
97
- externalLogger.flush((err) => {
98
- expect(externalLogger.queue.length).to.equal(0)
99
- done(err)
100
- })
101
- })
102
-
103
- it('tracer logger should handle error response codes from Logs API', (done) => {
104
- interceptor = nock('https://http-intake.logs.datadoghq.com:443')
105
- .post('/api/v2/logs')
106
- .reply(400, {})
107
-
108
- externalLogger.enqueue({})
109
- externalLogger.flush((err) => {
110
- expect(err).to.be.an.instanceOf(Error)
111
- expect(errorLog.getCall(0).args[0]).to.be.equal(
112
- 'failed to send 1 logs, received response code 400'
113
- )
114
- done()
115
- })
116
- })
117
-
118
- it('tracer logger should handle simulated network error', (done) => {
119
- interceptor = nock('https://http-intake.logs.datadoghq.com:443')
120
- .post('/api/v2/logs')
121
- .replyWithError('missing API key')
122
-
123
- externalLogger.enqueue({})
124
- externalLogger.flush((err) => {
125
- expect(err).to.be.an.instanceOf(Error)
126
- expect(errorLog.getCall(0).args[0]).to.be.equal(
127
- 'failed to send 1 log(s), with error missing API key'
128
- )
129
- done()
130
- })
131
- })
132
-
133
- it('causes a flush when exceeding log queue limit', (done) => {
134
- const flusher = sinon.stub(externalLogger, 'flush')
135
-
136
- for (let i = 0; i < 10; i++) {
137
- externalLogger.enqueue({})
138
- }
139
- expect(flusher).to.not.have.been.called
140
-
141
- externalLogger.enqueue({})
142
- expect(flusher).to.have.been.called
143
-
144
- flusher.restore()
145
- done()
146
- })
147
- })
@@ -1,71 +0,0 @@
1
- /* eslint-disable no-console */
2
-
3
- const childProcess = require('child_process')
4
- const ORIGIN = 'origin/'
5
-
6
- let releaseBranch = process.env['GITHUB_BASE_REF'] // 'origin/v3.x'
7
- let releaseVersion = releaseBranch
8
- if (releaseBranch.startsWith(ORIGIN)) {
9
- releaseVersion = releaseBranch.substring(ORIGIN.length)
10
- } else {
11
- releaseBranch = ORIGIN + releaseBranch
12
- }
13
- let currentBranch = process.env['GITHUB_HEAD_REF'] // 'ugaitz/workflow-to-verify-dont-land-on-v3.x'
14
- if (!currentBranch.startsWith(ORIGIN)) {
15
- currentBranch = ORIGIN + currentBranch
16
- }
17
-
18
- const getHashesCommandWithExclusions = 'branch-diff --user DataDog --repo dd-trace-js --exclude-label=semver-major' +
19
- ` --exclude-label=dont-land-on-${releaseVersion} ${releaseBranch} ${currentBranch}`
20
- const getHashesCommandWithoutExclusions =
21
- `branch-diff --user DataDog --repo dd-trace-js ${releaseBranch} ${currentBranch}`
22
-
23
- childProcess.exec(getHashesCommandWithExclusions, { timeout: 30000 },
24
- (withExclusionError, withExclusionStdout, withExclusionStderr) => {
25
- if (withExclusionError) {
26
- console.error(`stdout:
27
- ${withExclusionStdout}
28
- stderr:
29
- ${withExclusionStderr}
30
- `, withExclusionError)
31
- process.exit(1)
32
- return
33
- }
34
- if (withExclusionStderr) {
35
- console.error(withExclusionStderr)
36
- process.exit(1)
37
- return
38
- }
39
- const commitsHashesWithExclusions = withExclusionStdout.split('\n')
40
-
41
- childProcess.exec(getHashesCommandWithoutExclusions,
42
- (withoutExclusionError, withoutExclusionStdout, withoutExclusionStderr) => {
43
- if (withoutExclusionError) {
44
- console.error(`stdout:
45
- ${withoutExclusionStdout}
46
- stderr:
47
- ${withoutExclusionStderr}
48
- `, withoutExclusionError)
49
- process.exit(1)
50
- return
51
- }
52
- if (withoutExclusionStderr) {
53
- console.error(withoutExclusionStderr)
54
- process.exit(1)
55
- return
56
- }
57
- const commitsHashesWithoutExclusions = withoutExclusionStdout.split('\n')
58
- if (commitsHashesWithExclusions.length !== commitsHashesWithoutExclusions.length) {
59
- const commitsWithInvalidLabels = []
60
- commitsHashesWithoutExclusions.filter(c1 => {
61
- if (!commitsHashesWithExclusions.some(c2 => c2 === c1)) {
62
- commitsWithInvalidLabels.push(c1)
63
- }
64
- })
65
- console.error('Some excluded label added in the release proposal', commitsWithInvalidLabels)
66
- process.exit(1)
67
- } else {
68
- console.log('Commit PRs label looks OK')
69
- }
70
- })
71
- })
@@ -1,69 +0,0 @@
1
- 'use strict'
2
-
3
- const fs = require('fs')
4
- const path = require('path')
5
- const readline = require('readline')
6
- const pkg = require(path.join(__dirname, '..', '/package.json'))
7
-
8
- const filePath = path.join(__dirname, '..', '/LICENSE-3rdparty.csv')
9
- const deps = new Set(Object.keys(pkg.dependencies || {}))
10
- const devDeps = new Set(Object.keys(pkg.devDependencies || {}))
11
-
12
- let index = 0
13
-
14
- const licenses = {
15
- require: new Set(),
16
- dev: new Set(),
17
- file: new Set()
18
- }
19
-
20
- const lineReader = readline.createInterface({
21
- input: fs.createReadStream(filePath)
22
- })
23
-
24
- lineReader.on('line', line => {
25
- if (index !== 0) {
26
- const columns = line.split(',')
27
- const type = columns[0]
28
- const license = columns[1]
29
-
30
- licenses[type].add(license)
31
- }
32
-
33
- index++
34
- })
35
-
36
- lineReader.on('close', () => {
37
- if (!checkLicenses(deps, 'require') || !checkLicenses(devDeps, 'dev')) {
38
- process.exit(1)
39
- }
40
- })
41
-
42
- function checkLicenses (typeDeps, type) {
43
- /* eslint-disable no-console */
44
-
45
- const missing = []
46
- const extraneous = []
47
-
48
- for (const dep of typeDeps) {
49
- if (!licenses[type].has(dep)) {
50
- missing.push(dep)
51
- }
52
- }
53
-
54
- for (const dep of licenses[type]) {
55
- if (!typeDeps.has(dep)) {
56
- extraneous.push(dep)
57
- }
58
- }
59
-
60
- if (missing.length) {
61
- console.log(`Missing 3rd-party license for ${missing.join(', ')}.`)
62
- }
63
-
64
- if (extraneous.length) {
65
- console.log(`Extraneous 3rd-party license for ${extraneous.join(', ')}.`)
66
- }
67
-
68
- return missing.length === 0 && extraneous.length === 0
69
- }
@@ -1,8 +0,0 @@
1
- 'use strict'
2
-
3
- // https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
4
- module.exports = {
5
- GRAY: '\\033[1;90m',
6
- CYAN: '\\033[1;36m',
7
- NONE: '\\033[0m'
8
- }
@@ -1,22 +0,0 @@
1
- 'use strict'
2
-
3
- const execSync = require('child_process').execSync
4
- const color = require('./color')
5
-
6
- function exec (command, options) {
7
- options = Object.assign({ stdio: [0, 1, 2] }, options)
8
-
9
- execSync(`echo "${color.GRAY}$ ${command}${color.NONE}"`, { stdio: [0, 1, 2] })
10
-
11
- return execSync(command, options)
12
- }
13
-
14
- function pipe (command, options) {
15
- return exec(command, Object.assign({ stdio: 'pipe' }, options))
16
- .toString()
17
- .replace(/\n$/, '')
18
- }
19
-
20
- exec.pipe = pipe
21
-
22
- module.exports = exec
@@ -1,15 +0,0 @@
1
- 'use strict'
2
-
3
- const exec = require('child_process').execSync
4
- const color = require('./color')
5
-
6
- function title (str) {
7
- const options = { stdio: [0, 1, 2] }
8
- const line = ''.padStart(str.length, '=')
9
-
10
- exec(`echo "${color.CYAN}${line}${color.NONE}"`, options)
11
- exec(`echo "${color.CYAN}${str}${color.NONE}"`, options)
12
- exec(`echo "${color.CYAN}${line}${color.NONE}"`, options)
13
- }
14
-
15
- module.exports = title
@@ -1,248 +0,0 @@
1
- 'use strict'
2
-
3
- const fs = require('fs')
4
- const os = require('os')
5
- const path = require('path')
6
- const crypto = require('crypto')
7
- const semver = require('semver')
8
- const proxyquire = require('proxyquire')
9
- const exec = require('./helpers/exec')
10
- const childProcess = require('child_process')
11
- const externals = require('../packages/dd-trace/test/plugins/externals')
12
-
13
- const requirePackageJsonPath = require.resolve('../packages/dd-trace/src/require-package-json')
14
-
15
- // Can remove couchbase after removing support for couchbase <= 3.2.0
16
- const excludeList = os.arch() === 'arm64' ? ['couchbase', 'grpc', 'oracledb'] : []
17
- const workspaces = new Set()
18
- const versionLists = {}
19
- const deps = {}
20
- const names = []
21
- const filter = process.env.hasOwnProperty('PLUGINS') && process.env.PLUGINS.split('|')
22
-
23
- Object.keys(externals).forEach(external => externals[external].forEach(thing => {
24
- if (thing.dep) {
25
- if (!deps[external]) {
26
- deps[external] = []
27
- }
28
- deps[external].push(thing.name)
29
- }
30
- }))
31
-
32
- fs.readdirSync(path.join(__dirname, '../packages/datadog-instrumentations/src'))
33
- .filter(file => file.endsWith('js'))
34
- .forEach(file => {
35
- file = file.replace('.js', '')
36
-
37
- if (!filter || filter.includes(file)) {
38
- names.push(file)
39
- }
40
- })
41
-
42
- run()
43
-
44
- async function run () {
45
- assertFolder()
46
- await assertVersions()
47
- assertWorkspace()
48
- // Some native addon packages rely on libraries that are not supported on ARM64
49
- excludeList.forEach(pkg => delete workspaces[pkg])
50
- install()
51
- }
52
-
53
- async function assertVersions () {
54
- const internals = names
55
- .map(key => {
56
- const instrumentations = []
57
- const name = key
58
-
59
- try {
60
- loadInstFile(`${name}/server.js`, instrumentations)
61
- loadInstFile(`${name}/client.js`, instrumentations)
62
- } catch (e) {
63
- loadInstFile(`${name}.js`, instrumentations)
64
- }
65
-
66
- return instrumentations
67
- })
68
- .reduce((prev, next) => prev.concat(next), [])
69
-
70
- for (const inst of internals) {
71
- await assertInstrumentation(inst, false)
72
- }
73
-
74
- const externalNames = Object.keys(externals).filter(name => ~names.indexOf(name))
75
- for (const name of externalNames) {
76
- for (const inst of [].concat(externals[name])) {
77
- await assertInstrumentation(inst, true)
78
- }
79
- }
80
- }
81
-
82
- async function assertInstrumentation (instrumentation, external) {
83
- const versions = process.env.PACKAGE_VERSION_RANGE ? [process.env.PACKAGE_VERSION_RANGE]
84
- : [].concat(instrumentation.versions || [])
85
-
86
- for (const version of versions) {
87
- if (version) {
88
- await assertModules(instrumentation.name, semver.coerce(version).version, external)
89
- await assertModules(instrumentation.name, version, external)
90
- }
91
- }
92
- }
93
-
94
- async function assertModules (name, version, external) {
95
- const range = process.env.RANGE
96
- if (range && !semver.subset(version, range)) return
97
- addFolder(name)
98
- addFolder(name, version)
99
- assertFolder(name)
100
- assertFolder(name, version)
101
- await assertPackage(name, null, version, external)
102
- await assertPackage(name, version, version, external)
103
- assertIndex(name)
104
- assertIndex(name, version)
105
- }
106
-
107
- function assertFolder (name, version) {
108
- if (!fs.existsSync(folder())) {
109
- fs.mkdirSync(folder())
110
- }
111
-
112
- if (name && name.includes(path.sep)) {
113
- name.split(path.sep).reduce(parent => assertFolder(parent))
114
- }
115
-
116
- if (!fs.existsSync(folder(name, version))) {
117
- fs.mkdirSync(folder(name, version))
118
- }
119
- }
120
-
121
- async function assertPackage (name, version, dependency, external) {
122
- const dependencies = { [name]: dependency }
123
- if (deps[name]) {
124
- await addDependencies(dependencies, name, dependency)
125
- }
126
- const pkg = {
127
- name: [name, sha1(name).substr(0, 8), sha1(version)].filter(val => val).join('-'),
128
- version: '1.0.0',
129
- license: 'BSD-3-Clause',
130
- private: true,
131
- dependencies
132
- }
133
-
134
- if (!external) {
135
- if (name === 'aerospike') {
136
- pkg.installConfig = {
137
- 'hoistingLimits': 'workspaces'
138
- }
139
- } else {
140
- pkg.workspaces = {
141
- nohoist: ['**/**']
142
- }
143
- }
144
- }
145
- fs.writeFileSync(filename(name, version, 'package.json'), JSON.stringify(pkg, null, 2) + '\n')
146
- }
147
-
148
- async function addDependencies (dependencies, name, versionRange) {
149
- const versionList = await getVersionList(name)
150
- const version = semver.maxSatisfying(versionList, versionRange)
151
- const pkgJson = await npmView(`${name}@${version}`)
152
- for (const dep of deps[name]) {
153
- for (const section of ['devDependencies', 'peerDependencies']) {
154
- if (pkgJson[section] && dep in pkgJson[section]) {
155
- dependencies[dep] = pkgJson[section][dep]
156
- break
157
- }
158
- }
159
- }
160
- }
161
-
162
- async function getVersionList (name) {
163
- if (versionLists[name]) {
164
- return versionLists[name]
165
- }
166
- const list = await npmView(`${name} versions`)
167
- versionLists[name] = list
168
- return list
169
- }
170
-
171
- function npmView (input) {
172
- return new Promise((resolve, reject) => {
173
- childProcess.exec(`npm view ${input} --json`, (err, stdout) => {
174
- if (err) {
175
- reject(err)
176
- return
177
- }
178
- resolve(JSON.parse(stdout.toString('utf8')))
179
- })
180
- })
181
- }
182
-
183
- function assertIndex (name, version) {
184
- const index = `'use strict'
185
-
186
- const requirePackageJson = require('${requirePackageJsonPath}')
187
-
188
- module.exports = {
189
- get (id) { return require(id || '${name}') },
190
- getPath (id) { return require.resolve(id || '${name}' ) },
191
- version () { return requirePackageJson('${name}', module).version }
192
- }
193
- `
194
- fs.writeFileSync(filename(name, version, 'index.js'), index)
195
- }
196
-
197
- function assertWorkspace () {
198
- fs.writeFileSync(filename(null, null, 'package.json'), JSON.stringify({
199
- name: 'versions',
200
- version: '1.0.0',
201
- license: 'BSD-3-Clause',
202
- private: true,
203
- workspaces: {
204
- packages: Array.from(workspaces)
205
- }
206
- }, null, 2) + '\n')
207
- }
208
-
209
- function install () {
210
- exec('yarn --ignore-engines', { cwd: folder() })
211
- }
212
-
213
- function addFolder (name, version) {
214
- const basename = [name, version].filter(val => val).join('@')
215
- if (!excludeList.includes(name)) workspaces.add(basename)
216
- }
217
-
218
- function folder (name, version) {
219
- const basename = [name, version].filter(val => val).join('@')
220
- return path.join(__dirname, '..', 'versions', basename)
221
- }
222
-
223
- function filename (name, version, file) {
224
- return path.join(folder(name, version), file)
225
- }
226
-
227
- function sha1 (str) {
228
- if (!str) return
229
-
230
- const shasum = crypto.createHash('sha1')
231
- shasum.update(str)
232
- return shasum.digest('hex')
233
- }
234
-
235
- function loadInstFile (file, instrumentations) {
236
- const instrument = {
237
- addHook (instrumentation) {
238
- instrumentations.push(instrumentation)
239
- }
240
- }
241
-
242
- const instPath = path.join(__dirname, `../packages/datadog-instrumentations/src/${file}`)
243
-
244
- proxyquire.noPreserveCache()(instPath, {
245
- './helpers/instrument': instrument,
246
- '../helpers/instrument': instrument
247
- })
248
- }
@@ -1,21 +0,0 @@
1
- 'use strict'
2
-
3
- const exec = require('./helpers/exec')
4
- const title = require('./helpers/title')
5
-
6
- title(`Publishing API documentation to GitHub Pages`)
7
-
8
- const msg = process.argv[2]
9
-
10
- if (!msg) {
11
- throw new Error('Please provide a reason for the change. Example: node scripts/publish_docs.js "fix typo"')
12
- }
13
-
14
- exec('yarn install', { cwd: './docs' })
15
- exec('rm -rf ./out', { cwd: './docs' })
16
- exec('yarn type:doc') // run first because typedoc requires an empty directory
17
- exec('git init', { cwd: './docs/out' }) // cloning would overwrite generated docs
18
- exec('git remote add origin git@github.com:DataDog/dd-trace-js.git', { cwd: './docs/out' })
19
- exec('git add -A', { cwd: './docs/out' })
20
- exec(`git commit -m "${msg}"`, { cwd: './docs/out' })
21
- exec('git push -f origin main:gh-pages', { cwd: './docs/out' })