dd-trace 4.29.0 → 4.31.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 +7 -0
- package/ci/cypress/after-spec.js +1 -0
- package/index.d.ts +1502 -1485
- package/package.json +4 -4
- package/packages/datadog-core/src/utils/src/get.js +11 -0
- package/packages/datadog-core/src/utils/src/has.js +14 -0
- package/packages/datadog-core/src/utils/src/set.js +16 -0
- package/packages/datadog-instrumentations/src/amqplib.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +2 -1
- package/packages/datadog-instrumentations/src/grpc/server.js +3 -1
- package/packages/datadog-instrumentations/src/jest.js +11 -5
- package/packages/datadog-instrumentations/src/mocha.js +4 -1
- package/packages/datadog-instrumentations/src/mongodb-core.js +34 -3
- package/packages/datadog-instrumentations/src/playwright.js +78 -16
- package/packages/datadog-plugin-amqplib/src/consumer.js +5 -4
- package/packages/datadog-plugin-amqplib/src/producer.js +3 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -11
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -6
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +5 -7
- package/packages/datadog-plugin-cucumber/src/index.js +2 -2
- package/packages/datadog-plugin-cypress/src/after-spec.js +3 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +123 -58
- package/packages/datadog-plugin-cypress/src/support.js +50 -3
- package/packages/datadog-plugin-graphql/src/index.js +1 -1
- package/packages/datadog-plugin-graphql/src/resolve.js +10 -8
- package/packages/datadog-plugin-grpc/src/util.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +13 -4
- package/packages/datadog-plugin-kafkajs/src/consumer.js +4 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -5
- package/packages/datadog-plugin-mocha/src/index.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +34 -3
- package/packages/datadog-plugin-rhea/src/consumer.js +5 -3
- package/packages/datadog-plugin-rhea/src/producer.js +3 -4
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +23 -12
- package/packages/dd-trace/src/appsec/iast/index.js +10 -0
- package/packages/dd-trace/src/appsec/iast/path-line.js +9 -6
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +6 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +14 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +34 -27
- package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +39 -11
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +7 -6
- package/packages/dd-trace/src/appsec/recommended.json +67 -27
- package/packages/dd-trace/src/appsec/remote_config/index.js +1 -1
- package/packages/dd-trace/src/appsec/reporter.js +24 -11
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +6 -1
- package/packages/dd-trace/src/config.js +451 -460
- package/packages/dd-trace/src/data_streams_context.js +1 -1
- package/packages/dd-trace/src/datastreams/pathway.js +58 -1
- package/packages/dd-trace/src/datastreams/processor.js +3 -5
- package/packages/dd-trace/src/format.js +0 -1
- package/packages/dd-trace/src/lambda/runtime/ritm.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +22 -3
- package/packages/dd-trace/src/opentracing/span.js +2 -0
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/plugins/util/test.js +4 -2
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/priority_sampler.js +11 -6
- package/packages/dd-trace/src/profiling/exporters/agent.js +38 -2
- package/packages/dd-trace/src/telemetry/index.js +32 -33
- package/packages/dd-trace/src/tracer.js +3 -3
- package/register.js +4 -0
- package/CONTRIBUTING.md +0 -171
- package/MIGRATING.md +0 -224
- package/packages/dd-trace/src/external-logger/test/index.spec.js +0 -147
- package/scripts/check-proposal-labels.js +0 -71
- package/scripts/check_licenses.js +0 -69
- package/scripts/helpers/color.js +0 -8
- package/scripts/helpers/exec.js +0 -22
- package/scripts/helpers/title.js +0 -15
- package/scripts/install_plugin_modules.js +0 -248
- package/scripts/publish_docs.js +0 -21
- package/scripts/st.js +0 -105
- /package/packages/{utils → datadog-core/src/utils}/src/kebabcase.js +0 -0
- /package/packages/{utils → datadog-core/src/utils}/src/pick.js +0 -0
- /package/packages/{utils → datadog-core/src/utils}/src/uniq.js +0 -0
|
@@ -5,7 +5,8 @@ const { channel } = require('dc-polyfill')
|
|
|
5
5
|
const iastLog = require('./iast-log')
|
|
6
6
|
const Plugin = require('../../plugins/plugin')
|
|
7
7
|
const iastTelemetry = require('./telemetry')
|
|
8
|
-
const { getInstrumentedMetric, getExecutedMetric, TagKey, EXECUTED_SOURCE } =
|
|
8
|
+
const { getInstrumentedMetric, getExecutedMetric, TagKey, EXECUTED_SOURCE, formatTags } =
|
|
9
|
+
require('./telemetry/iast-metric')
|
|
9
10
|
const { storage } = require('../../../../datadog-core')
|
|
10
11
|
const { getIastContext } = require('./iast-context')
|
|
11
12
|
const instrumentations = require('../../../../datadog-instrumentations/src/helpers/instrumentations')
|
|
@@ -20,25 +21,29 @@ const instrumentations = require('../../../../datadog-instrumentations/src/helpe
|
|
|
20
21
|
* - tagKey can be only SOURCE_TYPE (Source) or VULNERABILITY_TYPE (Sink)
|
|
21
22
|
*/
|
|
22
23
|
class IastPluginSubscription {
|
|
23
|
-
constructor (moduleName, channelName,
|
|
24
|
+
constructor (moduleName, channelName, tagValues, tagKey = TagKey.VULNERABILITY_TYPE) {
|
|
24
25
|
this.moduleName = moduleName
|
|
25
26
|
this.channelName = channelName
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
this.
|
|
29
|
-
|
|
27
|
+
|
|
28
|
+
tagValues = Array.isArray(tagValues) ? tagValues : [tagValues]
|
|
29
|
+
this.tags = formatTags(tagValues, tagKey)
|
|
30
|
+
|
|
31
|
+
this.executedMetric = getExecutedMetric(tagKey)
|
|
32
|
+
this.instrumentedMetric = getInstrumentedMetric(tagKey)
|
|
33
|
+
|
|
30
34
|
this.moduleInstrumented = false
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
increaseInstrumented () {
|
|
34
|
-
if (this.moduleInstrumented)
|
|
38
|
+
if (!this.moduleInstrumented) {
|
|
39
|
+
this.moduleInstrumented = true
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
this.tags.forEach(tag => this.instrumentedMetric.inc(undefined, tag))
|
|
42
|
+
}
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
increaseExecuted (iastContext) {
|
|
41
|
-
this.executedMetric.inc(
|
|
46
|
+
this.tags.forEach(tag => this.executedMetric.inc(iastContext, tag))
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
matchesModuleInstrumented (name) {
|
|
@@ -76,10 +81,16 @@ class IastPlugin extends Plugin {
|
|
|
76
81
|
}
|
|
77
82
|
}
|
|
78
83
|
|
|
79
|
-
_execHandlerAndIncMetric ({ handler, metric,
|
|
84
|
+
_execHandlerAndIncMetric ({ handler, metric, tags, iastContext = getIastContext(storage.getStore()) }) {
|
|
80
85
|
try {
|
|
81
86
|
const result = handler()
|
|
82
|
-
iastTelemetry.isEnabled()
|
|
87
|
+
if (iastTelemetry.isEnabled()) {
|
|
88
|
+
if (Array.isArray(tags)) {
|
|
89
|
+
tags.forEach(tag => metric.inc(iastContext, tag))
|
|
90
|
+
} else {
|
|
91
|
+
metric.inc(iastContext, tags)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
83
94
|
return result
|
|
84
95
|
} catch (e) {
|
|
85
96
|
iastLog.errorAndPublish(e)
|
|
@@ -21,7 +21,11 @@ const requestStart = dc.channel('dd-trace:incomingHttpRequestStart')
|
|
|
21
21
|
const requestClose = dc.channel('dd-trace:incomingHttpRequestEnd')
|
|
22
22
|
const iastResponseEnd = dc.channel('datadog:iast:response-end')
|
|
23
23
|
|
|
24
|
+
let isEnabled = false
|
|
25
|
+
|
|
24
26
|
function enable (config, _tracer) {
|
|
27
|
+
if (isEnabled) return
|
|
28
|
+
|
|
25
29
|
iastTelemetry.configure(config, config.iast?.telemetryVerbosity)
|
|
26
30
|
enableAllAnalyzers(config)
|
|
27
31
|
enableTaintTracking(config.iast, iastTelemetry.verbosity)
|
|
@@ -30,9 +34,15 @@ function enable (config, _tracer) {
|
|
|
30
34
|
overheadController.configure(config.iast)
|
|
31
35
|
overheadController.startGlobalContext()
|
|
32
36
|
vulnerabilityReporter.start(config, _tracer)
|
|
37
|
+
|
|
38
|
+
isEnabled = true
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
function disable () {
|
|
42
|
+
if (!isEnabled) return
|
|
43
|
+
|
|
44
|
+
isEnabled = false
|
|
45
|
+
|
|
36
46
|
iastTelemetry.stop()
|
|
37
47
|
disableAllAnalyzers()
|
|
38
48
|
disableTaintTracking()
|
|
@@ -29,13 +29,16 @@ function getCallSiteInfo () {
|
|
|
29
29
|
const previousStackTraceLimit = Error.stackTraceLimit
|
|
30
30
|
let callsiteList
|
|
31
31
|
Error.stackTraceLimit = 100
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
try {
|
|
33
|
+
Error.prepareStackTrace = function (_, callsites) {
|
|
34
|
+
callsiteList = callsites
|
|
35
|
+
}
|
|
36
|
+
const e = new Error()
|
|
37
|
+
e.stack
|
|
38
|
+
} finally {
|
|
39
|
+
Error.prepareStackTrace = previousPrepareStackTrace
|
|
40
|
+
Error.stackTraceLimit = previousStackTraceLimit
|
|
34
41
|
}
|
|
35
|
-
const e = new Error()
|
|
36
|
-
e.stack
|
|
37
|
-
Error.prepareStackTrace = previousPrepareStackTrace
|
|
38
|
-
Error.stackTraceLimit = previousStackTraceLimit
|
|
39
42
|
return callsiteList
|
|
40
43
|
}
|
|
41
44
|
|
|
@@ -19,7 +19,7 @@ let onRemoveTransaction = (transactionId, iastContext) => {}
|
|
|
19
19
|
function onRemoveTransactionInformationTelemetry (transactionId, iastContext) {
|
|
20
20
|
const metrics = TaintedUtils.getMetrics(transactionId, iastTelemetry.verbosity)
|
|
21
21
|
if (metrics?.requestCount) {
|
|
22
|
-
REQUEST_TAINTED.
|
|
22
|
+
REQUEST_TAINTED.inc(iastContext, metrics.requestCount)
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -14,6 +14,10 @@ const {
|
|
|
14
14
|
HTTP_REQUEST_PATH_PARAM,
|
|
15
15
|
HTTP_REQUEST_URI
|
|
16
16
|
} = require('./source-types')
|
|
17
|
+
const { EXECUTED_SOURCE } = require('../telemetry/iast-metric')
|
|
18
|
+
|
|
19
|
+
const REQ_HEADER_TAGS = EXECUTED_SOURCE.formatTags(HTTP_REQUEST_HEADER_VALUE, HTTP_REQUEST_HEADER_NAME)
|
|
20
|
+
const REQ_URI_TAGS = EXECUTED_SOURCE.formatTags(HTTP_REQUEST_URI)
|
|
17
21
|
|
|
18
22
|
class TaintTrackingPlugin extends SourceIastPlugin {
|
|
19
23
|
constructor () {
|
|
@@ -97,7 +101,7 @@ class TaintTrackingPlugin extends SourceIastPlugin {
|
|
|
97
101
|
taintHeaders (headers, iastContext) {
|
|
98
102
|
this.execSource({
|
|
99
103
|
handler: () => taintObject(iastContext, headers, HTTP_REQUEST_HEADER_VALUE, true, HTTP_REQUEST_HEADER_NAME),
|
|
100
|
-
|
|
104
|
+
tags: REQ_HEADER_TAGS,
|
|
101
105
|
iastContext
|
|
102
106
|
})
|
|
103
107
|
}
|
|
@@ -107,7 +111,7 @@ class TaintTrackingPlugin extends SourceIastPlugin {
|
|
|
107
111
|
handler: function () {
|
|
108
112
|
req.url = newTaintedString(iastContext, req.url, HTTP_REQUEST_URI, HTTP_REQUEST_URI)
|
|
109
113
|
},
|
|
110
|
-
|
|
114
|
+
tags: REQ_URI_TAGS,
|
|
111
115
|
iastContext
|
|
112
116
|
})
|
|
113
117
|
}
|
|
@@ -14,7 +14,7 @@ const telemetryRewriter = {
|
|
|
14
14
|
|
|
15
15
|
const metrics = response.metrics
|
|
16
16
|
if (metrics && metrics.instrumentedPropagation) {
|
|
17
|
-
INSTRUMENTED_PROPAGATION.
|
|
17
|
+
INSTRUMENTED_PROPAGATION.inc(undefined, metrics.instrumentedPropagation)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
return response
|
|
@@ -12,6 +12,7 @@ const dc = require('dc-polyfill')
|
|
|
12
12
|
const hardcodedSecretCh = dc.channel('datadog:secrets:result')
|
|
13
13
|
let rewriter
|
|
14
14
|
let getPrepareStackTrace
|
|
15
|
+
let kSymbolPrepareStackTrace
|
|
15
16
|
|
|
16
17
|
let getRewriterOriginalPathAndLineFromSourceMap = function (path, line, column) {
|
|
17
18
|
return { path, line, column }
|
|
@@ -44,6 +45,7 @@ function getRewriter (telemetryVerbosity) {
|
|
|
44
45
|
const iastRewriter = require('@datadog/native-iast-rewriter')
|
|
45
46
|
const Rewriter = iastRewriter.Rewriter
|
|
46
47
|
getPrepareStackTrace = iastRewriter.getPrepareStackTrace
|
|
48
|
+
kSymbolPrepareStackTrace = iastRewriter.kSymbolPrepareStackTrace
|
|
47
49
|
|
|
48
50
|
const chainSourceMap = isFlagPresent('--enable-source-maps')
|
|
49
51
|
const getOriginalPathAndLineFromSourceMap = iastRewriter.getOriginalPathAndLineFromSourceMap
|
|
@@ -65,8 +67,9 @@ function getRewriter (telemetryVerbosity) {
|
|
|
65
67
|
return rewriter
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
let originalPrepareStackTrace
|
|
70
|
+
let originalPrepareStackTrace
|
|
69
71
|
function getPrepareStackTraceAccessor () {
|
|
72
|
+
originalPrepareStackTrace = Error.prepareStackTrace
|
|
70
73
|
let actual = getPrepareStackTrace(originalPrepareStackTrace)
|
|
71
74
|
return {
|
|
72
75
|
configurable: true,
|
|
@@ -121,7 +124,16 @@ function enableRewriter (telemetryVerbosity) {
|
|
|
121
124
|
|
|
122
125
|
function disableRewriter () {
|
|
123
126
|
shimmer.unwrap(Module.prototype, '_compile')
|
|
124
|
-
|
|
127
|
+
|
|
128
|
+
if (!Error.prepareStackTrace?.[kSymbolPrepareStackTrace]) return
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
delete Error.prepareStackTrace
|
|
132
|
+
|
|
133
|
+
Error.prepareStackTrace = originalPrepareStackTrace
|
|
134
|
+
} catch (e) {
|
|
135
|
+
iastLog.warn(e)
|
|
136
|
+
}
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
function getOriginalPathAndLineFromSourceMap ({ path, line, column }) {
|
|
@@ -19,6 +19,19 @@ const TagKey = {
|
|
|
19
19
|
PROPAGATION_TYPE: 'propagation_type'
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function formatTags (tags, tagKey) {
|
|
23
|
+
return tags.map(tagValue => tagValue ? [`${tagKey}:${tagValue.toLowerCase()}`] : undefined)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getNamespace (scope, context) {
|
|
27
|
+
let namespace = globalNamespace
|
|
28
|
+
|
|
29
|
+
if (scope === Scope.REQUEST) {
|
|
30
|
+
namespace = getNamespaceFromContext(context) || globalNamespace
|
|
31
|
+
}
|
|
32
|
+
return namespace
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
class IastMetric {
|
|
23
36
|
constructor (name, scope, tagKey) {
|
|
24
37
|
this.name = name
|
|
@@ -26,30 +39,26 @@ class IastMetric {
|
|
|
26
39
|
this.tagKey = tagKey
|
|
27
40
|
}
|
|
28
41
|
|
|
29
|
-
|
|
30
|
-
return
|
|
42
|
+
formatTags (...tags) {
|
|
43
|
+
return formatTags(tags, this.tagKey)
|
|
31
44
|
}
|
|
32
45
|
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
inc (context, tags, value = 1) {
|
|
47
|
+
const namespace = getNamespace(this.scope, context)
|
|
48
|
+
namespace.count(this.name, tags).inc(value)
|
|
35
49
|
}
|
|
50
|
+
}
|
|
36
51
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
.inc(value)
|
|
41
|
-
}
|
|
52
|
+
class NoTaggedIastMetric extends IastMetric {
|
|
53
|
+
constructor (name, scope) {
|
|
54
|
+
super(name, scope)
|
|
42
55
|
|
|
43
|
-
|
|
44
|
-
if (Array.isArray(tagValue)) {
|
|
45
|
-
tagValue.forEach(tag => this.addValue(value, tag, context))
|
|
46
|
-
} else {
|
|
47
|
-
this.addValue(value, tagValue, context)
|
|
48
|
-
}
|
|
56
|
+
this.tags = []
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
inc (
|
|
52
|
-
this.
|
|
59
|
+
inc (context, value = 1) {
|
|
60
|
+
const namespace = getNamespace(this.scope, context)
|
|
61
|
+
namespace.count(this.name, this.tags).inc(value)
|
|
53
62
|
}
|
|
54
63
|
}
|
|
55
64
|
|
|
@@ -61,21 +70,18 @@ function getInstrumentedMetric (tagKey) {
|
|
|
61
70
|
return tagKey === TagKey.VULNERABILITY_TYPE ? INSTRUMENTED_SINK : INSTRUMENTED_SOURCE
|
|
62
71
|
}
|
|
63
72
|
|
|
64
|
-
const INSTRUMENTED_PROPAGATION = new
|
|
73
|
+
const INSTRUMENTED_PROPAGATION = new NoTaggedIastMetric('instrumented.propagation', Scope.GLOBAL)
|
|
65
74
|
const INSTRUMENTED_SOURCE = new IastMetric('instrumented.source', Scope.GLOBAL, TagKey.SOURCE_TYPE)
|
|
66
75
|
const INSTRUMENTED_SINK = new IastMetric('instrumented.sink', Scope.GLOBAL, TagKey.VULNERABILITY_TYPE)
|
|
67
76
|
|
|
68
77
|
const EXECUTED_SOURCE = new IastMetric('executed.source', Scope.REQUEST, TagKey.SOURCE_TYPE)
|
|
69
78
|
const EXECUTED_SINK = new IastMetric('executed.sink', Scope.REQUEST, TagKey.VULNERABILITY_TYPE)
|
|
70
79
|
|
|
71
|
-
const REQUEST_TAINTED = new
|
|
80
|
+
const REQUEST_TAINTED = new NoTaggedIastMetric('request.tainted', Scope.REQUEST)
|
|
72
81
|
|
|
73
82
|
// DEBUG using metrics
|
|
74
|
-
const EXECUTED_PROPAGATION = new
|
|
75
|
-
const EXECUTED_TAINTED = new
|
|
76
|
-
|
|
77
|
-
// DEBUG using distribution endpoint
|
|
78
|
-
const INSTRUMENTATION_TIME = new IastMetric('instrumentation.time', Scope.GLOBAL)
|
|
83
|
+
const EXECUTED_PROPAGATION = new NoTaggedIastMetric('executed.propagation', Scope.REQUEST)
|
|
84
|
+
const EXECUTED_TAINTED = new NoTaggedIastMetric('executed.tainted', Scope.REQUEST)
|
|
79
85
|
|
|
80
86
|
module.exports = {
|
|
81
87
|
INSTRUMENTED_PROPAGATION,
|
|
@@ -89,13 +95,14 @@ module.exports = {
|
|
|
89
95
|
|
|
90
96
|
REQUEST_TAINTED,
|
|
91
97
|
|
|
92
|
-
INSTRUMENTATION_TIME,
|
|
93
|
-
|
|
94
98
|
PropagationType,
|
|
95
99
|
TagKey,
|
|
96
100
|
|
|
97
101
|
IastMetric,
|
|
102
|
+
NoTaggedIastMetric,
|
|
98
103
|
|
|
99
104
|
getExecutedMetric,
|
|
100
|
-
getInstrumentedMetric
|
|
105
|
+
getInstrumentedMetric,
|
|
106
|
+
|
|
107
|
+
formatTags
|
|
101
108
|
}
|
|
@@ -10,13 +10,13 @@ const DD_IAST_METRICS_NAMESPACE = Symbol('_dd.iast.request.metrics.namespace')
|
|
|
10
10
|
function initRequestNamespace (context) {
|
|
11
11
|
if (!context) return
|
|
12
12
|
|
|
13
|
-
const namespace = new
|
|
13
|
+
const namespace = new IastNamespace()
|
|
14
14
|
context[DD_IAST_METRICS_NAMESPACE] = namespace
|
|
15
15
|
return namespace
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function getNamespaceFromContext (context) {
|
|
19
|
-
return context
|
|
19
|
+
return context?.[DD_IAST_METRICS_NAMESPACE]
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function finalizeRequestNamespace (context, rootSpan) {
|
|
@@ -40,11 +40,14 @@ function finalizeRequestNamespace (context, rootSpan) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function merge (metrics) {
|
|
43
|
-
metrics.forEach(metric =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
metrics.forEach(metric => {
|
|
44
|
+
const { metric: metricName, type, tags, points } = metric
|
|
45
|
+
|
|
46
|
+
if (points?.length && type === 'count') {
|
|
47
|
+
const gMetric = globalNamespace.count(metricName, getTagsObject(tags))
|
|
48
|
+
points.forEach(point => gMetric.inc(point[1]))
|
|
49
|
+
}
|
|
50
|
+
})
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
function getTagsObject (tags) {
|
|
@@ -56,11 +59,34 @@ function getTagsObject (tags) {
|
|
|
56
59
|
class IastNamespace extends Namespace {
|
|
57
60
|
constructor () {
|
|
58
61
|
super('iast')
|
|
62
|
+
|
|
63
|
+
this.iastMetrics = new Map()
|
|
59
64
|
}
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
this.
|
|
63
|
-
|
|
66
|
+
getIastMetrics (name) {
|
|
67
|
+
let metrics = this.iastMetrics.get(name)
|
|
68
|
+
if (!metrics) {
|
|
69
|
+
metrics = new Map()
|
|
70
|
+
this.iastMetrics.set(name, metrics)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return metrics
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getMetric (name, tags, type = 'count') {
|
|
77
|
+
const metrics = this.getIastMetrics(name)
|
|
78
|
+
|
|
79
|
+
let metric = metrics.get(tags)
|
|
80
|
+
if (!metric) {
|
|
81
|
+
metric = super[type](name, Array.isArray(tags) ? [...tags] : tags)
|
|
82
|
+
metrics.set(tags, metric)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return metric
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
count (name, tags) {
|
|
89
|
+
return this.getMetric(name, tags, 'count')
|
|
64
90
|
}
|
|
65
91
|
}
|
|
66
92
|
|
|
@@ -72,5 +98,7 @@ module.exports = {
|
|
|
72
98
|
finalizeRequestNamespace,
|
|
73
99
|
globalNamespace,
|
|
74
100
|
|
|
75
|
-
DD_IAST_METRICS_NAMESPACE
|
|
101
|
+
DD_IAST_METRICS_NAMESPACE,
|
|
102
|
+
|
|
103
|
+
IastNamespace
|
|
76
104
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
function addMetricsToSpan (rootSpan, metrics, tagPrefix) {
|
|
4
|
-
if (!rootSpan
|
|
4
|
+
if (!rootSpan?.addTags || !metrics) return
|
|
5
5
|
|
|
6
6
|
const flattenMap = new Map()
|
|
7
7
|
metrics
|
|
8
|
-
.filter(data => data
|
|
8
|
+
.filter(data => data?.metric)
|
|
9
9
|
.forEach(data => {
|
|
10
10
|
const name = taggedMetricName(data)
|
|
11
11
|
let total = flattenMap.get(name)
|
|
@@ -27,19 +27,20 @@ function addMetricsToSpan (rootSpan, metrics, tagPrefix) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
function flatten (metricData) {
|
|
30
|
-
|
|
30
|
+
const { points } = metricData
|
|
31
|
+
return points ? points.map(point => point[1]).reduce((total, value) => total + value, 0) : 0
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
function taggedMetricName (data) {
|
|
34
35
|
const metric = data.metric
|
|
35
|
-
const tags =
|
|
36
|
-
return !tags
|
|
36
|
+
const tags = filterTags(data.tags)
|
|
37
|
+
return !tags?.length
|
|
37
38
|
? metric
|
|
38
39
|
: `${metric}.${processTagValue(tags)}`
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
function filterTags (tags) {
|
|
42
|
-
return tags
|
|
43
|
+
return tags?.filter(tag => !tag.startsWith('lib_language') && !tag.startsWith('version'))
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
function processTagValue (tags) {
|