dd-trace 3.14.1 → 3.16.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 (187) hide show
  1. package/LICENSE-3rdparty.csv +2 -2
  2. package/README.md +9 -5
  3. package/ci/init.js +9 -1
  4. package/ext/exporters.d.ts +2 -1
  5. package/ext/exporters.js +2 -1
  6. package/index.d.ts +36 -3
  7. package/package.json +21 -19
  8. package/packages/datadog-instrumentations/src/cucumber.js +80 -3
  9. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +100 -27
  10. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  11. package/packages/datadog-instrumentations/src/jest.js +35 -3
  12. package/packages/datadog-instrumentations/src/ldapjs.js +12 -2
  13. package/packages/datadog-instrumentations/src/mariadb.js +130 -11
  14. package/packages/datadog-instrumentations/src/mocha.js +30 -6
  15. package/packages/datadog-instrumentations/src/mongodb-core.js +8 -2
  16. package/packages/datadog-instrumentations/src/mongoose.js +1 -1
  17. package/packages/datadog-instrumentations/src/next.js +33 -4
  18. package/packages/datadog-instrumentations/src/playwright.js +42 -13
  19. package/packages/datadog-plugin-amqp10/src/consumer.js +1 -1
  20. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  21. package/packages/datadog-plugin-amqp10/src/producer.js +3 -2
  22. package/packages/datadog-plugin-amqplib/src/client.js +3 -2
  23. package/packages/datadog-plugin-amqplib/src/consumer.js +1 -1
  24. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  25. package/packages/datadog-plugin-amqplib/src/producer.js +3 -2
  26. package/packages/datadog-plugin-aws-sdk/src/base.js +7 -2
  27. package/packages/datadog-plugin-aws-sdk/src/index.js +1 -1
  28. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +2 -0
  29. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +2 -0
  30. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -0
  31. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -0
  32. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +2 -0
  33. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +2 -0
  34. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +2 -0
  35. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -0
  36. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -0
  37. package/packages/datadog-plugin-bunyan/src/index.js +1 -1
  38. package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -2
  39. package/packages/datadog-plugin-connect/src/index.js +1 -1
  40. package/packages/datadog-plugin-couchbase/src/index.js +1 -1
  41. package/packages/datadog-plugin-cucumber/src/index.js +33 -6
  42. package/packages/datadog-plugin-cypress/src/index.js +1 -1
  43. package/packages/datadog-plugin-cypress/src/plugin.js +40 -33
  44. package/packages/datadog-plugin-dns/src/index.js +1 -1
  45. package/packages/datadog-plugin-dns/src/lookup.js +1 -1
  46. package/packages/datadog-plugin-dns/src/lookup_service.js +1 -1
  47. package/packages/datadog-plugin-dns/src/resolve.js +1 -1
  48. package/packages/datadog-plugin-dns/src/reverse.js +1 -1
  49. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  50. package/packages/datadog-plugin-express/src/index.js +1 -1
  51. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  52. package/packages/datadog-plugin-find-my-way/src/index.js +1 -1
  53. package/packages/datadog-plugin-fs/src/index.js +1 -1
  54. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +5 -5
  55. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -1
  56. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
  57. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +7 -6
  58. package/packages/datadog-plugin-graphql/src/execute.js +1 -1
  59. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  60. package/packages/datadog-plugin-graphql/src/parse.js +1 -1
  61. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  62. package/packages/datadog-plugin-graphql/src/validate.js +1 -1
  63. package/packages/datadog-plugin-grpc/src/client.js +1 -1
  64. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  65. package/packages/datadog-plugin-grpc/src/server.js +1 -1
  66. package/packages/datadog-plugin-hapi/src/index.js +1 -1
  67. package/packages/datadog-plugin-http/src/client.js +2 -2
  68. package/packages/datadog-plugin-http/src/index.js +1 -1
  69. package/packages/datadog-plugin-http/src/server.js +3 -3
  70. package/packages/datadog-plugin-http2/src/client.js +4 -3
  71. package/packages/datadog-plugin-http2/src/index.js +1 -1
  72. package/packages/datadog-plugin-http2/src/server.js +3 -3
  73. package/packages/datadog-plugin-ioredis/src/index.js +1 -1
  74. package/packages/datadog-plugin-jest/src/index.js +53 -19
  75. package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -1
  76. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  77. package/packages/datadog-plugin-kafkajs/src/producer.js +1 -1
  78. package/packages/datadog-plugin-koa/src/index.js +1 -1
  79. package/packages/datadog-plugin-mariadb/src/index.js +18 -1
  80. package/packages/datadog-plugin-memcached/src/index.js +3 -2
  81. package/packages/datadog-plugin-microgateway-core/src/index.js +1 -1
  82. package/packages/datadog-plugin-mocha/src/index.js +13 -9
  83. package/packages/datadog-plugin-moleculer/src/client.js +1 -1
  84. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  85. package/packages/datadog-plugin-moleculer/src/server.js +1 -1
  86. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -1
  87. package/packages/datadog-plugin-mysql/src/index.js +3 -2
  88. package/packages/datadog-plugin-mysql2/src/index.js +1 -1
  89. package/packages/datadog-plugin-net/src/index.js +9 -75
  90. package/packages/datadog-plugin-net/src/ipc.js +1 -1
  91. package/packages/datadog-plugin-net/src/tcp.js +3 -2
  92. package/packages/datadog-plugin-next/src/index.js +3 -3
  93. package/packages/datadog-plugin-opensearch/src/index.js +1 -1
  94. package/packages/datadog-plugin-oracledb/src/index.js +3 -2
  95. package/packages/datadog-plugin-paperplane/src/index.js +1 -1
  96. package/packages/datadog-plugin-paperplane/src/logger.js +1 -1
  97. package/packages/datadog-plugin-paperplane/src/server.js +1 -1
  98. package/packages/datadog-plugin-pg/src/index.js +3 -2
  99. package/packages/datadog-plugin-pino/src/index.js +1 -1
  100. package/packages/datadog-plugin-playwright/src/index.js +5 -4
  101. package/packages/datadog-plugin-redis/src/index.js +3 -2
  102. package/packages/datadog-plugin-restify/src/index.js +1 -1
  103. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  104. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  105. package/packages/datadog-plugin-rhea/src/producer.js +3 -2
  106. package/packages/datadog-plugin-router/src/index.js +8 -8
  107. package/packages/datadog-plugin-sharedb/src/index.js +1 -1
  108. package/packages/datadog-plugin-tedious/src/index.js +3 -2
  109. package/packages/datadog-plugin-web/src/index.js +1 -1
  110. package/packages/datadog-plugin-winston/src/index.js +1 -1
  111. package/packages/dd-trace/src/appsec/addresses.js +3 -1
  112. package/packages/dd-trace/src/appsec/blocking.js +35 -9
  113. package/packages/dd-trace/src/appsec/gateway/engine/runner.js +2 -1
  114. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +2 -0
  115. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +2 -2
  116. package/packages/dd-trace/src/appsec/iast/iast-context.js +6 -2
  117. package/packages/dd-trace/src/appsec/iast/iast-log.js +111 -0
  118. package/packages/dd-trace/src/appsec/iast/index.js +10 -6
  119. package/packages/dd-trace/src/appsec/iast/path-line.js +3 -6
  120. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +2 -0
  121. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -0
  122. package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +2 -0
  123. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -0
  124. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +9 -4
  125. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +5 -3
  126. package/packages/dd-trace/src/appsec/iast/telemetry/log_collector.js +96 -0
  127. package/packages/dd-trace/src/appsec/iast/telemetry/logs.js +87 -0
  128. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +27 -2
  129. package/packages/dd-trace/src/appsec/index.js +4 -4
  130. package/packages/dd-trace/src/appsec/recommended.json +76 -75
  131. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
  132. package/packages/dd-trace/src/appsec/remote_config/index.js +3 -0
  133. package/packages/dd-trace/src/appsec/sdk/index.js +19 -1
  134. package/packages/dd-trace/src/appsec/sdk/noop.js +6 -0
  135. package/packages/dd-trace/src/appsec/sdk/set_user.js +30 -0
  136. package/packages/dd-trace/src/appsec/sdk/track_event.js +2 -2
  137. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +73 -0
  138. package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +27 -0
  139. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +17 -9
  140. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +14 -8
  141. package/packages/dd-trace/src/ci-visibility/exporters/jest-worker/index.js +33 -0
  142. package/packages/dd-trace/src/ci-visibility/exporters/jest-worker/writer.js +37 -0
  143. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +12 -4
  144. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +12 -4
  145. package/packages/dd-trace/src/config.js +24 -5
  146. package/packages/dd-trace/src/constants.js +2 -1
  147. package/packages/dd-trace/src/datastreams/encoding.js +80 -0
  148. package/packages/dd-trace/src/exporter.js +7 -9
  149. package/packages/dd-trace/src/exporters/common/agents.js +42 -0
  150. package/packages/dd-trace/src/exporters/common/docker.js +4 -1
  151. package/packages/dd-trace/src/exporters/common/request.js +1 -4
  152. package/packages/dd-trace/src/lambda/handler.js +19 -12
  153. package/packages/dd-trace/src/log/writer.js +32 -24
  154. package/packages/dd-trace/src/metrics.js +18 -0
  155. package/packages/dd-trace/src/noop/proxy.js +2 -2
  156. package/packages/dd-trace/src/opentracing/span.js +5 -0
  157. package/packages/dd-trace/src/opentracing/span_context.js +1 -1
  158. package/packages/dd-trace/src/plugin_manager.js +7 -7
  159. package/packages/dd-trace/src/plugins/ci_plugin.js +20 -17
  160. package/packages/dd-trace/src/plugins/index.js +1 -0
  161. package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
  162. package/packages/dd-trace/src/plugins/outgoing.js +2 -1
  163. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  164. package/packages/dd-trace/src/plugins/util/ci.js +12 -0
  165. package/packages/dd-trace/src/plugins/util/exec.js +2 -2
  166. package/packages/dd-trace/src/plugins/util/git.js +16 -1
  167. package/packages/dd-trace/src/plugins/util/ip_extractor.js +23 -27
  168. package/packages/dd-trace/src/plugins/util/test.js +26 -7
  169. package/packages/dd-trace/src/profiler.js +3 -0
  170. package/packages/dd-trace/src/profiling/config.js +92 -20
  171. package/packages/dd-trace/src/profiling/constants.js +16 -0
  172. package/packages/dd-trace/src/profiling/exporter_cli.js +62 -0
  173. package/packages/dd-trace/src/profiling/exporters/agent.js +2 -1
  174. package/packages/dd-trace/src/profiling/exporters/file.js +13 -2
  175. package/packages/dd-trace/src/profiling/profiler.js +42 -12
  176. package/packages/dd-trace/src/profiling/profilers/space.js +21 -1
  177. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -0
  178. package/packages/dd-trace/src/proxy.js +1 -1
  179. package/packages/dd-trace/src/span_processor.js +1 -1
  180. package/packages/dd-trace/src/span_sampler.js +71 -54
  181. package/packages/dd-trace/src/startup-log.js +3 -6
  182. package/packages/dd-trace/src/telemetry/index.js +16 -2
  183. package/packages/dd-trace/src/tracer.js +0 -16
  184. package/packages/dd-trace/src/util.js +10 -1
  185. package/scripts/install_plugin_modules.js +5 -1
  186. package/scripts/junit_report.js +0 -25
  187. package/scripts/tdd.js +0 -34
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const log = require('../log')
3
4
  const { channel } = require('../../../datadog-instrumentations/src/helpers/instrument')
