dd-trace 4.38.1 → 4.40.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 +0 -3
- package/README.md +8 -18
- package/ci/init.js +7 -0
- package/ext/exporters.d.ts +1 -0
- package/ext/exporters.js +2 -1
- package/ext/tags.d.ts +1 -0
- package/ext/tags.js +1 -0
- package/index.d.ts +18 -3
- package/initialize.mjs +52 -0
- package/package.json +9 -12
- package/packages/datadog-instrumentations/src/amqplib.js +5 -2
- package/packages/datadog-instrumentations/src/apollo-server-core.js +0 -1
- package/packages/datadog-instrumentations/src/apollo-server.js +0 -1
- package/packages/datadog-instrumentations/src/body-parser.js +0 -1
- package/packages/datadog-instrumentations/src/check_require_cache.js +67 -5
- package/packages/datadog-instrumentations/src/cookie-parser.js +0 -1
- package/packages/datadog-instrumentations/src/express.js +0 -1
- package/packages/datadog-instrumentations/src/graphql.js +0 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +5 -2
- package/packages/datadog-instrumentations/src/http/server.js +0 -1
- package/packages/datadog-instrumentations/src/jest.js +6 -3
- package/packages/datadog-instrumentations/src/mocha/common.js +48 -0
- package/packages/datadog-instrumentations/src/mocha/main.js +487 -0
- package/packages/datadog-instrumentations/src/mocha/utils.js +306 -0
- package/packages/datadog-instrumentations/src/mocha/worker.js +51 -0
- package/packages/datadog-instrumentations/src/mocha.js +4 -673
- package/packages/datadog-instrumentations/src/openai.js +188 -17
- package/packages/datadog-instrumentations/src/playwright.js +4 -3
- package/packages/datadog-instrumentations/src/router.js +1 -1
- package/packages/datadog-instrumentations/src/selenium.js +13 -6
- package/packages/datadog-plugin-graphql/src/resolve.js +4 -0
- package/packages/datadog-plugin-mocha/src/index.js +82 -8
- package/packages/datadog-plugin-next/src/index.js +1 -2
- package/packages/datadog-plugin-openai/src/index.js +219 -73
- package/packages/dd-trace/src/appsec/addresses.js +4 -2
- package/packages/dd-trace/src/appsec/blocking.js +19 -25
- package/packages/dd-trace/src/appsec/channels.js +2 -1
- package/packages/dd-trace/src/appsec/graphql.js +10 -3
- package/packages/dd-trace/src/appsec/index.js +11 -4
- package/packages/dd-trace/src/appsec/rasp.js +35 -0
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +1 -0
- package/packages/dd-trace/src/appsec/rule_manager.js +15 -25
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -5
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +3 -1
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +5 -1
- package/packages/dd-trace/src/config.js +97 -22
- package/packages/dd-trace/src/constants.js +2 -0
- package/packages/dd-trace/src/encode/0.4.js +47 -8
- package/packages/dd-trace/src/exporter.js +1 -0
- package/packages/dd-trace/src/flare/file.js +44 -0
- package/packages/dd-trace/src/flare/index.js +98 -0
- package/packages/dd-trace/src/log/channels.js +54 -29
- package/packages/dd-trace/src/log/writer.js +7 -49
- package/packages/dd-trace/src/opentelemetry/span.js +8 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +57 -12
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
- package/packages/dd-trace/src/plugins/util/test.js +6 -0
- package/packages/dd-trace/src/priority_sampler.js +8 -4
- package/packages/dd-trace/src/profiler.js +2 -1
- package/packages/dd-trace/src/profiling/config.js +1 -0
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/{ssi-telemetry.js → ssi-heuristics.js} +64 -36
- package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +4 -9
- package/packages/dd-trace/src/proxy.js +49 -15
- package/packages/dd-trace/src/ritm.js +13 -1
- package/packages/dd-trace/src/sampling_rule.js +2 -1
- package/packages/dd-trace/src/startup-log.js +19 -15
- package/packages/dd-trace/src/telemetry/index.js +6 -2
- package/packages/dd-trace/src/tracer.js +3 -0
- package/packages/dd-trace/src/plugins/util/ip_blocklist.js +0 -51
|
@@ -2,28 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
const telemetryMetrics = require('../telemetry/metrics')
|
|
4
4
|
const profilersNamespace = telemetryMetrics.manager.namespace('profilers')
|
|
5
|
-
const performance = require('perf_hooks').performance
|
|
6
5
|
const dc = require('dc-polyfill')
|
|
7
|
-
const { isTrue, isFalse } = require('../util')
|
|
8
6
|
|
|
9
|
-
// If the process
|
|
10
|
-
const
|
|
7
|
+
// If the process lives for at least 30 seconds, it's considered long-lived
|
|
8
|
+
const DEFAULT_LONG_LIVED_THRESHOLD = 30000
|
|
11
9
|
|
|
12
10
|
const EnablementChoice = {
|
|
13
11
|
MANUALLY_ENABLED: Symbol('SSITelemetry.EnablementChoice.MANUALLY_ENABLED'),
|
|
14
12
|
SSI_ENABLED: Symbol('SSITelemetry.EnablementChoice.SSI_ENABLED'),
|
|
15
13
|
SSI_NOT_ENABLED: Symbol('SSITelemetry.EnablementChoice.SSI_NOT_ENABLED'),
|
|
16
|
-
DISABLED: Symbol('SSITelemetry.EnablementChoice.
|
|
14
|
+
DISABLED: Symbol('SSITelemetry.EnablementChoice.DISABLED')
|
|
17
15
|
}
|
|
18
16
|
Object.freeze(EnablementChoice)
|
|
19
17
|
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
if (DD_INJECTION_ENABLED === undefined || isFalse(DD_PROFILING_ENABLED)) {
|
|
18
|
+
function getEnablementChoiceFromConfig (config) {
|
|
19
|
+
if (config.ssi === false || config.enabled === false) {
|
|
23
20
|
return EnablementChoice.DISABLED
|
|
24
|
-
} else if (
|
|
21
|
+
} else if (config.heuristicsEnabled === true) {
|
|
25
22
|
return EnablementChoice.SSI_ENABLED
|
|
26
|
-
} else if (
|
|
23
|
+
} else if (config.enabled === true) {
|
|
27
24
|
return EnablementChoice.MANUALLY_ENABLED
|
|
28
25
|
} else {
|
|
29
26
|
return EnablementChoice.SSI_NOT_ENABLED
|
|
@@ -38,39 +35,38 @@ function enablementChoiceToTagValue (enablementChoice) {
|
|
|
38
35
|
return 'ssi_enabled'
|
|
39
36
|
case EnablementChoice.SSI_NOT_ENABLED:
|
|
40
37
|
return 'not_enabled'
|
|
41
|
-
case EnablementChoice.
|
|
38
|
+
case EnablementChoice.DISABLED:
|
|
42
39
|
// Can't emit this one as a tag
|
|
43
40
|
throw new Error('Invalid enablement choice')
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
|
|
47
44
|
/**
|
|
48
|
-
* This class
|
|
49
|
-
*
|
|
45
|
+
* This class embodies the SSI profiler-triggering heuristics and also emits telemetry metrics about
|
|
46
|
+
* the profiler behavior under SSI. It emits the following metrics:
|
|
50
47
|
* - `number_of_profiles`: The number of profiles that were submitted
|
|
51
|
-
* - `number_of_runtime_id`: The number of runtime IDs in the app (always 1 for Node.js
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* the profiler
|
|
56
|
-
*
|
|
48
|
+
* - `number_of_runtime_id`: The number of runtime IDs in the app (always 1 for Node.js, emitted
|
|
49
|
+
* once when the tags won't change for the remaineder of of the app's lifetime.)
|
|
50
|
+
* It will also add tags describing the state of heuristics triggers, the enablement choice, and
|
|
51
|
+
* whether actual profiles were sent (as opposed to mock profiles). There is a mock profiler that is
|
|
52
|
+
* activated when the profiler is not enabled, and it will emit mock profile submission events at
|
|
53
|
+
* the same cadence the profiler would, providing insight into how many profiles would've been
|
|
54
|
+
* emitted if SSI enabled profiling. Note that heuristics (and thus telemetry) is per tracer
|
|
55
|
+
* instance, and each worker thread will have its own instance.
|
|
57
56
|
*/
|
|
58
|
-
class
|
|
59
|
-
constructor ({
|
|
60
|
-
enablementChoice =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
throw new Error('
|
|
65
|
-
}
|
|
66
|
-
if (typeof shortLivedThreshold !== 'number' || shortLivedThreshold <= 0) {
|
|
67
|
-
throw new Error('Short-lived threshold must be a positive number')
|
|
57
|
+
class SSIHeuristics {
|
|
58
|
+
constructor (config) {
|
|
59
|
+
this.enablementChoice = getEnablementChoiceFromConfig(config)
|
|
60
|
+
|
|
61
|
+
const longLivedThreshold = config.longLivedThreshold || DEFAULT_LONG_LIVED_THRESHOLD
|
|
62
|
+
if (typeof longLivedThreshold !== 'number' || longLivedThreshold <= 0) {
|
|
63
|
+
throw new Error('Long-lived threshold must be a positive number')
|
|
68
64
|
}
|
|
69
|
-
this.
|
|
70
|
-
this.shortLivedThreshold = shortLivedThreshold
|
|
65
|
+
this.longLivedThreshold = longLivedThreshold
|
|
71
66
|
|
|
72
67
|
this.hasSentProfiles = false
|
|
73
68
|
this.noSpan = true
|
|
69
|
+
this.shortLived = true
|
|
74
70
|
}
|
|
75
71
|
|
|
76
72
|
enabled () {
|
|
@@ -83,7 +79,10 @@ class SSITelemetry {
|
|
|
83
79
|
// reference point, but the tracer initialization point is more relevant, as we couldn't be
|
|
84
80
|
// collecting profiles earlier anyway. The difference is not particularly significant if the
|
|
85
81
|
// tracer is initialized early in the process lifetime.
|
|
86
|
-
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
this.shortLived = false
|
|
84
|
+
this._maybeTriggered()
|
|
85
|
+
}, this.longLivedThreshold).unref()
|
|
87
86
|
|
|
88
87
|
this._onSpanCreated = this._onSpanCreated.bind(this)
|
|
89
88
|
this._onProfileSubmitted = this._onProfileSubmitted.bind(this)
|
|
@@ -97,8 +96,31 @@ class SSITelemetry {
|
|
|
97
96
|
}
|
|
98
97
|
}
|
|
99
98
|
|
|
99
|
+
onTriggered (callback) {
|
|
100
|
+
switch (typeof callback) {
|
|
101
|
+
case 'undefined':
|
|
102
|
+
case 'function':
|
|
103
|
+
this.triggeredCallback = callback
|
|
104
|
+
process.nextTick(() => {
|
|
105
|
+
this._maybeTriggered()
|
|
106
|
+
})
|
|
107
|
+
break
|
|
108
|
+
default:
|
|
109
|
+
throw new TypeError('callback must be a function or undefined')
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_maybeTriggered () {
|
|
114
|
+
if (!this.shortLived && !this.noSpan) {
|
|
115
|
+
if (typeof this.triggeredCallback === 'function') {
|
|
116
|
+
this.triggeredCallback.call(null)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
100
121
|
_onSpanCreated () {
|
|
101
122
|
this.noSpan = false
|
|
123
|
+
this._maybeTriggered()
|
|
102
124
|
dc.unsubscribe('dd-trace:span:start', this._onSpanCreated)
|
|
103
125
|
}
|
|
104
126
|
|
|
@@ -121,7 +143,7 @@ class SSITelemetry {
|
|
|
121
143
|
if (this.noSpan) {
|
|
122
144
|
decision.push('no_span')
|
|
123
145
|
}
|
|
124
|
-
if (
|
|
146
|
+
if (this.shortLived) {
|
|
125
147
|
decision.push('short_lived')
|
|
126
148
|
}
|
|
127
149
|
if (decision.length === 0) {
|
|
@@ -138,8 +160,14 @@ class SSITelemetry {
|
|
|
138
160
|
this._profileCount = profilersNamespace.count('ssi_heuristic.number_of_profiles', tags)
|
|
139
161
|
this._runtimeIdCount = profilersNamespace.count('ssi_heuristic.number_of_runtime_id', tags)
|
|
140
162
|
|
|
141
|
-
if (
|
|
142
|
-
|
|
163
|
+
if (
|
|
164
|
+
!this._emittedRuntimeId &&
|
|
165
|
+
decision[0] === 'triggered' &&
|
|
166
|
+
// When enablement choice is SSI_ENABLED, hasSentProfiles can transition from false to true when the
|
|
167
|
+
// profiler gets started and the first profile is submitted, so we have to wait for it.
|
|
168
|
+
(this.enablementChoice !== EnablementChoice.SSI_ENABLED || this.hasSentProfiles)
|
|
169
|
+
) {
|
|
170
|
+
// Tags won't change anymore, so we can emit the runtime ID metric now.
|
|
143
171
|
this._emittedRuntimeId = true
|
|
144
172
|
this._runtimeIdCount.inc()
|
|
145
173
|
}
|
|
@@ -164,4 +192,4 @@ class SSITelemetry {
|
|
|
164
192
|
}
|
|
165
193
|
}
|
|
166
194
|
|
|
167
|
-
module.exports = {
|
|
195
|
+
module.exports = { SSIHeuristics, EnablementChoice }
|
|
@@ -12,16 +12,11 @@ module.exports = {
|
|
|
12
12
|
// Copied from packages/dd-trace/src/profiler.js
|
|
13
13
|
const flushInterval = coalesce(config.interval, Number(DD_PROFILING_UPLOAD_PERIOD) * 1000, 65 * 1000)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
timerId = setTimeout(emitProfileSubmit, flushInterval)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function emitProfileSubmit () {
|
|
15
|
+
timerId = setTimeout(() => {
|
|
20
16
|
profileSubmittedChannel.publish()
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
scheduleProfileSubmit()
|
|
17
|
+
timerId.refresh()
|
|
18
|
+
}, flushInterval)
|
|
19
|
+
timerId.unref()
|
|
25
20
|
},
|
|
26
21
|
|
|
27
22
|
stop: () => {
|
|
@@ -13,7 +13,7 @@ const AppsecSdk = require('./appsec/sdk')
|
|
|
13
13
|
const dogstatsd = require('./dogstatsd')
|
|
14
14
|
const NoopDogStatsDClient = require('./noop/dogstatsd')
|
|
15
15
|
const spanleak = require('./spanleak')
|
|
16
|
-
const {
|
|
16
|
+
const { SSIHeuristics } = require('./profiling/ssi-heuristics')
|
|
17
17
|
const telemetryLog = require('dc-polyfill').channel('datadog:telemetry:log')
|
|
18
18
|
|
|
19
19
|
class LazyModule {
|
|
@@ -40,6 +40,7 @@ class Tracer extends NoopProxy {
|
|
|
40
40
|
this._pluginManager = new PluginManager(this)
|
|
41
41
|
this.dogstatsd = new NoopDogStatsDClient()
|
|
42
42
|
this._tracingInitialized = false
|
|
43
|
+
this._flare = new LazyModule(() => require('./flare'))
|
|
43
44
|
|
|
44
45
|
// these requires must work with esm bundler
|
|
45
46
|
this._modules = {
|
|
@@ -90,29 +91,46 @@ class Tracer extends NoopProxy {
|
|
|
90
91
|
}
|
|
91
92
|
this._enableOrDisableTracing(config)
|
|
92
93
|
})
|
|
94
|
+
|
|
95
|
+
rc.on('AGENT_CONFIG', (action, conf) => {
|
|
96
|
+
if (!conf?.name?.startsWith('flare-log-level.')) return
|
|
97
|
+
|
|
98
|
+
if (action === 'unapply') {
|
|
99
|
+
this._flare.disable()
|
|
100
|
+
} else if (conf.config?.log_level) {
|
|
101
|
+
this._flare.enable(config)
|
|
102
|
+
this._flare.module.prepare(conf.config.log_level)
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
rc.on('AGENT_TASK', (action, conf) => {
|
|
107
|
+
if (action === 'unapply' || !conf) return
|
|
108
|
+
if (conf.task_type !== 'tracer_flare' || !conf.args) return
|
|
109
|
+
|
|
110
|
+
this._flare.enable(config)
|
|
111
|
+
this._flare.module.send(conf.args)
|
|
112
|
+
})
|
|
93
113
|
}
|
|
94
114
|
|
|
95
115
|
if (config.isGCPFunction || config.isAzureFunction) {
|
|
96
116
|
require('./serverless').maybeStartServerlessMiniAgent(config)
|
|
97
117
|
}
|
|
98
118
|
|
|
99
|
-
const
|
|
100
|
-
|
|
119
|
+
const ssiHeuristics = new SSIHeuristics(config.profiling)
|
|
120
|
+
ssiHeuristics.start()
|
|
101
121
|
if (config.profiling.enabled) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
122
|
+
this._profilerStarted = this._startProfiler(config)
|
|
123
|
+
} else if (config.profiling.ssi) {
|
|
124
|
+
const mockProfiler = require('./profiling/ssi-telemetry-mock-profiler')
|
|
125
|
+
mockProfiler.start(config)
|
|
126
|
+
|
|
127
|
+
if (config.profiling.heuristicsEnabled) {
|
|
128
|
+
ssiHeuristics.onTriggered(() => {
|
|
129
|
+
mockProfiler.stop()
|
|
130
|
+
this._startProfiler(config)
|
|
131
|
+
ssiHeuristics.onTriggered()
|
|
112
132
|
})
|
|
113
133
|
}
|
|
114
|
-
} else if (ssiTelemetry.enabled()) {
|
|
115
|
-
require('./profiling/ssi-telemetry-mock-profiler').start(config)
|
|
116
134
|
}
|
|
117
135
|
if (!this._profilerStarted) {
|
|
118
136
|
this._profilerStarted = Promise.resolve(false)
|
|
@@ -138,6 +156,22 @@ class Tracer extends NoopProxy {
|
|
|
138
156
|
return this
|
|
139
157
|
}
|
|
140
158
|
|
|
159
|
+
_startProfiler (config) {
|
|
160
|
+
// do not stop tracer initialization if the profiler fails to be imported
|
|
161
|
+
try {
|
|
162
|
+
return require('./profiler').start(config)
|
|
163
|
+
} catch (e) {
|
|
164
|
+
log.error(e)
|
|
165
|
+
if (telemetryLog.hasSubscribers) {
|
|
166
|
+
telemetryLog.publish({
|
|
167
|
+
message: e.message,
|
|
168
|
+
level: 'ERROR',
|
|
169
|
+
stack_trace: e.stack
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
141
175
|
_enableOrDisableTracing (config) {
|
|
142
176
|
if (config.tracing !== false) {
|
|
143
177
|
if (config.appsec.enabled) {
|
|
@@ -50,8 +50,20 @@ function Hook (modules, options, onrequire) {
|
|
|
50
50
|
|
|
51
51
|
if (patchedRequire) return
|
|
52
52
|
|
|
53
|
+
const _origRequire = Module.prototype.require
|
|
53
54
|
patchedRequire = Module.prototype.require = function (request) {
|
|
54
|
-
|
|
55
|
+
/*
|
|
56
|
+
If resolving the filename for a `require(...)` fails, defer to the wrapped
|
|
57
|
+
require implementation rather than failing right away. This allows a
|
|
58
|
+
possibly monkey patched `require` to work.
|
|
59
|
+
*/
|
|
60
|
+
let filename
|
|
61
|
+
try {
|
|
62
|
+
filename = Module._resolveFilename(request, this)
|
|
63
|
+
} catch (resolveErr) {
|
|
64
|
+
return _origRequire.apply(this, arguments)
|
|
65
|
+
}
|
|
66
|
+
|
|
55
67
|
const core = filename.indexOf(path.sep) === -1
|
|
56
68
|
let name, basedir, hooks
|
|
57
69
|
// return known patched modules immediately
|
|
@@ -64,7 +64,7 @@ function serviceLocator (span) {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
class SamplingRule {
|
|
67
|
-
constructor ({ name, service, resource, tags, sampleRate = 1.0, maxPerSecond } = {}) {
|
|
67
|
+
constructor ({ name, service, resource, tags, sampleRate = 1.0, provenance = undefined, maxPerSecond } = {}) {
|
|
68
68
|
this.matchers = []
|
|
69
69
|
|
|
70
70
|
if (name) {
|
|
@@ -82,6 +82,7 @@ class SamplingRule {
|
|
|
82
82
|
|
|
83
83
|
this._sampler = new Sampler(sampleRate)
|
|
84
84
|
this._limiter = undefined
|
|
85
|
+
this.provenance = provenance
|
|
85
86
|
|
|
86
87
|
if (Number.isFinite(maxPerSecond)) {
|
|
87
88
|
this._limiter = new RateLimiter(maxPerSecond)
|
|
@@ -37,6 +37,23 @@ function startupLog ({ agentError } = {}) {
|
|
|
37
37
|
return
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
const out = tracerInfo({ agentError })
|
|
41
|
+
|
|
42
|
+
if (agentError) {
|
|
43
|
+
out.agent_error = agentError.message
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
info('DATADOG TRACER CONFIGURATION - ' + out)
|
|
47
|
+
if (agentError) {
|
|
48
|
+
warn('DATADOG TRACER DIAGNOSTIC - Agent Error: ' + agentError.message)
|
|
49
|
+
errors.agentError = {
|
|
50
|
+
code: agentError.code ? agentError.code : '',
|
|
51
|
+
message: `Agent Error:${agentError.message}`
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function tracerInfo () {
|
|
40
57
|
const url = config.url || `http://${config.hostname || 'localhost'}:${config.port}`
|
|
41
58
|
|
|
42
59
|
const out = {
|
|
@@ -59,9 +76,6 @@ function startupLog ({ agentError } = {}) {
|
|
|
59
76
|
out.enabled = config.enabled
|
|
60
77
|
out.service = config.service
|
|
61
78
|
out.agent_url = url
|
|
62
|
-
if (agentError) {
|
|
63
|
-
out.agent_error = agentError.message
|
|
64
|
-
}
|
|
65
79
|
out.debug = !!config.debug
|
|
66
80
|
out.sample_rate = config.sampler.sampleRate
|
|
67
81
|
out.sampling_rules = samplingRules
|
|
@@ -87,18 +101,7 @@ function startupLog ({ agentError } = {}) {
|
|
|
87
101
|
// out.service_mapping
|
|
88
102
|
// out.service_mapping_error
|
|
89
103
|
|
|
90
|
-
|
|
91
|
-
if (agentError) {
|
|
92
|
-
warn('DATADOG TRACER DIAGNOSTIC - Agent Error: ' + agentError.message)
|
|
93
|
-
errors.agentError = {
|
|
94
|
-
code: agentError.code ? agentError.code : '',
|
|
95
|
-
message: `Agent Error:${agentError.message}`
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
config = undefined
|
|
100
|
-
pluginManager = undefined
|
|
101
|
-
samplingRules = undefined
|
|
104
|
+
return out
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
function setStartupLogConfig (aConfig) {
|
|
@@ -118,5 +121,6 @@ module.exports = {
|
|
|
118
121
|
setStartupLogConfig,
|
|
119
122
|
setStartupLogPluginManager,
|
|
120
123
|
setSamplingRules,
|
|
124
|
+
tracerInfo,
|
|
121
125
|
errors
|
|
122
126
|
}
|
|
@@ -313,7 +313,8 @@ function updateConfig (changes, config) {
|
|
|
313
313
|
sampleRate: 'DD_TRACE_SAMPLE_RATE',
|
|
314
314
|
logInjection: 'DD_LOG_INJECTION',
|
|
315
315
|
headerTags: 'DD_TRACE_HEADER_TAGS',
|
|
316
|
-
tags: 'DD_TAGS'
|
|
316
|
+
tags: 'DD_TAGS',
|
|
317
|
+
'sampler.rules': 'DD_TRACE_SAMPLING_RULES'
|
|
317
318
|
}
|
|
318
319
|
|
|
319
320
|
const namesNeedFormatting = new Set(['DD_TAGS', 'peerServiceMapping'])
|
|
@@ -328,9 +329,12 @@ function updateConfig (changes, config) {
|
|
|
328
329
|
const { origin, value } = change
|
|
329
330
|
const entry = { name, value, origin }
|
|
330
331
|
|
|
331
|
-
if (Array.isArray(value)) entry.value = value.join(',')
|
|
332
332
|
if (namesNeedFormatting.has(entry.name)) entry.value = formatMapForTelemetry(entry.value)
|
|
333
333
|
if (entry.name === 'url' && entry.value) entry.value = entry.value.toString()
|
|
334
|
+
if (entry.name === 'DD_TRACE_SAMPLING_RULES') {
|
|
335
|
+
entry.value = JSON.stringify(entry.value)
|
|
336
|
+
}
|
|
337
|
+
if (Array.isArray(entry.value)) entry.value = value.join(',')
|
|
334
338
|
|
|
335
339
|
configuration.push(entry)
|
|
336
340
|
}
|
|
@@ -11,6 +11,8 @@ const { DataStreamsProcessor } = require('./datastreams/processor')
|
|
|
11
11
|
const { DsmPathwayCodec } = require('./datastreams/pathway')
|
|
12
12
|
const { DD_MAJOR } = require('../../../version')
|
|
13
13
|
const DataStreamsContext = require('./data_streams_context')
|
|
14
|
+
const { flushStartupLogs } = require('../../datadog-instrumentations/src/check_require_cache')
|
|
15
|
+
const log = require('./log/writer')
|
|
14
16
|
|
|
15
17
|
const SPAN_TYPE = tags.SPAN_TYPE
|
|
16
18
|
const RESOURCE_NAME = tags.RESOURCE_NAME
|
|
@@ -23,6 +25,7 @@ class DatadogTracer extends Tracer {
|
|
|
23
25
|
this._dataStreamsProcessor = new DataStreamsProcessor(config)
|
|
24
26
|
this._scope = new Scope()
|
|
25
27
|
setStartupLogConfig(config)
|
|
28
|
+
flushStartupLogs(log)
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
configure ({ env, sampler }) {
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const semver = require('semver')
|
|
4
|
-
|
|
5
|
-
if (semver.satisfies(process.version, '>=14.18.0')) {
|
|
6
|
-
const net = require('net')
|
|
7
|
-
|
|
8
|
-
module.exports = net.BlockList
|
|
9
|
-
} else {
|
|
10
|
-
const ipaddr = require('ipaddr.js')
|
|
11
|
-
|
|
12
|
-
module.exports = class BlockList {
|
|
13
|
-
constructor () {
|
|
14
|
-
this.v4Ranges = []
|
|
15
|
-
this.v6Ranges = []
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
addSubnet (net, prefix, type) {
|
|
19
|
-
this[type === 'ipv4' ? 'v4Ranges' : 'v6Ranges'].push(ipaddr.parseCIDR(`${net}/${prefix}`))
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
check (address, type) {
|
|
23
|
-
try {
|
|
24
|
-
let ip = ipaddr.parse(address)
|
|
25
|
-
|
|
26
|
-
type = ip.kind()
|
|
27
|
-
|
|
28
|
-
if (type === 'ipv6') {
|
|
29
|
-
for (const range of this.v6Ranges) {
|
|
30
|
-
if (ip.match(range)) return true
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (ip.isIPv4MappedAddress()) {
|
|
34
|
-
ip = ip.toIPv4Address()
|
|
35
|
-
type = ip.kind()
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (type === 'ipv4') {
|
|
40
|
-
for (const range of this.v4Ranges) {
|
|
41
|
-
if (ip.match(range)) return true
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return false
|
|
46
|
-
} catch {
|
|
47
|
-
return false
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|