dd-trace 4.6.0 → 4.8.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/README.md +2 -2
- package/package.json +4 -4
- package/packages/datadog-core/src/storage/async_resource.js +4 -0
- package/packages/datadog-instrumentations/src/couchbase.js +4 -4
- package/packages/datadog-instrumentations/src/cucumber.js +5 -2
- package/packages/datadog-instrumentations/src/grpc/client.js +44 -42
- package/packages/datadog-instrumentations/src/grpc/server.js +69 -60
- package/packages/datadog-instrumentations/src/http2/client.js +25 -26
- package/packages/datadog-instrumentations/src/jest.js +9 -5
- package/packages/datadog-instrumentations/src/mocha.js +5 -3
- package/packages/datadog-plugin-cypress/src/plugin.js +4 -2
- package/packages/datadog-plugin-graphql/src/execute.js +6 -4
- package/packages/datadog-plugin-grpc/src/client.js +29 -11
- package/packages/datadog-plugin-grpc/src/server.js +22 -6
- package/packages/datadog-plugin-http2/src/client.js +46 -29
- package/packages/datadog-plugin-jest/src/index.js +8 -3
- package/packages/datadog-plugin-openai/src/index.js +39 -16
- package/packages/datadog-plugin-openai/src/services.js +13 -9
- package/packages/datadog-plugin-router/src/index.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +3 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +3 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +7 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +45 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/index.js +3 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +3 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +66 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +19 -15
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +5 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +2 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +27 -8
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +18 -19
- package/packages/dd-trace/src/appsec/iast/analyzers/weak-cipher-analyzer.js +3 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +3 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/xcontenttype-header-missing-analyzer.js +19 -0
- package/packages/dd-trace/src/appsec/iast/iast-log.js +1 -1
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +205 -0
- package/packages/dd-trace/src/appsec/iast/index.js +11 -7
- package/packages/dd-trace/src/appsec/iast/tags.js +2 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +6 -6
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +7 -5
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +23 -4
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +49 -17
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +33 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +23 -16
- package/packages/dd-trace/src/appsec/iast/taint-tracking/{origin-types.js → source-types.js} +1 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +76 -37
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +101 -0
- package/packages/dd-trace/src/appsec/iast/telemetry/index.js +45 -0
- package/packages/dd-trace/src/appsec/iast/telemetry/{logs.js → log/index.js} +5 -5
- package/packages/dd-trace/src/appsec/iast/telemetry/{log_collector.js → log/log-collector.js} +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +76 -0
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +53 -0
- package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +42 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +5 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +3 -1
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
- package/packages/dd-trace/src/config.js +47 -12
- package/packages/dd-trace/src/constants.js +1 -0
- package/packages/dd-trace/src/external-logger/src/index.js +9 -1
- package/packages/dd-trace/src/external-logger/test/index.spec.js +1 -1
- package/packages/dd-trace/src/format.js +1 -1
- package/packages/dd-trace/src/lambda/handler.js +8 -1
- package/packages/dd-trace/src/opentelemetry/span.js +3 -1
- package/packages/dd-trace/src/opentracing/span_context.js +2 -1
- package/packages/dd-trace/src/opentracing/tracer.js +1 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
- package/packages/dd-trace/src/plugins/outbound.js +29 -12
- package/packages/dd-trace/src/plugins/plugin.js +28 -0
- package/packages/dd-trace/src/plugins/tracing.js +33 -16
- package/packages/dd-trace/src/plugins/util/ci.js +3 -2
- package/packages/dd-trace/src/plugins/util/test.js +55 -11
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -22
- package/packages/dd-trace/src/plugins/util/web.js +1 -0
- package/packages/dd-trace/src/profiling/config.js +8 -8
- package/packages/dd-trace/src/profiling/exporters/agent.js +4 -1
- package/packages/dd-trace/src/profiling/index.js +0 -2
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/wall.js +162 -10
- package/packages/dd-trace/src/service-naming/index.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/graphql.js +12 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/graphql.js +12 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -1
- package/packages/dd-trace/src/span_processor.js +0 -4
- package/packages/dd-trace/src/span_sampler.js +1 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +24 -12
- package/packages/dd-trace/src/telemetry/metrics.js +11 -1
- package/packages/diagnostics_channel/src/index.js +64 -0
- package/scripts/install_plugin_modules.js +1 -0
- package/packages/dd-trace/src/profiling/profilers/cpu.js +0 -126
- package/scripts/version.js +0 -66
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const log = require('../../../log')
|
|
4
|
+
const { Namespace } = require('../../../telemetry/metrics')
|
|
5
|
+
const { addMetricsToSpan, filterTags } = require('./span-tags')
|
|
6
|
+
const { IAST_TRACE_METRIC_PREFIX } = require('../tags')
|
|
7
|
+
|
|
8
|
+
const DD_IAST_METRICS_NAMESPACE = Symbol('_dd.iast.request.metrics.namespace')
|
|
9
|
+
|
|
10
|
+
function initRequestNamespace (context) {
|
|
11
|
+
if (!context) return
|
|
12
|
+
|
|
13
|
+
const namespace = new Namespace('iast')
|
|
14
|
+
context[DD_IAST_METRICS_NAMESPACE] = namespace
|
|
15
|
+
return namespace
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getNamespaceFromContext (context) {
|
|
19
|
+
return context && context[DD_IAST_METRICS_NAMESPACE]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function finalizeRequestNamespace (context, rootSpan) {
|
|
23
|
+
try {
|
|
24
|
+
const namespace = getNamespaceFromContext(context)
|
|
25
|
+
if (!namespace) return
|
|
26
|
+
|
|
27
|
+
const metrics = [...namespace.metrics.values()]
|
|
28
|
+
namespace.metrics.clear()
|
|
29
|
+
|
|
30
|
+
addMetricsToSpan(rootSpan, metrics, IAST_TRACE_METRIC_PREFIX)
|
|
31
|
+
|
|
32
|
+
merge(metrics)
|
|
33
|
+
} catch (e) {
|
|
34
|
+
log.error(e)
|
|
35
|
+
} finally {
|
|
36
|
+
if (context) {
|
|
37
|
+
delete context[DD_IAST_METRICS_NAMESPACE]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function merge (metrics) {
|
|
43
|
+
metrics.forEach(metric => metric.points.forEach(point => {
|
|
44
|
+
globalNamespace
|
|
45
|
+
.count(metric.metric, getTagsObject(metric.tags))
|
|
46
|
+
.inc(point[1])
|
|
47
|
+
}))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getTagsObject (tags) {
|
|
51
|
+
if (tags && tags.length > 0) {
|
|
52
|
+
return filterTags(tags)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class IastNamespace extends Namespace {
|
|
57
|
+
constructor () {
|
|
58
|
+
super('iast')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
reset () {
|
|
62
|
+
this.metrics.clear()
|
|
63
|
+
this.distributions.clear()
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const globalNamespace = new IastNamespace()
|
|
68
|
+
|
|
69
|
+
module.exports = {
|
|
70
|
+
initRequestNamespace,
|
|
71
|
+
getNamespaceFromContext,
|
|
72
|
+
finalizeRequestNamespace,
|
|
73
|
+
globalNamespace,
|
|
74
|
+
|
|
75
|
+
DD_IAST_METRICS_NAMESPACE
|
|
76
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
function addMetricsToSpan (rootSpan, metrics, tagPrefix) {
|
|
4
|
+
if (!rootSpan || !rootSpan.addTags || !metrics) return
|
|
5
|
+
|
|
6
|
+
const flattenMap = new Map()
|
|
7
|
+
metrics
|
|
8
|
+
.filter(data => data && data.metric)
|
|
9
|
+
.forEach(data => {
|
|
10
|
+
const name = taggedMetricName(data)
|
|
11
|
+
let total = flattenMap.get(name)
|
|
12
|
+
const value = flatten(data)
|
|
13
|
+
if (!total) {
|
|
14
|
+
total = value
|
|
15
|
+
} else {
|
|
16
|
+
total += value
|
|
17
|
+
}
|
|
18
|
+
flattenMap.set(name, total)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
for (const [key, value] of flattenMap) {
|
|
22
|
+
const tagName = `${tagPrefix}.${key}`
|
|
23
|
+
rootSpan.addTags({
|
|
24
|
+
[tagName]: value
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function flatten (metricData) {
|
|
30
|
+
return metricData.points && metricData.points.map(point => point[1]).reduce((total, value) => total + value, 0)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function taggedMetricName (data) {
|
|
34
|
+
const metric = data.metric
|
|
35
|
+
const tags = data.tags && filterTags(data.tags)
|
|
36
|
+
return !tags || !tags.length
|
|
37
|
+
? metric
|
|
38
|
+
: `${metric}.${processTagValue(tags)}`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function filterTags (tags) {
|
|
42
|
+
return tags.filter(tag => !tag.startsWith('lib_language') && !tag.startsWith('version'))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function processTagValue (tags) {
|
|
46
|
+
return tags.map(tag => tag.includes(':') ? tag.split(':')[1] : tag)
|
|
47
|
+
.join('_').replace(/\./g, '_')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = {
|
|
51
|
+
addMetricsToSpan,
|
|
52
|
+
filterTags
|
|
53
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Verbosity = {
|
|
4
|
+
OFF: 0,
|
|
5
|
+
MANDATORY: 1,
|
|
6
|
+
INFORMATION: 2,
|
|
7
|
+
DEBUG: 3
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function isDebugAllowed (value) {
|
|
11
|
+
return value >= Verbosity.DEBUG
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function isInfoAllowed (value) {
|
|
15
|
+
return value >= Verbosity.INFORMATION
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getVerbosity (verbosity) {
|
|
19
|
+
if (verbosity) {
|
|
20
|
+
verbosity = verbosity.toUpperCase()
|
|
21
|
+
return Verbosity[verbosity] !== undefined ? Verbosity[verbosity] : Verbosity.INFORMATION
|
|
22
|
+
} else {
|
|
23
|
+
return Verbosity.INFORMATION
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getName (verbosityValue) {
|
|
28
|
+
for (const name in Verbosity) {
|
|
29
|
+
if (Verbosity[name] === verbosityValue) {
|
|
30
|
+
return name
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return 'OFF'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
Verbosity,
|
|
38
|
+
isDebugAllowed,
|
|
39
|
+
isInfoAllowed,
|
|
40
|
+
getVerbosity,
|
|
41
|
+
getName
|
|
42
|
+
}
|
|
@@ -54,7 +54,11 @@ class VulnerabilityFormatter {
|
|
|
54
54
|
|
|
55
55
|
formatEvidence (type, evidence, sourcesIndexes, sources) {
|
|
56
56
|
if (!evidence.ranges) {
|
|
57
|
-
|
|
57
|
+
if (typeof evidence.value === 'undefined') {
|
|
58
|
+
return undefined
|
|
59
|
+
} else {
|
|
60
|
+
return { value: evidence.value }
|
|
61
|
+
}
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
return this._redactVulnearbilities
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
COMMAND_INJECTION: 'COMMAND_INJECTION',
|
|
3
|
+
HSTS_HEADER_MISSING: 'HSTS_HEADER_MISSING',
|
|
3
4
|
INSECURE_COOKIE: 'INSECURE_COOKIE',
|
|
4
5
|
LDAP_INJECTION: 'LDAP_INJECTION',
|
|
5
6
|
NO_HTTPONLY_COOKIE: 'NO_HTTPONLY_COOKIE',
|
|
@@ -9,5 +10,6 @@ module.exports = {
|
|
|
9
10
|
SSRF: 'SSRF',
|
|
10
11
|
UNVALIDATED_REDIRECT: 'UNVALIDATED_REDIRECT',
|
|
11
12
|
WEAK_CIPHER: 'WEAK_CIPHER',
|
|
12
|
-
WEAK_HASH: 'WEAK_HASH'
|
|
13
|
+
WEAK_HASH: 'WEAK_HASH',
|
|
14
|
+
XCONTENTTYPE_HEADER_MISSING: 'XCONTENTTYPE_HEADER_MISSING'
|
|
13
15
|
}
|
|
@@ -28,7 +28,7 @@ function addVulnerability (iastContext, vulnerability) {
|
|
|
28
28
|
|
|
29
29
|
function isValidVulnerability (vulnerability) {
|
|
30
30
|
return vulnerability && vulnerability.type &&
|
|
31
|
-
vulnerability.evidence &&
|
|
31
|
+
vulnerability.evidence &&
|
|
32
32
|
vulnerability.location && vulnerability.location.spanId
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -247,6 +247,10 @@ class Config {
|
|
|
247
247
|
process.env.DD_TELEMETRY_DEBUG,
|
|
248
248
|
false
|
|
249
249
|
)
|
|
250
|
+
const DD_TELEMETRY_METRICS_ENABLED = coalesce(
|
|
251
|
+
process.env.DD_TELEMETRY_METRICS_ENABLED,
|
|
252
|
+
false
|
|
253
|
+
)
|
|
250
254
|
const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
|
|
251
255
|
options.protocolVersion,
|
|
252
256
|
process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
|
|
@@ -277,7 +281,7 @@ class Config {
|
|
|
277
281
|
process.env.DD_TRACE_EXPERIMENTAL_B3_ENABLED,
|
|
278
282
|
false
|
|
279
283
|
)
|
|
280
|
-
const defaultPropagationStyle = ['
|
|
284
|
+
const defaultPropagationStyle = ['datadog', 'tracecontext']
|
|
281
285
|
if (isTrue(DD_TRACE_B3_ENABLED)) {
|
|
282
286
|
defaultPropagationStyle.push('b3')
|
|
283
287
|
defaultPropagationStyle.push('b3 single header')
|
|
@@ -317,13 +321,38 @@ class Config {
|
|
|
317
321
|
false
|
|
318
322
|
)
|
|
319
323
|
const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
|
|
320
|
-
|
|
324
|
+
coalesce(
|
|
325
|
+
options.spanAttributeSchema,
|
|
326
|
+
process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
|
|
327
|
+
)
|
|
328
|
+
)
|
|
329
|
+
const DD_TRACE_PEER_SERVICE_MAPPING = coalesce(
|
|
330
|
+
options.peerServiceMapping,
|
|
331
|
+
process.env.DD_TRACE_PEER_SERVICE_MAPPING ? fromEntries(
|
|
332
|
+
process.env.DD_TRACE_PEER_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
|
|
333
|
+
) : {}
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
const peerServiceSet = (
|
|
337
|
+
options.hasOwnProperty('spanComputePeerService') ||
|
|
338
|
+
process.env.hasOwnProperty('DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED')
|
|
339
|
+
)
|
|
340
|
+
const peerServiceValue = coalesce(
|
|
341
|
+
options.spanComputePeerService,
|
|
342
|
+
process.env.DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
const DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED = (
|
|
346
|
+
DD_TRACE_SPAN_ATTRIBUTE_SCHEMA === 'v0'
|
|
347
|
+
// In v0, peer service is computed only if it is explicitly set to true
|
|
348
|
+
? peerServiceSet && isTrue(peerServiceValue)
|
|
349
|
+
// In >v0, peer service is false only if it is explicitly set to false
|
|
350
|
+
: (peerServiceSet ? !isFalse(peerServiceValue) : true)
|
|
321
351
|
)
|
|
322
|
-
const DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED = process.env.DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
|
|
323
352
|
|
|
324
353
|
const DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED = coalesce(
|
|
325
|
-
|
|
326
|
-
|
|
354
|
+
options.spanRemoveIntegrationFromService,
|
|
355
|
+
isTrue(process.env.DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED)
|
|
327
356
|
)
|
|
328
357
|
const DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH = coalesce(
|
|
329
358
|
process.env.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
|
|
@@ -461,6 +490,12 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
461
490
|
true
|
|
462
491
|
)
|
|
463
492
|
|
|
493
|
+
const DD_IAST_TELEMETRY_VERBOSITY = coalesce(
|
|
494
|
+
iastOptions && iastOptions.telemetryVerbosity,
|
|
495
|
+
process.env.DD_IAST_TELEMETRY_VERBOSITY,
|
|
496
|
+
'INFORMATION'
|
|
497
|
+
)
|
|
498
|
+
|
|
464
499
|
const DD_CIVISIBILITY_GIT_UPLOAD_ENABLED = coalesce(
|
|
465
500
|
process.env.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED,
|
|
466
501
|
true
|
|
@@ -549,11 +584,9 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
549
584
|
exporters: DD_PROFILING_EXPORTERS
|
|
550
585
|
}
|
|
551
586
|
this.spanAttributeSchema = DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
|
|
552
|
-
this.spanComputePeerService =
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
)
|
|
556
|
-
this.traceRemoveIntegrationServiceNamesEnabled = DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED
|
|
587
|
+
this.spanComputePeerService = DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
|
|
588
|
+
this.spanRemoveIntegrationFromService = DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED
|
|
589
|
+
this.peerServiceMapping = DD_TRACE_PEER_SERVICE_MAPPING
|
|
557
590
|
this.lookup = options.lookup
|
|
558
591
|
this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
|
|
559
592
|
// Disabled for CI Visibility's agentless
|
|
@@ -561,7 +594,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
561
594
|
enabled: DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_TRACE_TELEMETRY_ENABLED),
|
|
562
595
|
heartbeatInterval: DD_TELEMETRY_HEARTBEAT_INTERVAL,
|
|
563
596
|
logCollection: isTrue(DD_TELEMETRY_LOG_COLLECTION_ENABLED),
|
|
564
|
-
debug: isTrue(DD_TELEMETRY_DEBUG)
|
|
597
|
+
debug: isTrue(DD_TELEMETRY_DEBUG),
|
|
598
|
+
metrics: isTrue(DD_TELEMETRY_METRICS_ENABLED)
|
|
565
599
|
}
|
|
566
600
|
this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
|
|
567
601
|
this.tagsHeaderMaxLength = parseInt(DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
|
|
@@ -590,7 +624,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
590
624
|
maxConcurrentRequests: DD_IAST_MAX_CONCURRENT_REQUESTS,
|
|
591
625
|
maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS,
|
|
592
626
|
deduplicationEnabled: DD_IAST_DEDUPLICATION_ENABLED,
|
|
593
|
-
redactionEnabled: DD_IAST_REDACTION_ENABLED
|
|
627
|
+
redactionEnabled: DD_IAST_REDACTION_ENABLED,
|
|
628
|
+
telemetryVerbosity: DD_IAST_TELEMETRY_VERBOSITY
|
|
594
629
|
}
|
|
595
630
|
|
|
596
631
|
this.isCiVisibility = isTrue(DD_IS_CIVISIBILITY)
|
|
@@ -28,6 +28,7 @@ module.exports = {
|
|
|
28
28
|
CLIENT_PORT_KEY: 'network.destination.port',
|
|
29
29
|
PEER_SERVICE_KEY: 'peer.service',
|
|
30
30
|
PEER_SERVICE_SOURCE_KEY: '_dd.peer.service.source',
|
|
31
|
+
PEER_SERVICE_REMAP_KEY: '_dd.peer.service.remapped_from',
|
|
31
32
|
SCI_REPOSITORY_URL: '_dd.git.repository_url',
|
|
32
33
|
SCI_COMMIT_SHA: '_dd.git.commit.sha'
|
|
33
34
|
}
|
|
@@ -127,4 +127,12 @@ class ExternalLogger {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
class NoopExternalLogger {
|
|
131
|
+
log () { }
|
|
132
|
+
enqueue () { }
|
|
133
|
+
shutdown () { }
|
|
134
|
+
flush () { }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
module.exports.ExternalLogger = ExternalLogger
|
|
138
|
+
module.exports.NoopExternalLogger = NoopExternalLogger
|
|
@@ -107,7 +107,7 @@ function extractTags (trace, span) {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
setSingleSpanIngestionTags(trace, context.
|
|
110
|
+
setSingleSpanIngestionTags(trace, context._spanSampling)
|
|
111
111
|
|
|
112
112
|
addTag(trace.meta, trace.metrics, 'language', 'javascript')
|
|
113
113
|
addTag(trace.meta, trace.metrics, PROCESS_ID, process.pid)
|
|
@@ -86,6 +86,13 @@ exports.datadog = function datadog (lambdaHandler) {
|
|
|
86
86
|
const context = extractContext(args)
|
|
87
87
|
|
|
88
88
|
checkTimeout(context)
|
|
89
|
-
|
|
89
|
+
const result = lambdaHandler.apply(this, args)
|
|
90
|
+
if (result && typeof result.then === 'function') {
|
|
91
|
+
return result.then((res) => {
|
|
92
|
+
clearTimeout(__lambdaTimeout)
|
|
93
|
+
return res
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
return result
|
|
90
97
|
}
|
|
91
98
|
}
|
|
@@ -10,6 +10,7 @@ const { timeInputToHrTime } = require('@opentelemetry/core')
|
|
|
10
10
|
const tracer = require('../../')
|
|
11
11
|
const DatadogSpan = require('../opentracing/span')
|
|
12
12
|
const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../constants')
|
|
13
|
+
const { SERVICE_NAME, RESOURCE_NAME } = require('../../../../ext/tags')
|
|
13
14
|
|
|
14
15
|
const SpanContext = require('./span_context')
|
|
15
16
|
|
|
@@ -40,7 +41,8 @@ class Span {
|
|
|
40
41
|
hostname: _tracer._hostname,
|
|
41
42
|
integrationName: 'otel',
|
|
42
43
|
tags: {
|
|
43
|
-
|
|
44
|
+
[SERVICE_NAME]: _tracer._service,
|
|
45
|
+
[RESOURCE_NAME]: spanName
|
|
44
46
|
}
|
|
45
47
|
}, _tracer._debug)
|
|
46
48
|
|
|
@@ -12,7 +12,8 @@ class DatadogSpanContext {
|
|
|
12
12
|
this._name = props.name
|
|
13
13
|
this._isFinished = props.isFinished || false
|
|
14
14
|
this._tags = props.tags || {}
|
|
15
|
-
this._sampling =
|
|
15
|
+
this._sampling = props.sampling || {}
|
|
16
|
+
this._spanSampling = undefined
|
|
16
17
|
this._baggageItems = props.baggageItems || {}
|
|
17
18
|
this._traceparent = props.traceparent
|
|
18
19
|
this._tracestate = props.tracestate
|
|
@@ -27,6 +27,7 @@ class DatadogTracer {
|
|
|
27
27
|
this._env = config.env
|
|
28
28
|
this._tags = config.tags
|
|
29
29
|
this._computePeerService = config.spanComputePeerService
|
|
30
|
+
this._peerServiceMapping = config.peerServiceMapping
|
|
30
31
|
this._logInjection = config.logInjection
|
|
31
32
|
this._debug = config.debug
|
|
32
33
|
this._prioritySampler = new PrioritySampler(config.env, config.sampler)
|
|
@@ -111,7 +111,12 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
111
111
|
const childOf = getTestParentSpan(this.tracer)
|
|
112
112
|
|
|
113
113
|
let testTags = {
|
|
114
|
-
...getTestCommonTags(
|
|
114
|
+
...getTestCommonTags(
|
|
115
|
+
testName,
|
|
116
|
+
testSuite,
|
|
117
|
+
this.frameworkVersion,
|
|
118
|
+
this.constructor.id
|
|
119
|
+
),
|
|
115
120
|
[COMPONENT]: this.constructor.id,
|
|
116
121
|
...extraTags
|
|
117
122
|
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
const {
|
|
4
4
|
CLIENT_PORT_KEY,
|
|
5
5
|
PEER_SERVICE_KEY,
|
|
6
|
-
PEER_SERVICE_SOURCE_KEY
|
|
6
|
+
PEER_SERVICE_SOURCE_KEY,
|
|
7
|
+
PEER_SERVICE_REMAP_KEY
|
|
7
8
|
} = require('../constants')
|
|
8
9
|
const TracingPlugin = require('./tracing')
|
|
9
10
|
|
|
@@ -34,9 +35,11 @@ class OutboundPlugin extends TracingPlugin {
|
|
|
34
35
|
* - If `peer.service` was defined _before_ we compute it (for example in custom instrumentation),
|
|
35
36
|
* `_dd.peer.service.source`'s value is `peer.service`
|
|
36
37
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
if (tags[PEER_SERVICE_KEY] !== undefined) {
|
|
39
|
+
return {
|
|
40
|
+
[PEER_SERVICE_KEY]: tags[PEER_SERVICE_KEY],
|
|
41
|
+
[PEER_SERVICE_SOURCE_KEY]: PEER_SERVICE_KEY
|
|
42
|
+
}
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
const sourceTags = [
|
|
@@ -52,23 +55,37 @@ class OutboundPlugin extends TracingPlugin {
|
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
|
-
return
|
|
58
|
+
return undefined
|
|
56
59
|
}
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
getPeerServiceRemap (peerData) {
|
|
62
|
+
/**
|
|
63
|
+
* If DD_TRACE_PEER_SERVICE_MAPPING is matched, we need to override the existing
|
|
64
|
+
* peer service and add the value we overrode.
|
|
65
|
+
*/
|
|
66
|
+
const peerService = peerData[PEER_SERVICE_KEY]
|
|
67
|
+
if (peerService && this.tracer._peerServiceMapping[peerService]) {
|
|
68
|
+
return {
|
|
69
|
+
...peerData,
|
|
70
|
+
[PEER_SERVICE_KEY]: this.tracer._peerServiceMapping[peerService],
|
|
71
|
+
[PEER_SERVICE_REMAP_KEY]: peerService
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return peerData
|
|
61
75
|
}
|
|
62
76
|
|
|
63
77
|
finish () {
|
|
64
|
-
|
|
78
|
+
this.tagPeerService(this.activeSpan)
|
|
79
|
+
super.finish(...arguments)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
tagPeerService (span) {
|
|
65
83
|
if (this.tracer._computePeerService) {
|
|
66
84
|
const peerData = this.getPeerService(span.context()._tags)
|
|
67
|
-
if (peerData) {
|
|
68
|
-
span.addTags(peerData)
|
|
85
|
+
if (peerData !== undefined) {
|
|
86
|
+
span.addTags(this.getPeerServiceRemap(peerData))
|
|
69
87
|
}
|
|
70
88
|
}
|
|
71
|
-
super.finish(...arguments)
|
|
72
89
|
}
|
|
73
90
|
|
|
74
91
|
connect (url) {
|
|
@@ -25,9 +25,31 @@ class Subscription {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
class StoreBinding {
|
|
29
|
+
constructor (event, transform) {
|
|
30
|
+
this._channel = dc.channel(event)
|
|
31
|
+
this._transform = data => {
|
|
32
|
+
const store = storage.getStore()
|
|
33
|
+
|
|
34
|
+
return !store || !store.noop
|
|
35
|
+
? transform(data)
|
|
36
|
+
: store
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
enable () {
|
|
41
|
+
this._channel.bindStore(storage, this._transform)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
disable () {
|
|
45
|
+
this._channel.unbindStore(storage, this._transform)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
28
49
|
module.exports = class Plugin {
|
|
29
50
|
constructor (tracer, tracerConfig) {
|
|
30
51
|
this._subscriptions = []
|
|
52
|
+
this._bindings = []
|
|
31
53
|
this._enabled = false
|
|
32
54
|
this._tracer = tracer
|
|
33
55
|
this.config = {} // plugin-specific configuration, unset until .configure() is called
|
|
@@ -53,6 +75,10 @@ module.exports = class Plugin {
|
|
|
53
75
|
this._subscriptions.push(new Subscription(channelName, handler))
|
|
54
76
|
}
|
|
55
77
|
|
|
78
|
+
addBind (channelName, transform) {
|
|
79
|
+
this._bindings.push(new StoreBinding(channelName, transform))
|
|
80
|
+
}
|
|
81
|
+
|
|
56
82
|
addError (error) {
|
|
57
83
|
const store = storage.getStore()
|
|
58
84
|
|
|
@@ -71,9 +97,11 @@ module.exports = class Plugin {
|
|
|
71
97
|
if (config.enabled && !this._enabled) {
|
|
72
98
|
this._enabled = true
|
|
73
99
|
this._subscriptions.forEach(sub => sub.enable())
|
|
100
|
+
this._bindings.forEach(sub => sub.enable())
|
|
74
101
|
} else if (!config.enabled && this._enabled) {
|
|
75
102
|
this._enabled = false
|
|
76
103
|
this._subscriptions.forEach(sub => sub.disable())
|
|
104
|
+
this._bindings.forEach(sub => sub.disable())
|
|
77
105
|
}
|
|
78
106
|
}
|
|
79
107
|
}
|
|
@@ -13,17 +13,7 @@ class TracingPlugin extends Plugin {
|
|
|
13
13
|
this.component = this.constructor.component || this.constructor.id
|
|
14
14
|
this.operation = this.constructor.operation
|
|
15
15
|
|
|
16
|
-
this.
|
|
17
|
-
this.start(message)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
this.addTraceSub('error', err => {
|
|
21
|
-
this.error(err)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
this.addTraceSub('finish', message => {
|
|
25
|
-
this.finish(message)
|
|
26
|
-
})
|
|
16
|
+
this.addTraceSubs()
|
|
27
17
|
}
|
|
28
18
|
|
|
29
19
|
get activeSpan () {
|
|
@@ -65,19 +55,43 @@ class TracingPlugin extends Plugin {
|
|
|
65
55
|
this.addError(error)
|
|
66
56
|
}
|
|
67
57
|
|
|
58
|
+
addTraceSubs () {
|
|
59
|
+
const events = ['start', 'end', 'asyncStart', 'asyncEnd', 'error', 'finish']
|
|
60
|
+
|
|
61
|
+
for (const event of events) {
|
|
62
|
+
const bindName = `bind${event.charAt(0).toUpperCase()}${event.slice(1)}`
|
|
63
|
+
|
|
64
|
+
if (this[event]) {
|
|
65
|
+
this.addTraceSub(event, message => {
|
|
66
|
+
this[event](message)
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (this[bindName]) {
|
|
71
|
+
this.addTraceBind(event, message => this[bindName](message))
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
68
76
|
addTraceSub (eventName, handler) {
|
|
69
|
-
this.
|
|
77
|
+
const prefix = this.constructor.prefix || `apm:${this.component}:${this.operation}`
|
|
78
|
+
this.addSub(`${prefix}:${eventName}`, handler)
|
|
70
79
|
}
|
|
71
80
|
|
|
72
|
-
|
|
73
|
-
const
|
|
81
|
+
addTraceBind (eventName, transform) {
|
|
82
|
+
const prefix = this.constructor.prefix || `apm:${this.component}:${this.operation}`
|
|
83
|
+
this.addBind(`${prefix}:${eventName}`, transform)
|
|
84
|
+
}
|
|
74
85
|
|
|
86
|
+
addError (error, span = this.activeSpan) {
|
|
75
87
|
if (!span._spanContext._tags['error']) {
|
|
88
|
+
// Errors may be wrapped in a context.
|
|
89
|
+
error = (error && error.error) || error
|
|
76
90
|
span.setTag('error', error || 1)
|
|
77
91
|
}
|
|
78
92
|
}
|
|
79
93
|
|
|
80
|
-
startSpan (name, { childOf, kind, meta, metrics, service, resource, type } = {}) {
|
|
94
|
+
startSpan (name, { childOf, kind, meta, metrics, service, resource, type } = {}, enter = true) {
|
|
81
95
|
const store = storage.getStore()
|
|
82
96
|
|
|
83
97
|
if (store && childOf === undefined) {
|
|
@@ -100,7 +114,10 @@ class TracingPlugin extends Plugin {
|
|
|
100
114
|
|
|
101
115
|
analyticsSampler.sample(span, this.config.measured)
|
|
102
116
|
|
|
103
|
-
|
|
117
|
+
// TODO: Remove this after migration to TracingChannel is done.
|
|
118
|
+
if (enter) {
|
|
119
|
+
storage.enterWith({ ...store, span })
|
|
120
|
+
}
|
|
104
121
|
|
|
105
122
|
return span
|
|
106
123
|
}
|
|
@@ -77,7 +77,7 @@ function filterSensitiveInfoFromRepository (repositoryUrl) {
|
|
|
77
77
|
|
|
78
78
|
return `${protocol}//${hostname}${pathname}`
|
|
79
79
|
} catch (e) {
|
|
80
|
-
return
|
|
80
|
+
return ''
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -399,6 +399,7 @@ module.exports = {
|
|
|
399
399
|
BITBUCKET_BRANCH,
|
|
400
400
|
BITBUCKET_COMMIT,
|
|
401
401
|
BITBUCKET_GIT_SSH_ORIGIN,
|
|
402
|
+
BITBUCKET_GIT_HTTP_ORIGIN,
|
|
402
403
|
BITBUCKET_TAG,
|
|
403
404
|
BITBUCKET_PIPELINE_UUID,
|
|
404
405
|
BITBUCKET_CLONE_DIR
|
|
@@ -416,7 +417,7 @@ module.exports = {
|
|
|
416
417
|
[CI_PIPELINE_URL]: url,
|
|
417
418
|
[GIT_BRANCH]: BITBUCKET_BRANCH,
|
|
418
419
|
[GIT_TAG]: BITBUCKET_TAG,
|
|
419
|
-
[GIT_REPOSITORY_URL]: BITBUCKET_GIT_SSH_ORIGIN,
|
|
420
|
+
[GIT_REPOSITORY_URL]: BITBUCKET_GIT_SSH_ORIGIN || BITBUCKET_GIT_HTTP_ORIGIN,
|
|
420
421
|
[CI_WORKSPACE_PATH]: BITBUCKET_CLONE_DIR,
|
|
421
422
|
[CI_PIPELINE_ID]: BITBUCKET_PIPELINE_UUID && BITBUCKET_PIPELINE_UUID.replace(/{|}/gm, '')
|
|
422
423
|
}
|