dd-trace 2.0.0-beta.0 → 2.1.1
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/MIGRATING.md +65 -0
- package/NOTICE +4 -0
- package/package.json +2 -2
- package/packages/datadog-instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/dns.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/instrument.js +24 -25
- package/packages/datadog-instrumentations/src/memcached.js +3 -5
- package/packages/datadog-instrumentations/src/mysql.js +7 -9
- package/packages/datadog-instrumentations/src/mysql2.js +76 -0
- package/packages/datadog-instrumentations/src/q.js +9 -1
- package/packages/datadog-plugin-aws-sdk/src/helpers.js +4 -3
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +48 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +56 -6
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +33 -6
- package/packages/datadog-plugin-mysql/src/index.js +4 -4
- package/packages/datadog-plugin-mysql2/src/index.js +5 -88
- package/packages/datadog-plugin-next/src/index.js +10 -6
- package/packages/datadog-plugin-pino/src/index.js +25 -1
- package/packages/datadog-plugin-winston/src/index.js +30 -12
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +13 -16
- package/packages/dd-trace/src/appsec/recommended.json +5708 -1
- package/packages/dd-trace/src/appsec/reporter.js +15 -3
- package/packages/dd-trace/src/config.js +7 -1
- package/packages/dd-trace/src/profiling/config.js +5 -1
- package/packages/dd-trace/src/profiling/profiler.js +15 -6
- package/packages/dd-trace/src/profiling/profilers/cpu.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/heap.js +3 -2
- package/scripts/publish_docs.js +1 -1
- package/scripts/tracer-runner.js +13 -0
- package/packages/dd-trace/src/profiling/mapper.js +0 -91
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const addresses = require('./addresses')
|
|
4
|
+
const Limiter = require('../rate_limiter')
|
|
5
|
+
|
|
6
|
+
// default limiter, configurable with setRateLimit()
|
|
7
|
+
let limiter = new Limiter(100)
|
|
4
8
|
|
|
5
9
|
const REQUEST_HEADERS_PASSLIST = [
|
|
6
10
|
'accept',
|
|
@@ -85,8 +89,11 @@ function reportAttack (attackData, store) {
|
|
|
85
89
|
const currentTags = topSpan.context()._tags
|
|
86
90
|
|
|
87
91
|
const newTags = {
|
|
88
|
-
'appsec.event': true
|
|
89
|
-
|
|
92
|
+
'appsec.event': 'true'
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (limiter.isAllowed()) {
|
|
96
|
+
newTags['manual.keep'] = 'true' // TODO: figure out how to keep appsec traces with sampling revamp
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
// TODO: maybe add this to format.js later (to take decision as late as possible)
|
|
@@ -136,11 +143,16 @@ function finishAttacks (req, context) {
|
|
|
136
143
|
topSpan.addTags(newTags)
|
|
137
144
|
}
|
|
138
145
|
|
|
146
|
+
function setRateLimit (rateLimit) {
|
|
147
|
+
limiter = new Limiter(rateLimit)
|
|
148
|
+
}
|
|
149
|
+
|
|
139
150
|
module.exports = {
|
|
140
151
|
resolveHTTPRequest,
|
|
141
152
|
resolveHTTPResponse,
|
|
142
153
|
filterHeaders,
|
|
143
154
|
formatHeaderName,
|
|
144
155
|
reportAttack,
|
|
145
|
-
finishAttacks
|
|
156
|
+
finishAttacks,
|
|
157
|
+
setRateLimit
|
|
146
158
|
}
|
|
@@ -134,6 +134,11 @@ class Config {
|
|
|
134
134
|
process.env.DD_APPSEC_RULES,
|
|
135
135
|
path.join(__dirname, 'appsec', 'recommended.json')
|
|
136
136
|
)
|
|
137
|
+
const DD_APPSEC_TRACE_RATE_LIMIT = coalesce(
|
|
138
|
+
appsec.rateLimit,
|
|
139
|
+
process.env.DD_APPSEC_TRACE_RATE_LIMIT,
|
|
140
|
+
100
|
|
141
|
+
)
|
|
137
142
|
|
|
138
143
|
const sampler = (options.experimental && options.experimental.sampler) || {}
|
|
139
144
|
const ingestion = options.ingestion || {}
|
|
@@ -198,7 +203,8 @@ class Config {
|
|
|
198
203
|
this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
|
|
199
204
|
this.appsec = {
|
|
200
205
|
enabled: isTrue(DD_APPSEC_ENABLED),
|
|
201
|
-
rules: DD_APPSEC_RULES
|
|
206
|
+
rules: DD_APPSEC_RULES,
|
|
207
|
+
rateLimit: DD_APPSEC_TRACE_RATE_LIMIT
|
|
202
208
|
}
|
|
203
209
|
|
|
204
210
|
tagger.add(this.tags, {
|
|
@@ -20,7 +20,8 @@ const {
|
|
|
20
20
|
DD_TRACE_AGENT_URL,
|
|
21
21
|
DD_AGENT_HOST,
|
|
22
22
|
DD_TRACE_AGENT_PORT,
|
|
23
|
-
DD_PROFILING_UPLOAD_TIMEOUT
|
|
23
|
+
DD_PROFILING_UPLOAD_TIMEOUT,
|
|
24
|
+
DD_PROFILING_SOURCE_MAP
|
|
24
25
|
} = process.env
|
|
25
26
|
|
|
26
27
|
class Config {
|
|
@@ -34,6 +35,8 @@ class Config {
|
|
|
34
35
|
const flushInterval = coalesce(options.interval, 65 * 1000)
|
|
35
36
|
const uploadTimeout = coalesce(options.uploadTimeout,
|
|
36
37
|
DD_PROFILING_UPLOAD_TIMEOUT, 60 * 1000)
|
|
38
|
+
const sourceMap = coalesce(options.sourceMap,
|
|
39
|
+
DD_PROFILING_SOURCE_MAP, true)
|
|
37
40
|
|
|
38
41
|
this.enabled = String(enabled) !== 'false'
|
|
39
42
|
this.service = service
|
|
@@ -49,6 +52,7 @@ class Config {
|
|
|
49
52
|
this.logger = ensureLogger(options.logger)
|
|
50
53
|
this.flushInterval = flushInterval
|
|
51
54
|
this.uploadTimeout = uploadTimeout
|
|
55
|
+
this.sourceMap = sourceMap
|
|
52
56
|
|
|
53
57
|
const hostname = coalesce(options.hostname, DD_AGENT_HOST, 'localhost')
|
|
54
58
|
const port = coalesce(options.port, DD_TRACE_AGENT_PORT, 8126)
|
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
const { EventEmitter } = require('events')
|
|
4
4
|
const { Config } = require('./config')
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
function maybeSourceMap (sourceMap) {
|
|
7
|
+
if (!sourceMap) return
|
|
8
|
+
|
|
9
|
+
const { SourceMapper } = require('@datadog/pprof')
|
|
10
|
+
return SourceMapper.create([
|
|
11
|
+
process.cwd()
|
|
12
|
+
])
|
|
13
|
+
}
|
|
6
14
|
|
|
7
15
|
class Profiler extends EventEmitter {
|
|
8
16
|
constructor () {
|
|
@@ -15,18 +23,21 @@ class Profiler extends EventEmitter {
|
|
|
15
23
|
}
|
|
16
24
|
|
|
17
25
|
start (options) {
|
|
26
|
+
this._start(options).catch(() => {})
|
|
27
|
+
return this
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async _start (options) {
|
|
18
31
|
if (this._enabled) return
|
|
19
32
|
|
|
20
33
|
const config = this._config = new Config(options)
|
|
21
|
-
|
|
22
34
|
if (!config.enabled) return
|
|
23
35
|
|
|
24
36
|
this._logger = config.logger
|
|
25
|
-
|
|
26
37
|
this._enabled = true
|
|
27
38
|
|
|
28
39
|
try {
|
|
29
|
-
const mapper = config.sourceMap
|
|
40
|
+
const mapper = await maybeSourceMap(config.sourceMap)
|
|
30
41
|
|
|
31
42
|
for (const profiler of config.profilers) {
|
|
32
43
|
// TODO: move this out of Profiler when restoring sourcemap support
|
|
@@ -39,8 +50,6 @@ class Profiler extends EventEmitter {
|
|
|
39
50
|
this._logger.error(e)
|
|
40
51
|
this.stop()
|
|
41
52
|
}
|
|
42
|
-
|
|
43
|
-
return this
|
|
44
53
|
}
|
|
45
54
|
|
|
46
55
|
stop () {
|
|
@@ -8,13 +8,14 @@ class NativeHeapProfiler {
|
|
|
8
8
|
this._pprof = undefined
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
start () {
|
|
11
|
+
start ({ mapper } = {}) {
|
|
12
|
+
this._mapper = mapper
|
|
12
13
|
this._pprof = require('@datadog/pprof')
|
|
13
14
|
this._pprof.heap.start(this._samplingInterval, this._stackDepth)
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
profile () {
|
|
17
|
-
return this._pprof.heap.profile()
|
|
18
|
+
return this._pprof.heap.profile(undefined, this._mapper)
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
encode (profile) {
|
package/scripts/publish_docs.js
CHANGED
|
@@ -18,4 +18,4 @@ exec('git init', { cwd: './docs/out' }) // cloning would overwrite generated doc
|
|
|
18
18
|
exec('git remote add origin git@github.com:DataDog/dd-trace-js.git', { cwd: './docs/out' })
|
|
19
19
|
exec('git add -A', { cwd: './docs/out' })
|
|
20
20
|
exec(`git commit -m "${msg}"`, { cwd: './docs/out' })
|
|
21
|
-
exec('git push -f origin
|
|
21
|
+
exec('git push -f origin main:gh-pages', { cwd: './docs/out' })
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const spawnWrap = require('spawn-wrap')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
|
|
6
|
+
spawnWrap(['--require', path.join(__dirname, '..', 'init.js')])
|
|
7
|
+
|
|
8
|
+
const { spawn } = require('child_process')
|
|
9
|
+
|
|
10
|
+
const [command, ...argv] = process.argv.slice(2)
|
|
11
|
+
spawn(command, argv, {
|
|
12
|
+
stdio: 'inherit'
|
|
13
|
+
})
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
// TODO: use sourceRoot when set, possibly from source-map-resolve
|
|
4
|
-
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const { SourceMapConsumer } = require('source-map')
|
|
7
|
-
const sourceMapResolve = require('source-map-resolve')
|
|
8
|
-
const { fileURLToPath, pathToFileURL } = require('url')
|
|
9
|
-
|
|
10
|
-
class SourceMapper {
|
|
11
|
-
constructor () {
|
|
12
|
-
this._consumers = Object.create(null)
|
|
13
|
-
this._sources = Object.create(null)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async getSource (callFrame) {
|
|
17
|
-
const { url, lineNumber, columnNumber, functionName } = callFrame
|
|
18
|
-
const key = `${url}:${functionName}:${lineNumber}:${columnNumber}`
|
|
19
|
-
|
|
20
|
-
if (!this._sources[key]) {
|
|
21
|
-
this._sources[key] = await this._getMapping(callFrame)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return this._sources[key]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async _getConsumer (url) {
|
|
28
|
-
if (this._consumers[url] === undefined) {
|
|
29
|
-
this._consumers[url] = this._createConsumer(url)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return this._consumers[url]
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async _createConsumer (url) {
|
|
36
|
-
try {
|
|
37
|
-
const map = await this._resolve(url)
|
|
38
|
-
|
|
39
|
-
return map ? new SourceMapConsumer(map) : null
|
|
40
|
-
} catch (e) {
|
|
41
|
-
return null
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async _getMapping (callFrame) {
|
|
46
|
-
const { url, functionName, lineNumber, columnNumber } = callFrame
|
|
47
|
-
|
|
48
|
-
// Runtime.CallFrame is 0-based for both line and column numbers.
|
|
49
|
-
// When the line or column number is not known the value is -1.
|
|
50
|
-
// https://chromedevtools.github.io/devtools-protocol/v8/Runtime/#type-CallFrame
|
|
51
|
-
if (lineNumber < 0 || columnNumber < 0) return callFrame
|
|
52
|
-
|
|
53
|
-
const consumer = await this._getConsumer(url)
|
|
54
|
-
|
|
55
|
-
if (!consumer) return callFrame
|
|
56
|
-
|
|
57
|
-
// SourceMapConsumer is 1-based for lines and 0-based for columns
|
|
58
|
-
// https://github.com/mozilla/source-map/blob/0.7.3/lib/source-map-consumer.js#L464-L487
|
|
59
|
-
const map = consumer.originalPositionFor({
|
|
60
|
-
line: lineNumber + 1,
|
|
61
|
-
column: columnNumber
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
if (!map || !map.source || !map.line) return callFrame
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
url: pathToFileURL(map.source).href,
|
|
68
|
-
lineNumber: map.line - 1, // reset to 0-based from 1-based
|
|
69
|
-
columnNumber: map.column !== null ? map.column : -1,
|
|
70
|
-
functionName: map.name || functionName
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async _resolve (url) {
|
|
75
|
-
const filename = fileURLToPath(url)
|
|
76
|
-
const code = (await fs.promises.readFile(filename)).toString()
|
|
77
|
-
|
|
78
|
-
return new Promise((resolve, reject) => {
|
|
79
|
-
sourceMapResolve.resolve(code, filename, fs.readFile, (error, result) => {
|
|
80
|
-
if (!result || error) return resolve(null)
|
|
81
|
-
|
|
82
|
-
result.map.sourcesContent = result.sourcesContent
|
|
83
|
-
result.map.sources = result.sourcesResolved
|
|
84
|
-
|
|
85
|
-
resolve(result.map)
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
module.exports = { SourceMapper }
|