dd-trace 3.15.0 → 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 (161) hide show
  1. package/LICENSE-3rdparty.csv +1 -2
  2. package/README.md +4 -0
  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 +6 -2
  7. package/package.json +18 -17
  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/mariadb.js +130 -11
  13. package/packages/datadog-instrumentations/src/mocha.js +30 -6
  14. package/packages/datadog-instrumentations/src/mongodb-core.js +8 -2
  15. package/packages/datadog-instrumentations/src/mongoose.js +1 -1
  16. package/packages/datadog-instrumentations/src/next.js +32 -4
  17. package/packages/datadog-instrumentations/src/playwright.js +2 -2
  18. package/packages/datadog-plugin-amqp10/src/consumer.js +1 -1
  19. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  20. package/packages/datadog-plugin-amqp10/src/producer.js +3 -2
  21. package/packages/datadog-plugin-amqplib/src/client.js +3 -2
  22. package/packages/datadog-plugin-amqplib/src/consumer.js +1 -1
  23. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  24. package/packages/datadog-plugin-amqplib/src/producer.js +3 -2
  25. package/packages/datadog-plugin-aws-sdk/src/base.js +7 -2
  26. package/packages/datadog-plugin-aws-sdk/src/index.js +1 -1
  27. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +2 -0
  28. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +2 -0
  29. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -0
  30. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -0
  31. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +2 -0
  32. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +2 -0
  33. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +2 -0
  34. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -0
  35. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -0
  36. package/packages/datadog-plugin-bunyan/src/index.js +1 -1
  37. package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -2
  38. package/packages/datadog-plugin-connect/src/index.js +1 -1
  39. package/packages/datadog-plugin-couchbase/src/index.js +1 -1
  40. package/packages/datadog-plugin-cucumber/src/index.js +33 -6
  41. package/packages/datadog-plugin-cypress/src/index.js +1 -1
  42. package/packages/datadog-plugin-cypress/src/plugin.js +40 -33
  43. package/packages/datadog-plugin-dns/src/index.js +1 -1
  44. package/packages/datadog-plugin-dns/src/lookup.js +1 -1
  45. package/packages/datadog-plugin-dns/src/lookup_service.js +1 -1
  46. package/packages/datadog-plugin-dns/src/resolve.js +1 -1
  47. package/packages/datadog-plugin-dns/src/reverse.js +1 -1
  48. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  49. package/packages/datadog-plugin-express/src/index.js +1 -1
  50. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  51. package/packages/datadog-plugin-find-my-way/src/index.js +1 -1
  52. package/packages/datadog-plugin-fs/src/index.js +1 -1
  53. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +5 -5
  54. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -1
  55. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
  56. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +7 -6
  57. package/packages/datadog-plugin-graphql/src/execute.js +1 -1
  58. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  59. package/packages/datadog-plugin-graphql/src/parse.js +1 -1
  60. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  61. package/packages/datadog-plugin-graphql/src/validate.js +1 -1
  62. package/packages/datadog-plugin-grpc/src/client.js +1 -1
  63. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  64. package/packages/datadog-plugin-grpc/src/server.js +1 -1
  65. package/packages/datadog-plugin-hapi/src/index.js +1 -1
  66. package/packages/datadog-plugin-http/src/client.js +2 -2
  67. package/packages/datadog-plugin-http/src/index.js +1 -1
  68. package/packages/datadog-plugin-http/src/server.js +2 -2
  69. package/packages/datadog-plugin-http2/src/client.js +4 -3
  70. package/packages/datadog-plugin-http2/src/index.js +1 -1
  71. package/packages/datadog-plugin-http2/src/server.js +2 -2
  72. package/packages/datadog-plugin-ioredis/src/index.js +1 -1
  73. package/packages/datadog-plugin-jest/src/index.js +53 -19
  74. package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -1
  75. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  76. package/packages/datadog-plugin-kafkajs/src/producer.js +1 -1
  77. package/packages/datadog-plugin-koa/src/index.js +1 -1
  78. package/packages/datadog-plugin-mariadb/src/index.js +18 -1
  79. package/packages/datadog-plugin-memcached/src/index.js +3 -2
  80. package/packages/datadog-plugin-microgateway-core/src/index.js +1 -1
  81. package/packages/datadog-plugin-mocha/src/index.js +13 -9
  82. package/packages/datadog-plugin-moleculer/src/client.js +1 -1
  83. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  84. package/packages/datadog-plugin-moleculer/src/server.js +1 -1
  85. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -1
  86. package/packages/datadog-plugin-mysql/src/index.js +3 -2
  87. package/packages/datadog-plugin-mysql2/src/index.js +1 -1
  88. package/packages/datadog-plugin-net/src/index.js +9 -75
  89. package/packages/datadog-plugin-net/src/ipc.js +1 -1
  90. package/packages/datadog-plugin-net/src/tcp.js +3 -2
  91. package/packages/datadog-plugin-next/src/index.js +3 -3
  92. package/packages/datadog-plugin-opensearch/src/index.js +1 -1
  93. package/packages/datadog-plugin-oracledb/src/index.js +3 -2
  94. package/packages/datadog-plugin-paperplane/src/index.js +1 -1
  95. package/packages/datadog-plugin-paperplane/src/logger.js +1 -1
  96. package/packages/datadog-plugin-paperplane/src/server.js +1 -1
  97. package/packages/datadog-plugin-pg/src/index.js +3 -2
  98. package/packages/datadog-plugin-pino/src/index.js +1 -1
  99. package/packages/datadog-plugin-playwright/src/index.js +5 -4
  100. package/packages/datadog-plugin-redis/src/index.js +3 -2
  101. package/packages/datadog-plugin-restify/src/index.js +1 -1
  102. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  103. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  104. package/packages/datadog-plugin-rhea/src/producer.js +3 -2
  105. package/packages/datadog-plugin-router/src/index.js +8 -8
  106. package/packages/datadog-plugin-sharedb/src/index.js +1 -1
  107. package/packages/datadog-plugin-tedious/src/index.js +3 -2
  108. package/packages/datadog-plugin-web/src/index.js +1 -1
  109. package/packages/datadog-plugin-winston/src/index.js +1 -1
  110. package/packages/dd-trace/src/appsec/gateway/engine/runner.js +2 -1
  111. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +2 -0
  112. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +2 -2
  113. package/packages/dd-trace/src/appsec/iast/iast-log.js +111 -0
  114. package/packages/dd-trace/src/appsec/iast/index.js +7 -4
  115. package/packages/dd-trace/src/appsec/iast/path-line.js +3 -6
  116. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +2 -0
  117. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -0
  118. package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +2 -0
  119. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -0
  120. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -3
  121. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +5 -3
  122. package/packages/dd-trace/src/appsec/iast/telemetry/log_collector.js +96 -0
  123. package/packages/dd-trace/src/appsec/iast/telemetry/logs.js +87 -0
  124. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +27 -2
  125. package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +27 -0
  126. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +2 -9
  127. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +7 -7
  128. package/packages/dd-trace/src/ci-visibility/exporters/jest-worker/index.js +33 -0
  129. package/packages/dd-trace/src/ci-visibility/exporters/jest-worker/writer.js +37 -0
  130. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +8 -2
  131. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +8 -2
  132. package/packages/dd-trace/src/config.js +23 -4
  133. package/packages/dd-trace/src/constants.js +2 -1
  134. package/packages/dd-trace/src/datastreams/encoding.js +80 -0
  135. package/packages/dd-trace/src/exporter.js +7 -9
  136. package/packages/dd-trace/src/exporters/common/agents.js +42 -0
  137. package/packages/dd-trace/src/exporters/common/docker.js +4 -1
  138. package/packages/dd-trace/src/exporters/common/request.js +1 -4
  139. package/packages/dd-trace/src/lambda/handler.js +14 -6
  140. package/packages/dd-trace/src/opentracing/span.js +5 -0
  141. package/packages/dd-trace/src/plugin_manager.js +7 -7
  142. package/packages/dd-trace/src/plugins/ci_plugin.js +16 -16
  143. package/packages/dd-trace/src/plugins/index.js +1 -0
  144. package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
  145. package/packages/dd-trace/src/plugins/outgoing.js +2 -1
  146. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  147. package/packages/dd-trace/src/plugins/util/ci.js +12 -0
  148. package/packages/dd-trace/src/plugins/util/ip_extractor.js +23 -27
  149. package/packages/dd-trace/src/plugins/util/test.js +26 -7
  150. package/packages/dd-trace/src/profiling/config.js +87 -20
  151. package/packages/dd-trace/src/profiling/constants.js +16 -0
  152. package/packages/dd-trace/src/profiling/exporter_cli.js +62 -0
  153. package/packages/dd-trace/src/profiling/exporters/agent.js +2 -1
  154. package/packages/dd-trace/src/profiling/profiler.js +21 -8
  155. package/packages/dd-trace/src/profiling/profilers/space.js +21 -1
  156. package/packages/dd-trace/src/span_sampler.js +3 -2
  157. package/packages/dd-trace/src/telemetry/index.js +16 -2
  158. package/packages/dd-trace/src/util.js +10 -1
  159. package/scripts/install_plugin_modules.js +5 -1
  160. package/scripts/junit_report.js +0 -25
  161. package/scripts/tdd.js +0 -34
