dd-trace 3.26.0 → 3.28.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
+ }
@@ -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,
@@ -319,6 +323,12 @@ class Config {
319
323
  const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
320
324
  process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
321
325
  )
326
+ const DD_TRACE_PEER_SERVICE_MAPPING = coalesce(
327
+ options.peerServiceMapping,
328
+ process.env.DD_TRACE_PEER_SERVICE_MAPPING ? fromEntries(
329
+ process.env.DD_TRACE_PEER_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
330
+ ) : {}
331
+ )
322
332
  const DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED = process.env.DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
323
333
 
324
334
  const DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED = coalesce(
@@ -461,6 +471,12 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
461
471
  true
462
472
  )
463
473
 
474
+ const DD_IAST_TELEMETRY_VERBOSITY = coalesce(
475
+ iastOptions && iastOptions.telemetryVerbosity,
476
+ process.env.DD_IAST_TELEMETRY_VERBOSITY,
477
+ 'INFORMATION'
478
+ )
479
+
464
480
  const DD_CIVISIBILITY_GIT_UPLOAD_ENABLED = coalesce(
465
481
  process.env.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED,
466
482
  true
@@ -554,6 +570,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
554
570
  : true
555
571
  )
556
572
  this.traceRemoveIntegrationServiceNamesEnabled = DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED
573
+ this.peerServiceMapping = DD_TRACE_PEER_SERVICE_MAPPING
557
574
  this.lookup = options.lookup
558
575
  this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
559
576
  // Disabled for CI Visibility's agentless
@@ -561,7 +578,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
561
578
  enabled: DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_TRACE_TELEMETRY_ENABLED),
562
579
  heartbeatInterval: DD_TELEMETRY_HEARTBEAT_INTERVAL,
563
580
  logCollection: isTrue(DD_TELEMETRY_LOG_COLLECTION_ENABLED),
564
- debug: isTrue(DD_TELEMETRY_DEBUG)
581
+ debug: isTrue(DD_TELEMETRY_DEBUG),
582
+ metrics: isTrue(DD_TELEMETRY_METRICS_ENABLED)
565
583
  }
566
584
  this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
567
585
  this.tagsHeaderMaxLength = parseInt(DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
@@ -590,7 +608,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
590
608
  maxConcurrentRequests: DD_IAST_MAX_CONCURRENT_REQUESTS,
591
609
  maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS,
592
610
  deduplicationEnabled: DD_IAST_DEDUPLICATION_ENABLED,
593
- redactionEnabled: DD_IAST_REDACTION_ENABLED
611
+ redactionEnabled: DD_IAST_REDACTION_ENABLED,
612
+ telemetryVerbosity: DD_IAST_TELEMETRY_VERBOSITY
594
613
  }
595
614
 
596
615
  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
  }