dd-trace 2.39.0 → 2.41.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.
Files changed (62) hide show
  1. package/package.json +3 -3
  2. package/packages/datadog-instrumentations/src/cucumber.js +5 -2
  3. package/packages/datadog-instrumentations/src/grpc/client.js +44 -42
  4. package/packages/datadog-instrumentations/src/grpc/server.js +69 -60
  5. package/packages/datadog-instrumentations/src/http2/client.js +25 -26
  6. package/packages/datadog-instrumentations/src/jest.js +3 -1
  7. package/packages/datadog-instrumentations/src/kafkajs.js +11 -2
  8. package/packages/datadog-instrumentations/src/mocha.js +5 -3
  9. package/packages/datadog-instrumentations/src/redis.js +48 -5
  10. package/packages/datadog-plugin-cypress/src/plugin.js +4 -2
  11. package/packages/datadog-plugin-grpc/src/client.js +29 -11
  12. package/packages/datadog-plugin-grpc/src/server.js +22 -6
  13. package/packages/datadog-plugin-http2/src/client.js +46 -29
  14. package/packages/datadog-plugin-kafkajs/src/producer.js +6 -1
  15. package/packages/datadog-plugin-openai/src/services.js +14 -10
  16. package/packages/datadog-plugin-router/src/index.js +1 -1
  17. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +3 -0
  18. package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +7 -1
  19. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +3 -0
  20. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +19 -15
  21. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +5 -2
  22. package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +2 -0
  23. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +3 -1
  24. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +18 -19
  25. package/packages/dd-trace/src/appsec/iast/analyzers/weak-cipher-analyzer.js +3 -0
  26. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +3 -0
  27. package/packages/dd-trace/src/appsec/iast/iast-log.js +1 -1
  28. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +205 -0
  29. package/packages/dd-trace/src/appsec/iast/index.js +6 -5
  30. package/packages/dd-trace/src/appsec/iast/tags.js +2 -1
  31. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +6 -6
  32. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +3 -3
  33. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +23 -4
  34. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +32 -16
  35. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +33 -0
  36. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +23 -16
  37. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +76 -37
  38. package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +101 -0
  39. package/packages/dd-trace/src/appsec/iast/telemetry/index.js +45 -0
  40. package/packages/dd-trace/src/appsec/iast/telemetry/{logs.js → log/index.js} +5 -5
  41. package/packages/dd-trace/src/appsec/iast/telemetry/{log_collector.js → log/log-collector.js} +1 -1
  42. package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +76 -0
  43. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +53 -0
  44. package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +42 -0
  45. package/packages/dd-trace/src/config.js +21 -2
  46. package/packages/dd-trace/src/constants.js +1 -0
  47. package/packages/dd-trace/src/dogstatsd.js +14 -1
  48. package/packages/dd-trace/src/metrics.js +2 -2
  49. package/packages/dd-trace/src/opentracing/tracer.js +1 -0
  50. package/packages/dd-trace/src/plugins/ci_plugin.js +6 -1
  51. package/packages/dd-trace/src/plugins/outbound.js +29 -12
  52. package/packages/dd-trace/src/plugins/plugin.js +28 -0
  53. package/packages/dd-trace/src/plugins/tracing.js +33 -16
  54. package/packages/dd-trace/src/plugins/util/ci.js +1 -1
  55. package/packages/dd-trace/src/plugins/util/test.js +55 -11
  56. package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -22
  57. package/packages/dd-trace/src/profiling/config.js +0 -3
  58. package/packages/dd-trace/src/profiling/index.js +0 -2
  59. package/packages/dd-trace/src/profiling/profilers/wall.js +23 -11
  60. package/packages/diagnostics_channel/src/index.js +64 -0
  61. package/packages/dd-trace/src/profiling/profilers/cpu.js +0 -126
  62. /package/packages/dd-trace/src/appsec/iast/taint-tracking/{origin-types.js → source-types.js} +0 -0
@@ -4,30 +4,45 @@ const TaintedUtils = require('@datadog/native-iast-taint-tracking')
4
4
  const { storage } = require('../../../../../datadog-core')
5
5
  const iastContextFunctions = require('../iast-context')
6
6
  const iastLog = require('../iast-log')
7
+ const { EXECUTED_PROPAGATION } = require('../telemetry/iast-metric')
8
+ const { isDebugAllowed } = require('../telemetry/verbosity')
7
9
 
8
10
  function noop (res) { return res }
