dd-trace 4.9.0 → 4.11.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/CONTRIBUTING.md +66 -0
- package/package.json +1 -1
- package/packages/datadog-instrumentations/src/couchbase.js +41 -5
- package/packages/datadog-instrumentations/src/http2/client.js +2 -0
- package/packages/datadog-plugin-aws-sdk/src/base.js +22 -10
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +16 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +18 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +23 -0
- package/packages/datadog-plugin-cassandra-driver/src/index.js +1 -1
- package/packages/datadog-plugin-couchbase/src/index.js +32 -30
- package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
- package/packages/datadog-plugin-http/src/client.js +14 -23
- package/packages/datadog-plugin-http/src/server.js +10 -2
- package/packages/datadog-plugin-http2/src/client.js +2 -16
- package/packages/datadog-plugin-http2/src/server.js +10 -1
- package/packages/datadog-plugin-memcached/src/index.js +1 -1
- package/packages/datadog-plugin-mongodb-core/src/index.js +1 -1
- package/packages/datadog-plugin-mysql/src/index.js +1 -1
- package/packages/datadog-plugin-next/src/index.js +2 -2
- package/packages/datadog-plugin-oracledb/src/index.js +1 -1
- package/packages/datadog-plugin-pg/src/index.js +2 -2
- package/packages/datadog-plugin-redis/src/index.js +1 -1
- package/packages/datadog-plugin-tedious/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/tracing.js +16 -9
- 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/service-naming/index.js +7 -11
- package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -4
- package/packages/dd-trace/src/service-naming/schemas/util.js +21 -3
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +20 -8
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +33 -23
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +33 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +14 -2
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +12 -9
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +33 -1
- 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
|
@@ -19,11 +19,11 @@ class NextPlugin extends ServerPlugin {
|
|
|
19
19
|
start ({ req, res }) {
|
|
20
20
|
const store = storage.getStore()
|
|
21
21
|
const childOf = store ? store.span : store
|
|
22
|
-
const span = this.tracer.startSpan(
|
|
22
|
+
const span = this.tracer.startSpan(this.operationName(), {
|
|
23
23
|
childOf,
|
|
24
24
|
tags: {
|
|
25
25
|
[COMPONENT]: this.constructor.id,
|
|
26
|
-
'service.name': this.config.service || this.
|
|
26
|
+
'service.name': this.config.service || this.serviceName(),
|
|
27
27
|
'resource.name': req.method,
|
|
28
28
|
'span.type': 'web',
|
|
29
29
|
'span.kind': 'server',
|
|
@@ -10,7 +10,7 @@ class OracledbPlugin extends DatabasePlugin {
|
|
|
10
10
|
static get peerServicePrecursors () { return ['db.instance', 'db.hostname'] }
|
|
11
11
|
|
|
12
12
|
start ({ query, connAttrs }) {
|
|
13
|
-
const service = this.serviceName(this.config, connAttrs)
|
|
13
|
+
const service = this.serviceName({ pluginConfig: this.config, params: connAttrs })
|
|
14
14
|
const url = getUrl(connAttrs.connectString)
|
|
15
15
|
|
|
16
16
|
this.startSpan(this.operationName(), {
|
|
@@ -9,8 +9,8 @@ class PGPlugin extends DatabasePlugin {
|
|
|
9
9
|
static get system () { return 'postgres' }
|
|
10
10
|
|
|
11
11
|
start ({ params = {}, query, processId }) {
|
|
12
|
-
const service = this.serviceName(this.config, params)
|
|
13
|
-
const originalStatement = query.text
|
|
12
|
+
const service = this.serviceName({ pluginConfig: this.config, params })
|
|
13
|
+
const originalStatement = this.maybeTruncate(query.text)
|
|
14
14
|
|
|
15
15
|
this.startSpan(this.operationName(), {
|
|
16
16
|
service,
|
|
@@ -15,7 +15,7 @@ class RedisPlugin extends CachePlugin {
|
|
|
15
15
|
|
|
16
16
|
this.startSpan({
|
|
17
17
|
resource,
|
|
18
|
-
service: this.serviceName(this.config, this.system, connectionName),
|
|
18
|
+
service: this.serviceName({ pluginConfig: this.config, system: this.system, connectionName }),
|
|
19
19
|
type: 'redis',
|
|
20
20
|
meta: {
|
|
21
21
|
'db.type': 'redis',
|
|
@@ -10,7 +10,7 @@ class TediousPlugin extends DatabasePlugin {
|
|
|
10
10
|
|
|
11
11
|
start ({ queryOrProcedure, connectionConfig }) {
|
|
12
12
|
this.startSpan(this.operationName(), {
|
|
13
|
-
service: this.serviceName(this.config, this.system),
|
|
13
|
+
service: this.serviceName({ pluginConfig: this.config, system: this.system }),
|
|
14
14
|
resource: queryOrProcedure,
|
|
15
15
|
type: 'sql',
|
|
16
16
|
kind: 'client',
|
|
@@ -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 =>
|
|
@@ -130,11 +131,6 @@ class Config {
|
|
|
130
131
|
'agent'
|
|
131
132
|
)
|
|
132
133
|
const DD_PROFILING_SOURCE_MAP = process.env.DD_PROFILING_SOURCE_MAP
|
|
133
|
-
const DD_LOGS_INJECTION = coalesce(
|
|
134
|
-
options.logInjection,
|
|
135
|
-
process.env.DD_LOGS_INJECTION,
|
|
136
|
-
false
|
|
137
|
-
)
|
|
138
134
|
const DD_RUNTIME_METRICS_ENABLED = coalesce(
|
|
139
135
|
options.runtimeMetrics, // TODO: remove when enabled by default
|
|
140
136
|
process.env.DD_RUNTIME_METRICS_ENABLED,
|
|
@@ -239,7 +235,7 @@ class Config {
|
|
|
239
235
|
!inServerlessEnvironment
|
|
240
236
|
)
|
|
241
237
|
const DD_TELEMETRY_HEARTBEAT_INTERVAL = process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL
|
|
242
|
-
?
|
|
238
|
+
? Math.floor(parseFloat(process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL) * 1000)
|
|
243
239
|
: 60000
|
|
244
240
|
const DD_OPENAI_SPAN_CHAR_LIMIT = process.env.DD_OPENAI_SPAN_CHAR_LIMIT
|
|
245
241
|
? parseInt(process.env.DD_OPENAI_SPAN_CHAR_LIMIT)
|
|
@@ -441,8 +437,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
441
437
|
!inServerlessEnvironment
|
|
442
438
|
)
|
|
443
439
|
const DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS = coalesce(
|
|
444
|
-
|
|
445
|
-
|
|
440
|
+
parseFloat(remoteConfigOptions.pollInterval),
|
|
441
|
+
parseFloat(process.env.DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS),
|
|
446
442
|
5 // seconds
|
|
447
443
|
)
|
|
448
444
|
|
|
@@ -510,11 +506,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
510
506
|
const ingestion = options.ingestion || {}
|
|
511
507
|
const dogstatsd = coalesce(options.dogstatsd, {})
|
|
512
508
|
const sampler = {
|
|
513
|
-
sampleRate: coalesce(
|
|
514
|
-
options.sampleRate,
|
|
515
|
-
process.env.DD_TRACE_SAMPLE_RATE,
|
|
516
|
-
ingestion.sampleRate
|
|
517
|
-
),
|
|
518
509
|
rateLimit: coalesce(options.rateLimit, process.env.DD_TRACE_RATE_LIMIT, ingestion.rateLimit),
|
|
519
510
|
rules: coalesce(
|
|
520
511
|
options.samplingRules,
|
|
@@ -538,14 +529,13 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
538
529
|
})
|
|
539
530
|
}
|
|
540
531
|
|
|
541
|
-
const defaultFlushInterval =
|
|
532
|
+
const defaultFlushInterval = inAWSLambda ? 0 : 2000
|
|
542
533
|
|
|
543
534
|
this.tracing = !isFalse(DD_TRACING_ENABLED)
|
|
544
535
|
this.dbmPropagationMode = DD_DBM_PROPAGATION_MODE
|
|
545
536
|
this.dsmEnabled = isTrue(DD_DATA_STREAMS_ENABLED)
|
|
546
537
|
this.openAiLogsEnabled = DD_OPENAI_LOGS_ENABLED
|
|
547
538
|
this.apiKey = DD_API_KEY
|
|
548
|
-
this.logInjection = isTrue(DD_LOGS_INJECTION)
|
|
549
539
|
this.env = DD_ENV
|
|
550
540
|
this.url = DD_CIVISIBILITY_AGENTLESS_URL ? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
|
|
551
541
|
: getAgentUrl(DD_TRACE_AGENT_URL, options)
|
|
@@ -554,7 +544,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
554
544
|
this.port = String(DD_TRACE_AGENT_PORT || (this.url && this.url.port))
|
|
555
545
|
this.flushInterval = coalesce(parseInt(options.flushInterval, 10), defaultFlushInterval)
|
|
556
546
|
this.flushMinSpans = DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
|
|
557
|
-
this.sampleRate = coalesce(Math.min(Math.max(sampler.sampleRate, 0), 1), 1)
|
|
558
547
|
this.queryStringObfuscation = DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP
|
|
559
548
|
this.clientIpEnabled = DD_TRACE_CLIENT_IP_ENABLED
|
|
560
549
|
this.clientIpHeader = DD_TRACE_CLIENT_IP_HEADER
|
|
@@ -687,6 +676,139 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
687
676
|
version: this.version,
|
|
688
677
|
'runtime-id': uuid()
|
|
689
678
|
})
|
|
679
|
+
|
|
680
|
+
this._applyDefaults()
|
|
681
|
+
this._applyEnvironment()
|
|
682
|
+
this._applyOptions(options)
|
|
683
|
+
this._applyRemote({})
|
|
684
|
+
this._merge()
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// Supports only a subset of options for now.
|
|
688
|
+
configure (options, remote) {
|
|
689
|
+
if (remote) {
|
|
690
|
+
this._applyRemote(options)
|
|
691
|
+
} else {
|
|
692
|
+
this._applyOptions(options)
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
this._merge()
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
_applyDefaults () {
|
|
699
|
+
const defaults = this._defaults = {}
|
|
700
|
+
|
|
701
|
+
this._setUnit(defaults, 'sampleRate', undefined)
|
|
702
|
+
this._setBoolean(defaults, 'logInjection', false)
|
|
703
|
+
this._setArray(defaults, 'headerTags', [])
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
_applyEnvironment () {
|
|
707
|
+
const {
|
|
708
|
+
DD_TRACE_SAMPLE_RATE,
|
|
709
|
+
DD_LOGS_INJECTION,
|
|
710
|
+
DD_TRACE_HEADER_TAGS
|
|
711
|
+
} = process.env
|
|
712
|
+
|
|
713
|
+
const env = this._env = {}
|
|
714
|
+
|
|
715
|
+
this._setUnit(env, 'sampleRate', DD_TRACE_SAMPLE_RATE)
|
|
716
|
+
this._setBoolean(env, 'logInjection', DD_LOGS_INJECTION)
|
|
717
|
+
this._setArray(env, 'headerTags', DD_TRACE_HEADER_TAGS)
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
_applyOptions (options) {
|
|
721
|
+
const opts = this._options = this._options || {}
|
|
722
|
+
|
|
723
|
+
options = Object.assign({ ingestion: {} }, options, opts)
|
|
724
|
+
|
|
725
|
+
this._setUnit(opts, 'sampleRate', coalesce(options.sampleRate, options.ingestion.sampleRate))
|
|
726
|
+
this._setBoolean(opts, 'logInjection', options.logInjection)
|
|
727
|
+
this._setArray(opts, 'headerTags', options.headerTags)
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
_applyRemote (options) {
|
|
731
|
+
const opts = this._remote = this._remote || {}
|
|
732
|
+
const headerTags = options.tracing_header_tags
|
|
733
|
+
? options.tracing_header_tags.map(tag => {
|
|
734
|
+
return tag.tag_name ? `${tag.header}:${tag.tag_name}` : tag.header
|
|
735
|
+
})
|
|
736
|
+
: undefined
|
|
737
|
+
|
|
738
|
+
this._setUnit(opts, 'sampleRate', options.tracing_sampling_rate)
|
|
739
|
+
this._setBoolean(opts, 'logInjection', options.log_injection_enabled)
|
|
740
|
+
this._setArray(opts, 'headerTags', headerTags)
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
_setBoolean (obj, name, value) {
|
|
744
|
+
if (value === undefined || value === null) {
|
|
745
|
+
this._setValue(obj, name, value)
|
|
746
|
+
} else if (isTrue(value)) {
|
|
747
|
+
this._setValue(obj, name, true)
|
|
748
|
+
} else if (isFalse(value)) {
|
|
749
|
+
this._setValue(obj, name, false)
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
_setUnit (obj, name, value) {
|
|
754
|
+
if (value === null || value === undefined) {
|
|
755
|
+
return this._setValue(obj, name, value)
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
value = parseFloat(value)
|
|
759
|
+
|
|
760
|
+
if (!isNaN(value)) {
|
|
761
|
+
// TODO: Ignore out of range values instead of normalizing them.
|
|
762
|
+
this._setValue(obj, name, Math.min(Math.max(value, 0), 1))
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
_setArray (obj, name, value) {
|
|
767
|
+
if (value === null || value === undefined) {
|
|
768
|
+
return this._setValue(obj, name, null)
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
if (typeof value === 'string') {
|
|
772
|
+
value = value && value.split(',')
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if (Array.isArray(value)) {
|
|
776
|
+
this._setValue(obj, name, value)
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
_setValue (obj, name, value) {
|
|
781
|
+
obj[name] = value
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// TODO: Report origin changes and errors to telemetry.
|
|
785
|
+
// TODO: Deeply merge configurations.
|
|
786
|
+
// TODO: Move change tracking to telemetry.
|
|
787
|
+
_merge () {
|
|
788
|
+
const containers = [this._remote, this._options, this._env, this._defaults]
|
|
789
|
+
const origins = ['remote_config', 'code', 'env_var', 'default']
|
|
790
|
+
const changes = []
|
|
791
|
+
|
|
792
|
+
for (const name in this._defaults) {
|
|
793
|
+
for (let i = 0; i < containers.length; i++) {
|
|
794
|
+
const container = containers[i]
|
|
795
|
+
const origin = origins[i]
|
|
796
|
+
|
|
797
|
+
if ((container[name] !== null && container[name] !== undefined) || container === this._defaults) {
|
|
798
|
+
if (this[name] === container[name] && this.hasOwnProperty(name)) break
|
|
799
|
+
|
|
800
|
+
const value = this[name] = container[name]
|
|
801
|
+
|
|
802
|
+
changes.push({ name, value, origin })
|
|
803
|
+
|
|
804
|
+
break
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
this.sampler.sampleRate = this.sampleRate
|
|
810
|
+
|
|
811
|
+
updateConfig(changes, this)
|
|
690
812
|
}
|
|
691
813
|
}
|
|
692
814
|
|
|
@@ -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
|
|
@@ -22,17 +22,24 @@ class TracingPlugin extends Plugin {
|
|
|
22
22
|
return store && store.span
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
serviceName (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
serviceName (opts = {}) {
|
|
26
|
+
const {
|
|
27
|
+
type = this.constructor.type,
|
|
28
|
+
id = this.constructor.id,
|
|
29
|
+
kind = this.constructor.kind
|
|
30
|
+
} = opts
|
|
31
|
+
|
|
32
|
+
return Nomenclature.serviceName(type, kind, id, opts)
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
operationName (
|
|
34
|
-
const {
|
|
35
|
-
|
|
35
|
+
operationName (opts = {}) {
|
|
36
|
+
const {
|
|
37
|
+
type = this.constructor.type,
|
|
38
|
+
id = this.constructor.id,
|
|
39
|
+
kind = this.constructor.kind
|
|
40
|
+
} = opts
|
|
41
|
+
|
|
42
|
+
return Nomenclature.opName(type, kind, id, opts)
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
configure (config) {
|
|
@@ -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')
|
|
@@ -18,20 +18,16 @@ class SchemaManager {
|
|
|
18
18
|
return this.config.spanRemoveIntegrationFromService && this.version === 'v0'
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
opName (type, kind, plugin,
|
|
22
|
-
return this.schema.getOpName(type, kind, plugin,
|
|
21
|
+
opName (type, kind, plugin, opts) {
|
|
22
|
+
return this.schema.getOpName(type, kind, plugin, opts)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
serviceName (type, kind, plugin,
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
serviceName (type, kind, plugin, opts) {
|
|
26
|
+
const schema = this.shouldUseConsistentServiceNaming
|
|
27
|
+
? this.schemas.v1
|
|
28
|
+
: this.schema
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
// We're short-circuiting, so we do not obey custom service functions
|
|
31
|
-
if (typeof pluginConfig.service === 'function') {
|
|
32
|
-
return this.config.service
|
|
33
|
-
}
|
|
34
|
-
return pluginConfig.service || this.config.service
|
|
30
|
+
return schema.getServiceName(type, kind, plugin, { ...opts, tracerService: this.config.service })
|
|
35
31
|
}
|
|
36
32
|
|
|
37
33
|
configure (config = {}) {
|
|
@@ -10,14 +10,14 @@ class SchemaDefinition {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
getOpName (type, kind, plugin,
|
|
13
|
+
getOpName (type, kind, plugin, opts) {
|
|
14
14
|
const item = this.getSchemaItem(type, kind, plugin)
|
|
15
|
-
return item.opName(
|
|
15
|
+
return item.opName(opts)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
getServiceName (type, kind, plugin,
|
|
18
|
+
getServiceName (type, kind, plugin, opts) {
|
|
19
19
|
const item = this.getSchemaItem(type, kind, plugin)
|
|
20
|
-
return item.serviceName(
|
|
20
|
+
return item.serviceName(opts)
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -1,5 +1,23 @@
|
|
|
1
|
-
function identityService (
|
|
2
|
-
return
|
|
1
|
+
function identityService ({ tracerService }) {
|
|
2
|
+
return tracerService
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
function getFormattedHostString ({ host, port }) {
|
|
6
|
+
return [host, port].filter(val => val).join(':')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function httpPluginClientService ({ tracerService, pluginConfig, sessionDetails }) {
|
|
10
|
+
if (pluginConfig.splitByDomain) {
|
|
11
|
+
return getFormattedHostString(sessionDetails)
|
|
12
|
+
} else if (pluginConfig.service) {
|
|
13
|
+
return pluginConfig.service
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return tracerService
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function awsServiceV0 ({ tracerService, awsService }) {
|
|
20
|
+
return `${tracerService}-aws-${awsService}`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = { identityService, httpPluginClientService, awsServiceV0 }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const { identityService } = require('../util')
|
|
1
|
+
const { identityService, awsServiceV0 } = require('../util')
|
|
2
2
|
|
|
3
|
-
function amqpServiceName (
|
|
4
|
-
return `${
|
|
3
|
+
function amqpServiceName ({ tracerService }) {
|
|
4
|
+
return `${tracerService}-amqp`
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
const messaging = {
|
|
@@ -16,15 +16,23 @@ const messaging = {
|
|
|
16
16
|
},
|
|
17
17
|
'google-cloud-pubsub': {
|
|
18
18
|
opName: () => 'pubsub.request',
|
|
19
|
-
serviceName:
|
|
19
|
+
serviceName: ({ tracerService }) => `${tracerService}-pubsub`
|
|
20
20
|
},
|
|
21
21
|
kafkajs: {
|
|
22
22
|
opName: () => 'kafka.produce',
|
|
23
|
-
serviceName:
|
|
23
|
+
serviceName: ({ tracerService }) => `${tracerService}-kafka`
|
|
24
24
|
},
|
|
25
25
|
rhea: {
|
|
26
26
|
opName: () => 'amqp.send',
|
|
27
|
-
serviceName:
|
|
27
|
+
serviceName: ({ tracerService }) => `${tracerService}-amqp-producer`
|
|
28
|
+
},
|
|
29
|
+
sqs: {
|
|
30
|
+
opName: () => 'aws.request',
|
|
31
|
+
serviceName: awsServiceV0
|
|
32
|
+
},
|
|
33
|
+
sns: {
|
|
34
|
+
opName: () => 'aws.request',
|
|
35
|
+
serviceName: awsServiceV0
|
|
28
36
|
}
|
|
29
37
|
},
|
|
30
38
|
consumer: {
|
|
@@ -42,11 +50,15 @@ const messaging = {
|
|
|
42
50
|
},
|
|
43
51
|
kafkajs: {
|
|
44
52
|
opName: () => 'kafka.consume',
|
|
45
|
-
serviceName:
|
|
53
|
+
serviceName: ({ tracerService }) => `${tracerService}-kafka`
|
|
46
54
|
},
|
|
47
55
|
rhea: {
|
|
48
56
|
opName: () => 'amqp.receive',
|
|
49
57
|
serviceName: identityService
|
|
58
|
+
},
|
|
59
|
+
sqs: {
|
|
60
|
+
opName: () => 'aws.request',
|
|
61
|
+
serviceName: awsServiceV0
|
|
50
62
|
}
|
|
51
63
|
},
|
|
52
64
|
client: {
|
|
@@ -56,7 +68,7 @@ const messaging = {
|
|
|
56
68
|
},
|
|
57
69
|
'google-cloud-pubsub': {
|
|
58
70
|
opName: () => 'pubsub.request',
|
|
59
|
-
serviceName:
|
|
71
|
+
serviceName: ({ tracerService }) => `${tracerService}-pubsub`
|
|
60
72
|
}
|
|
61
73
|
}
|
|
62
74
|
}
|