dd-trace 2.12.1 → 3.2.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 +3 -2
- package/MIGRATING.md +119 -0
- package/ci/init.js +2 -27
- package/ext/formats.js +3 -5
- package/ext/tags.d.ts +2 -1
- package/ext/tags.js +2 -1
- package/index.d.ts +44 -38
- package/package.json +9 -8
- package/packages/datadog-core/src/storage/async_resource.js +19 -1
- package/packages/datadog-core/src/storage/index.js +1 -1
- package/packages/datadog-instrumentations/index.js +1 -52
- package/packages/datadog-instrumentations/src/connect.js +1 -1
- package/packages/datadog-instrumentations/src/crypto.js +30 -0
- package/packages/datadog-instrumentations/src/cucumber.js +15 -0
- package/packages/datadog-instrumentations/src/grpc/client.js +2 -2
- package/packages/datadog-instrumentations/src/grpc/server.js +1 -1
- package/packages/datadog-instrumentations/src/hapi.js +3 -31
- package/packages/datadog-instrumentations/src/helpers/hooks.js +69 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +5 -34
- package/packages/datadog-instrumentations/src/helpers/instrumentations.js +7 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +59 -0
- package/packages/datadog-instrumentations/src/http/server.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +33 -11
- package/packages/datadog-instrumentations/src/koa.js +1 -1
- package/packages/datadog-instrumentations/src/mocha.js +4 -1
- package/packages/datadog-instrumentations/src/net.js +13 -0
- package/packages/datadog-instrumentations/src/pg.js +2 -2
- package/packages/datadog-instrumentations/src/restify.js +27 -5
- package/packages/datadog-instrumentations/src/router.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
- package/packages/datadog-plugin-cucumber/src/index.js +4 -0
- package/packages/datadog-plugin-grpc/src/client.js +2 -2
- package/packages/datadog-plugin-grpc/src/server.js +2 -2
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +1 -1
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +25 -4
- package/packages/datadog-plugin-mocha/src/index.js +2 -2
- package/packages/datadog-plugin-mongodb-core/src/index.js +32 -8
- package/packages/datadog-plugin-oracledb/src/index.js +12 -4
- package/packages/datadog-plugin-restify/src/index.js +7 -0
- package/packages/dd-trace/index.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +3 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/index.js +20 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +48 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +24 -0
- package/packages/dd-trace/src/appsec/iast/iast-context.js +50 -0
- package/packages/dd-trace/src/appsec/iast/index.js +59 -0
- package/packages/dd-trace/src/appsec/iast/overhead-controller.js +94 -0
- package/packages/dd-trace/src/appsec/iast/path-line.js +70 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +113 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +50 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +53 -8
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +23 -24
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +220 -0
- package/packages/dd-trace/src/config.js +97 -10
- package/packages/dd-trace/src/constants.js +9 -1
- package/packages/dd-trace/src/encode/0.4.js +55 -58
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +13 -34
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +84 -0
- package/packages/dd-trace/src/encode/span-stats.js +155 -0
- package/packages/dd-trace/src/exporters/agent/index.js +25 -7
- package/packages/dd-trace/src/exporters/agent/writer.js +7 -4
- package/packages/dd-trace/src/{profiling/exporters → exporters/common}/form-data.js +0 -0
- package/packages/dd-trace/src/exporters/common/request.js +69 -39
- package/packages/dd-trace/src/exporters/common/writer.js +16 -6
- package/packages/dd-trace/src/exporters/span-stats/index.js +20 -0
- package/packages/dd-trace/src/exporters/span-stats/writer.js +54 -0
- package/packages/dd-trace/src/format.js +2 -0
- package/packages/dd-trace/src/id.js +16 -13
- package/packages/dd-trace/src/iitm.js +12 -1
- package/packages/dd-trace/src/index.js +10 -0
- package/packages/dd-trace/src/noop/proxy.js +77 -0
- package/packages/dd-trace/src/noop/scope.js +2 -6
- package/packages/dd-trace/src/noop/span.js +12 -12
- package/packages/dd-trace/src/noop/tracer.js +8 -9
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +77 -6
- package/packages/dd-trace/src/opentracing/span.js +63 -49
- package/packages/dd-trace/src/opentracing/span_context.js +1 -5
- package/packages/dd-trace/src/opentracing/tracer.js +32 -37
- package/packages/dd-trace/src/plugin_manager.js +111 -64
- package/packages/dd-trace/src/plugins/index.js +57 -45
- package/packages/dd-trace/src/plugins/log_plugin.js +16 -9
- package/packages/dd-trace/src/plugins/util/ci.js +34 -9
- package/packages/dd-trace/src/plugins/util/git.js +52 -2
- package/packages/dd-trace/src/plugins/util/ip_blocklist.js +25 -0
- package/packages/dd-trace/src/plugins/util/tags.js +4 -1
- package/packages/dd-trace/src/plugins/util/web.js +149 -6
- package/packages/dd-trace/src/priority_sampler.js +36 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/cpu.js +3 -3
- package/packages/dd-trace/src/proxy.js +21 -90
- package/packages/dd-trace/src/ritm.js +10 -1
- package/packages/dd-trace/src/scope.js +2 -184
- package/packages/dd-trace/src/span_processor.js +7 -1
- package/packages/dd-trace/src/span_stats.js +210 -0
- package/packages/dd-trace/src/startup-log.js +8 -19
- package/packages/dd-trace/src/telemetry/dependencies.js +83 -0
- package/packages/dd-trace/src/{telemetry.js → telemetry/index.js} +11 -79
- package/packages/dd-trace/src/telemetry/send-data.js +35 -0
- package/packages/dd-trace/src/tracer.js +0 -4
- package/scripts/install_plugin_modules.js +17 -26
- package/ci/jest/env.js +0 -39
- package/cypress/plugin.js +0 -5
- package/cypress/support.js +0 -1
- package/packages/datadog-plugin-fs/src/index.js +0 -548
|
@@ -6,9 +6,14 @@ const ext = require('../../../ext')
|
|
|
6
6
|
const { setSamplingRules } = require('./startup-log')
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
|
+
SAMPLING_MECHANISM_DEFAULT,
|
|
10
|
+
SAMPLING_MECHANISM_AGENT,
|
|
11
|
+
SAMPLING_MECHANISM_RULE,
|
|
12
|
+
SAMPLING_MECHANISM_MANUAL,
|
|
9
13
|
SAMPLING_RULE_DECISION,
|
|
10
14
|
SAMPLING_LIMIT_DECISION,
|
|
11
|
-
SAMPLING_AGENT_DECISION
|
|
15
|
+
SAMPLING_AGENT_DECISION,
|
|
16
|
+
DECISION_MAKER_KEY
|
|
12
17
|
} = require('./constants')
|
|
13
18
|
|
|
14
19
|
const SERVICE_NAME = ext.tags.SERVICE_NAME
|
|
@@ -45,6 +50,7 @@ class PrioritySampler {
|
|
|
45
50
|
const context = this._getContext(span)
|
|
46
51
|
const root = context._trace.started[0]
|
|
47
52
|
|
|
53
|
+
// TODO: remove the decision maker tag when priority is less than AUTO_KEEP
|
|
48
54
|
if (context._sampling.priority !== undefined) return
|
|
49
55
|
if (!root) return // noop span
|
|
50
56
|
|
|
@@ -52,9 +58,14 @@ class PrioritySampler {
|
|
|
52
58
|
|
|
53
59
|
if (this.validate(tag)) {
|
|
54
60
|
context._sampling.priority = tag
|
|
61
|
+
context._sampling.mechanism = SAMPLING_MECHANISM_MANUAL
|
|
55
62
|
} else if (auto) {
|
|
56
63
|
context._sampling.priority = this._getPriorityFromAuto(root)
|
|
64
|
+
} else {
|
|
65
|
+
return
|
|
57
66
|
}
|
|
67
|
+
|
|
68
|
+
this._addDecisionMaker(root)
|
|
58
69
|
}
|
|
59
70
|
|
|
60
71
|
update (rates) {
|
|
@@ -115,6 +126,7 @@ class PrioritySampler {
|
|
|
115
126
|
|
|
116
127
|
_getPriorityByRule (context, rule) {
|
|
117
128
|
context._trace[SAMPLING_RULE_DECISION] = rule.sampleRate
|
|
129
|
+
context._sampling.mechanism = SAMPLING_MECHANISM_RULE
|
|
118
130
|
|
|
119
131
|
return rule.sampler.isSampled(context) && this._isSampledByRateLimit(context) ? USER_KEEP : USER_REJECT
|
|
120
132
|
}
|
|
@@ -133,10 +145,33 @@ class PrioritySampler {
|
|
|
133
145
|
|
|
134
146
|
context._trace[SAMPLING_AGENT_DECISION] = sampler.rate()
|
|
135
147
|
|
|
148
|
+
if (sampler === defaultSampler) {
|
|
149
|
+
context._sampling.mechanism = SAMPLING_MECHANISM_DEFAULT
|
|
150
|
+
} else {
|
|
151
|
+
context._sampling.mechanism = SAMPLING_MECHANISM_AGENT
|
|
152
|
+
}
|
|
153
|
+
|
|
136
154
|
return sampler.isSampled(context) ? AUTO_KEEP : AUTO_REJECT
|
|
137
155
|
}
|
|
138
156
|
|
|
157
|
+
_addDecisionMaker (span) {
|
|
158
|
+
const context = span.context()
|
|
159
|
+
const trace = context._trace
|
|
160
|
+
const priority = context._sampling.priority
|
|
161
|
+
const mechanism = context._sampling.mechanism
|
|
162
|
+
|
|
163
|
+
if (priority >= AUTO_KEEP) {
|
|
164
|
+
if (!trace.tags[DECISION_MAKER_KEY]) {
|
|
165
|
+
trace.tags[DECISION_MAKER_KEY] = `-${mechanism}`
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
delete trace.tags[DECISION_MAKER_KEY]
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
139
172
|
_normalizeRules (rules, sampleRate) {
|
|
173
|
+
rules = [].concat(rules || [])
|
|
174
|
+
|
|
140
175
|
return rules
|
|
141
176
|
.concat({ sampleRate })
|
|
142
177
|
.map(rule => ({ ...rule, sampleRate: parseFloat(rule.sampleRate) }))
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
const retry = require('retry')
|
|
4
4
|
const { request } = require('http')
|
|
5
|
-
const FormData = require('./form-data')
|
|
6
5
|
|
|
7
6
|
// TODO: avoid using dd-trace internals. Make this a separate module?
|
|
8
7
|
const docker = require('../../exporters/common/docker')
|
|
8
|
+
const FormData = require('../../exporters/common/form-data')
|
|
9
9
|
const version = require('../../../../../package.json').version
|
|
10
10
|
|
|
11
11
|
const containerId = docker.id()
|
|
@@ -20,7 +20,7 @@ function getStartedSpans (activeSpan) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function getSpanContextTags (span) {
|
|
23
|
-
return span.
|
|
23
|
+
return span.context()._tags
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
function isWebServerSpan (tags) {
|
|
@@ -55,13 +55,13 @@ class NativeCpuProfiler {
|
|
|
55
55
|
const active = getActiveSpan()
|
|
56
56
|
if (!active) return
|
|
57
57
|
|
|
58
|
-
const activeCtx = active.
|
|
58
|
+
const activeCtx = active.context()
|
|
59
59
|
if (!activeCtx) return
|
|
60
60
|
|
|
61
61
|
const spans = getStartedSpans(active)
|
|
62
62
|
if (!spans || !spans.length) return
|
|
63
63
|
|
|
64
|
-
const firstCtx = spans[0].
|
|
64
|
+
const firstCtx = spans[0].context()
|
|
65
65
|
if (!firstCtx) return
|
|
66
66
|
|
|
67
67
|
const labels = {
|
|
@@ -1,36 +1,25 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const NoopTracer = require('./noop/tracer')
|
|
3
|
+
const NoopProxy = require('./noop/proxy')
|
|
5
4
|
const DatadogTracer = require('./tracer')
|
|
6
5
|
const Config = require('./config')
|
|
7
|
-
const Instrumenter = require('./instrumenter')
|
|
8
|
-
const PluginManager = require('./plugin_manager')
|
|
9
6
|
const metrics = require('./metrics')
|
|
10
7
|
const log = require('./log')
|
|
11
|
-
const {
|
|
12
|
-
const { setStartupLogInstrumenter } = require('./startup-log')
|
|
8
|
+
const { setStartupLogPluginManager } = require('./startup-log')
|
|
13
9
|
const telemetry = require('./telemetry')
|
|
10
|
+
const PluginManager = require('./plugin_manager')
|
|
11
|
+
const { sendGitMetadata } = require('./ci-visibility/exporters/git/git_metadata')
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class Tracer extends BaseTracer {
|
|
13
|
+
class Tracer extends NoopProxy {
|
|
18
14
|
constructor () {
|
|
19
15
|
super()
|
|
20
16
|
|
|
21
17
|
this._initialized = false
|
|
22
|
-
this._tracer = noop
|
|
23
|
-
this._instrumenter = new Instrumenter(this)
|
|
24
18
|
this._pluginManager = new PluginManager(this)
|
|
25
|
-
this._deprecate = method => log.deprecate(`tracer.${method}`, [
|
|
26
|
-
`tracer.${method}() is deprecated.`,
|
|
27
|
-
'Please use tracer.startSpan() and tracer.scope() instead.',
|
|
28
|
-
'See: https://datadog.github.io/dd-trace-js/#manual-instrumentation.'
|
|
29
|
-
].join(' '))
|
|
30
19
|
}
|
|
31
20
|
|
|
32
21
|
init (options) {
|
|
33
|
-
if (
|
|
22
|
+
if (this._initialized) return this
|
|
34
23
|
|
|
35
24
|
this._initialized = true
|
|
36
25
|
|
|
@@ -59,12 +48,24 @@ class Tracer extends BaseTracer {
|
|
|
59
48
|
if (config.appsec.enabled) {
|
|
60
49
|
require('./appsec').enable(config)
|
|
61
50
|
}
|
|
51
|
+
if (config.iast.enabled) {
|
|
52
|
+
require('./appsec/iast').enable(config)
|
|
53
|
+
}
|
|
62
54
|
|
|
63
55
|
this._tracer = new DatadogTracer(config)
|
|
64
|
-
this._instrumenter.enable(config)
|
|
65
56
|
this._pluginManager.configure(config)
|
|
66
|
-
|
|
67
|
-
telemetry.start(config, this.
|
|
57
|
+
setStartupLogPluginManager(this._pluginManager)
|
|
58
|
+
telemetry.start(config, this._pluginManager)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (config.isGitUploadEnabled) {
|
|
62
|
+
sendGitMetadata(config.site, (err) => {
|
|
63
|
+
if (err) {
|
|
64
|
+
log.error(`Error uploading git metadata: ${err}`)
|
|
65
|
+
} else {
|
|
66
|
+
log.debug('Successfully uploaded git metadata')
|
|
67
|
+
}
|
|
68
|
+
})
|
|
68
69
|
}
|
|
69
70
|
} catch (e) {
|
|
70
71
|
log.error(e)
|
|
@@ -74,79 +75,9 @@ class Tracer extends BaseTracer {
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
use () {
|
|
77
|
-
this._instrumenter.use(...arguments)
|
|
78
78
|
this._pluginManager.configurePlugin(...arguments)
|
|
79
79
|
return this
|
|
80
80
|
}
|
|
81
|
-
|
|
82
|
-
trace (name, options, fn) {
|
|
83
|
-
if (!fn) {
|
|
84
|
-
fn = options
|
|
85
|
-
options = {}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (typeof fn !== 'function') return
|
|
89
|
-
|
|
90
|
-
options = options || {}
|
|
91
|
-
|
|
92
|
-
return this._tracer.trace(name, options, fn)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
wrap (name, options, fn) {
|
|
96
|
-
if (!fn) {
|
|
97
|
-
fn = options
|
|
98
|
-
options = {}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (typeof fn !== 'function') return fn
|
|
102
|
-
|
|
103
|
-
options = options || {}
|
|
104
|
-
|
|
105
|
-
return this._tracer.wrap(name, options, fn)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
setUrl () {
|
|
109
|
-
this._tracer.setUrl.apply(this._tracer, arguments)
|
|
110
|
-
return this
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
startSpan () {
|
|
114
|
-
return this._tracer.startSpan.apply(this._tracer, arguments)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
inject () {
|
|
118
|
-
return this._tracer.inject.apply(this._tracer, arguments)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
extract () {
|
|
122
|
-
return this._tracer.extract.apply(this._tracer, arguments)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
scope () {
|
|
126
|
-
return this._tracer.scope.apply(this._tracer, arguments)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
currentSpan () {
|
|
130
|
-
this._deprecate('currentSpan')
|
|
131
|
-
return this._tracer.currentSpan.apply(this._tracer, arguments)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
bind (callback) {
|
|
135
|
-
this._deprecate('bind')
|
|
136
|
-
return callback
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
bindEmitter () {
|
|
140
|
-
this._deprecate('bindEmitter')
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
getRumData () {
|
|
144
|
-
return this._tracer.getRumData.apply(this._tracer, arguments)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
setUser () {
|
|
148
|
-
return this._tracer.setUser.apply(this.tracer, arguments)
|
|
149
|
-
}
|
|
150
81
|
}
|
|
151
82
|
|
|
152
83
|
module.exports = Tracer
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const path = require('path')
|
|
4
4
|
const Module = require('module')
|
|
5
5
|
const parse = require('module-details-from-path')
|
|
6
|
+
const dc = require('diagnostics_channel')
|
|
6
7
|
|
|
7
8
|
const origRequire = Module.prototype.require
|
|
8
9
|
|
|
@@ -14,7 +15,7 @@ let moduleHooks = Object.create(null)
|
|
|
14
15
|
let cache = Object.create(null)
|
|
15
16
|
let patching = Object.create(null)
|
|
16
17
|
let patchedRequire = null
|
|
17
|
-
|
|
18
|
+
const moduleLoadStartChannel = dc.channel('dd-trace:moduleLoadStart')
|
|
18
19
|
function Hook (modules, options, onrequire) {
|
|
19
20
|
if (!(this instanceof Hook)) return new Hook(modules, options, onrequire)
|
|
20
21
|
if (typeof modules === 'function') {
|
|
@@ -78,6 +79,14 @@ function Hook (modules, options, onrequire) {
|
|
|
78
79
|
// so the patching mark can be cleaned up.
|
|
79
80
|
delete patching[filename]
|
|
80
81
|
|
|
82
|
+
if (moduleLoadStartChannel.hasSubscribers) {
|
|
83
|
+
moduleLoadStartChannel.publish({
|
|
84
|
+
filename,
|
|
85
|
+
module: exports,
|
|
86
|
+
request
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
81
90
|
if (core) {
|
|
82
91
|
hooks = moduleHooks[filename]
|
|
83
92
|
if (!hooks) return exports // abort if module name isn't on whitelist
|
|
@@ -2,13 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const { storage } = require('../../datadog-core')
|
|
4
4
|
|
|
5
|
-
// TODO:
|
|
5
|
+
// TODO: refactor bind to use shimmer once the new internal tracer lands
|
|
6
6
|
|
|
7
7
|
const originals = new WeakMap()
|
|
8
|
-
const listenerMaps = new WeakMap()
|
|
9
|
-
const emitterSpans = new WeakMap()
|
|
10
|
-
const emitterScopes = new WeakMap()
|
|
11
|
-
const emitters = new WeakSet()
|
|
12
8
|
|
|
13
9
|
class Scope {
|
|
14
10
|
active () {
|
|
@@ -38,23 +34,7 @@ class Scope {
|
|
|
38
34
|
}
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
bind (
|
|
42
|
-
target = this._bindEmitter(target, span)
|
|
43
|
-
target = this._bindPromise(target, span)
|
|
44
|
-
target = this._bindFn(target, span)
|
|
45
|
-
|
|
46
|
-
return target
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
unbind (target) {
|
|
50
|
-
target = this._unbindFn(target)
|
|
51
|
-
target = this._unbindPromise(target)
|
|
52
|
-
target = this._unbindEmitter(target)
|
|
53
|
-
|
|
54
|
-
return target
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
_bindFn (fn, span) {
|
|
37
|
+
bind (fn, span) {
|
|
58
38
|
if (typeof fn !== 'function') return fn
|
|
59
39
|
|
|
60
40
|
const scope = this
|
|
@@ -71,175 +51,13 @@ class Scope {
|
|
|
71
51
|
return bound
|
|
72
52
|
}
|
|
73
53
|
|
|
74
|
-
_unbindFn (fn) {
|
|
75
|
-
if (typeof fn !== 'function') return fn
|
|
76
|
-
|
|
77
|
-
return originals.get(fn) || fn
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
_bindEmitter (emitter, span) {
|
|
81
|
-
if (!this._isEmitter(emitter)) return emitter
|
|
82
|
-
if (!emitters.has(emitter)) {
|
|
83
|
-
Scope._wrapEmitter(emitter)
|
|
84
|
-
}
|
|
85
|
-
emitterSpans.set(emitter, span)
|
|
86
|
-
emitterScopes.set(emitter, this)
|
|
87
|
-
return emitter
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Occasionally we want to wrap a prototype rather than emitter instances,
|
|
91
|
-
// so we're exposing this as a static method. This gives us a faster
|
|
92
|
-
// path for binding instances of known EventEmitter subclasses.
|
|
93
|
-
static _wrapEmitter (emitter) {
|
|
94
|
-
wrapMethod(emitter, 'addListener', wrapAddListener)
|
|
95
|
-
wrapMethod(emitter, 'prependListener', wrapAddListener)
|
|
96
|
-
wrapMethod(emitter, 'on', wrapAddListener)
|
|
97
|
-
wrapMethod(emitter, 'once', wrapAddListener)
|
|
98
|
-
wrapMethod(emitter, 'removeListener', wrapRemoveListener)
|
|
99
|
-
wrapMethod(emitter, 'off', wrapRemoveListener)
|
|
100
|
-
wrapMethod(emitter, 'removeAllListeners', wrapRemoveAllListeners)
|
|
101
|
-
emitters.add(emitter)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
_unbindEmitter (emitter) {
|
|
105
|
-
if (!this._isEmitter(emitter)) return emitter
|
|
106
|
-
emitterScopes.delete(emitter)
|
|
107
|
-
emitterSpans.delete(emitter)
|
|
108
|
-
return emitter
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
_bindPromise (promise, span) {
|
|
112
|
-
if (!this._isPromise(promise)) return promise
|
|
113
|
-
|
|
114
|
-
wrapMethod(promise, 'then', wrapThen, this, span)
|
|
115
|
-
|
|
116
|
-
return promise
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
_unbindPromise (promise) {
|
|
120
|
-
if (!this._isPromise(promise)) return promise
|
|
121
|
-
|
|
122
|
-
promise.then = originals.get(promise.then) || promise.then
|
|
123
|
-
|
|
124
|
-
return promise
|
|
125
|
-
}
|
|
126
|
-
|
|
127
54
|
_spanOrActive (span) {
|
|
128
55
|
return span !== undefined ? span : this.active()
|
|
129
56
|
}
|
|
130
57
|
|
|
131
|
-
_isEmitter (emitter) {
|
|
132
|
-
return emitter &&
|
|
133
|
-
typeof emitter.emit === 'function' &&
|
|
134
|
-
typeof emitter.on === 'function' &&
|
|
135
|
-
typeof emitter.addListener === 'function' &&
|
|
136
|
-
typeof emitter.removeListener === 'function'
|
|
137
|
-
}
|
|
138
|
-
|
|
139
58
|
_isPromise (promise) {
|
|
140
59
|
return promise && typeof promise.then === 'function'
|
|
141
60
|
}
|
|
142
61
|
}
|
|
143
62
|
|
|
144
|
-
function getScope (emitter) {
|
|
145
|
-
return emitterScopes.get(emitter) || emitterScopes.get(emitter.constructor.prototype)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function getSpan (emitter) {
|
|
149
|
-
return emitterSpans.get(emitter) || emitterSpans.get(emitter.constructor.prototype)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function hasScope (emitter) {
|
|
153
|
-
return emitterScopes.has(emitter) || emitterScopes.has(emitter.constructor.prototype)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function wrapThen (then, scope, span) {
|
|
157
|
-
return function thenWithTrace (onFulfilled, onRejected) {
|
|
158
|
-
const args = new Array(arguments.length)
|
|
159
|
-
|
|
160
|
-
for (let i = 0, l = args.length; i < l; i++) {
|
|
161
|
-
args[i] = scope.bind(arguments[i], span)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return then.apply(this, args)
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function wrapAddListener (addListener) {
|
|
169
|
-
return function addListenerWithTrace (eventName, listener) {
|
|
170
|
-
const scope = getScope(this)
|
|
171
|
-
if (!scope || !listener || originals.has(listener) || listener.listener) {
|
|
172
|
-
return addListener.apply(this, arguments)
|
|
173
|
-
}
|
|
174
|
-
const span = getSpan(this)
|
|
175
|
-
|
|
176
|
-
const bound = scope.bind(listener, scope._spanOrActive(span))
|
|
177
|
-
const listenerMap = listenerMaps.get(this) || {}
|
|
178
|
-
|
|
179
|
-
listenerMaps.set(this, listenerMap)
|
|
180
|
-
|
|
181
|
-
if (!listenerMap[eventName]) {
|
|
182
|
-
listenerMap[eventName] = new WeakMap()
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const events = listenerMap[eventName]
|
|
186
|
-
|
|
187
|
-
if (!events.has(listener)) {
|
|
188
|
-
events.set(listener, [])
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
events.get(listener).push(bound)
|
|
192
|
-
|
|
193
|
-
return addListener.call(this, eventName, bound)
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function wrapRemoveListener (removeListener) {
|
|
198
|
-
return function removeListenerWithTrace (eventName, listener) {
|
|
199
|
-
if (!hasScope(this)) {
|
|
200
|
-
return removeListener.apply(this, arguments)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const listenerMap = listenerMaps.get(this)
|
|
204
|
-
const listeners = listenerMap && listenerMap[eventName]
|
|
205
|
-
|
|
206
|
-
if (!listener || !listeners || !listeners.has(listener)) {
|
|
207
|
-
return removeListener.apply(this, arguments)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
for (const bound of listeners.get(listener)) {
|
|
211
|
-
removeListener.call(this, eventName, bound)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
listeners.delete(listener)
|
|
215
|
-
|
|
216
|
-
return removeListener.apply(this, arguments)
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function wrapRemoveAllListeners (removeAllListeners) {
|
|
221
|
-
return function removeAllListenersWithTrace (eventName) {
|
|
222
|
-
const listenerMap = listenerMaps.get(this)
|
|
223
|
-
|
|
224
|
-
if (hasScope(this) && listenerMap) {
|
|
225
|
-
if (eventName) {
|
|
226
|
-
delete listenerMap[eventName]
|
|
227
|
-
} else {
|
|
228
|
-
listenerMaps.delete(this)
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return removeAllListeners.apply(this, arguments)
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function wrapMethod (target, name, wrapper, ...args) {
|
|
237
|
-
if (!target[name] || originals.has(target[name])) return
|
|
238
|
-
|
|
239
|
-
const original = target[name]
|
|
240
|
-
|
|
241
|
-
target[name] = wrapper(target[name], ...args)
|
|
242
|
-
originals.set(target[name], original)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
63
|
module.exports = Scope
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
const log = require('./log')
|
|
4
4
|
const format = require('./format')
|
|
5
5
|
|
|
6
|
+
const { SpanStatsProcessor } = require('./span_stats')
|
|
7
|
+
|
|
6
8
|
const startedSpans = new WeakSet()
|
|
7
9
|
const finishedSpans = new WeakSet()
|
|
8
10
|
|
|
@@ -11,6 +13,8 @@ class SpanProcessor {
|
|
|
11
13
|
this._exporter = exporter
|
|
12
14
|
this._prioritySampler = prioritySampler
|
|
13
15
|
this._config = config
|
|
16
|
+
|
|
17
|
+
this._stats = new SpanStatsProcessor(config)
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
process (span) {
|
|
@@ -26,7 +30,9 @@ class SpanProcessor {
|
|
|
26
30
|
|
|
27
31
|
for (const span of started) {
|
|
28
32
|
if (span._duration !== undefined) {
|
|
29
|
-
|
|
33
|
+
const formattedSpan = format(span)
|
|
34
|
+
this._stats.onSpanFinished(formattedSpan)
|
|
35
|
+
formatted.push(formattedSpan)
|
|
30
36
|
} else {
|
|
31
37
|
active.push(span)
|
|
32
38
|
}
|