dd-trace 2.28.0 → 2.29.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
  }
@@ -158,7 +158,7 @@ class Config {
158
158
 
159
159
  const DD_CIVISIBILITY_ITR_ENABLED = coalesce(
160
160
  process.env.DD_CIVISIBILITY_ITR_ENABLED,
161
- false
161
+ true
162
162
  )
163
163
 
164
164
  const DD_SERVICE = options.service ||
@@ -194,6 +194,10 @@ class Config {
194
194
  process.env.DD_TRACE_TELEMETRY_ENABLED,
195
195
  !process.env.AWS_LAMBDA_FUNCTION_NAME
196
196
  )
197
+ const DD_TELEMETRY_DEBUG_ENABLED = coalesce(
198
+ process.env.DD_TELEMETRY_DEBUG_ENABLED,
199
+ false
200
+ )
197
201
  const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
198
202
  options.protocolVersion,
199
203
  process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
@@ -349,6 +353,10 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
349
353
  process.env.DD_IAST_ENABLED,
350
354
  false
351
355
  )
356
+ const DD_TELEMETRY_LOG_COLLECTION_ENABLED = coalesce(
357
+ process.env.DD_TELEMETRY_LOG_COLLECTION_ENABLED,
358
+ DD_IAST_ENABLED
359
+ )
352
360
 
353
361
  const defaultIastRequestSampling = 30
354
362
  const iastRequestSampling = coalesce(
@@ -371,6 +379,12 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
371
379
  2
372
380
  )
373
381
 
382
+ const DD_IAST_DEDUPLICATION_ENABLED = coalesce(
383
+ iastOptions && iastOptions.deduplicationEnabled,
384
+ process.env.DD_IAST_DEDUPLICATION_ENABLED && isTrue(process.env.DD_IAST_DEDUPLICATION_ENABLED),
385
+ true
386
+ )
387
+
374
388
  const DD_CIVISIBILITY_GIT_UPLOAD_ENABLED = coalesce(
375
389
  process.env.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED,
376
390
  true
@@ -453,7 +467,11 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
453
467
  this.lookup = options.lookup
454
468
  this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
455
469
  // Disabled for CI Visibility's agentless
456
- this.telemetryEnabled = DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_TRACE_TELEMETRY_ENABLED)
470
+ this.telemetry = {
471
+ enabled: DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_TRACE_TELEMETRY_ENABLED),
472
+ logCollection: isTrue(DD_TELEMETRY_LOG_COLLECTION_ENABLED),
473
+ debug: isTrue(DD_TELEMETRY_DEBUG_ENABLED)
474
+ }
457
475
  this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
458
476
  this.tagsHeaderMaxLength = parseInt(DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
459
477
  this.appsec = {
@@ -474,14 +492,15 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
474
492
  enabled: isTrue(DD_IAST_ENABLED),
475
493
  requestSampling: DD_IAST_REQUEST_SAMPLING,
476
494
  maxConcurrentRequests: DD_IAST_MAX_CONCURRENT_REQUESTS,
477
- maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS
495
+ maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS,
496
+ deduplicationEnabled: DD_IAST_DEDUPLICATION_ENABLED
478
497
  }
479
498
 
480
499
  this.isCiVisibility = isTrue(DD_IS_CIVISIBILITY)
481
500
 
482
501
  this.isIntelligentTestRunnerEnabled = this.isCiVisibility && isTrue(DD_CIVISIBILITY_ITR_ENABLED)
483
502
  this.isGitUploadEnabled = this.isCiVisibility &&
484
- (this.isIntelligentTestRunnerEnabled || isTrue(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED))
503
+ (this.isIntelligentTestRunnerEnabled && !isFalse(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED))
485
504
 
486
505
  this.stats = {
487
506
  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)