4
5
  const { ERROR_MESSAGE, ERROR_TYPE } = require('../constants')
5
6
  const { ImpendingTimeout } = require('./runtime/errors')
@@ -22,15 +23,14 @@ let __lambdaTimeout
22
23
  * @param {*} context AWS Lambda context object.
23
24
  */
24
25
  function checkTimeout (context) {
25
- let remainingTimeInMillis = context.getRemainingTimeInMillis()
26
- const apmFlushDeadline = parseInt(process.env.DD_APM_FLUSH_DEADLINE)
27
- if (apmFlushDeadline && apmFlushDeadline <= remainingTimeInMillis) {
28
- remainingTimeInMillis = apmFlushDeadline
29
- }
26
+ const remainingTimeInMillis = context.getRemainingTimeInMillis()
27
+
28
+ let apmFlushDeadline = parseInt(process.env.DD_APM_FLUSH_DEADLINE_MILLISECONDS) || 100
29
+ apmFlushDeadline = apmFlushDeadline < 0 ? 100 : apmFlushDeadline
30
30
 
31
31
  __lambdaTimeout = setTimeout(() => {
32
32
  timeoutChannel.publish(undefined)
33
- }, remainingTimeInMillis - 50)
33
+ }, remainingTimeInMillis - apmFlushDeadline)
34
34
  }
