dd-trace 2.30.1 → 2.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +1 -1
- package/esbuild.js +3 -0
- package/index.d.ts +10 -9
- package/package.json +12 -12
- package/packages/datadog-core/src/storage/async_resource.js +1 -1
- package/packages/datadog-esbuild/index.js +9 -2
- package/packages/datadog-instrumentations/src/body-parser.js +15 -9
- package/packages/datadog-instrumentations/src/cucumber.js +11 -1
- package/packages/datadog-instrumentations/src/express.js +32 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/http/server.js +2 -1
- package/packages/datadog-instrumentations/src/jest.js +6 -3
- package/packages/datadog-instrumentations/src/mocha.js +19 -2
- package/packages/datadog-instrumentations/src/playwright.js +5 -2
- package/packages/datadog-plugin-amqp10/src/consumer.js +1 -3
- package/packages/datadog-plugin-amqp10/src/producer.js +1 -3
- package/packages/datadog-plugin-amqplib/src/client.js +4 -3
- package/packages/datadog-plugin-amqplib/src/consumer.js +1 -3
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -3
- package/packages/datadog-plugin-cucumber/src/index.js +6 -4
- package/packages/datadog-plugin-cypress/src/plugin.js +5 -1
- package/packages/datadog-plugin-cypress/src/support.js +4 -0
- package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -3
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +2 -2
- package/packages/datadog-plugin-http2/src/server.js +0 -5
- package/packages/datadog-plugin-jest/src/index.js +10 -5
- package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -4
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -3
- package/packages/datadog-plugin-mocha/src/index.js +9 -4
- package/packages/datadog-plugin-playwright/src/index.js +6 -5
- package/packages/datadog-plugin-redis/src/index.js +16 -5
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -3
- package/packages/datadog-plugin-rhea/src/producer.js +1 -5
- package/packages/dd-trace/src/appsec/addresses.js +0 -3
- package/packages/dd-trace/src/appsec/blocked_templates.js +2 -9
- package/packages/dd-trace/src/appsec/blocking.js +1 -1
- package/packages/dd-trace/src/appsec/{gateway/channels.js → channels.js} +4 -4
- package/packages/dd-trace/src/appsec/iast/index.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +21 -13
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/logs.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +87 -79
- package/packages/dd-trace/src/appsec/recommended.json +448 -121
- package/packages/dd-trace/src/appsec/remote_config/apply_states.js +7 -0
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -0
- package/packages/dd-trace/src/appsec/remote_config/index.js +30 -11
- package/packages/dd-trace/src/appsec/remote_config/manager.js +33 -12
- package/packages/dd-trace/src/appsec/reporter.js +27 -58
- package/packages/dd-trace/src/appsec/rule_manager.js +160 -32
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +4 -12
- package/packages/dd-trace/src/appsec/waf/index.js +75 -0
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +57 -0
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +66 -0
- package/packages/dd-trace/src/config.js +18 -1
- package/packages/dd-trace/src/dcitm.js +2 -0
- package/packages/dd-trace/src/encode/0.4.js +12 -4
- package/packages/dd-trace/src/encode/tags-processors.js +40 -68
- package/packages/dd-trace/src/exporters/common/request.js +2 -2
- package/packages/dd-trace/src/format.js +2 -1
- package/packages/dd-trace/src/iitm.js +1 -1
- package/packages/dd-trace/src/log/channels.js +11 -12
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +2 -2
- package/packages/dd-trace/src/plugin_manager.js +3 -1
- package/packages/dd-trace/src/plugins/client.js +3 -2
- package/packages/dd-trace/src/plugins/consumer.js +17 -2
- package/packages/dd-trace/src/plugins/inbound.js +7 -0
- package/packages/dd-trace/src/plugins/{outgoing.js → outbound.js} +2 -2
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/producer.js +17 -2
- package/packages/dd-trace/src/plugins/server.js +2 -2
- package/packages/dd-trace/src/plugins/tracing.js +11 -0
- package/packages/dd-trace/src/plugins/util/test.js +19 -1
- package/packages/dd-trace/src/profiling/profilers/cpu.js +1 -1
- package/packages/dd-trace/src/ritm.js +1 -1
- package/packages/dd-trace/src/service-naming/index.js +41 -0
- package/packages/dd-trace/src/service-naming/schemas/definition.js +28 -0
- package/packages/dd-trace/src/service-naming/schemas/index.js +6 -0
- package/packages/dd-trace/src/service-naming/schemas/v0.js +66 -0
- package/packages/dd-trace/src/service-naming/schemas/v1.js +58 -0
- package/packages/dd-trace/src/span_stats.js +1 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
- package/packages/dd-trace/src/telemetry/index.js +1 -1
- package/packages/diagnostics_channel/index.js +3 -0
- package/packages/diagnostics_channel/src/index.js +57 -0
- package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +0 -137
- package/packages/dd-trace/src/appsec/callbacks/index.js +0 -7
- package/packages/dd-trace/src/appsec/gateway/als.js +0 -6
- package/packages/dd-trace/src/appsec/gateway/engine/engine.js +0 -140
- package/packages/dd-trace/src/appsec/gateway/engine/index.js +0 -51
- package/packages/dd-trace/src/appsec/gateway/engine/runner.js +0 -42
- package/packages/dd-trace/src/instrumenter.js +0 -203
- package/packages/dd-trace/src/loader.js +0 -131
- package/packages/dd-trace/src/plugins/incoming.js +0 -7
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const log = require('../../log')
|
|
4
|
+
const Reporter = require('../reporter')
|
|
5
|
+
|
|
6
|
+
class WAFContextWrapper {
|
|
7
|
+
constructor (ddwafContext, requiredAddresses, wafTimeout, rulesInfo) {
|
|
8
|
+
this.ddwafContext = ddwafContext
|
|
9
|
+
this.requiredAddresses = requiredAddresses
|
|
10
|
+
this.wafTimeout = wafTimeout
|
|
11
|
+
this.rulesInfo = rulesInfo
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
run (params) {
|
|
15
|
+
const inputs = {}
|
|
16
|
+
let someInputAdded = false
|
|
17
|
+
|
|
18
|
+
// TODO: possible optimizaion: only send params that haven't already been sent with same value to this wafContext
|
|
19
|
+
for (const key of Object.keys(params)) {
|
|
20
|
+
if (this.requiredAddresses.has(key)) {
|
|
21
|
+
inputs[key] = params[key]
|
|
22
|
+
someInputAdded = true
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!someInputAdded) return
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const start = process.hrtime.bigint()
|
|
30
|
+
|
|
31
|
+
const result = this.ddwafContext.run(inputs, this.wafTimeout)
|
|
32
|
+
|
|
33
|
+
const end = process.hrtime.bigint()
|
|
34
|
+
|
|
35
|
+
Reporter.reportMetrics({
|
|
36
|
+
duration: result.totalRuntime / 1e3,
|
|
37
|
+
durationExt: parseInt(end - start) / 1e3,
|
|
38
|
+
rulesVersion: this.rulesInfo.version
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
if (result.data && result.data !== '[]') {
|
|
42
|
+
Reporter.reportAttack(result.data)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return result.actions
|
|
46
|
+
} catch (err) {
|
|
47
|
+
log.error('Error while running the AppSec WAF')
|
|
48
|
+
log.error(err)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
dispose () {
|
|
53
|
+
this.ddwafContext.dispose()
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = WAFContextWrapper
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const log = require('../../log')
|
|
4
|
+
const Reporter = require('../reporter')
|
|
5
|
+
const WAFContextWrapper = require('./waf_context_wrapper')
|
|
6
|
+
|
|
7
|
+
const contexts = new WeakMap()
|
|
8
|
+
|
|
9
|
+
class WAFManager {
|
|
10
|
+
constructor (rules, config) {
|
|
11
|
+
this.config = config
|
|
12
|
+
this.wafTimeout = config.wafTimeout
|
|
13
|
+
this.ddwaf = this._loadDDWAF(rules)
|
|
14
|
+
this._reportMetrics()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_loadDDWAF (rules) {
|
|
18
|
+
try {
|
|
19
|
+
// require in `try/catch` because this can throw at require time
|
|
20
|
+
const { DDWAF } = require('@datadog/native-appsec')
|
|
21
|
+
|
|
22
|
+
const { obfuscatorKeyRegex, obfuscatorValueRegex } = this.config
|
|
23
|
+
return new DDWAF(rules, { obfuscatorKeyRegex, obfuscatorValueRegex })
|
|
24
|
+
} catch (err) {
|
|
25
|
+
log.error('AppSec could not load native package. In-app WAF features will not be available.')
|
|
26
|
+
|
|
27
|
+
throw err
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_reportMetrics () {
|
|
32
|
+
Reporter.metricsQueue.set('_dd.appsec.waf.version', this.ddwaf.constructor.version())
|
|
33
|
+
|
|
34
|
+
const { loaded, failed, errors } = this.ddwaf.rulesInfo
|
|
35
|
+
|
|
36
|
+
Reporter.metricsQueue.set('_dd.appsec.event_rules.loaded', loaded)
|
|
37
|
+
Reporter.metricsQueue.set('_dd.appsec.event_rules.error_count', failed)
|
|
38
|
+
if (failed) Reporter.metricsQueue.set('_dd.appsec.event_rules.errors', JSON.stringify(errors))
|
|
39
|
+
|
|
40
|
+
Reporter.metricsQueue.set('manual.keep', 'true')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getWAFContext (req) {
|
|
44
|
+
let wafContext = contexts.get(req)
|
|
45
|
+
|
|
46
|
+
if (!wafContext) {
|
|
47
|
+
wafContext = new WAFContextWrapper(
|
|
48
|
+
this.ddwaf.createContext(),
|
|
49
|
+
this.ddwaf.requiredAddresses,
|
|
50
|
+
this.wafTimeout,
|
|
51
|
+
this.ddwaf.rulesInfo
|
|
52
|
+
)
|
|
53
|
+
contexts.set(req, wafContext)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return wafContext
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
destroy () {
|
|
60
|
+
if (this.ddwaf) {
|
|
61
|
+
this.ddwaf.dispose()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = WAFManager
|
|
@@ -31,6 +31,19 @@ function safeJsonParse (input) {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
const namingVersions = ['v0', 'v1']
|
|
35
|
+
const defaultVersion = 'v0'
|
|
36
|
+
|
|
37
|
+
function validateNamingVersion (versionString) {
|
|
38
|
+
if (!namingVersions.includes(versionString)) {
|
|
39
|
+
log.warn(
|
|
40
|
+
`Unexpected input for config.spanAttributeSchema, picked default ${defaultVersion}`
|
|
41
|
+
)
|
|
42
|
+
return defaultVersion
|
|
43
|
+
}
|
|
44
|
+
return versionString
|
|
45
|
+
}
|
|
46
|
+
|
|
34
47
|
// Shallow clone with property name remapping
|
|
35
48
|
function remapify (input, mappings) {
|
|
36
49
|
if (!input) return
|
|
@@ -257,7 +270,9 @@ class Config {
|
|
|
257
270
|
process.env.DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED,
|
|
258
271
|
false
|
|
259
272
|
)
|
|
260
|
-
|
|
273
|
+
const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
|
|
274
|
+
process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
|
|
275
|
+
)
|
|
261
276
|
const DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH = coalesce(
|
|
262
277
|
process.env.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
|
|
263
278
|
'512'
|
|
@@ -464,6 +479,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
464
479
|
sourceMap: !isFalse(DD_PROFILING_SOURCE_MAP),
|
|
465
480
|
exporters: DD_PROFILING_EXPORTERS
|
|
466
481
|
}
|
|
482
|
+
this.spanAttributeSchema = DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
|
|
467
483
|
this.lookup = options.lookup
|
|
468
484
|
this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
|
|
469
485
|
// Disabled for CI Visibility's agentless
|
|
@@ -477,6 +493,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
477
493
|
this.appsec = {
|
|
478
494
|
enabled: DD_APPSEC_ENABLED,
|
|
479
495
|
rules: DD_APPSEC_RULES ? safeJsonParse(maybeFile(DD_APPSEC_RULES)) : require('./appsec/recommended.json'),
|
|
496
|
+
customRulesProvided: !!DD_APPSEC_RULES,
|
|
480
497
|
rateLimit: DD_APPSEC_TRACE_RATE_LIMIT,
|
|
481
498
|
wafTimeout: DD_APPSEC_WAF_TIMEOUT,
|
|
482
499
|
obfuscatorKeyRegex: DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
const { truncateSpan, normalizeSpan } = require('./tags-processors')
|
|
4
4
|
const Chunk = require('./chunk')
|
|
5
5
|
const log = require('../log')
|
|
6
|
+
const { isTrue } = require('../util')
|
|
7
|
+
const coalesce = require('koalas')
|
|
6
8
|
|
|
7
9
|
const SOFT_LIMIT = 8 * 1024 * 1024 // 8MB
|
|
8
10
|
|
|
@@ -24,6 +26,10 @@ class AgentEncoder {
|
|
|
24
26
|
this._stringBytes = new Chunk()
|
|
25
27
|
this._writer = writer
|
|
26
28
|
this._reset()
|
|
29
|
+
this._debugEncoding = isTrue(coalesce(
|
|
30
|
+
process.env.DD_TRACE_ENCODING_DEBUG,
|
|
31
|
+
false
|
|
32
|
+
))
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
count () {
|
|
@@ -40,11 +46,13 @@ class AgentEncoder {
|
|
|
40
46
|
|
|
41
47
|
const end = bytes.length
|
|
42
48
|
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
if (this._debugEncoding) {
|
|
50
|
+
log.debug(() => {
|
|
51
|
+
const hex = bytes.buffer.subarray(start, end).toString('hex').match(/../g).join(' ')
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
return `Adding encoded trace to buffer: ${hex}`
|
|
54
|
+
})
|
|
55
|
+
}
|
|
48
56
|
|
|
49
57
|
// we can go over the soft limit since the agent has a 50MB hard limit
|
|
50
58
|
if (this._traceBytes.length > this._limit || this._stringBytes.length > this._limit) {
|
|
@@ -9,8 +9,6 @@ const MAX_META_KEY_LENGTH = 200
|
|
|
9
9
|
const MAX_META_VALUE_LENGTH = 25000
|
|
10
10
|
// MAX_METRIC_KEY_LENGTH the maximum length of a metric name key
|
|
11
11
|
const MAX_METRIC_KEY_LENGTH = MAX_META_KEY_LENGTH
|
|
12
|
-
// MAX_METRIC_VALUE_LENGTH the maximum length of a metric name value
|
|
13
|
-
const MAX_METRIC_VALUE_LENGTH = MAX_META_VALUE_LENGTH
|
|
14
12
|
|
|
15
13
|
// From agent normalizer:
|
|
16
14
|
// https://github.com/DataDog/datadog-agent/blob/main/pkg/trace/traceutil/normalize.go
|
|
@@ -25,80 +23,55 @@ const MAX_SERVICE_LENGTH = 100
|
|
|
25
23
|
// MAX_TYPE_LENGTH the maximum length a span type can have
|
|
26
24
|
const MAX_TYPE_LENGTH = 100
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
function truncateToLength (value, maxLength) {
|
|
32
|
-
if (!value) {
|
|
33
|
-
return value
|
|
34
|
-
}
|
|
35
|
-
if (value.length > maxLength) {
|
|
36
|
-
return `${value.slice(0, maxLength)}...`
|
|
37
|
-
}
|
|
38
|
-
return value
|
|
39
|
-
}
|
|
26
|
+
// TODO (bengl) Pretty much everything in this file should happen in
|
|
27
|
+
// `format.js`, so that we're not iterating over all the spans and modifying
|
|
28
|
+
// them yet again.
|
|
40
29
|
|
|
41
30
|
// normally the agent truncates the resource and parses it in certain scenarios (e.g. SQL Queries)
|
|
42
31
|
function truncateSpan (span, shouldTruncateResourceName = true) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
32
|
+
if (shouldTruncateResourceName && span.resource && span.resource.length > MAX_RESOURCE_NAME_LENGTH) {
|
|
33
|
+
span.resource = `${span.resource.slice(0, MAX_RESOURCE_NAME_LENGTH)}...`
|
|
34
|
+
}
|
|
35
|
+
for (let metaKey in span.meta) {
|
|
36
|
+
const val = span.meta[metaKey]
|
|
37
|
+
if (metaKey.length > MAX_META_KEY_LENGTH) {
|
|
38
|
+
delete span.meta[metaKey]
|
|
39
|
+
metaKey = `${metaKey.slice(0, MAX_META_KEY_LENGTH)}...`
|
|
40
|
+
span.metrics[metaKey] = val
|
|
41
|
+
}
|
|
42
|
+
if (val && val.length > MAX_META_VALUE_LENGTH) {
|
|
43
|
+
span.meta[metaKey] = `${val.slice(0, MAX_META_VALUE_LENGTH)}...`
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
for (let metricsKey in span.metrics) {
|
|
47
|
+
const val = span.metrics[metricsKey]
|
|
48
|
+
if (metricsKey.length > MAX_METRIC_KEY_LENGTH) {
|
|
49
|
+
delete span.metrics[metricsKey]
|
|
50
|
+
metricsKey = `${metricsKey.slice(0, MAX_METRIC_KEY_LENGTH)}...`
|
|
51
|
+
span.metrics[metricsKey] = val
|
|
57
52
|
}
|
|
58
|
-
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return span
|
|
59
56
|
}
|
|
60
57
|
|
|
61
58
|
function normalizeSpan (span) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (!value) {
|
|
66
|
-
return [key, DEFAULT_SERVICE_NAME]
|
|
67
|
-
}
|
|
68
|
-
if (value.length > MAX_SERVICE_LENGTH) {
|
|
69
|
-
return [key, value.slice(0, MAX_SERVICE_LENGTH)]
|
|
70
|
-
}
|
|
71
|
-
break
|
|
72
|
-
case 'name':
|
|
73
|
-
if (!value) {
|
|
74
|
-
return [key, DEFAULT_SPAN_NAME]
|
|
75
|
-
}
|
|
76
|
-
if (value.length > MAX_NAME_LENGTH) {
|
|
77
|
-
return [key, value.slice(0, MAX_NAME_LENGTH)]
|
|
78
|
-
}
|
|
79
|
-
break
|
|
80
|
-
case 'resource':
|
|
81
|
-
if (!value) {
|
|
82
|
-
return [key, span.name || DEFAULT_SPAN_NAME]
|
|
83
|
-
}
|
|
84
|
-
break
|
|
85
|
-
case 'type':
|
|
86
|
-
if (!value) {
|
|
87
|
-
return [key, value]
|
|
88
|
-
}
|
|
89
|
-
if (value.length > MAX_TYPE_LENGTH) {
|
|
90
|
-
return [key, value.slice(0, MAX_TYPE_LENGTH)]
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return [key, value]
|
|
94
|
-
}))
|
|
95
|
-
if (!normalizedSpan.service) {
|
|
96
|
-
normalizedSpan.service = DEFAULT_SERVICE_NAME
|
|
59
|
+
span.service = span.service || DEFAULT_SERVICE_NAME
|
|
60
|
+
if (span.service.length > MAX_SERVICE_LENGTH) {
|
|
61
|
+
span.service = span.service.slice(0, MAX_SERVICE_LENGTH)
|
|
97
62
|
}
|
|
98
|
-
|
|
99
|
-
|
|
63
|
+
span.name = span.name || DEFAULT_SPAN_NAME
|
|
64
|
+
if (span.name.length > MAX_NAME_LENGTH) {
|
|
65
|
+
span.name = span.name.slice(0, MAX_NAME_LENGTH)
|
|
100
66
|
}
|
|
101
|
-
|
|
67
|
+
if (!span.resource) {
|
|
68
|
+
span.resource = span.name
|
|
69
|
+
}
|
|
70
|
+
if (span.type && span.type.length > MAX_TYPE_LENGTH) {
|
|
71
|
+
span.type = span.type.slice(0, MAX_TYPE_LENGTH)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return span
|
|
102
75
|
}
|
|
103
76
|
|
|
104
77
|
module.exports = {
|
|
@@ -107,7 +80,6 @@ module.exports = {
|
|
|
107
80
|
MAX_META_KEY_LENGTH,
|
|
108
81
|
MAX_META_VALUE_LENGTH,
|
|
109
82
|
MAX_METRIC_KEY_LENGTH,
|
|
110
|
-
MAX_METRIC_VALUE_LENGTH,
|
|
111
83
|
MAX_NAME_LENGTH,
|
|
112
84
|
MAX_SERVICE_LENGTH,
|
|
113
85
|
MAX_TYPE_LENGTH,
|
|
@@ -54,13 +54,13 @@ function request (data, options, callback) {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
if (options.url) {
|
|
57
|
-
const url = typeof options.url === 'object' ? options.url : fromUrlString(options.url)
|
|
57
|
+
const url = typeof options.url === 'object' ? urlToOptions(options.url) : fromUrlString(options.url)
|
|
58
58
|
if (url.protocol === 'unix:') {
|
|
59
59
|
options.socketPath = url.pathname
|
|
60
60
|
} else {
|
|
61
61
|
if (!options.path) options.path = url.path
|
|
62
62
|
options.protocol = url.protocol
|
|
63
|
-
options.hostname = url.hostname
|
|
63
|
+
options.hostname = url.hostname // for IPv6 this should be '::1' and not '[::1]'
|
|
64
64
|
options.port = url.port
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -146,7 +146,8 @@ function extractError (trace, error) {
|
|
|
146
146
|
trace.error = 1
|
|
147
147
|
|
|
148
148
|
if (isError(error)) {
|
|
149
|
-
|
|
149
|
+
// AggregateError only has a code and no message.
|
|
150
|
+
addTag(trace.meta, trace.metrics, ERROR_MESSAGE, error.message || error.code)
|
|
150
151
|
addTag(trace.meta, trace.metrics, ERROR_TYPE, error.name)
|
|
151
152
|
addTag(trace.meta, trace.metrics, ERROR_STACK, error.stack)
|
|
152
153
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const semver = require('semver')
|
|
4
4
|
const logger = require('./log')
|
|
5
5
|
const { addHook } = require('import-in-the-middle')
|
|
6
|
-
const dc = require('diagnostics_channel')
|
|
6
|
+
const dc = require('../../diagnostics_channel')
|
|
7
7
|
|
|
8
8
|
if (semver.satisfies(process.versions.node, '^12.20.0 || >=14.13.1')) {
|
|
9
9
|
const moduleLoadStartChannel = dc.channel('dd-trace:moduleLoadStart')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const { channel } = require('../../../diagnostics_channel')
|
|
4
4
|
|
|
5
5
|
const Level = {
|
|
6
6
|
Debug: 'debug',
|
|
@@ -11,19 +11,18 @@ const Level = {
|
|
|
11
11
|
|
|
12
12
|
const defaultLevel = Level.Debug
|
|
13
13
|
|
|
14
|
-
class LogChannel extends dc.Channel {
|
|
15
|
-
constructor (name, logLevel) {
|
|
16
|
-
super(`datadog:log:${name}`)
|
|
17
|
-
this.logLevel = logLevel
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
14
|
// based on: https://github.com/trentm/node-bunyan#levels
|
|
22
15
|
const logChannels = {
|
|
23
|
-
[Level.Debug]:
|
|
24
|
-
[Level.Info]:
|
|
25
|
-
[Level.Warn]:
|
|
26
|
-
[Level.Error]:
|
|
16
|
+
[Level.Debug]: createLogChannel(Level.Debug, 20),
|
|
17
|
+
[Level.Info]: createLogChannel(Level.Info, 30),
|
|
18
|
+
[Level.Warn]: createLogChannel(Level.Warn, 40),
|
|
19
|
+
[Level.Error]: createLogChannel(Level.Error, 50)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function createLogChannel (name, logLevel) {
|
|
23
|
+
const logChannel = channel(`datadog:log:${name}`)
|
|
24
|
+
logChannel.logLevel = logLevel
|
|
25
|
+
return logChannel
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
function getChannelLogLevel (level) {
|
|
@@ -343,10 +343,10 @@ class TextMapPropagator {
|
|
|
343
343
|
spanContext._trace.origin = value
|
|
344
344
|
break
|
|
345
345
|
case 't.dm': {
|
|
346
|
-
const mechanism = parseInt(value, 10)
|
|
346
|
+
const mechanism = -Math.abs(parseInt(value, 10))
|
|
347
347
|
if (Number.isInteger(mechanism)) {
|
|
348
348
|
spanContext._sampling.mechanism = mechanism
|
|
349
|
-
spanContext._trace.tags['_dd.p.dm'] = mechanism
|
|
349
|
+
spanContext._trace.tags['_dd.p.dm'] = String(mechanism)
|
|
350
350
|
}
|
|
351
351
|
break
|
|
352
352
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { channel } = require('diagnostics_channel')
|
|
3
|
+
const { channel } = require('../../diagnostics_channel')
|
|
4
4
|
const { isFalse } = require('./util')
|
|
5
5
|
const plugins = require('./plugins')
|
|
6
6
|
const log = require('./log')
|
|
7
|
+
const Nomenclature = require('./service-naming')
|
|
7
8
|
|
|
8
9
|
const loadChannel = channel('dd-trace:instrumentation:load')
|
|
9
10
|
|
|
@@ -96,6 +97,7 @@ module.exports = class PluginManager {
|
|
|
96
97
|
// like instrumenter.enable()
|
|
97
98
|
configure (config = {}) {
|
|
98
99
|
this._tracerConfig = config
|
|
100
|
+
Nomenclature.configure(config)
|
|
99
101
|
|
|
100
102
|
for (const name in pluginClasses) {
|
|
101
103
|
this.loadPlugin(name)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const OutboundPlugin = require('./outbound')
|
|
4
4
|
|
|
5
|
-
class ClientPlugin extends
|
|
5
|
+
class ClientPlugin extends OutboundPlugin {
|
|
6
6
|
static get operation () { return 'request' }
|
|
7
|
+
static get kind () { return 'client' }
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
module.exports = ClientPlugin
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const InboundPlugin = require('./inbound')
|
|
4
4
|
|
|
5
|
-
class ConsumerPlugin extends
|
|
5
|
+
class ConsumerPlugin extends InboundPlugin {
|
|
6
6
|
static get operation () { return 'receive' }
|
|
7
|
+
static get kind () { return 'consumer' }
|
|
8
|
+
static get type () { return 'messaging' }
|
|
9
|
+
|
|
10
|
+
startSpan (options) {
|
|
11
|
+
const spanDefaults = {
|
|
12
|
+
service: this.config.service || this.serviceName(),
|
|
13
|
+
kind: this.constructor.kind
|
|
14
|
+
}
|
|
15
|
+
Object.keys(spanDefaults).forEach(
|
|
16
|
+
key => {
|
|
17
|
+
if (!options[key]) options[key] = spanDefaults[key]
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
return super.startSpan(this.operationName(), options)
|
|
21
|
+
}
|
|
7
22
|
}
|
|
8
23
|
|
|
9
24
|
module.exports = ConsumerPlugin
|
|
@@ -4,7 +4,7 @@ const { CLIENT_PORT_KEY } = require('../constants')
|
|
|
4
4
|
const TracingPlugin = require('./tracing')
|
|
5
5
|
|
|
6
6
|
// TODO: Exit span on finish when AsyncResource instances are removed.
|
|
7
|
-
class
|
|
7
|
+
class OutboundPlugin extends TracingPlugin {
|
|
8
8
|
constructor (...args) {
|
|
9
9
|
super(...args)
|
|
10
10
|
|
|
@@ -29,4 +29,4 @@ class OutgoingPlugin extends TracingPlugin {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
module.exports =
|
|
32
|
+
module.exports = OutboundPlugin
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const OutboundPlugin = require('./outbound')
|
|
4
4
|
|
|
5
|
-
class ProducerPlugin extends
|
|
5
|
+
class ProducerPlugin extends OutboundPlugin {
|
|
6
6
|
static get operation () { return 'publish' }
|
|
7
|
+
static get kind () { return 'producer' }
|
|
8
|
+
static get type () { return 'messaging' }
|
|
9
|
+
|
|
10
|
+
startSpan (options) {
|
|
11
|
+
const spanDefaults = {
|
|
12
|
+
service: this.config.service || this.serviceName(),
|
|
13
|
+
kind: this.constructor.kind
|
|
14
|
+
}
|
|
15
|
+
Object.keys(spanDefaults).forEach(
|
|
16
|
+
key => {
|
|
17
|
+
if (!options[key]) options[key] = spanDefaults[key]
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
return super.startSpan(this.operationName(), options)
|
|
21
|
+
}
|
|
7
22
|
}
|
|
8
23
|
|
|
9
24
|
module.exports = ProducerPlugin
|
|
@@ -4,6 +4,7 @@ const Plugin = require('./plugin')
|
|
|
4
4
|
const { storage } = require('../../../datadog-core')
|
|
5
5
|
const analyticsSampler = require('../analytics_sampler')
|
|
6
6
|
const { COMPONENT } = require('../constants')
|
|
7
|
+
const Nomenclature = require('../service-naming')
|
|
7
8
|
|
|
8
9
|
class TracingPlugin extends Plugin {
|
|
9
10
|
constructor (...args) {
|
|
@@ -31,6 +32,16 @@ class TracingPlugin extends Plugin {
|
|
|
31
32
|
return store && store.span
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
serviceName (serviceArgs) {
|
|
36
|
+
const { type, id, kind } = this.constructor
|
|
37
|
+
return Nomenclature.serviceName(type, kind, id, serviceArgs)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
operationName (opNameArgs) {
|
|
41
|
+
const { type, id, kind } = this.constructor
|
|
42
|
+
return Nomenclature.opName(type, kind, id, opNameArgs)
|
|
43
|
+
}
|
|
44
|
+
|
|
34
45
|
configure (config) {
|
|
35
46
|
return super.configure({
|
|
36
47
|
...config,
|
|
@@ -36,6 +36,7 @@ const TEST_SKIP_REASON = 'test.skip_reason'
|
|
|
36
36
|
const TEST_IS_RUM_ACTIVE = 'test.is_rum_active'
|
|
37
37
|
const TEST_CODE_OWNERS = 'test.codeowners'
|
|
38
38
|
const TEST_SOURCE_FILE = 'test.source.file'
|
|
39
|
+
const TEST_SOURCE_START = 'test.source.start'
|
|
39
40
|
const LIBRARY_VERSION = 'library_version'
|
|
40
41
|
const TEST_COMMAND = 'test.command'
|
|
41
42
|
const TEST_MODULE = 'test.module'
|
|
@@ -77,6 +78,7 @@ module.exports = {
|
|
|
77
78
|
LIBRARY_VERSION,
|
|
78
79
|
JEST_WORKER_TRACE_PAYLOAD_CODE,
|
|
79
80
|
JEST_WORKER_COVERAGE_PAYLOAD_CODE,
|
|
81
|
+
TEST_SOURCE_START,
|
|
80
82
|
getTestEnvironmentMetadata,
|
|
81
83
|
getTestParametersString,
|
|
82
84
|
finishAllTraceSpans,
|
|
@@ -104,7 +106,8 @@ module.exports = {
|
|
|
104
106
|
getCoveredFilenamesFromCoverage,
|
|
105
107
|
resetCoverage,
|
|
106
108
|
mergeCoverage,
|
|
107
|
-
fromCoverageMapToCoverage
|
|
109
|
+
fromCoverageMapToCoverage,
|
|
110
|
+
getTestLineStart
|
|
108
111
|
}
|
|
109
112
|
|
|
110
113
|
// Returns pkg manager and its version, separated by '-', e.g. npm-8.15.0 or yarn-1.22.19
|
|
@@ -381,3 +384,18 @@ function fromCoverageMapToCoverage (coverageMap) {
|
|
|
381
384
|
return acc
|
|
382
385
|
}, {})
|
|
383
386
|
}
|
|
387
|
+
|
|
388
|
+
// Get the start line of a test by inspecting a given error's stack trace
|
|
389
|
+
function getTestLineStart (err, testSuitePath) {
|
|
390
|
+
if (!err.stack) {
|
|
391
|
+
return null
|
|
392
|
+
}
|
|
393
|
+
// From https://github.com/felixge/node-stack-trace/blob/ba06dcdb50d465cd440d84a563836e293b360427/index.js#L40
|
|
394
|
+
const testFileLine = err.stack.split('\n').find(line => line.includes(testSuitePath))
|
|
395
|
+
try {
|
|
396
|
+
const testFileLineMatch = testFileLine.match(/at (?:(.+?)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/)
|
|
397
|
+
return parseInt(testFileLineMatch[3], 10) || null
|
|
398
|
+
} catch (e) {
|
|
399
|
+
return null
|
|
400
|
+
}
|
|
401
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { storage } = require('../../../../datadog-core')
|
|
4
4
|
|
|
5
|
-
const dc = require('diagnostics_channel')
|
|
5
|
+
const dc = require('../../../../diagnostics_channel')
|
|
6
6
|
|
|
7
7
|
const beforeCh = dc.channel('dd-trace:storage:before')
|
|
8
8
|
const afterCh = dc.channel('dd-trace:storage:after')
|