dd-trace 2.27.0 → 2.28.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/LICENSE-3rdparty.csv +1 -0
- package/README.md +5 -5
- package/index.d.ts +30 -1
- package/package.json +5 -4
- package/packages/datadog-instrumentations/src/ldapjs.js +12 -2
- package/packages/datadog-instrumentations/src/mongoose.js +1 -1
- package/packages/datadog-instrumentations/src/next.js +2 -1
- package/packages/datadog-instrumentations/src/playwright.js +40 -11
- package/packages/datadog-plugin-hapi/src/index.js +5 -1
- package/packages/datadog-plugin-http/src/server.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +1 -1
- package/packages/dd-trace/src/appsec/addresses.js +3 -1
- package/packages/dd-trace/src/appsec/blocking.js +35 -9
- package/packages/dd-trace/src/appsec/iast/iast-context.js +6 -2
- package/packages/dd-trace/src/appsec/iast/index.js +3 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -2
- package/packages/dd-trace/src/appsec/index.js +4 -4
- package/packages/dd-trace/src/appsec/recommended.json +76 -75
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +3 -0
- package/packages/dd-trace/src/appsec/sdk/index.js +19 -1
- package/packages/dd-trace/src/appsec/sdk/noop.js +6 -0
- package/packages/dd-trace/src/appsec/sdk/set_user.js +30 -0
- package/packages/dd-trace/src/appsec/sdk/track_event.js +2 -2
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +73 -0
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +15 -0
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +7 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +4 -2
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +4 -2
- package/packages/dd-trace/src/config.js +1 -1
- package/packages/dd-trace/src/lambda/handler.js +5 -6
- package/packages/dd-trace/src/log/writer.js +32 -24
- package/packages/dd-trace/src/metrics.js +18 -0
- package/packages/dd-trace/src/noop/proxy.js +2 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +2 -0
- package/packages/dd-trace/src/opentracing/span_context.js +5 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +4 -1
- package/packages/dd-trace/src/plugins/util/exec.js +2 -2
- package/packages/dd-trace/src/plugins/util/git.js +16 -1
- package/packages/dd-trace/src/profiler.js +3 -0
- package/packages/dd-trace/src/profiling/config.js +8 -3
- package/packages/dd-trace/src/profiling/exporters/file.js +13 -2
- package/packages/dd-trace/src/profiling/profiler.js +23 -6
- package/packages/dd-trace/src/profiling/profilers/wall.js +1 -0
- package/packages/dd-trace/src/proxy.js +1 -1
- package/packages/dd-trace/src/span_processor.js +1 -1
- package/packages/dd-trace/src/span_sampler.js +68 -52
- package/packages/dd-trace/src/startup-log.js +3 -6
- package/packages/dd-trace/src/tracer.js +0 -16
|
@@ -8,6 +8,7 @@ const os = require('os')
|
|
|
8
8
|
const Client = require('./dogstatsd')
|
|
9
9
|
const log = require('./log')
|
|
10
10
|
const Histogram = require('./histogram')
|
|
11
|
+
const { performance } = require('perf_hooks')
|
|
11
12
|
|
|
12
13
|
const INTERVAL = 10 * 1000
|
|
13
14
|
|
|
@@ -20,6 +21,7 @@ let cpuUsage
|
|
|
20
21
|
let gauges
|
|
21
22
|
let counters
|
|
22
23
|
let histograms
|
|
24
|
+
let elu
|
|
23
25
|
|
|
24
26
|
reset()
|
|
25
27
|
|
|
@@ -259,6 +261,21 @@ function captureHistograms () {
|
|
|
259
261
|
})
|
|
260
262
|
}
|
|
261
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Gathers and reports Event Loop Utilization (ELU) since last run
|
|
266
|
+
*
|
|
267
|
+
* ELU is a measure of how busy the event loop is, like running JavaScript or
|
|
268
|
+
* waiting on *Sync functions. The value is between 0 (idle) and 1 (exhausted).
|
|
269
|
+
*
|
|
270
|
+
* performance.eventLoopUtilization available in Node.js >= v14.10, >= v12.19, >= v16
|
|
271
|
+
*/
|
|
272
|
+
const captureELU = ('eventLoopUtilization' in performance) ? () => {
|
|
273
|
+
// if elu is undefined (first run) the measurement is from start of process
|
|
274
|
+
elu = performance.eventLoopUtilization(elu)
|
|
275
|
+
|
|
276
|
+
client.gauge('runtime.node.event_loop.utilization', elu.utilization)
|
|
277
|
+
} : () => {}
|
|
278
|
+
|
|
262
279
|
function captureCommonMetrics () {
|
|
263
280
|
captureMemoryUsage()
|
|
264
281
|
captureProcess()
|
|
@@ -266,6 +283,7 @@ function captureCommonMetrics () {
|
|
|
266
283
|
captureGauges()
|
|
267
284
|
captureCounters()
|
|
268
285
|
captureHistograms()
|
|
286
|
+
captureELU()
|
|
269
287
|
}
|
|
270
288
|
|
|
271
289
|
function captureNativeMetrics () {
|
|
@@ -302,6 +302,7 @@ class TextMapPropagator {
|
|
|
302
302
|
const matches = headerValue.trim().match(traceparentExpr)
|
|
303
303
|
if (matches.length) {
|
|
304
304
|
const [ version, traceId, spanId, flags, tail ] = matches.slice(1)
|
|
305
|
+
const traceparent = { version }
|
|
305
306
|
const tracestate = TraceState.fromString(carrier.tracestate)
|
|
306
307
|
if (invalidSegment.test(traceId)) return null
|
|
307
308
|
if (invalidSegment.test(spanId)) return null
|
|
@@ -316,6 +317,7 @@ class TextMapPropagator {
|
|
|
316
317
|
traceId: id(traceId, 16),
|
|
317
318
|
spanId: id(spanId, 16),
|
|
318
319
|
sampling: { priority: parseInt(flags, 10) & 1 ? 1 : 0 },
|
|
320
|
+
traceparent,
|
|
319
321
|
tracestate
|
|
320
322
|
})
|
|
321
323
|
|
|
@@ -12,8 +12,9 @@ class DatadogSpanContext {
|
|
|
12
12
|
this._name = props.name
|
|
13
13
|
this._isFinished = props.isFinished || false
|
|
14
14
|
this._tags = props.tags || {}
|
|
15
|
-
this._sampling = props.sampling
|
|
15
|
+
this._sampling = Object.assign({}, props.sampling)
|
|
16
16
|
this._baggageItems = props.baggageItems || {}
|
|
17
|
+
this._traceparent = props.traceparent
|
|
17
18
|
this._tracestate = props.tracestate
|
|
18
19
|
this._noop = props.noop || null
|
|
19
20
|
this._trace = props.trace || {
|
|
@@ -32,10 +33,11 @@ class DatadogSpanContext {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
toTraceparent () {
|
|
35
|
-
const
|
|
36
|
+
const flags = this._sampling.priority >= AUTO_KEEP ? '01' : '00'
|
|
36
37
|
const traceId = this._traceId.toString(16).padStart(32, '0')
|
|
37
38
|
const spanId = this._spanId.toString(16).padStart(16, '0')
|
|
38
|
-
|
|
39
|
+
const version = (this._traceparent && this._traceparent.version) || '00'
|
|
40
|
+
return `${version}-${traceId}-${spanId}-${flags}`
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
43
|
|
|
@@ -128,10 +128,13 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
128
128
|
const suiteTags = {
|
|
129
129
|
[TEST_SUITE_ID]: testSuiteSpan.context().toSpanId(),
|
|
130
130
|
[TEST_SESSION_ID]: testSuiteSpan.context().toTraceId(),
|
|
131
|
-
[TEST_MODULE_ID]: testSuiteSpan.context()._parentId.toString(10),
|
|
132
131
|
[TEST_COMMAND]: testSuiteSpan.context()._tags[TEST_COMMAND],
|
|
133
132
|
[TEST_BUNDLE]: testSuiteSpan.context()._tags[TEST_COMMAND]
|
|
134
133
|
}
|
|
134
|
+
if (testSuiteSpan.context()._parentId) {
|
|
135
|
+
suiteTags[TEST_MODULE_ID] = testSuiteSpan.context()._parentId.toString(10)
|
|
136
|
+
}
|
|
137
|
+
|
|
135
138
|
testTags = {
|
|
136
139
|
...testTags,
|
|
137
140
|
...suiteTags
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const
|
|
1
|
+
const cp = require('child_process')
|
|
2
2
|
|
|
3
3
|
const sanitizedExec = (cmd, options = {}) => {
|
|
4
4
|
try {
|
|
5
|
-
return execSync(cmd, options).toString().replace(/(\r\n|\n|\r)/gm, '')
|
|
5
|
+
return cp.execSync(cmd, options).toString().replace(/(\r\n|\n|\r)/gm, '')
|
|
6
6
|
} catch (e) {
|
|
7
7
|
return ''
|
|
8
8
|
}
|
|
@@ -21,6 +21,19 @@ const {
|
|
|
21
21
|
|
|
22
22
|
const GIT_REV_LIST_MAX_BUFFER = 8 * 1024 * 1024 // 8MB
|
|
23
23
|
|
|
24
|
+
function isShallowRepository () {
|
|
25
|
+
return sanitizedExec('git rev-parse --is-shallow-repository', { stdio: 'pipe' }) === 'true'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function unshallowRepository () {
|
|
29
|
+
try {
|
|
30
|
+
execSync('git config remote.origin.partialclonefilter "blob:none"', { stdio: 'pipe' })
|
|
31
|
+
execSync('git fetch --shallow-since="1 month ago" --update-shallow --refetch', { stdio: 'pipe' })
|
|
32
|
+
} catch (err) {
|
|
33
|
+
log.error(err)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
function getRepositoryUrl () {
|
|
25
38
|
return sanitizedExec('git config --get remote.origin.url', { stdio: 'pipe' })
|
|
26
39
|
}
|
|
@@ -146,5 +159,7 @@ module.exports = {
|
|
|
146
159
|
getRepositoryUrl,
|
|
147
160
|
generatePackFilesForCommits,
|
|
148
161
|
getCommitsToUpload,
|
|
149
|
-
GIT_REV_LIST_MAX_BUFFER
|
|
162
|
+
GIT_REV_LIST_MAX_BUFFER,
|
|
163
|
+
isShallowRepository,
|
|
164
|
+
unshallowRepository
|
|
150
165
|
}
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
const log = require('./log')
|
|
4
4
|
const { profiler } = require('./profiling')
|
|
5
5
|
|
|
6
|
+
// Stop profiler upon exit in order to collect and export the current profile
|
|
7
|
+
process.once('beforeExit', () => { profiler.stop() })
|
|
8
|
+
|
|
6
9
|
module.exports = {
|
|
7
10
|
start: config => {
|
|
8
11
|
const { service, version, env, url, hostname, port, tags } = config
|
|
@@ -23,7 +23,9 @@ const {
|
|
|
23
23
|
DD_AGENT_HOST,
|
|
24
24
|
DD_TRACE_AGENT_PORT,
|
|
25
25
|
DD_PROFILING_UPLOAD_TIMEOUT,
|
|
26
|
-
DD_PROFILING_SOURCE_MAP
|
|
26
|
+
DD_PROFILING_SOURCE_MAP,
|
|
27
|
+
DD_PROFILING_UPLOAD_PERIOD,
|
|
28
|
+
DD_PROFILING_PPROF_PREFIX
|
|
27
29
|
} = process.env
|
|
28
30
|
|
|
29
31
|
class Config {
|
|
@@ -35,13 +37,15 @@ class Config {
|
|
|
35
37
|
const version = coalesce(options.version, DD_VERSION)
|
|
36
38
|
const functionname = process.env.AWS_LAMBDA_FUNCTION_NAME
|
|
37
39
|
// Must be longer than one minute so pad with five seconds
|
|
38
|
-
const flushInterval = coalesce(options.interval, 65 * 1000)
|
|
40
|
+
const flushInterval = coalesce(options.interval, Number(DD_PROFILING_UPLOAD_PERIOD) * 1000, 65 * 1000)
|
|
39
41
|
const uploadTimeout = coalesce(options.uploadTimeout,
|
|
40
|
-
DD_PROFILING_UPLOAD_TIMEOUT, 60 * 1000)
|
|
42
|
+
Number(DD_PROFILING_UPLOAD_TIMEOUT), 60 * 1000)
|
|
41
43
|
const sourceMap = coalesce(options.sourceMap,
|
|
42
44
|
DD_PROFILING_SOURCE_MAP, true)
|
|
43
45
|
const endpointCollection = coalesce(options.endpointCollection,
|
|
44
46
|
DD_PROFILING_ENDPOINT_COLLECTION_ENABLED, false)
|
|
47
|
+
const pprofPrefix = coalesce(options.pprofPrefix,
|
|
48
|
+
DD_PROFILING_PPROF_PREFIX)
|
|
45
49
|
|
|
46
50
|
this.enabled = String(enabled) !== 'false'
|
|
47
51
|
this.service = service
|
|
@@ -60,6 +64,7 @@ class Config {
|
|
|
60
64
|
this.uploadTimeout = uploadTimeout
|
|
61
65
|
this.sourceMap = sourceMap
|
|
62
66
|
this.endpointCollection = endpointCollection
|
|
67
|
+
this.pprofPrefix = pprofPrefix
|
|
63
68
|
|
|
64
69
|
const hostname = coalesce(options.hostname, DD_AGENT_HOST) || 'localhost'
|
|
65
70
|
const port = coalesce(options.port, DD_TRACE_AGENT_PORT) || 8126
|
|
@@ -4,11 +4,22 @@ const fs = require('fs')
|
|
|
4
4
|
const { promisify } = require('util')
|
|
5
5
|
const writeFile = promisify(fs.writeFile)
|
|
6
6
|
|
|
7
|
+
function formatDateTime (t) {
|
|
8
|
+
const pad = (n) => String(n).padStart(2, '0')
|
|
9
|
+
return `${t.getUTCFullYear()}${pad(t.getUTCMonth() + 1)}${pad(t.getUTCDate())}` +
|
|
10
|
+
`T${pad(t.getUTCHours())}${pad(t.getUTCMinutes())}${pad(t.getUTCSeconds())}Z`
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
class FileExporter {
|
|
8
|
-
|
|
14
|
+
constructor ({ pprofPrefix } = {}) {
|
|
15
|
+
this._pprofPrefix = pprofPrefix || ''
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export ({ profiles, end }) {
|
|
9
19
|
const types = Object.keys(profiles)
|
|
20
|
+
const dateStr = formatDateTime(end)
|
|
10
21
|
const tasks = types.map(type => {
|
|
11
|
-
return writeFile(`${type}.
|
|
22
|
+
return writeFile(`${this._pprofPrefix}${type}_${dateStr}.pprof`, profiles[type])
|
|
12
23
|
})
|
|
13
24
|
|
|
14
25
|
return Promise.all(tasks)
|
|
@@ -56,7 +56,7 @@ class Profiler extends EventEmitter {
|
|
|
56
56
|
this._capture(this._timeoutInterval)
|
|
57
57
|
} catch (e) {
|
|
58
58
|
this._logger.error(e)
|
|
59
|
-
this.
|
|
59
|
+
this._stop()
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -64,7 +64,16 @@ class Profiler extends EventEmitter {
|
|
|
64
64
|
this._timeoutInterval = this._config.flushInterval
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
stop () {
|
|
67
|
+
async stop () {
|
|
68
|
+
if (!this._enabled) return
|
|
69
|
+
|
|
70
|
+
// collect and export current profiles
|
|
71
|
+
// once collect returns, profilers can be safely stopped
|
|
72
|
+
this._collect()
|
|
73
|
+
this._stop()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
_stop () {
|
|
68
77
|
if (!this._enabled) return
|
|
69
78
|
|
|
70
79
|
this._enabled = false
|
|
@@ -92,16 +101,24 @@ class Profiler extends EventEmitter {
|
|
|
92
101
|
}
|
|
93
102
|
|
|
94
103
|
async _collect () {
|
|
104
|
+
if (!this._enabled) return
|
|
105
|
+
|
|
95
106
|
const start = this._lastStart
|
|
96
107
|
const end = new Date()
|
|
97
|
-
const profiles =
|
|
108
|
+
const profiles = []
|
|
109
|
+
const encodedProfiles = {}
|
|
98
110
|
|
|
99
111
|
try {
|
|
112
|
+
// collect profiles synchronously so that profilers can be safely stopped asynchronously
|
|
100
113
|
for (const profiler of this._config.profilers) {
|
|
101
114
|
const profile = profiler.profile()
|
|
102
115
|
if (!profile) continue
|
|
116
|
+
profiles.push({ profiler, profile })
|
|
117
|
+
}
|
|
103
118
|
|
|
104
|
-
|
|
119
|
+
// encode and export asynchronously
|
|
120
|
+
for (const { profiler, profile } of profiles) {
|
|
121
|
+
encodedProfiles[profiler.type] = await profiler.encode(profile)
|
|
105
122
|
this._logger.debug(() => {
|
|
106
123
|
const profileJson = JSON.stringify(profile, (key, value) => {
|
|
107
124
|
return typeof value === 'bigint' ? value.toString() : value
|
|
@@ -111,11 +128,11 @@ class Profiler extends EventEmitter {
|
|
|
111
128
|
}
|
|
112
129
|
|
|
113
130
|
this._capture(this._timeoutInterval)
|
|
114
|
-
await this._submit(
|
|
131
|
+
await this._submit(encodedProfiles, start, end)
|
|
115
132
|
this._logger.debug('Submitted profiles')
|
|
116
133
|
} catch (err) {
|
|
117
134
|
this._logger.error(err)
|
|
118
|
-
this.
|
|
135
|
+
this._stop()
|
|
119
136
|
}
|
|
120
137
|
}
|
|
121
138
|
|
|
@@ -51,7 +51,7 @@ class Tracer extends NoopProxy {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
this._tracer = new DatadogTracer(config)
|
|
54
|
-
this.appsec = new AppsecSdk(this._tracer)
|
|
54
|
+
this.appsec = new AppsecSdk(this._tracer, config)
|
|
55
55
|
|
|
56
56
|
if (config.iast.enabled) {
|
|
57
57
|
require('./appsec/iast').enable(config, this._tracer)
|
|
@@ -2,76 +2,92 @@
|
|
|
2
2
|
const { globMatch } = require('../src/util')
|
|
3
3
|
const { USER_KEEP, AUTO_KEEP } = require('../../../ext').priority
|
|
4
4
|
const RateLimiter = require('./rate_limiter')
|
|
5
|
+
const Sampler = require('./sampler')
|
|
5
6
|
|
|
6
|
-
class
|
|
7
|
-
constructor ({
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
7
|
+
class SpanSamplingRule {
|
|
8
|
+
constructor ({ service, name, sampleRate = 1.0, maxPerSecond } = {}) {
|
|
9
|
+
this.service = service
|
|
10
|
+
this.name = name
|
|
11
|
+
|
|
12
|
+
this._sampler = new Sampler(sampleRate)
|
|
13
|
+
this._limiter = undefined
|
|
14
|
+
|
|
15
|
+
if (Number.isFinite(maxPerSecond)) {
|
|
16
|
+
this._limiter = new RateLimiter(maxPerSecond)
|
|
17
|
+
}
|
|
10
18
|
}
|
|
11
19
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
20
|
+
get sampleRate () {
|
|
21
|
+
return this._sampler.rate()
|
|
22
|
+
}
|
|
15
23
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const name = span._name
|
|
20
|
-
const rule = findRule(this._rules, service, name)
|
|
21
|
-
if (!rule) continue
|
|
24
|
+
get maxPerSecond () {
|
|
25
|
+
return this._limiter && this._limiter._rateLimit
|
|
26
|
+
}
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (!sampled) continue
|
|
28
|
+
static from (config) {
|
|
29
|
+
return new SpanSamplingRule(config)
|
|
30
|
+
}
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
span.context()._sampling.spanSampling = {
|
|
32
|
-
sampleRate,
|
|
33
|
-
maxPerSecond
|
|
34
|
-
}
|
|
35
|
-
}
|
|
32
|
+
match (service, name) {
|
|
33
|
+
if (this.service && !globMatch(this.service, service)) {
|
|
34
|
+
return false
|
|
36
35
|
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const servicePattern = getService(rule.service)
|
|
43
|
-
const namePattern = getName(rule.name)
|
|
44
|
-
if (globMatch(servicePattern, service) && globMatch(namePattern, name)) {
|
|
45
|
-
return rule
|
|
37
|
+
if (this.name && !globMatch(this.name, name)) {
|
|
38
|
+
return false
|
|
46
39
|
}
|
|
40
|
+
|
|
41
|
+
return true
|
|
47
42
|
}
|
|
48
|
-
}
|
|
49
43
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
sample () {
|
|
45
|
+
if (!this._sampler.isSampled()) {
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (this._limiter) {
|
|
50
|
+
return this._limiter.isAllowed()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return true
|
|
53
54
|
}
|
|
54
|
-
return list[key]
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
class SpanSampler {
|
|
58
|
+
constructor ({ spanSamplingRules = [] } = {}) {
|
|
59
|
+
this._rules = spanSamplingRules.map(SpanSamplingRule.from)
|
|
60
|
+
}
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
findRule (service, name) {
|
|
63
|
+
for (const rule of this._rules) {
|
|
64
|
+
if (rule.match(service, name)) {
|
|
65
|
+
return rule
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
64
69
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
70
|
+
sample (spanContext) {
|
|
71
|
+
const decision = spanContext._sampling.priority
|
|
72
|
+
if (decision === USER_KEEP || decision === AUTO_KEEP) return
|
|
68
73
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
74
|
+
const { started } = spanContext._trace
|
|
75
|
+
for (const span of started) {
|
|
76
|
+
const tags = span.context()._tags || {}
|
|
77
|
+
const name = span._name
|
|
78
|
+
const service = tags.service ||
|
|
79
|
+
tags['service.name'] ||
|
|
80
|
+
span.tracer()._service
|
|
72
81
|
|
|
73
|
-
|
|
74
|
-
|
|
82
|
+
const rule = this.findRule(service, name)
|
|
83
|
+
if (rule && rule.sample()) {
|
|
84
|
+
span.context()._sampling.spanSampling = {
|
|
85
|
+
sampleRate: rule.sampleRate,
|
|
86
|
+
maxPerSecond: rule.maxPerSecond
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
75
91
|
}
|
|
76
92
|
|
|
77
93
|
module.exports = SpanSampler
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const { info, warn } = require('./log/writer')
|
|
4
4
|
|
|
5
5
|
const os = require('os')
|
|
6
6
|
const { inspect } = require('util')
|
|
7
7
|
const tracerVersion = require('../../../package.json').version
|
|
8
8
|
|
|
9
|
-
const logger = Object.create(mainLogger)
|
|
10
|
-
logger.toggle(true)
|
|
11
|
-
|
|
12
9
|
let config
|
|
13
10
|
let pluginManager
|
|
14
11
|
let samplingRules = []
|
|
@@ -89,9 +86,9 @@ function startupLog ({ agentError } = {}) {
|
|
|
89
86
|
// out.service_mapping
|
|
90
87
|
// out.service_mapping_error
|
|
91
88
|
|
|
92
|
-
|
|
89
|
+
info('DATADOG TRACER CONFIGURATION - ' + out)
|
|
93
90
|
if (agentError) {
|
|
94
|
-
|
|
91
|
+
warn('DATADOG TRACER DIAGNOSTIC - Agent Error: ' + agentError.message)
|
|
95
92
|
}
|
|
96
93
|
|
|
97
94
|
config = undefined
|
|
@@ -127,22 +127,6 @@ class DatadogTracer extends Tracer {
|
|
|
127
127
|
<meta name="dd-trace-id" content="${traceId}" />\
|
|
128
128
|
<meta name="dd-trace-time" content="${traceTime}" />`
|
|
129
129
|
}
|
|
130
|
-
|
|
131
|
-
setUser (user) {
|
|
132
|
-
if (!user || !user.id) return this
|
|
133
|
-
|
|
134
|
-
const span = this.scope().active()
|
|
135
|
-
if (!span) return this
|
|
136
|
-
|
|
137
|
-
const rootSpan = span._spanContext._trace.started[0]
|
|
138
|
-
if (!rootSpan) return this
|
|
139
|
-
|
|
140
|
-
for (const k of Object.keys(user)) {
|
|
141
|
-
rootSpan.setTag(`usr.${k}`, '' + user[k])
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return this
|
|
145
|
-
}
|
|
146
130
|
}
|
|
147
131
|
|
|
148
132
|
function addError (span, error) {
|