@@ -4,8 +4,11 @@ const VULNERABILITIES_KEY = 'vulnerabilities'
4
4
  const IAST_JSON_TAG_KEY = '_dd.iast.json'
5
5
  const VULNERABILITY_HASHES_MAX_SIZE = 1000
6
6
  const VULNERABILITY_HASHES = new LRU({ max: VULNERABILITY_HASHES_MAX_SIZE })
7
+ const RESET_VULNERABILITY_CACHE_INTERVAL = 60 * 60 * 1000 // 1 hour
7
8
 
8
9
  let tracer
10
+ let resetVulnerabilityCacheTimer
11
+ let deduplicationEnabled = true
9
12
 
10
13
  function createVulnerability (type, evidence, spanId, location) {
11
14
  if (type && evidence) {
@@ -164,7 +167,20 @@ function clearCache () { // only for test purposes
164
167
  VULNERABILITY_HASHES.clear()
165
168
  }
166
169
 
170
+ function startClearCacheTimer () {
171
+ resetVulnerabilityCacheTimer = setInterval(clearCache, RESET_VULNERABILITY_CACHE_INTERVAL)
172
+ resetVulnerabilityCacheTimer.unref()
173
+ }
174
+
175
+ function stopClearCacheTimer () {
176
+ if (resetVulnerabilityCacheTimer) {
177
+ clearInterval(resetVulnerabilityCacheTimer)
178
+ resetVulnerabilityCacheTimer = null
179
+ }
180
+ }
181
+
167
182
  function deduplicateVulnerabilities (vulnerabilities) {
183
+ if (!deduplicationEnabled) return vulnerabilities
168
184
  const deduplicated = vulnerabilities.filter((vulnerability) => {
169
185
  const key = `${vulnerability.type}${vulnerability.hash}`
170
186
  if (!VULNERABILITY_HASHES.get(key)) {
@@ -176,14 +192,23 @@ function deduplicateVulnerabilities (vulnerabilities) {
176
192
  return deduplicated
177
193
  }
178
194
 
179
- function setTracer (_tracer) {
195
+ function start (config, _tracer) {
196
+ deduplicationEnabled = config.iast.deduplicationEnabled
197
+ if (deduplicationEnabled) {
198
+ startClearCacheTimer()
199
+ }
180
200
  tracer = _tracer
181
201
  }
182
202
 
203
+ function stop () {
204
+ stopClearCacheTimer()
205
+ }
206
+
183
207
  module.exports = {
184
208
  createVulnerability,
185
209
  addVulnerability,
186
210
  sendVulnerabilities,
187
211
  clearCache,
188
- setTracer
212
+ start,
213
+ stop
189
214
  }
@@ -0,0 +1,27 @@
1
+ 'use strict'
2
+
3
+ class JSONEncoder {
4
+ constructor () {
5
+ this.payloads = []
6
+ }
7
+
8
+ encode (payload) {
9
+ this.payloads.push(payload)
10
+ }
11
+
12
+ count () {
13
+ return this.payloads.length
14
+ }
15
+
16
+ reset () {
17
+ this.payloads = []
18
+ }
19
+
20
+ makePayload () {
21
+ const data = JSON.stringify(this.payloads)
22
+ this.reset()
23
+ return data
24
+ }
25
+ }
26
+
27
+ module.exports = { JSONEncoder }
@@ -178,23 +178,16 @@ class CiVisibilityExporter extends AgentInfoExporter {
178
178
  this._export(trace)
179
179
  }
180
180
 
181
- exportCoverage (coveragePayload) {
181
+ exportCoverage (formattedCoverage) {
182
182
  // Until it's initialized, we just store the coverages as is
183
183
  if (!this._isInitialized) {
184
- this._coverageBuffer.push(coveragePayload)
184
+ this._coverageBuffer.push(formattedCoverage)
185
185
  return
186
186
  }
187
187
  if (!this.canReportCodeCoverage()) {
188
188
  return
189
189
  }
190
190
 
191
- const { span, coverageFiles } = coveragePayload
192
- const formattedCoverage = {
193
- traceId: span.context()._traceId,
194
- spanId: span.context()._spanId,
195
- files: coverageFiles
196
- }
197
-
198
191
  this._export(formattedCoverage, this._coverageWriter, '_coverageTimer')
199
192
  }
200
193
 
@@ -15,18 +15,18 @@ const {
15
15
  unshallowRepository
16
16
  } = require('../../../plugins/util/git')
17
17
 
18
- const isValidSha = (sha) => /[0-9a-f]{40}/.test(sha)
18
+ const isValidSha1 = (sha) => /^[0-9a-f]{40}$/.test(sha)
19
+ const isValidSha256 = (sha) => /^[0-9a-f]{64}$/.test(sha)
19
20
 
20
- function sanitizeCommits (commits) {
21
+ function validateCommits (commits) {
21
22
  return commits.map(({ id: commitSha, type }) => {
22
23
  if (type !== 'commit') {
23
24
  throw new Error('Invalid commit type response')
24
25
  }
25
- const sanitizedCommit = commitSha.replace(/[^0-9a-f]+/g, '')
26
- if (sanitizedCommit !== commitSha || !isValidSha(sanitizedCommit)) {
27
- throw new Error('Invalid commit format')
26
+ if (isValidSha1(commitSha) || isValidSha256(commitSha)) {
27
+ return commitSha.replace(/[^0-9a-f]+/g, '')
28
28
  }
29
- return sanitizedCommit
29
+ throw new Error('Invalid commit format')
30
30
  })
31
31
  }
32
32
 
@@ -84,7 +84,7 @@ function getCommitsToExclude ({ url, isEvpProxy, repositoryUrl }, callback) {
84
84
  }
85
85
  let commitsToExclude
86
86
  try {
87
- commitsToExclude = sanitizeCommits(JSON.parse(response).data)
87
+ commitsToExclude = validateCommits(JSON.parse(response).data)
88
88
  } catch (e) {
89
89
  return callback(new Error(`Can't parse commits to exclude response: ${e.message}`))
90
90
  }
@@ -0,0 +1,33 @@
1
+ 'use strict'
2
+
3
+ const Writer = require('./writer')
4
+ const {
5
+ JEST_WORKER_COVERAGE_PAYLOAD_CODE,
6
+ JEST_WORKER_TRACE_PAYLOAD_CODE
7
+ } = require('../../../plugins/util/test')
8
+
9
+ /**
10
+ * Lightweight exporter whose writers only do simple JSON serialization
11
+ * of trace and coverage payloads, which they send to the jest main process.
12
+ */
13
+ class JestWorkerCiVisibilityExporter {
14
+ constructor () {
15
+ this._writer = new Writer(JEST_WORKER_TRACE_PAYLOAD_CODE)
16
+ this._coverageWriter = new Writer(JEST_WORKER_COVERAGE_PAYLOAD_CODE)
17
+ }
18
+
19
+ export (payload) {
20
+ this._writer.append(payload)
21
+ }
22
+
23
+ exportCoverage (formattedCoverage) {
24
+ this._coverageWriter.append(formattedCoverage)
25
+ }
26
+
27
+ flush () {
28
+ this._writer.flush()
29
+ this._coverageWriter.flush()
30
+ }
31
+ }
32
+
33
+ module.exports = JestWorkerCiVisibilityExporter
@@ -0,0 +1,37 @@
1
+ 'use strict'
2
+ const { JSONEncoder } = require('../../encode/json-encoder')
3
+
4
+ class Writer {
5
+ constructor (interprocessCode) {
6
+ this._encoder = new JSONEncoder()
7
+ // Code used to identify the type of payload being sent to the main process
8
+ this._interprocessCode = interprocessCode
9
+ }
10
+
11
+ flush () {
12
+ const count = this._encoder.count()
13
+
14
+ if (count > 0) {
15
+ const payload = this._encoder.makePayload()
16
+
17
+ this._sendPayload(payload)
18
+ }
19
+ }
20
+
21
+ append (payload) {
22
+ this._encoder.encode(payload)
23
+ }
24
+
25
+ _sendPayload (data) {
26
+ // Only available when `child_process` is used for the jest worker.
27
+ // eslint-disable-next-line
28
+ // https://github.com/facebook/jest/blob/bb39cb2c617a3334bf18daeca66bd87b7ccab28b/packages/jest-worker/README.md#experimental-worker
29
+ // If worker_threads is used, this will not work
30
+ // TODO: make it compatible with worker_threads
31
+ if (process.send) { // it only works if process.send is available
32
+ process.send([this._interprocessCode, data])
33
+ }
34
+ }
35
+ }
36
+
37
+ module.exports = Writer
@@ -36,9 +36,15 @@ function getItrConfiguration ({
36
36
  process.env.DATADOG_APPLICATION_KEY ||
37
37
  process.env.DD_APPLICATION_KEY
38
38
 
39
- if (!apiKey || !appKey) {
40
- return done(new Error('App key or API key undefined'))
39
+ const messagePrefix = 'Request to settings endpoint was not done because Datadog'
40
+
41
+ if (!appKey) {
42
+ return done(new Error(`${messagePrefix} application key is not defined.`))
43
+ }
44
+ if (!apiKey) {
45
+ return done(new Error(`${messagePrefix} API key is not defined.`))
41
46
  }
47
+
42
48
  options.headers['dd-api-key'] = apiKey
43
49
  options.headers['dd-application-key'] = appKey
44
50
  }
@@ -35,9 +35,15 @@ function getSkippableSuites ({
35
35
  process.env.DATADOG_APPLICATION_KEY ||
36
36
  process.env.DD_APPLICATION_KEY
37
37
 
38
- if (!apiKey || !appKey) {
39
- return done(new Error('App key or API key undefined'))
38
+ const messagePrefix = 'Skippable suites were not fetched because Datadog'
39
+
40
+ if (!appKey) {
41
+ return done(new Error(`${messagePrefix} application key is not defined.`))
42
+ }
43
+ if (!apiKey) {
44
+ return done(new Error(`${messagePrefix} API key is not defined.`))
40
45
  }
46
+
41
47
  options.headers['dd-api-key'] = apiKey
42
48
  options.headers['dd-application-key'] = appKey
43
49
  }
@@ -161,7 +161,7 @@ class Config {
161
161
 
162
162
  const DD_CIVISIBILITY_ITR_ENABLED = coalesce(
163
163
  process.env.DD_CIVISIBILITY_ITR_ENABLED,
164
- false
164
+ true
165
165
  )
166
166
 
167
167
  const DD_SERVICE = options.service ||
@@ -197,6 +197,10 @@ class Config {
197
197
  process.env.DD_TRACE_TELEMETRY_ENABLED,
198
198
  !process.env.AWS_LAMBDA_FUNCTION_NAME
199
199
  )
200
+ const DD_TELEMETRY_DEBUG_ENABLED = coalesce(
201
+ process.env.DD_TELEMETRY_DEBUG_ENABLED,
202
+ false
203
+ )
200
204
  const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
201
205
  options.protocolVersion,
202
206
  process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
@@ -352,6 +356,10 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
352
356
  process.env.DD_IAST_ENABLED,
353
357
  false
354
358
  )
359
+ const DD_TELEMETRY_LOG_COLLECTION_ENABLED = coalesce(
360
+ process.env.DD_TELEMETRY_LOG_COLLECTION_ENABLED,
361
+ DD_IAST_ENABLED
362
+ )
355
363
 
356
364
  const defaultIastRequestSampling = 30
357
365
  const iastRequestSampling = coalesce(
@@ -374,6 +382,12 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
374
382
  2
375
383
  )
376
384
 
385
+ const DD_IAST_DEDUPLICATION_ENABLED = coalesce(
386
+ iastOptions && iastOptions.deduplicationEnabled,
387
+ process.env.DD_IAST_DEDUPLICATION_ENABLED && isTrue(process.env.DD_IAST_DEDUPLICATION_ENABLED),
388
+ true
389
+ )
390
+
377
391
  const DD_CIVISIBILITY_GIT_UPLOAD_ENABLED = coalesce(
378
392
  process.env.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED,
379
393
  true
@@ -456,7 +470,11 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
456
470
  this.lookup = options.lookup
457
471
  this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
458
472
  // Disabled for CI Visibility's agentless
459
- this.telemetryEnabled = DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_TRACE_TELEMETRY_ENABLED)
473
+ this.telemetry = {
474
+ enabled: DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_TRACE_TELEMETRY_ENABLED),
475
+ logCollection: isTrue(DD_TELEMETRY_LOG_COLLECTION_ENABLED),
476
+ debug: isTrue(DD_TELEMETRY_DEBUG_ENABLED)
477
+ }
460
478
  this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
461
479
  this.tagsHeaderMaxLength = parseInt(DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
462
480
  this.appsec = {
@@ -477,14 +495,15 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
477
495
  enabled: isTrue(DD_IAST_ENABLED),
478
496
  requestSampling: DD_IAST_REQUEST_SAMPLING,
479
497
  maxConcurrentRequests: DD_IAST_MAX_CONCURRENT_REQUESTS,
480
- maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS
498
+ maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS,
499
+ deduplicationEnabled: DD_IAST_DEDUPLICATION_ENABLED
481
500
  }
482
501
 
483
502
  this.isCiVisibility = isTrue(DD_IS_CIVISIBILITY)
484
503
 
485
504
  this.isIntelligentTestRunnerEnabled = this.isCiVisibility && isTrue(DD_CIVISIBILITY_ITR_ENABLED)
486
505
  this.isGitUploadEnabled = this.isCiVisibility &&
487
- (this.isIntelligentTestRunnerEnabled || isTrue(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED))
506
+ (this.isIntelligentTestRunnerEnabled && !isFalse(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED))
488
507
 
489
508
  this.stats = {
490
509
  enabled: isTrue(DD_TRACE_STATS_COMPUTATION_ENABLED)
@@ -24,5 +24,6 @@ module.exports = {
24
24
  ERROR_TYPE: 'error.type',
25
25
  ERROR_MESSAGE: 'error.message',
26
26
  ERROR_STACK: 'error.stack',
27
- COMPONENT: 'component'
27
+ COMPONENT: 'component',
28
+ CLIENT_PORT_KEY: 'network.destination.port'
28
29
  }
@@ -0,0 +1,80 @@
1
+ // encodes positive and negative numbers, using zig zag encoding to reduce the size of the variable length encoding.
2
+ // uses high and low part to ensure those parts are under the limit for byte operations in javascript (32 bits)
3
+ // maximum number possible to encode is MAX_SAFE_INTEGER/2 (using zig zag shifts the bits by 1 to the left)
4
+ function encodeVarint (v) {
5
+ const sign = v >= 0 ? 0 : 1
6
+ // we leave the least significant bit for the sign.
7
+ const double = Math.abs(v) * 2
8
+ if (double > Number.MAX_SAFE_INTEGER) {
9
+ return undefined
10
+ }
11
+ const high = Math.floor(double / 0x100000000)
12
+ const low = (double & 0xffffffff) | sign
13
+ return encodeUvarint64(low, high)
14
+ }
15
+
16
+ // decodes positive and negative numbers, using zig zag encoding to reduce the size of the variable length encoding.
17
+ // uses high and low part to ensure those parts are under the limit for byte operations in javascript (32 bits)
18
+ function decodeVarint (b) {
19
+ const [low, high] = decodeUvarint64(b)
20
+ if (low === undefined || high === undefined) {
21
+ return undefined
22
+ }
23
+ const positive = (low & 1) === 0
24
+ const abs = (low >>> 1) + high * 0x80000000
25
+ return positive ? abs : -abs
26
+ }
27
+
28
+ const maxVarLen64 = 9
29
+
30
+ function encodeUvarint64 (low, high) {
31
+ const result = new Uint8Array(maxVarLen64)
32
+ let i = 0
33
+ // if first byte is 1, the number is negative in javascript, but we want to interpret it as positive
34
+ while ((high !== 0 || low < 0 || low > 0x80) && i < maxVarLen64 - 1) {
35
+ result[i] = (low & 0x7f) | 0x80
36
+ low >>>= 7
37
+ low |= (high & 0x7f) << 25
38
+ high >>>= 7
39
+ i++
40
+ }
41
+ result[i] = low & 0x7f
42
+ return result.slice(0, i + 1)
43
+ }
44
+
45
+ function decodeUvarint64 (
46
+ bytes
47
+ ) {
48
+ let low = 0
49
+ let high = 0
50
+ let s = 0
51
+ for (let i = 0; ; i++) {
52
+ if (bytes.length <= i) {
53
+ return [undefined, undefined]
54
+ }
55
+ const n = bytes[i]
56
+ if (n < 0x80 || i === maxVarLen64 - 1) {
57
+ bytes = bytes.slice(i + 1)
58
+ if (s < 32) {
59
+ low |= n << s
60
+ }
61
+ if (s > 0) {
62
+ high |= s - 32 > 0 ? n << (s - 32) : n >> (32 - s)
63
+ }
64
+ return [low, high]
65
+ }
66
+ if (s < 32) {
67
+ low |= (n & 0x7f) << s
68
+ }
69
+ if (s > 0) {
70
+ high |=
71
+ s - 32 > 0 ? (n & 0x7f) << (s - 32) : (n & 0x7f) >> (32 - s)
72
+ }
73
+ s += 7
74
+ }
75
+ }
76
+
77
+ module.exports = {
78
+ encodeVarint,
79
+ decodeVarint
80
+ }
@@ -1,9 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const AgentExporter = require('./exporters/agent')
4
- const LogExporter = require('./exporters/log')
5
- const AgentlessCiVisibilityExporter = require('./ci-visibility/exporters/agentless')
6
- const AgentProxyCiVisibilityExporter = require('./ci-visibility/exporters/agent-proxy')
7
3
  const exporters = require('../../../ext/exporters')
8
4
  const fs = require('fs')
9
5
  const constants = require('./constants')
@@ -14,14 +10,16 @@ module.exports = name => {
14
10
 
15
11
  switch (name) {
16
12
  case exporters.LOG:
17
- return LogExporter
13
+ return require('./exporters/log')
18
14
  case exporters.AGENT:
19
- return AgentExporter
15
+ return require('./exporters/agent')
20
16
  case exporters.DATADOG:
21
- return AgentlessCiVisibilityExporter
17
+ return require('./ci-visibility/exporters/agentless')
22
18
  case exporters.AGENT_PROXY:
23
- return AgentProxyCiVisibilityExporter
19
+ return require('./ci-visibility/exporters/agent-proxy')
20
+ case exporters.JEST_WORKER:
21
+ return require('./ci-visibility/exporters/jest-worker')
24
22
  default:
25
- return inAWSLambda && !usingLambdaExtension ? LogExporter : AgentExporter
23
+ return inAWSLambda && !usingLambdaExtension ? require('./exporters/log') : require('./exporters/agent')
26
24
  }
27
25
  }
@@ -0,0 +1,42 @@
1
+ 'use strict'
2
+
3
+ const http = require('http')
4
+ const https = require('https')
5
+ const { storage } = require('../../../../datadog-core')
6
+
7
+ const keepAlive = true
8
+ const maxSockets = 1
9
+
10
+ function createAgentClass (BaseAgent) {
11
+ class CustomAgent extends BaseAgent {
12
+ constructor () {
13
+ super({ keepAlive, maxSockets })
14
+ }
15
+
16
+ createConnection (...args) {
17
+ return this._noop(() => super.createConnection(...args))
18
+ }
19
+
20
+ keepSocketAlive (...args) {
21
+ return this._noop(() => super.keepSocketAlive(...args))
22
+ }
23
+
24
+ reuseSocket (...args) {
25
+ return this._noop(() => super.reuseSocket(...args))
26
+ }
27
+
28
+ _noop (callback) {
29
+ return storage.run({ noop: true }, callback)
30
+ }
31
+ }
32
+
33
+ return CustomAgent
34
+ }
35
+
36
+ const HttpAgent = createAgentClass(http.Agent)
37
+ const HttpsAgent = createAgentClass(https.Agent)
38
+
39
+ module.exports = {
40
+ httpAgent: new HttpAgent(),
41
+ HttpsAgent: new HttpsAgent()
42
+ }
@@ -2,7 +2,10 @@
2
2
 
3
3
  const fs = require('fs')
4
4
 
5
- const uuidSource = '[0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{12}'
5
+ // The second part is the PCF / Garden regexp. We currently assume no suffix($) to avoid matching pod UIDs
6
+ // See https://github.com/DataDog/datadog-agent/blob/7.40.x/pkg/util/cgroups/reader.go#L50
7
+ const uuidSource =
8
+ '[0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{12}|[0-9a-f]{8}(?:-[0-9a-f]{4}){4}$'
6
9
  const containerSource = '[0-9a-f]{64}'
7
10
  const taskSource = '[0-9a-f]{32}-\\d+'
8
11
  const entityReg = new RegExp(`.*(${uuidSource}|${containerSource}|${taskSource})(?:\\.scope)?$`, 'm')
@@ -8,14 +8,11 @@ const http = require('http')
8
8
  const https = require('https')
9
9
  const { parse: urlParse } = require('url')
10
10
  const docker = require('./docker')
11
+ const { httpAgent, httpsAgent } = require('./agents')
11
12
  const { storage } = require('../../../../datadog-core')
12
13
  const log = require('../../log')
13
14
 
14
- const keepAlive = true
15
- const maxSockets = 1
16
15
  const maxActiveRequests = 8
17
- const httpAgent = new http.Agent({ keepAlive, maxSockets })
18
- const httpsAgent = new https.Agent({ keepAlive, maxSockets })
19
16
  const containerId = docker.id()
20
17
 
21
18
  let activeRequests = 0
@@ -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')
@@ -42,13 +43,20 @@ function checkTimeout (context) {
42
43
  */
43
44
  function crashFlush () {
44
45
  const activeSpan = tracer.scope().active()
45
- const error = new ImpendingTimeout('Datadog detected an impending timeout')
46
- activeSpan.addTags({
47
- [ERROR_MESSAGE]: error.message,
48
- [ERROR_TYPE]: error.name
49
- })
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
+
50
56
  tracer._processor.killAll()
51
- activeSpan.finish()
57
+ if (activeSpan !== null) {
58
+ activeSpan.finish()
59
+ }
52
60
  }
53
61
 
54
62
  /**
@@ -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)
@@ -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)