9
- const TaintTrackingDummy = {
11
+ // NOTE: methods of this object must be synchronized with csi-methods.js file definitions!
12
+ // Otherwise you may end up rewriting a method and not providing its rewritten implementation
13
+ const TaintTrackingNoop = {
10
14
  plusOperator: noop,
11
- trim: noop,
12
- trimEnd: noop,
13
15
  concat: noop,
14
- substring: noop,
15
- substr: noop,
16
+ replace: noop,
16
17
  slice: noop,
17
- replace: noop
18
+ substr: noop,
19
+ substring: noop,
20
+ trim: noop,
21
+ trimEnd: noop
18
22
  }
19
23
 
20
- function getTransactionId () {
21
- const store = storage.getStore()
22
- const iastContext = iastContextFunctions.getIastContext(store)
24
+ function getTransactionId (iastContext) {
23
25
  return iastContext && iastContext[iastContextFunctions.IAST_TRANSACTION_ID]
24
26
  }
25
27
 
26
- function getFilteredCsiFn (cb, filter) {
28
+ function getContextDefault () {
29
+ const store = storage.getStore()
30
+ return iastContextFunctions.getIastContext(store)
31
+ }
32
+
33
+ function getContextDebug () {
34
+ const iastContext = getContextDefault()
35
+ EXECUTED_PROPAGATION.inc(null, iastContext)
36
+ return iastContext
37
+ }
38
+
39
+ function getFilteredCsiFn (cb, filter, getContext) {
27
40
  return function csiCall (res, fn, target, ...rest) {
28
41
  try {
29
42
  if (filter(res, fn, target)) { return res }
30
- const transactionId = getTransactionId()
43
+
44
+ const context = getContext()
45
+ const transactionId = getTransactionId(context)
31
46
  if (transactionId) {
32
47
  return cb(transactionId, res, target, ...rest)
33
48
  }
@@ -47,7 +62,7 @@ function isValidCsiMethod (fn, protos) {
47
62
  return protos.some(proto => fn === proto)
48
63
  }
49
64
 
50
- function getCsiFn (cb, ...protos) {
65
+ function getCsiFn (cb, getContext, ...protos) {
51
66
  let filter
52
67
  if (!protos || protos.length === 0) {
53
68
  filter = (res, fn, target) => notString(res, target)
@@ -57,49 +72,73 @@ function getCsiFn (cb, ...protos) {
57
72
  } else {
58
73
  filter = (res, fn, target) => notString(res, target) || !isValidCsiMethod(fn, protos)
59
74
  }
60
- return getFilteredCsiFn(cb, filter)
75
+ return getFilteredCsiFn(cb, filter, getContext)
61
76
  }
62
77
 
63
- function csiMethodsDefaults (names, excluded) {
78
+ function csiMethodsDefaults (names, excluded, getContext) {
64
79
  const impl = {}
65
80
  names.forEach(name => {
66
81
  if (excluded.indexOf(name) !== -1) return
67
82
  impl[name] = getCsiFn(
68
83
  (transactionId, res, target, ...rest) => TaintedUtils[name](transactionId, res, target, ...rest),
84
+ getContext,
69
85
  String.prototype[name]
70
86
  )
71
87
  })
72
88
  return impl
73
89
  }
74
90
 
75
- const csiMethodsOverrides = {
76
- plusOperator: function (res, op1, op2) {
77
- try {
78
- if (notString(res) || (notString(op1) && notString(op2))) { return res }
79
- const transactionId = getTransactionId()
80
- if (transactionId) {
81
- return TaintedUtils.concat(transactionId, res, op1, op2)
91
+ function csiMethodsOverrides (getContext) {
92
+ return {
93
+ plusOperator: function (res, op1, op2) {
94
+ try {
95
+ if (notString(res) || (notString(op1) && notString(op2))) { return res }
96
+ const iastContext = getContext()
97
+ const transactionId = getTransactionId(iastContext)
98
+ if (transactionId) {
99
+ return TaintedUtils.concat(transactionId, res, op1, op2)
100
+ }
101
+ } catch (e) {
102
+ iastLog.error(`Error invoking CSI plusOperator`)
103
+ .errorAndPublish(e)
82
104
  }
83
- } catch (e) {
84
- iastLog.error(`Error invoking CSI plusOperator`)
85
- .errorAndPublish(e)
86
- }
87
- return res
88
- },
105
+ return res
106
+ },
107
+
108
+ trim: getCsiFn(
109
+ (transactionId, res, target) => TaintedUtils.trim(transactionId, res, target),
110
+ getContext,
111
+ String.prototype.trim,
112
+ String.prototype.trimStart
113
+ )
114
+ }
115
+ }
116
+
117
+ function createImplWith (getContext) {
118
+ const methodNames = Object.keys(TaintTrackingNoop)
119
+ const overrides = csiMethodsOverrides(getContext)
120
+
121
+ // impls could be cached but at the moment there is only one invocation to getTaintTrackingImpl
122
+ return {
123
+ ...csiMethodsDefaults(methodNames, Object.keys(overrides), getContext),
124
+ ...overrides
125
+ }
126
+ }
127
+
128
+ function getTaintTrackingImpl (telemetryVerbosity, dummy = false) {
129
+ if (dummy) return TaintTrackingNoop
89
130
 
90
- trim: getCsiFn(
91
- (transactionId, res, target) => TaintedUtils.trim(transactionId, res, target),
92
- String.prototype.trim,
93
- String.prototype.trimStart
94
- )
131
+ // with Verbosity.DEBUG every invocation of a TaintedUtils method increases the EXECUTED_PROPAGATION metric
132
+ return isDebugAllowed(telemetryVerbosity)
133
+ ? createImplWith(getContextDebug)
134
+ : createImplWith(getContextDefault)
95
135
  }
96
136
 
97
- const TaintTracking = {
98
- ...csiMethodsDefaults(Object.keys(TaintTrackingDummy), Object.keys(csiMethodsOverrides)),
99
- ...csiMethodsOverrides
137
+ function getTaintTrackingNoop () {
138
+ return getTaintTrackingImpl(null, true)
100
139
  }
101
140
 
102
141
  module.exports = {
103
- TaintTracking,
104
- TaintTrackingDummy
142
+ getTaintTrackingImpl,
143
+ getTaintTrackingNoop
105
144
  }
@@ -0,0 +1,101 @@
1
+ 'use strict'
2
+
3
+ const { getNamespaceFromContext, globalNamespace } = require('./namespaces')
4
+
5
+ const Scope = {
6
+ GLOBAL: 'GLOBAL',
7
+ REQUEST: 'REQUEST'
8
+ }
9
+
10
+ const PropagationType = {
11
+ STRING: 'STRING',
12
+ JSON: 'JSON',
13
+ URL: 'URL'
14
+ }
15
+
16
+ const TagKey = {
17
+ VULNERABILITY_TYPE: 'vulnerability_type',
18
+ SOURCE_TYPE: 'source_type',
19
+ PROPAGATION_TYPE: 'propagation_type'
20
+ }
21
+
22
+ class IastMetric {
23
+ constructor (name, scope, tagKey) {
24
+ this.name = name
25
+ this.scope = scope
26
+ this.tagKey = tagKey
27
+ }
28
+
29
+ getNamespace (context) {
30
+ return getNamespaceFromContext(context) || globalNamespace
31
+ }
32
+
33
+ getTag (tagValue) {
34
+ return tagValue ? { [this.tagKey]: tagValue } : undefined
35
+ }
36
+
37
+ addValue (value, tagValue, context) {
38
+ this.getNamespace(context)
39
+ .count(this.name, this.getTag(tagValue))
40
+ .inc(value)
41
+ }
42
+
43
+ add (value, tagValue, context) {
44
+ if (Array.isArray(tagValue)) {
45
+ tagValue.forEach(tag => this.addValue(value, tag, context))
46
+ } else {
47
+ this.addValue(value, tagValue, context)
48
+ }
49
+ }
50
+
51
+ inc (tagValue, context) {
52
+ this.add(1, tagValue, context)
53
+ }
54
+ }
55
+
56
+ function getExecutedMetric (tagKey) {
57
+ return tagKey === TagKey.VULNERABILITY_TYPE ? EXECUTED_SINK : EXECUTED_SOURCE
58
+ }
59
+
60
+ function getInstrumentedMetric (tagKey) {
61
+ return tagKey === TagKey.VULNERABILITY_TYPE ? INSTRUMENTED_SINK : INSTRUMENTED_SOURCE
62
+ }
63
+
64
+ const INSTRUMENTED_PROPAGATION = new IastMetric('instrumented.propagation', Scope.GLOBAL)
65
+ const INSTRUMENTED_SOURCE = new IastMetric('instrumented.source', Scope.GLOBAL, TagKey.SOURCE_TYPE)
66
+ const INSTRUMENTED_SINK = new IastMetric('instrumented.sink', Scope.GLOBAL, TagKey.VULNERABILITY_TYPE)
67
+
68
+ const EXECUTED_SOURCE = new IastMetric('executed.source', Scope.REQUEST, TagKey.SOURCE_TYPE)
69
+ const EXECUTED_SINK = new IastMetric('executed.sink', Scope.REQUEST, TagKey.VULNERABILITY_TYPE)
70
+
71
+ const REQUEST_TAINTED = new IastMetric('request.tainted', Scope.REQUEST)
72
+
73
+ // DEBUG using metrics
74
+ const EXECUTED_PROPAGATION = new IastMetric('executed.propagation', Scope.REQUEST)
75
+ const EXECUTED_TAINTED = new IastMetric('executed.tainted', Scope.REQUEST)
76
+
77
+ // DEBUG using distribution endpoint
78
+ const INSTRUMENTATION_TIME = new IastMetric('instrumentation.time', Scope.GLOBAL)
79
+
80
+ module.exports = {
81
+ INSTRUMENTED_PROPAGATION,
82
+ INSTRUMENTED_SOURCE,
83
+ INSTRUMENTED_SINK,
84
+
85
+ EXECUTED_PROPAGATION,
86
+ EXECUTED_SOURCE,
87
+ EXECUTED_SINK,
88
+ EXECUTED_TAINTED,
89
+
90
+ REQUEST_TAINTED,
91
+
92
+ INSTRUMENTATION_TIME,
93
+
94
+ PropagationType,
95
+ TagKey,
96
+
97
+ IastMetric,
98
+
99
+ getExecutedMetric,
100
+ getInstrumentedMetric
101
+ }
@@ -0,0 +1,45 @@
1
+ 'use strict'
2
+
3
+ const telemetryMetrics = require('../../../telemetry/metrics')
4
+ const telemetryLogs = require('./log')
5
+ const { Verbosity, getVerbosity } = require('./verbosity')
6
+ const { initRequestNamespace, finalizeRequestNamespace, globalNamespace } = require('./namespaces')
7
+
8
+ class Telemetry {
9
+ configure (config, verbosity) {
10
+ // in order to telemetry be enabled, tracer telemetry and metrics collection have to be enabled
11
+ this.enabled = config && config.telemetry && config.telemetry.enabled && config.telemetry.metrics
12
+ this.verbosity = this.enabled ? getVerbosity(verbosity) : Verbosity.OFF
13
+
14
+ if (this.enabled) {
15
+ telemetryMetrics.manager.set('iast', globalNamespace)
16
+ }
17
+
18
+ telemetryLogs.start()
19
+ }
20
+
21
+ stop () {
22
+ this.enabled = false
23
+ telemetryMetrics.manager.delete('iast')
24
+
25
+ telemetryLogs.stop()
26
+ }
27
+
28
+ isEnabled () {
29
+ return this.enabled
30
+ }
31
+
32
+ onRequestStart (context) {
33
+ if (this.isEnabled() && this.verbosity !== Verbosity.OFF) {
34
+ initRequestNamespace(context)
35
+ }
36
+ }
37
+
38
+ onRequestEnd (context, rootSpan) {
39
+ if (this.isEnabled() && this.verbosity !== Verbosity.OFF) {
40
+ finalizeRequestNamespace(context, rootSpan)
41
+ }
42
+ }
43
+ }
44
+
45
+ module.exports = new Telemetry()
@@ -1,9 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const dc = require('../../../../../diagnostics_channel')
4
- const logCollector = require('./log_collector')
5
- const { sendData } = require('../../../telemetry/send-data')
6
- const log = require('../../../log')
3
+ const dc = require('../../../../../../diagnostics_channel')
4
+ const logCollector = require('./log-collector')
5
+ const { sendData } = require('../../../../telemetry/send-data')
6
+ const log = require('../../../../log')
7
7
 
8
8
  const telemetryStartChannel = dc.channel('datadog:telemetry:start')
9
9
  const telemetryStopChannel = dc.channel('datadog:telemetry:stop')
@@ -37,7 +37,7 @@ function isLogCollectionEnabled (config) {
37
37
 
38
38
  function onTelemetryStart (msg) {
39
39
  if (!msg || !isLogCollectionEnabled(msg.config)) {
40
- log.info('IAST telemetry logs start received but log collection is not enabled or configuration is incorrect')
40
+ log.info('IAST telemetry logs start event received but log collection is not enabled or configuration is incorrect')
41
41
  return false
42
42
  }
43
43
 
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const log = require('../../../log')
3
+ const log = require('../../../../log')
4
4
 
5
5
  const logs = new Map()
6
6
 
@@ -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
+ }
@@ -244,6 +244,10 @@ class Config {
244
244
  process.env.DD_TELEMETRY_DEBUG,
245
245
  false
246
246
  )
247
+ const DD_TELEMETRY_METRICS_ENABLED = coalesce(
248
+ process.env.DD_TELEMETRY_METRICS_ENABLED,
249
+ false
250
+ )
247
251
  const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
248
252
  options.protocolVersion,
249
253
  process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
@@ -316,6 +320,12 @@ class Config {
316
320
  const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
317
321
  process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
318
322
  )
323
+ const DD_TRACE_PEER_SERVICE_MAPPING = coalesce(
324
+ options.peerServiceMapping,
325
+ process.env.DD_TRACE_PEER_SERVICE_MAPPING ? fromEntries(
326
+ process.env.DD_TRACE_PEER_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
327
+ ) : {}
328
+ )
319
329
  const DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED = process.env.DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
320
330
 
321
331
  const DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED = coalesce(
@@ -458,6 +468,12 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
458
468
  true
459
469
  )
460
470
 
471
+ const DD_IAST_TELEMETRY_VERBOSITY = coalesce(
472
+ iastOptions && iastOptions.telemetryVerbosity,
473
+ process.env.DD_IAST_TELEMETRY_VERBOSITY,
474
+ 'INFORMATION'
475
+ )
476
+
461
477
  const DD_CIVISIBILITY_GIT_UPLOAD_ENABLED = coalesce(
462
478
  process.env.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED,
463
479
  true
@@ -551,6 +567,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
551
567
  : true
552
568
  )
553
569
  this.traceRemoveIntegrationServiceNamesEnabled = DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED
570
+ this.peerServiceMapping = DD_TRACE_PEER_SERVICE_MAPPING
554
571
  this.lookup = options.lookup
555
572
  this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
556
573
  // Disabled for CI Visibility's agentless
@@ -558,7 +575,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
558
575
  enabled: DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_TRACE_TELEMETRY_ENABLED),
559
576
  heartbeatInterval: DD_TELEMETRY_HEARTBEAT_INTERVAL,
560
577
  logCollection: isTrue(DD_TELEMETRY_LOG_COLLECTION_ENABLED),
561
- debug: isTrue(DD_TELEMETRY_DEBUG)
578
+ debug: isTrue(DD_TELEMETRY_DEBUG),
579
+ metrics: isTrue(DD_TELEMETRY_METRICS_ENABLED)
562
580
  }
563
581
  this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
564
582
  this.tagsHeaderMaxLength = parseInt(DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
@@ -587,7 +605,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
587
605
  maxConcurrentRequests: DD_IAST_MAX_CONCURRENT_REQUESTS,
588
606
  maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS,
589
607
  deduplicationEnabled: DD_IAST_DEDUPLICATION_ENABLED,
590
- redactionEnabled: DD_IAST_REDACTION_ENABLED
608
+ redactionEnabled: DD_IAST_REDACTION_ENABLED,
609
+ telemetryVerbosity: DD_IAST_TELEMETRY_VERBOSITY
591
610
  }
592
611
 
593
612
  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
  }
@@ -143,4 +143,17 @@ class DogStatsDClient {
143
143
  }
144
144
  }
145
145
 
146
- module.exports = DogStatsDClient
146
+ class NoopDogStatsDClient {
147
+ gauge () { }
148
+
149
+ increment () { }
150
+
151
+ distribution () { }
152
+
153
+ flush () { }
154
+ }
155
+
156
+ module.exports = {
157
+ DogStatsDClient,
158
+ NoopDogStatsDClient
159
+ }
@@ -5,7 +5,7 @@
5
5
  const { URL, format } = require('url')
6
6
  const v8 = require('v8')
7
7
  const os = require('os')
8
- const Client = require('./dogstatsd')
8
+ const { DogStatsDClient } = require('./dogstatsd')
9
9
  const log = require('./log')
10
10
  const Histogram = require('./histogram')
11
11
  const { performance } = require('perf_hooks')
@@ -67,7 +67,7 @@ module.exports = {
67
67
  }))
68
68
  }
69
69
 
70
- client = new Client(clientConfig)
70
+ client = new DogStatsDClient(clientConfig)
71
71
 
72
72
  time = process.hrtime()
73
73
 
@@ -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(testName, testSuite, this.frameworkVersion),
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
  }