35
35
 
36
36
  /**
@@ -43,13 +43,20 @@ function checkTimeout (context) {
43
43
  */
44
44
  function crashFlush () {
45
45
  const activeSpan = tracer.scope().active()
46
- const error = new ImpendingTimeout('Datadog detected an impending timeout')
47
- activeSpan.addTags({
48
- [ERROR_MESSAGE]: error.message,
49
- [ERROR_TYPE]: error.name
50
- })
46
+ if (activeSpan !== null) {
47
+ const error = new ImpendingTimeout('Datadog detected an impending timeout')
48
+ activeSpan.addTags({
49
+ [ERROR_MESSAGE]: error.message,
50
+ [ERROR_TYPE]: error.name
51
+ })
52
+ } else {
53
+ log.warn('An impending timeout was reached, but no root span was found. No error will be tagged.')
54
+ }
55
+
51
56
  tracer._processor.killAll()
52
- activeSpan.finish()
57
+ if (activeSpan !== null) {
58
+ activeSpan.finish()
59
+ }
53
60
  }
54
61
 
55
62
  /**
@@ -78,39 +78,47 @@ function reset () {
78
78
  }
79
79
 
80
80
  function onError (err) {
81
- if (enabled) {
82
- if (typeof err !== 'object' || !err) {
83
- err = String(err)
84
- } else if (!err.stack) {
85
- err = String(err.message || err)
86
- }
87
-
88
- if (typeof err === 'string') {
89
- err = new Error(err)
90
- }
91
-
92
- withNoop(() => logger.error(err))
93
- }
81
+ if (enabled) error(err)
94
82
  }
95
83
 
96
84
  function onWarn (message) {
97
- if (!logger.warn) return onDebug(message)
98
- if (enabled) {
99
- withNoop(() => logger.warn(message))
100
- }
85
+ if (enabled) warn(message)
101
86
  }
102
87
 
103
88
  function onInfo (message) {
104
- if (!logger.info) return onDebug(message)
105
- if (enabled) {
106
- withNoop(() => logger.info(message))
107
- }
89
+ if (enabled) info(message)
108
90
  }
109
91
 
110
92
  function onDebug (message) {
111
- if (enabled) {
112
- withNoop(() => logger.debug(message))
93
+ if (enabled) debug(message)
94
+ }
95
+
96
+ function error (err) {
97
+ if (typeof err !== 'object' || !err) {
98
+ err = String(err)
99
+ } else if (!err.stack) {
100
+ err = String(err.message || err)
113
101
  }
102
+
103
+ if (typeof err === 'string') {
104
+ err = new Error(err)
105
+ }
106
+
107
+ withNoop(() => logger.error(err))
108
+ }
109
+
110
+ function warn (message) {
111
+ if (!logger.warn) return debug(message)
112
+ withNoop(() => logger.warn(message))
113
+ }
114
+
115
+ function info (message) {
116
+ if (!logger.info) return debug(message)
117
+ withNoop(() => logger.info(message))
118
+ }
119
+
120
+ function debug (message) {
121
+ withNoop(() => logger.debug(message))
114
122
  }
115
123
 
116
- module.exports = { use, toggle, reset }
124
+ module.exports = { use, toggle, reset, error, warn, info, debug }
@@ -8,6 +8,7 @@ const os = require('os')
8
8
  const Client = require('./dogstatsd')
9
9
  const log = require('./log')
10
10
  const Histogram = require('./histogram')
11
+ const { performance } = require('perf_hooks')
11
12
 
12
13
  const INTERVAL = 10 * 1000
13
14
 
@@ -20,6 +21,7 @@ let cpuUsage
20
21
  let gauges
21
22
  let counters
22
23
  let histograms
24
+ let elu
23
25
 
24
26
  reset()
25
27
 
@@ -259,6 +261,21 @@ function captureHistograms () {
259
261
  })
260
262
  }
261
263
 
264
+ /**
265
+ * Gathers and reports Event Loop Utilization (ELU) since last run
266
+ *
267
+ * ELU is a measure of how busy the event loop is, like running JavaScript or
268
+ * waiting on *Sync functions. The value is between 0 (idle) and 1 (exhausted).
269
+ *
270
+ * performance.eventLoopUtilization available in Node.js >= v14.10, >= v12.19, >= v16
271
+ */
272
+ const captureELU = ('eventLoopUtilization' in performance) ? () => {
273
+ // if elu is undefined (first run) the measurement is from start of process
274
+ elu = performance.eventLoopUtilization(elu)
275
+
276
+ client.gauge('runtime.node.event_loop.utilization', elu.utilization)
277
+ } : () => {}
278
+
262
279
  function captureCommonMetrics () {
263
280
  captureMemoryUsage()
264
281
  captureProcess()
@@ -266,6 +283,7 @@ function captureCommonMetrics () {
266
283
  captureGauges()
267
284
  captureCounters()
268
285
  captureHistograms()
286
+ captureELU()
269
287
  }
270
288
 
271
289
  function captureNativeMetrics () {
@@ -71,8 +71,8 @@ class Tracer {
71
71
  return this._tracer.getRumData.apply(this._tracer, arguments)
72
72
  }
73
73
 
74
- setUser () {
75
- this._tracer.setUser.apply(this._tracer, arguments)
74
+ setUser (user) {
75
+ this.appsec.setUser(user)
76
76
  return this
77
77
  }
78
78
  }
@@ -32,6 +32,11 @@ class DatadogSpan {
32
32
  this._processor = processor
33
33
  this._prioritySampler = prioritySampler
34
34
  this._store = storage.getStore()
35
+ this._duration = undefined
36
+
37
+ // For internal use only. You probably want `context()._name`.
38
+ // This name property is not updated when the span name changes.
39
+ // This is necessary for span count metrics.
35
40
  this._name = operationName
36
41
 
37
42
  this._spanContext = this._createContext(parent)
@@ -12,7 +12,7 @@ class DatadogSpanContext {
12
12
  this._name = props.name
13
13
  this._isFinished = props.isFinished || false
14
14
  this._tags = props.tags || {}
15
- this._sampling = props.sampling || {}
15
+ this._sampling = Object.assign({}, props.sampling)
16
16
  this._baggageItems = props.baggageItems || {}
17
17
  this._traceparent = props.traceparent
18
18
  this._tracestate = props.tracestate
@@ -28,17 +28,17 @@ loadChannel.subscribe(({ name }) => {
28
28
  const Plugin = plugins[name]
29
29
 
30
30
  if (!Plugin || typeof Plugin !== 'function') return
31
- if (!pluginClasses[Plugin.name]) {
32
- const envName = `DD_TRACE_${Plugin.name.toUpperCase()}_ENABLED`
31
+ if (!pluginClasses[Plugin.id]) {
32
+ const envName = `DD_TRACE_${Plugin.id.toUpperCase()}_ENABLED`
33
33
  const enabled = process.env[envName.replace(/[^a-z0-9_]/ig, '_')]
34
34
 
35
35
  // TODO: remove the need to load the plugin class in order to disable the plugin
36
- if (isFalse(enabled) || disabledPlugins.has(Plugin.name)) {
37
- log.debug(`Plugin "${Plugin.name}" was disabled via configuration option.`)
36
+ if (isFalse(enabled) || disabledPlugins.has(Plugin.id)) {
37
+ log.debug(`Plugin "${Plugin.id}" was disabled via configuration option.`)
38
38
 
39
- pluginClasses[Plugin.name] = null
39
+ pluginClasses[Plugin.id] = null
40
40
  } else {
41
- pluginClasses[Plugin.name] = Plugin
41
+ pluginClasses[Plugin.id] = Plugin
42
42
  }
43
43
  }
44
44
  })
@@ -56,7 +56,7 @@ module.exports = class PluginManager {
56
56
 
57
57
  if (!Plugin || typeof Plugin !== 'function') return
58
58
 
59
- this.loadPlugin(Plugin.name)
59
+ this.loadPlugin(Plugin.id)
60
60
  }
61
61
 
62
62
  loadChannel.subscribe(this._loadedSubscriber)
@@ -12,7 +12,7 @@ const {
12
12
  TEST_MODULE_ID,
13
13
  TEST_SESSION_ID,
14
14
  TEST_COMMAND,
15
- TEST_BUNDLE
15
+ TEST_MODULE
16
16
  } = require('./util/test')
17
17
  const Plugin = require('./plugin')
18
18
  const { COMPONENT } = require('../constants')
@@ -22,13 +22,13 @@ module.exports = class CiPlugin extends Plugin {
22
22
  constructor (...args) {
23
23
  super(...args)
24
24
 
25
- this.addSub(`ci:${this.constructor.name}:itr-configuration`, ({ onDone }) => {
25
+ this.addSub(`ci:${this.constructor.id}:itr-configuration`, ({ onDone }) => {
26
26
  if (!this.tracer._exporter || !this.tracer._exporter.getItrConfiguration) {
27
27
  return onDone({ err: new Error('CI Visibility was not initialized correctly') })
28
28
  }
29
29
  this.tracer._exporter.getItrConfiguration(this.testConfiguration, (err, itrConfig) => {
30
30
  if (err) {
31
- log.error(`Error fetching intelligent test runner configuration: ${err.message}`)
31
+ log.error(`Intelligent Test Runner configuration could not be fetched. ${err.message}`)
32
32
  } else {
33
33
  this.itrConfig = itrConfig
34
34
  }
@@ -36,40 +36,40 @@ module.exports = class CiPlugin extends Plugin {
36
36
  })
37
37
  })
38
38
 
39
- this.addSub(`ci:${this.constructor.name}:test-suite:skippable`, ({ onDone }) => {
39
+ this.addSub(`ci:${this.constructor.id}:test-suite:skippable`, ({ onDone }) => {
40
40
  if (!this.tracer._exporter || !this.tracer._exporter.getSkippableSuites) {
41
41
  return onDone({ err: new Error('CI Visibility was not initialized correctly') })
42
42
  }
43
43
  this.tracer._exporter.getSkippableSuites(this.testConfiguration, (err, skippableSuites) => {
44
44
  if (err) {
45
- log.error(`Error fetching skippable suites: ${err.message}`)
45
+ log.error(`Skippable suites could not be fetched. ${err.message}`)
46
46
  }
47
47
  onDone({ err, skippableSuites })
48
48
  })
49
49
  })
50
50
 
51
- this.addSub(`ci:${this.constructor.name}:session:start`, ({ command, frameworkVersion, rootDir }) => {
51
+ this.addSub(`ci:${this.constructor.id}:session:start`, ({ command, frameworkVersion, rootDir }) => {
52
52
  const childOf = getTestParentSpan(this.tracer)
53
- const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion)
54
- const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion)
53
+ const testSessionSpanMetadata = getTestSessionCommonTags(command, frameworkVersion, this.constructor.id)
54
+ const testModuleSpanMetadata = getTestModuleCommonTags(command, frameworkVersion, this.constructor.id)
55
55
 
56
56
  this.command = command
57
57
  this.frameworkVersion = frameworkVersion
58
58
  // only for playwright
59
59
  this.rootDir = rootDir
60
60
 
61
- this.testSessionSpan = this.tracer.startSpan(`${this.constructor.name}.test_session`, {
61
+ this.testSessionSpan = this.tracer.startSpan(`${this.constructor.id}.test_session`, {
62
62
  childOf,
63
63
  tags: {
64
- [COMPONENT]: this.constructor.name,
64
+ [COMPONENT]: this.constructor.id,
65
65
  ...this.testEnvironmentMetadata,
66
66
  ...testSessionSpanMetadata
67
67
  }
68
68
  })
69
- this.testModuleSpan = this.tracer.startSpan(`${this.constructor.name}.test_module`, {
69
+ this.testModuleSpan = this.tracer.startSpan(`${this.constructor.id}.test_module`, {
70
70
  childOf: this.testSessionSpan,
71
71
  tags: {
72
- [COMPONENT]: this.constructor.name,
72
+ [COMPONENT]: this.constructor.id,
73
73
  ...this.testEnvironmentMetadata,
74
74
  ...testModuleSpanMetadata
75
75
  }
@@ -79,7 +79,7 @@ module.exports = class CiPlugin extends Plugin {
79
79
 
80
80
  configure (config) {
81
81
  super.configure(config)
82
- this.testEnvironmentMetadata = getTestEnvironmentMetadata(this.constructor.name, this.config)
82
+ this.testEnvironmentMetadata = getTestEnvironmentMetadata(this.constructor.id, this.config)
83
83
  this.codeOwnersEntries = getCodeOwnersFileEntries()
84
84
 
85
85
  const {
@@ -110,7 +110,7 @@ module.exports = class CiPlugin extends Plugin {
110
110
 
111
111
  let testTags = {
112
112
  ...getTestCommonTags(testName, testSuite, this.frameworkVersion),
113
- [COMPONENT]: this.constructor.name,
113
+ [COMPONENT]: this.constructor.id,
114
114
  ...extraTags
115
115
  }
116
116
 
@@ -128,10 +128,13 @@ module.exports = class CiPlugin extends Plugin {
128
128
  const suiteTags = {
129
129
  [TEST_SUITE_ID]: testSuiteSpan.context().toSpanId(),
130
130
  [TEST_SESSION_ID]: testSuiteSpan.context().toTraceId(),
131
- [TEST_MODULE_ID]: testSuiteSpan.context()._parentId.toString(10),
132
131
  [TEST_COMMAND]: testSuiteSpan.context()._tags[TEST_COMMAND],
133
- [TEST_BUNDLE]: testSuiteSpan.context()._tags[TEST_COMMAND]
132
+ [TEST_MODULE]: this.constructor.id
134
133
  }
134
+ if (testSuiteSpan.context()._parentId) {
135
+ suiteTags[TEST_MODULE_ID] = testSuiteSpan.context()._parentId.toString(10)
136
+ }
137
+
135
138
  testTags = {
136
139
  ...testTags,
137
140
  ...suiteTags
@@ -139,7 +142,7 @@ module.exports = class CiPlugin extends Plugin {
139
142
  }
140
143
 
141
144
  const testSpan = this.tracer
142
- .startSpan(`${this.constructor.name}.test`, {
145
+ .startSpan(`${this.constructor.id}.test`, {
143
146
  childOf,
144
147
  tags: {
145
148
  ...this.testEnvironmentMetadata,
@@ -39,6 +39,7 @@ module.exports = {
39
39
  get 'jest-environment-node' () { return require('../../../datadog-plugin-jest/src') },
40
40
  get 'jest-environment-jsdom' () { return require('../../../datadog-plugin-jest/src') },
41
41
  get 'jest-jasmine2' () { return require('../../../datadog-plugin-jest/src') },
42
+ get 'jest-worker' () { return require('../../../datadog-plugin-jest/src') },
42
43
  get 'koa' () { return require('../../../datadog-plugin-koa/src') },
43
44
  get 'koa-router' () { return require('../../../datadog-plugin-koa/src') },
44
45
  get 'kafkajs' () { return require('../../../datadog-plugin-kafkajs/src') },
@@ -39,7 +39,7 @@ module.exports = class LogPlugin extends Plugin {
39
39
  constructor (...args) {
40
40
  super(...args)
41
41
 
42
- this.addSub(`apm:${this.constructor.name}:log`, (arg) => {
42
+ this.addSub(`apm:${this.constructor.id}:log`, (arg) => {
43
43
  const store = storage.getStore()
44
44
  const span = store && store.span
45
45
 
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { CLIENT_PORT_KEY } = require('../constants')
3
4
  const TracingPlugin = require('./tracing')
4
5
 
5
6
  // TODO: Exit span on finish when AsyncResource instances are removed.
@@ -23,7 +24,7 @@ class OutgoingPlugin extends TracingPlugin {
23
24
 
24
25
  span.addTags({
25
26
  'out.host': hostname,
26
- 'out.port': port
27
+ [CLIENT_PORT_KEY]: port
27
28
  })
28
29
  }
29
30
  }
@@ -9,7 +9,7 @@ class TracingPlugin extends Plugin {
9
9
  constructor (...args) {
10
10
  super(...args)
11
11
 
12
- this.component = this.constructor.component || this.constructor.name
12
+ this.component = this.constructor.component || this.constructor.id
13
13
  this.operation = this.constructor.operation
14
14
 
15
15
  this.addTraceSub('start', message => {
@@ -534,6 +534,18 @@ module.exports = {
534
534
  }
535
535
  }
536
536
 
537
+ if (env.TEAMCITY_VERSION) {
538
+ const { BUILD_URL, TEAMCITY_BUILDCONF_NAME, DATADOG_BUILD_ID } = env
539
+ tags = {
540
+ [CI_PROVIDER_NAME]: 'teamcity',
541
+ [CI_JOB_URL]: BUILD_URL,
542
+ [CI_JOB_NAME]: TEAMCITY_BUILDCONF_NAME,
543
+ [CI_ENV_VARS]: JSON.stringify({
544
+ DATADOG_BUILD_ID
545
+ })
546
+ }
547
+ }
548
+
537
549
  normalizeTag(tags, CI_WORKSPACE_PATH, resolveTilde)
538
550
  normalizeTag(tags, GIT_REPOSITORY_URL, filterSensitiveInfoFromRepository)
539
551
  normalizeTag(tags, GIT_BRANCH, normalizeRef)
@@ -1,8 +1,8 @@
1
- const { execSync } = require('child_process')
1
+ const cp = require('child_process')
2
2
 
3
3
  const sanitizedExec = (cmd, options = {}) => {
4
4
  try {
5
- return execSync(cmd, options).toString().replace(/(\r\n|\n|\r)/gm, '')
5
+ return cp.execSync(cmd, options).toString().replace(/(\r\n|\n|\r)/gm, '')
6
6
  } catch (e) {
7
7
  return ''
8
8
  }
@@ -21,6 +21,19 @@ const {
21
21
 
22
22
  const GIT_REV_LIST_MAX_BUFFER = 8 * 1024 * 1024 // 8MB
23
23
 
24
+ function isShallowRepository () {
25
+ return sanitizedExec('git rev-parse --is-shallow-repository', { stdio: 'pipe' }) === 'true'
26
+ }
27
+
28
+ function unshallowRepository () {
29
+ try {
30
+ execSync('git config remote.origin.partialclonefilter "blob:none"', { stdio: 'pipe' })
31
+ execSync('git fetch --shallow-since="1 month ago" --update-shallow --refetch', { stdio: 'pipe' })
32
+ } catch (err) {
33
+ log.error(err)
34
+ }
35
+ }
36
+
24
37
  function getRepositoryUrl () {
25
38
  return sanitizedExec('git config --get remote.origin.url', { stdio: 'pipe' })
26
39
  }
@@ -146,5 +159,7 @@ module.exports = {
146
159
  getRepositoryUrl,
147
160
  generatePackFilesForCommits,
148
161
  getCommitsToUpload,
149
- GIT_REV_LIST_MAX_BUFFER
162
+ GIT_REV_LIST_MAX_BUFFER,
163
+ isShallowRepository,
164
+ unshallowRepository
150
165
  }
@@ -2,18 +2,18 @@
2
2
 
3
3
  const BlockList = require('./ip_blocklist')
4
4
  const net = require('net')
5
- const log = require('../../log')
6
5
 
7
6
  const ipHeaderList = [
8
7
  'x-forwarded-for',
9
8
  'x-real-ip',
10
- 'client-ip',
9
+ 'true-client-ip',
10
+ 'x-client-ip',
11
11
  'x-forwarded',
12
- 'x-cluster-client-ip',
13
12
  'forwarded-for',
14
- 'forwarded',
15
- 'via',
16
- 'true-client-ip'
13
+ 'x-cluster-client-ip',
14
+ 'fastly-client-ip',
15
+ 'cf-connecting-ip',
16
+ 'cf-connecting-ipv6'
17
17
  ]
18
18
 
19
19
  const privateCIDRs = [
@@ -41,36 +41,31 @@ function extractIp (config, req) {
41
41
  const headers = req.headers
42
42
  if (config.clientIpHeader) {
43
43
  if (!headers) return
44
- const header = headers[config.clientIpHeader]
45
- if (!header) return
46
44
 
47
- return findFirstIp(header)
45
+ const ip = findFirstIp(headers[config.clientIpHeader])
46
+ return ip.public || ip.private
48
47
  }
49
48
 
50
- const foundHeaders = []
49
+ let firstPrivateIp
51
50
  if (headers) {
52
51
  for (let i = 0; i < ipHeaderList.length; i++) {
53
- if (headers[ipHeaderList[i]]) {
54
- foundHeaders.push(ipHeaderList[i])
52
+ const firstIp = findFirstIp(headers[ipHeaderList[i]])
53
+
54
+ if (firstIp.public) {
55
+ return firstIp.public
56
+ } else if (!firstPrivateIp && firstIp.private) {
57
+ firstPrivateIp = firstIp.private
55
58
  }
56
59
  }
57
60
  }
58
61
 
59
- if (foundHeaders.length === 1) {
60
- const header = headers[foundHeaders[0]]
61
- const firstIp = findFirstIp(header)
62
-
63
- if (firstIp) return firstIp
64
- } else if (foundHeaders.length > 1) {
65
- log.error(`Cannot find client IP: multiple IP headers detected ${foundHeaders}`)
66
- return
67
- }
68
-
69
- return req.socket && req.socket.remoteAddress
62
+ return firstPrivateIp || (req.socket && req.socket.remoteAddress)
70
63
  }
71
64
 
72
65
  function findFirstIp (str) {
73
- let firstPrivateIp
66
+ const result = {}
67
+ if (!str) return result
68
+
74
69
  const splitted = str.split(',')
75
70
 
76
71
  for (let i = 0; i < splitted.length; i++) {
@@ -83,14 +78,15 @@ function findFirstIp (str) {
83
78
 
84
79
  if (!privateIPMatcher.check(chunk, type === 6 ? 'ipv6' : 'ipv4')) {
85
80
  // it's public, return it immediately
86
- return chunk
81
+ result.public = chunk
82
+ break
87
83
  }
88
84
 
89
85
  // it's private, only save the first one found
90
- if (!firstPrivateIp) firstPrivateIp = chunk
86
+ if (!result.private) result.private = chunk
91
87
  }
92
88
 
93
- return firstPrivateIp
89
+ return result
94
90
  }
95
91
 
96
92
  module.exports = {
@@ -38,10 +38,11 @@ const TEST_CODE_OWNERS = 'test.codeowners'
38
38
  const TEST_SOURCE_FILE = 'test.source.file'
39
39
  const LIBRARY_VERSION = 'library_version'
40
40
  const TEST_COMMAND = 'test.command'
41
- const TEST_BUNDLE = 'test.bundle'
41
+ const TEST_MODULE = 'test.module'
42
42
  const TEST_SESSION_ID = 'test_session_id'
43
43
  const TEST_MODULE_ID = 'test_module_id'
44
44
  const TEST_SUITE_ID = 'test_suite_id'
45
+ const TEST_TOOLCHAIN = 'test.toolchain'
45
46
 
46
47
  const CI_APP_ORIGIN = 'ciapp-test'
47
48
 
@@ -55,6 +56,10 @@ const TEST_MODULE_CODE_COVERAGE_ENABLED = 'test_module.code_coverage.enabled'
55
56
 
56
57
  const TEST_CODE_COVERAGE_LINES_TOTAL = 'test.codecov_lines_total'
57
58
 
59
+ // jest worker variables
60
+ const JEST_WORKER_TRACE_PAYLOAD_CODE = 60
61
+ const JEST_WORKER_COVERAGE_PAYLOAD_CODE = 61
62
+
58
63
  module.exports = {
59
64
  TEST_CODE_OWNERS,
60
65
  TEST_FRAMEWORK,
@@ -70,6 +75,8 @@ module.exports = {
70
75
  TEST_SOURCE_FILE,
71
76
  CI_APP_ORIGIN,
72
77
  LIBRARY_VERSION,
78
+ JEST_WORKER_TRACE_PAYLOAD_CODE,
79
+ JEST_WORKER_COVERAGE_PAYLOAD_CODE,
73
80
  getTestEnvironmentMetadata,
74
81
  getTestParametersString,
75
82
  finishAllTraceSpans,
@@ -82,11 +89,12 @@ module.exports = {
82
89
  getTestModuleCommonTags,
83
90
  getTestSuiteCommonTags,
84
91
  TEST_COMMAND,
92
+ TEST_TOOLCHAIN,
85
93
  TEST_SESSION_ID,
86
94
  TEST_MODULE_ID,
87
95
  TEST_SUITE_ID,
88
96
  TEST_ITR_TESTS_SKIPPED,
89
- TEST_BUNDLE,
97
+ TEST_MODULE,
90
98
  TEST_SESSION_ITR_SKIPPING_ENABLED,
91
99
  TEST_SESSION_CODE_COVERAGE_ENABLED,
92
100
  TEST_MODULE_ITR_SKIPPING_ENABLED,
@@ -99,6 +107,15 @@ module.exports = {
99
107
  fromCoverageMapToCoverage
100
108
  }
101
109
 
110
+ // Returns pkg manager and its version, separated by '-', e.g. npm-8.15.0 or yarn-1.22.19
111
+ function getPkgManager () {
112
+ try {
113
+ return process.env.npm_config_user_agent.split(' ')[0].replace('/', '-')
114
+ } catch (e) {
115
+ return ''
116
+ }
117
+ }
118
+
102
119
  function getTestEnvironmentMetadata (testFramework, config) {
103
120
  // TODO: eventually these will come from the tracer (generally available)
104
121
  const ciMetadata = getCIMetadata()
@@ -261,28 +278,30 @@ function getTestLevelCommonTags (command, testFrameworkVersion) {
261
278
  }
262
279
  }
263
280
 
264
- function getTestSessionCommonTags (command, testFrameworkVersion) {
281
+ function getTestSessionCommonTags (command, testFrameworkVersion, testFramework) {
265
282
  return {
266
283
  [SPAN_TYPE]: 'test_session_end',
267
284
  [RESOURCE_NAME]: `test_session.${command}`,
285
+ [TEST_MODULE]: testFramework,
286
+ [TEST_TOOLCHAIN]: getPkgManager(),
268
287
  ...getTestLevelCommonTags(command, testFrameworkVersion)
269
288
  }
270
289
  }
271
290
 
272
- function getTestModuleCommonTags (command, testFrameworkVersion) {
291
+ function getTestModuleCommonTags (command, testFrameworkVersion, testFramework) {
273
292
  return {
274
293
  [SPAN_TYPE]: 'test_module_end',
275
294
  [RESOURCE_NAME]: `test_module.${command}`,
276
- [TEST_BUNDLE]: command,
295
+ [TEST_MODULE]: testFramework,
277
296
  ...getTestLevelCommonTags(command, testFrameworkVersion)
278
297
  }
279
298
  }
280
299
 
281
- function getTestSuiteCommonTags (command, testFrameworkVersion, testSuite) {
300
+ function getTestSuiteCommonTags (command, testFrameworkVersion, testSuite, testFramework) {
282
301
  return {
283
302
  [SPAN_TYPE]: 'test_suite_end',
284
303
  [RESOURCE_NAME]: `test_suite.${testSuite}`,
285
- [TEST_BUNDLE]: command,
304
+ [TEST_MODULE]: testFramework,
286
305
  [TEST_SUITE]: testSuite,
287
306
  ...getTestLevelCommonTags(command, testFrameworkVersion)
288
307
  }
@@ -3,6 +3,9 @@
3
3
  const log = require('./log')
4
4
  const { profiler } = require('./profiling')
5
5
 
6
+ // Stop profiler upon exit in order to collect and export the current profile
7
+ process.once('beforeExit', () => { profiler.stop() })
8
+
6
9
  module.exports = {
7
10
  start: config => {
8
11
  const { service, version, env, url, hostname, port, tags } = config