dd-trace 2.44.0 → 2.45.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/package.json +1 -1
- package/packages/datadog-instrumentations/src/http2/client.js +2 -0
- package/packages/datadog-plugin-http/src/client.js +7 -6
- package/packages/datadog-plugin-pg/src/index.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +2 -0
- package/packages/dd-trace/src/appsec/remote_config/manager.js +9 -4
- package/packages/dd-trace/src/config.js +138 -16
- package/packages/dd-trace/src/noop/tracer.js +2 -0
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/database.js +12 -0
- package/packages/dd-trace/src/plugins/util/web.js +6 -4
- package/packages/dd-trace/src/priority_sampler.js +6 -3
- package/packages/dd-trace/src/proxy.js +18 -3
- package/packages/dd-trace/src/startup-log.js +1 -1
- package/packages/dd-trace/src/telemetry/index.js +31 -3
- package/packages/dd-trace/src/tracer.js +4 -0
package/package.json
CHANGED
|
@@ -30,6 +30,8 @@ function createWrapEmit (ctx) {
|
|
|
30
30
|
function createWrapRequest (authority, options) {
|
|
31
31
|
return function wrapRequest (request) {
|
|
32
32
|
return function (headers) {
|
|
33
|
+
if (!startChannel.hasSubscribers) return request.apply(this, arguments)
|
|
34
|
+
|
|
33
35
|
const ctx = { headers, authority, options }
|
|
34
36
|
|
|
35
37
|
return startChannel.runStores(ctx, () => {
|
|
@@ -121,11 +121,11 @@ function addResponseHeaders (res, span, config) {
|
|
|
121
121
|
? Object.fromEntries(res.headers.entries())
|
|
122
122
|
: res.headers
|
|
123
123
|
|
|
124
|
-
config.headers.forEach(key => {
|
|
124
|
+
config.headers.forEach(([key, tag]) => {
|
|
125
125
|
const value = headers[key]
|
|
126
126
|
|
|
127
127
|
if (value) {
|
|
128
|
-
span.setTag(`${HTTP_RESPONSE_HEADERS}.${key}`, value)
|
|
128
|
+
span.setTag(tag || `${HTTP_RESPONSE_HEADERS}.${key}`, value)
|
|
129
129
|
}
|
|
130
130
|
})
|
|
131
131
|
}
|
|
@@ -135,11 +135,11 @@ function addRequestHeaders (req, span, config) {
|
|
|
135
135
|
? Object.fromEntries(req.headers.entries())
|
|
136
136
|
: req.headers || req.getHeaders()
|
|
137
137
|
|
|
138
|
-
config.headers.forEach(key => {
|
|
139
|
-
const value = headers[key]
|
|
138
|
+
config.headers.forEach(([key, tag]) => {
|
|
139
|
+
const value = Array.isArray(headers[key]) ? headers[key].toString() : headers[key]
|
|
140
140
|
|
|
141
141
|
if (value) {
|
|
142
|
-
span.setTag(`${HTTP_REQUEST_HEADERS}.${key}`,
|
|
142
|
+
span.setTag(tag || `${HTTP_REQUEST_HEADERS}.${key}`, value)
|
|
143
143
|
}
|
|
144
144
|
})
|
|
145
145
|
}
|
|
@@ -182,7 +182,8 @@ function getHeaders (config) {
|
|
|
182
182
|
|
|
183
183
|
return config.headers
|
|
184
184
|
.filter(key => typeof key === 'string')
|
|
185
|
-
.map(
|
|
185
|
+
.map(h => h.split(':'))
|
|
186
|
+
.map(([key, tag]) => [key.toLowerCase(), tag])
|
|
186
187
|
}
|
|
187
188
|
|
|
188
189
|
function getHooks (config) {
|
|
@@ -10,7 +10,7 @@ class PGPlugin extends DatabasePlugin {
|
|
|
10
10
|
|
|
11
11
|
start ({ params = {}, query, processId }) {
|
|
12
12
|
const service = this.serviceName({ pluginConfig: this.config, params })
|
|
13
|
-
const originalStatement = query.text
|
|
13
|
+
const originalStatement = this.maybeTruncate(query.text)
|
|
14
14
|
|
|
15
15
|
this.startSpan(this.operationName(), {
|
|
16
16
|
service,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { URL, format } = require('url')
|
|
3
4
|
const uuid = require('crypto-randomuuid')
|
|
4
5
|
const { EventEmitter } = require('events')
|
|
5
6
|
const Scheduler = require('./scheduler')
|
|
@@ -22,13 +23,17 @@ class RemoteConfigManager extends EventEmitter {
|
|
|
22
23
|
constructor (config) {
|
|
23
24
|
super()
|
|
24
25
|
|
|
25
|
-
const pollInterval = config.remoteConfig.pollInterval * 1000
|
|
26
|
+
const pollInterval = Math.floor(config.remoteConfig.pollInterval * 1000)
|
|
27
|
+
const url = config.url || new URL(format({
|
|
28
|
+
protocol: 'http:',
|
|
29
|
+
hostname: config.hostname || 'localhost',
|
|
30
|
+
port: config.port
|
|
31
|
+
}))
|
|
32
|
+
|
|
26
33
|
this.scheduler = new Scheduler((cb) => this.poll(cb), pollInterval)
|
|
27
34
|
|
|
28
35
|
this.requestOptions = {
|
|
29
|
-
url
|
|
30
|
-
hostname: config.hostname,
|
|
31
|
-
port: config.port,
|
|
36
|
+
url,
|
|
32
37
|
method: 'POST',
|
|
33
38
|
path: '/v0.7/config'
|
|
34
39
|
}
|
|
@@ -11,6 +11,7 @@ const tagger = require('./tagger')
|
|
|
11
11
|
const { isTrue, isFalse } = require('./util')
|
|
12
12
|
const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('./plugins/util/tags')
|
|
13
13
|
const { getGitMetadataFromGitProperties } = require('./git_properties')
|
|
14
|
+
const { updateConfig } = require('./telemetry')
|
|
14
15
|
const { getIsGCPFunction, getIsAzureFunctionConsumptionPlan } = require('./serverless')
|
|
15
16
|
|
|
16
17
|
const fromEntries = Object.fromEntries || (entries =>
|
|
@@ -127,11 +128,6 @@ class Config {
|
|
|
127
128
|
'agent'
|
|
128
129
|
)
|
|
129
130
|
const DD_PROFILING_SOURCE_MAP = process.env.DD_PROFILING_SOURCE_MAP
|
|
130
|
-
const DD_LOGS_INJECTION = coalesce(
|
|
131
|
-
options.logInjection,
|
|
132
|
-
process.env.DD_LOGS_INJECTION,
|
|
133
|
-
false
|
|
134
|
-
)
|
|
135
131
|
const DD_RUNTIME_METRICS_ENABLED = coalesce(
|
|
136
132
|
options.runtimeMetrics, // TODO: remove when enabled by default
|
|
137
133
|
process.env.DD_RUNTIME_METRICS_ENABLED,
|
|
@@ -236,7 +232,7 @@ class Config {
|
|
|
236
232
|
!inServerlessEnvironment
|
|
237
233
|
)
|
|
238
234
|
const DD_TELEMETRY_HEARTBEAT_INTERVAL = process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL
|
|
239
|
-
?
|
|
235
|
+
? Math.floor(parseFloat(process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL) * 1000)
|
|
240
236
|
: 60000
|
|
241
237
|
const DD_OPENAI_SPAN_CHAR_LIMIT = process.env.DD_OPENAI_SPAN_CHAR_LIMIT
|
|
242
238
|
? parseInt(process.env.DD_OPENAI_SPAN_CHAR_LIMIT)
|
|
@@ -438,8 +434,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
438
434
|
!inServerlessEnvironment
|
|
439
435
|
)
|
|
440
436
|
const DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS = coalesce(
|
|
441
|
-
|
|
442
|
-
|
|
437
|
+
parseFloat(remoteConfigOptions.pollInterval),
|
|
438
|
+
parseFloat(process.env.DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS),
|
|
443
439
|
5 // seconds
|
|
444
440
|
)
|
|
445
441
|
|
|
@@ -507,11 +503,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
507
503
|
const ingestion = options.ingestion || {}
|
|
508
504
|
const dogstatsd = coalesce(options.dogstatsd, {})
|
|
509
505
|
const sampler = {
|
|
510
|
-
sampleRate: coalesce(
|
|
511
|
-
options.sampleRate,
|
|
512
|
-
process.env.DD_TRACE_SAMPLE_RATE,
|
|
513
|
-
ingestion.sampleRate
|
|
514
|
-
),
|
|
515
506
|
rateLimit: coalesce(options.rateLimit, process.env.DD_TRACE_RATE_LIMIT, ingestion.rateLimit),
|
|
516
507
|
rules: coalesce(
|
|
517
508
|
options.samplingRules,
|
|
@@ -535,14 +526,13 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
535
526
|
})
|
|
536
527
|
}
|
|
537
528
|
|
|
538
|
-
const defaultFlushInterval =
|
|
529
|
+
const defaultFlushInterval = inAWSLambda ? 0 : 2000
|
|
539
530
|
|
|
540
531
|
this.tracing = !isFalse(DD_TRACING_ENABLED)
|
|
541
532
|
this.dbmPropagationMode = DD_DBM_PROPAGATION_MODE
|
|
542
533
|
this.dsmEnabled = isTrue(DD_DATA_STREAMS_ENABLED)
|
|
543
534
|
this.openAiLogsEnabled = DD_OPENAI_LOGS_ENABLED
|
|
544
535
|
this.apiKey = DD_API_KEY
|
|
545
|
-
this.logInjection = isTrue(DD_LOGS_INJECTION)
|
|
546
536
|
this.env = DD_ENV
|
|
547
537
|
this.url = DD_CIVISIBILITY_AGENTLESS_URL ? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
|
|
548
538
|
: getAgentUrl(DD_TRACE_AGENT_URL, options)
|
|
@@ -551,7 +541,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
551
541
|
this.port = String(DD_TRACE_AGENT_PORT || (this.url && this.url.port))
|
|
552
542
|
this.flushInterval = coalesce(parseInt(options.flushInterval, 10), defaultFlushInterval)
|
|
553
543
|
this.flushMinSpans = DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
|
|
554
|
-
this.sampleRate = coalesce(Math.min(Math.max(sampler.sampleRate, 0), 1), 1)
|
|
555
544
|
this.queryStringObfuscation = DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP
|
|
556
545
|
this.clientIpEnabled = DD_TRACE_CLIENT_IP_ENABLED
|
|
557
546
|
this.clientIpHeader = DD_TRACE_CLIENT_IP_HEADER
|
|
@@ -684,6 +673,139 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
684
673
|
version: this.version,
|
|
685
674
|
'runtime-id': uuid()
|
|
686
675
|
})
|
|
676
|
+
|
|
677
|
+
this._applyDefaults()
|
|
678
|
+
this._applyEnvironment()
|
|
679
|
+
this._applyOptions(options)
|
|
680
|
+
this._applyRemote({})
|
|
681
|
+
this._merge()
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Supports only a subset of options for now.
|
|
685
|
+
configure (options, remote) {
|
|
686
|
+
if (remote) {
|
|
687
|
+
this._applyRemote(options)
|
|
688
|
+
} else {
|
|
689
|
+
this._applyOptions(options)
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
this._merge()
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
_applyDefaults () {
|
|
696
|
+
const defaults = this._defaults = {}
|
|
697
|
+
|
|
698
|
+
this._setUnit(defaults, 'sampleRate', undefined)
|
|
699
|
+
this._setBoolean(defaults, 'logInjection', false)
|
|
700
|
+
this._setArray(defaults, 'headerTags', [])
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
_applyEnvironment () {
|
|
704
|
+
const {
|
|
705
|
+
DD_TRACE_SAMPLE_RATE,
|
|
706
|
+
DD_LOGS_INJECTION,
|
|
707
|
+
DD_TRACE_HEADER_TAGS
|
|
708
|
+
} = process.env
|
|
709
|
+
|
|
710
|
+
const env = this._env = {}
|
|
711
|
+
|
|
712
|
+
this._setUnit(env, 'sampleRate', DD_TRACE_SAMPLE_RATE)
|
|
713
|
+
this._setBoolean(env, 'logInjection', DD_LOGS_INJECTION)
|
|
714
|
+
this._setArray(env, 'headerTags', DD_TRACE_HEADER_TAGS)
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
_applyOptions (options) {
|
|
718
|
+
const opts = this._options = this._options || {}
|
|
719
|
+
|
|
720
|
+
options = Object.assign({ ingestion: {} }, options, opts)
|
|
721
|
+
|
|
722
|
+
this._setUnit(opts, 'sampleRate', coalesce(options.sampleRate, options.ingestion.sampleRate))
|
|
723
|
+
this._setBoolean(opts, 'logInjection', options.logInjection)
|
|
724
|
+
this._setArray(opts, 'headerTags', options.headerTags)
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
_applyRemote (options) {
|
|
728
|
+
const opts = this._remote = this._remote || {}
|
|
729
|
+
const headerTags = options.tracing_header_tags
|
|
730
|
+
? options.tracing_header_tags.map(tag => {
|
|
731
|
+
return tag.tag_name ? `${tag.header}:${tag.tag_name}` : tag.header
|
|
732
|
+
})
|
|
733
|
+
: undefined
|
|
734
|
+
|
|
735
|
+
this._setUnit(opts, 'sampleRate', options.tracing_sampling_rate)
|
|
736
|
+
this._setBoolean(opts, 'logInjection', options.log_injection_enabled)
|
|
737
|
+
this._setArray(opts, 'headerTags', headerTags)
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
_setBoolean (obj, name, value) {
|
|
741
|
+
if (value === undefined || value === null) {
|
|
742
|
+
this._setValue(obj, name, value)
|
|
743
|
+
} else if (isTrue(value)) {
|
|
744
|
+
this._setValue(obj, name, true)
|
|
745
|
+
} else if (isFalse(value)) {
|
|
746
|
+
this._setValue(obj, name, false)
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
_setUnit (obj, name, value) {
|
|
751
|
+
if (value === null || value === undefined) {
|
|
752
|
+
return this._setValue(obj, name, value)
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
value = parseFloat(value)
|
|
756
|
+
|
|
757
|
+
if (!isNaN(value)) {
|
|
758
|
+
// TODO: Ignore out of range values instead of normalizing them.
|
|
759
|
+
this._setValue(obj, name, Math.min(Math.max(value, 0), 1))
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
_setArray (obj, name, value) {
|
|
764
|
+
if (value === null || value === undefined) {
|
|
765
|
+
return this._setValue(obj, name, null)
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
if (typeof value === 'string') {
|
|
769
|
+
value = value && value.split(',')
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
if (Array.isArray(value)) {
|
|
773
|
+
this._setValue(obj, name, value)
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
_setValue (obj, name, value) {
|
|
778
|
+
obj[name] = value
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// TODO: Report origin changes and errors to telemetry.
|
|
782
|
+
// TODO: Deeply merge configurations.
|
|
783
|
+
// TODO: Move change tracking to telemetry.
|
|
784
|
+
_merge () {
|
|
785
|
+
const containers = [this._remote, this._options, this._env, this._defaults]
|
|
786
|
+
const origins = ['remote_config', 'code', 'env_var', 'default']
|
|
787
|
+
const changes = []
|
|
788
|
+
|
|
789
|
+
for (const name in this._defaults) {
|
|
790
|
+
for (let i = 0; i < containers.length; i++) {
|
|
791
|
+
const container = containers[i]
|
|
792
|
+
const origin = origins[i]
|
|
793
|
+
|
|
794
|
+
if ((container[name] !== null && container[name] !== undefined) || container === this._defaults) {
|
|
795
|
+
if (this[name] === container[name] && this.hasOwnProperty(name)) break
|
|
796
|
+
|
|
797
|
+
const value = this[name] = container[name]
|
|
798
|
+
|
|
799
|
+
changes.push({ name, value, origin })
|
|
800
|
+
|
|
801
|
+
break
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
this.sampler.sampleRate = this.sampleRate
|
|
807
|
+
|
|
808
|
+
updateConfig(changes, this)
|
|
687
809
|
}
|
|
688
810
|
}
|
|
689
811
|
|
|
@@ -134,6 +134,7 @@ module.exports = class PluginManager {
|
|
|
134
134
|
queryStringObfuscation,
|
|
135
135
|
site,
|
|
136
136
|
url,
|
|
137
|
+
headerTags,
|
|
137
138
|
dbmPropagationMode,
|
|
138
139
|
dsmEnabled,
|
|
139
140
|
clientIpEnabled
|
|
@@ -162,6 +163,7 @@ module.exports = class PluginManager {
|
|
|
162
163
|
|
|
163
164
|
sharedConfig.site = site
|
|
164
165
|
sharedConfig.url = url
|
|
166
|
+
sharedConfig.headers = headerTags || []
|
|
165
167
|
|
|
166
168
|
return sharedConfig
|
|
167
169
|
}
|
|
@@ -55,6 +55,18 @@ class DatabasePlugin extends StoragePlugin {
|
|
|
55
55
|
return `/*${servicePropagation},traceparent='${traceparent}'*/ ${query}`
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
maybeTruncate (query) {
|
|
60
|
+
const maxLength = typeof this.config.truncate === 'number'
|
|
61
|
+
? this.config.truncate
|
|
62
|
+
: 5000 // same as what the agent does
|
|
63
|
+
|
|
64
|
+
if (this.config.truncate && query && query.length > maxLength) {
|
|
65
|
+
query = `${query.slice(0, maxLength - 3)}...`
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return query
|
|
69
|
+
}
|
|
58
70
|
}
|
|
59
71
|
|
|
60
72
|
module.exports = DatabasePlugin
|
|
@@ -477,16 +477,16 @@ function addResourceTag (context) {
|
|
|
477
477
|
function addHeaders (context) {
|
|
478
478
|
const { req, res, config, span } = context
|
|
479
479
|
|
|
480
|
-
config.headers.forEach(key => {
|
|
480
|
+
config.headers.forEach(([key, tag]) => {
|
|
481
481
|
const reqHeader = req.headers[key]
|
|
482
482
|
const resHeader = res.getHeader(key)
|
|
483
483
|
|
|
484
484
|
if (reqHeader) {
|
|
485
|
-
span.setTag(`${HTTP_REQUEST_HEADERS}.${key}`, reqHeader)
|
|
485
|
+
span.setTag(tag || `${HTTP_REQUEST_HEADERS}.${key}`, reqHeader)
|
|
486
486
|
}
|
|
487
487
|
|
|
488
488
|
if (resHeader) {
|
|
489
|
-
span.setTag(`${HTTP_RESPONSE_HEADERS}.${key}`, resHeader)
|
|
489
|
+
span.setTag(tag || `${HTTP_RESPONSE_HEADERS}.${key}`, resHeader)
|
|
490
490
|
}
|
|
491
491
|
})
|
|
492
492
|
}
|
|
@@ -512,7 +512,9 @@ function getProtocol (req) {
|
|
|
512
512
|
function getHeadersToRecord (config) {
|
|
513
513
|
if (Array.isArray(config.headers)) {
|
|
514
514
|
try {
|
|
515
|
-
return config.headers
|
|
515
|
+
return config.headers
|
|
516
|
+
.map(h => h.split(':'))
|
|
517
|
+
.map(([key, tag]) => [key.toLowerCase(), tag])
|
|
516
518
|
} catch (err) {
|
|
517
519
|
log.error(err)
|
|
518
520
|
}
|
|
@@ -29,14 +29,17 @@ const DEFAULT_KEY = 'service:,env:'
|
|
|
29
29
|
const defaultSampler = new Sampler(AUTO_KEEP)
|
|
30
30
|
|
|
31
31
|
class PrioritySampler {
|
|
32
|
-
constructor (env,
|
|
32
|
+
constructor (env, config) {
|
|
33
|
+
this.configure(env, config)
|
|
34
|
+
this.update({})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
configure (env, { sampleRate, rateLimit = 100, rules = [] } = {}) {
|
|
33
38
|
this._env = env
|
|
34
39
|
this._rules = this._normalizeRules(rules, sampleRate)
|
|
35
40
|
this._limiter = new RateLimiter(rateLimit)
|
|
36
41
|
|
|
37
42
|
setSamplingRules(this._rules)
|
|
38
|
-
|
|
39
|
-
this.update({})
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
isSampled (span) {
|
|
@@ -24,10 +24,23 @@ class Tracer extends NoopProxy {
|
|
|
24
24
|
this._initialized = true
|
|
25
25
|
|
|
26
26
|
try {
|
|
27
|
-
const config = new Config(options) // TODO: support dynamic config
|
|
27
|
+
const config = new Config(options) // TODO: support dynamic code config
|
|
28
28
|
|
|
29
29
|
if (config.remoteConfig.enabled && !config.isCiVisibility) {
|
|
30
|
-
remoteConfig.enable(config)
|
|
30
|
+
const rc = remoteConfig.enable(config)
|
|
31
|
+
|
|
32
|
+
rc.on('APM_TRACING', (action, conf) => {
|
|
33
|
+
if (action === 'unapply') {
|
|
34
|
+
config.configure({}, true)
|
|
35
|
+
} else {
|
|
36
|
+
config.configure(conf.lib_config, true)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (config.tracing) {
|
|
40
|
+
this._tracer.configure(config)
|
|
41
|
+
this._pluginManager.configure(config)
|
|
42
|
+
}
|
|
43
|
+
})
|
|
31
44
|
}
|
|
32
45
|
|
|
33
46
|
if (config.isGCPFunction || config.isAzureFunctionConsumptionPlan) {
|
|
@@ -49,6 +62,9 @@ class Tracer extends NoopProxy {
|
|
|
49
62
|
}
|
|
50
63
|
|
|
51
64
|
if (config.tracing) {
|
|
65
|
+
// TODO: This should probably not require tracing to be enabled.
|
|
66
|
+
telemetry.start(config, this._pluginManager)
|
|
67
|
+
|
|
52
68
|
// dirty require for now so zero appsec code is executed unless explicitly enabled
|
|
53
69
|
if (config.appsec.enabled) {
|
|
54
70
|
require('./appsec').enable(config)
|
|
@@ -63,7 +79,6 @@ class Tracer extends NoopProxy {
|
|
|
63
79
|
|
|
64
80
|
this._pluginManager.configure(config)
|
|
65
81
|
setStartupLogPluginManager(this._pluginManager)
|
|
66
|
-
telemetry.start(config, this._pluginManager)
|
|
67
82
|
|
|
68
83
|
if (config.isManualApiEnabled) {
|
|
69
84
|
const TestApiManualPlugin = require('./ci-visibility/test-api-manual/test-api-manual-plugin')
|
|
@@ -62,7 +62,7 @@ function startupLog ({ agentError } = {}) {
|
|
|
62
62
|
out.agent_error = agentError.message
|
|
63
63
|
}
|
|
64
64
|
out.debug = !!config.debug
|
|
65
|
-
out.sample_rate = config.sampleRate
|
|
65
|
+
out.sample_rate = config.sampler.sampleRate
|
|
66
66
|
out.sampling_rules = samplingRules
|
|
67
67
|
out.tags = config.tags
|
|
68
68
|
if (config.tags && config.tags.version) {
|
|
@@ -66,7 +66,7 @@ function onBeforeExit () {
|
|
|
66
66
|
sendData(config, application, host, 'app-closing')
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
function createAppObject () {
|
|
69
|
+
function createAppObject (config) {
|
|
70
70
|
return {
|
|
71
71
|
service_name: config.service,
|
|
72
72
|
env: config.env,
|
|
@@ -116,7 +116,7 @@ function start (aConfig, thePluginManager) {
|
|
|
116
116
|
}
|
|
117
117
|
config = aConfig
|
|
118
118
|
pluginManager = thePluginManager
|
|
119
|
-
application = createAppObject()
|
|
119
|
+
application = createAppObject(config)
|
|
120
120
|
host = createHostObject()
|
|
121
121
|
heartbeatInterval = config.telemetry.heartbeatInterval
|
|
122
122
|
|
|
@@ -155,8 +155,36 @@ function updateIntegrations () {
|
|
|
155
155
|
sendData(config, application, host, 'app-integrations-change', { integrations })
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
function updateConfig (changes, config) {
|
|
159
|
+
if (!config.telemetry.enabled) return
|
|
160
|
+
if (changes.length === 0) return
|
|
161
|
+
|
|
162
|
+
// Hack to make system tests happy until we ship telemetry v2
|
|
163
|
+
if (process.env.DD_INTERNAL_TELEMETRY_V2_ENABLED !== '1') return
|
|
164
|
+
|
|
165
|
+
const application = createAppObject(config)
|
|
166
|
+
const host = createHostObject()
|
|
167
|
+
|
|
168
|
+
const names = {
|
|
169
|
+
sampleRate: 'DD_TRACE_SAMPLE_RATE',
|
|
170
|
+
logInjection: 'DD_LOG_INJECTION',
|
|
171
|
+
headerTags: 'DD_TRACE_HEADER_TAGS'
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const configuration = changes.map(change => ({
|
|
175
|
+
name: names[change.name],
|
|
176
|
+
value: Array.isArray(change.value) ? change.value.join(',') : change.value,
|
|
177
|
+
origin: change.origin
|
|
178
|
+
}))
|
|
179
|
+
|
|
180
|
+
sendData(config, application, host, 'app-client-configuration-change', {
|
|
181
|
+
configuration
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
158
185
|
module.exports = {
|
|
159
186
|
start,
|
|
160
187
|
stop,
|
|
161
|
-
updateIntegrations
|
|
188
|
+
updateIntegrations,
|
|
189
|
+
updateConfig
|
|
162
190
|
}
|
|
@@ -25,6 +25,10 @@ class DatadogTracer extends Tracer {
|
|
|
25
25
|
setStartupLogConfig(config)
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
configure ({ env, sampler }) {
|
|
29
|
+
this._prioritySampler.configure(env, sampler)
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
// todo[piochelepiotr] These two methods are not related to the tracer, but to data streams monitoring.
|
|
29
33
|
// They should be moved outside of the tracer in the future.
|
|
30
34
|
setCheckpoint (edgeTags) {
|