dd-trace 3.15.0 → 3.17.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 (180) hide show
  1. package/LICENSE-3rdparty.csv +2 -2
  2. package/README.md +53 -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 +24 -19
  8. package/packages/datadog-esbuild/index.js +104 -0
  9. package/packages/datadog-instrumentations/src/cucumber.js +80 -3
  10. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +100 -27
  11. package/packages/datadog-instrumentations/src/helpers/hook.js +13 -3
  12. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  13. package/packages/datadog-instrumentations/src/helpers/instrument.js +6 -0
  14. package/packages/datadog-instrumentations/src/helpers/register.js +2 -2
  15. package/packages/datadog-instrumentations/src/jest.js +35 -3
  16. package/packages/datadog-instrumentations/src/mariadb.js +130 -11
  17. package/packages/datadog-instrumentations/src/mocha.js +30 -6
  18. package/packages/datadog-instrumentations/src/mongodb-core.js +8 -2
  19. package/packages/datadog-instrumentations/src/mongoose.js +1 -1
  20. package/packages/datadog-instrumentations/src/next.js +32 -4
  21. package/packages/datadog-instrumentations/src/pg.js +16 -11
  22. package/packages/datadog-instrumentations/src/playwright.js +2 -2
  23. package/packages/datadog-plugin-amqp10/src/consumer.js +1 -1
  24. package/packages/datadog-plugin-amqp10/src/index.js +1 -1
  25. package/packages/datadog-plugin-amqp10/src/producer.js +3 -2
  26. package/packages/datadog-plugin-amqplib/src/client.js +3 -2
  27. package/packages/datadog-plugin-amqplib/src/consumer.js +1 -1
  28. package/packages/datadog-plugin-amqplib/src/index.js +1 -1
  29. package/packages/datadog-plugin-amqplib/src/producer.js +3 -2
  30. package/packages/datadog-plugin-aws-sdk/src/base.js +7 -2
  31. package/packages/datadog-plugin-aws-sdk/src/index.js +1 -1
  32. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +2 -0
  33. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +2 -0
  34. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +2 -0
  35. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -0
  36. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +2 -0
  37. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +2 -0
  38. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +2 -0
  39. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -0
  40. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -0
  41. package/packages/datadog-plugin-bunyan/src/index.js +1 -1
  42. package/packages/datadog-plugin-cassandra-driver/src/index.js +3 -2
  43. package/packages/datadog-plugin-connect/src/index.js +1 -1
  44. package/packages/datadog-plugin-couchbase/src/index.js +1 -1
  45. package/packages/datadog-plugin-cucumber/src/index.js +33 -6
  46. package/packages/datadog-plugin-cypress/src/index.js +1 -1
  47. package/packages/datadog-plugin-cypress/src/plugin.js +40 -33
  48. package/packages/datadog-plugin-dns/src/index.js +1 -1
  49. package/packages/datadog-plugin-dns/src/lookup.js +1 -1
  50. package/packages/datadog-plugin-dns/src/lookup_service.js +1 -1
  51. package/packages/datadog-plugin-dns/src/resolve.js +1 -1
  52. package/packages/datadog-plugin-dns/src/reverse.js +1 -1
  53. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  54. package/packages/datadog-plugin-express/src/index.js +1 -1
  55. package/packages/datadog-plugin-fastify/src/index.js +1 -1
  56. package/packages/datadog-plugin-find-my-way/src/index.js +1 -1
  57. package/packages/datadog-plugin-fs/src/index.js +1 -1
  58. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +5 -5
  59. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -1
  60. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +1 -1
  61. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +7 -6
  62. package/packages/datadog-plugin-graphql/src/execute.js +1 -1
  63. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  64. package/packages/datadog-plugin-graphql/src/parse.js +1 -1
  65. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  66. package/packages/datadog-plugin-graphql/src/validate.js +1 -1
  67. package/packages/datadog-plugin-grpc/src/client.js +1 -1
  68. package/packages/datadog-plugin-grpc/src/index.js +1 -1
  69. package/packages/datadog-plugin-grpc/src/server.js +1 -1
  70. package/packages/datadog-plugin-hapi/src/index.js +1 -1
  71. package/packages/datadog-plugin-http/src/client.js +2 -2
  72. package/packages/datadog-plugin-http/src/index.js +1 -1
  73. package/packages/datadog-plugin-http/src/server.js +2 -2
  74. package/packages/datadog-plugin-http2/src/client.js +4 -3
  75. package/packages/datadog-plugin-http2/src/index.js +1 -1
  76. package/packages/datadog-plugin-http2/src/server.js +2 -2
  77. package/packages/datadog-plugin-ioredis/src/index.js +1 -1
  78. package/packages/datadog-plugin-jest/src/index.js +53 -19
  79. package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -1
  80. package/packages/datadog-plugin-kafkajs/src/index.js +1 -1
  81. package/packages/datadog-plugin-kafkajs/src/producer.js +1 -1
  82. package/packages/datadog-plugin-koa/src/index.js +1 -1
  83. package/packages/datadog-plugin-mariadb/src/index.js +18 -1
  84. package/packages/datadog-plugin-memcached/src/index.js +3 -2
  85. package/packages/datadog-plugin-microgateway-core/src/index.js +1 -1
  86. package/packages/datadog-plugin-mocha/src/index.js +13 -9
  87. package/packages/datadog-plugin-moleculer/src/client.js +1 -1
  88. package/packages/datadog-plugin-moleculer/src/index.js +1 -1
  89. package/packages/datadog-plugin-moleculer/src/server.js +1 -1
  90. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -1
  91. package/packages/datadog-plugin-mysql/src/index.js +3 -2
  92. package/packages/datadog-plugin-mysql2/src/index.js +1 -1
  93. package/packages/datadog-plugin-net/src/index.js +9 -75
  94. package/packages/datadog-plugin-net/src/ipc.js +1 -1
  95. package/packages/datadog-plugin-net/src/tcp.js +3 -2
  96. package/packages/datadog-plugin-next/src/index.js +3 -3
  97. package/packages/datadog-plugin-opensearch/src/index.js +1 -1
  98. package/packages/datadog-plugin-oracledb/src/index.js +3 -2
  99. package/packages/datadog-plugin-paperplane/src/index.js +1 -1
  100. package/packages/datadog-plugin-paperplane/src/logger.js +1 -1
  101. package/packages/datadog-plugin-paperplane/src/server.js +1 -1
  102. package/packages/datadog-plugin-pg/src/index.js +3 -2
  103. package/packages/datadog-plugin-pino/src/index.js +1 -1
  104. package/packages/datadog-plugin-playwright/src/index.js +5 -4
  105. package/packages/datadog-plugin-redis/src/index.js +3 -2
  106. package/packages/datadog-plugin-restify/src/index.js +1 -1
  107. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  108. package/packages/datadog-plugin-rhea/src/index.js +1 -1
  109. package/packages/datadog-plugin-rhea/src/producer.js +3 -2
  110. package/packages/datadog-plugin-router/src/index.js +8 -8
  111. package/packages/datadog-plugin-sharedb/src/index.js +1 -1
  112. package/packages/datadog-plugin-tedious/src/index.js +3 -2
  113. package/packages/datadog-plugin-web/src/index.js +1 -1
  114. package/packages/datadog-plugin-winston/src/index.js +1 -1
  115. package/packages/dd-trace/src/appsec/{templates/blocked.html → blocked_templates.js} +19 -1
  116. package/packages/dd-trace/src/appsec/blocking.js +9 -24
  117. package/packages/dd-trace/src/appsec/gateway/engine/runner.js +2 -1
  118. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +2 -0
  119. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +12 -0
  120. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  121. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +11 -5
  122. package/packages/dd-trace/src/appsec/iast/iast-log.js +111 -0
  123. package/packages/dd-trace/src/appsec/iast/index.js +8 -4
  124. package/packages/dd-trace/src/appsec/iast/path-line.js +3 -6
  125. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +11 -2
  126. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +11 -0
  127. package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +2 -0
  128. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +2 -0
  129. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -3
  130. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +5 -3
  131. package/packages/dd-trace/src/appsec/iast/telemetry/log_collector.js +96 -0
  132. package/packages/dd-trace/src/appsec/iast/telemetry/logs.js +87 -0
  133. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +27 -2
  134. package/packages/dd-trace/src/appsec/index.js +4 -18
  135. package/packages/dd-trace/src/appsec/recommended.json +43 -14
  136. package/packages/dd-trace/src/appsec/remote_config/index.js +1 -1
  137. package/packages/dd-trace/src/appsec/sdk/index.js +2 -2
  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 +2 -9
  140. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +7 -7
  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 +8 -2
  144. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +8 -2
  145. package/packages/dd-trace/src/config.js +44 -22
  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/dcitm.js +51 -0
  149. package/packages/dd-trace/src/exporter.js +7 -9
  150. package/packages/dd-trace/src/exporters/common/agents.js +42 -0
  151. package/packages/dd-trace/src/exporters/common/docker.js +4 -1
  152. package/packages/dd-trace/src/exporters/common/request.js +1 -4
  153. package/packages/dd-trace/src/lambda/handler.js +14 -6
  154. package/packages/dd-trace/src/opentracing/propagation/log.js +23 -7
  155. package/packages/dd-trace/src/opentracing/propagation/text_map.js +28 -2
  156. package/packages/dd-trace/src/opentracing/span.js +19 -3
  157. package/packages/dd-trace/src/opentracing/span_context.js +3 -1
  158. package/packages/dd-trace/src/opentracing/tracer.js +3 -1
  159. package/packages/dd-trace/src/plugin_manager.js +7 -7
  160. package/packages/dd-trace/src/plugins/ci_plugin.js +16 -16
  161. package/packages/dd-trace/src/plugins/index.js +1 -0
  162. package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
  163. package/packages/dd-trace/src/plugins/outgoing.js +2 -1
  164. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  165. package/packages/dd-trace/src/plugins/util/ci.js +12 -0
  166. package/packages/dd-trace/src/plugins/util/ip_extractor.js +23 -27
  167. package/packages/dd-trace/src/plugins/util/test.js +26 -7
  168. package/packages/dd-trace/src/profiling/config.js +87 -20
  169. package/packages/dd-trace/src/profiling/constants.js +16 -0
  170. package/packages/dd-trace/src/profiling/exporter_cli.js +62 -0
  171. package/packages/dd-trace/src/profiling/exporters/agent.js +2 -1
  172. package/packages/dd-trace/src/profiling/profiler.js +21 -8
  173. package/packages/dd-trace/src/profiling/profilers/space.js +21 -1
  174. package/packages/dd-trace/src/span_sampler.js +3 -2
  175. package/packages/dd-trace/src/telemetry/index.js +16 -2
  176. package/packages/dd-trace/src/util.js +10 -1
  177. package/scripts/install_plugin_modules.js +5 -1
  178. package/packages/dd-trace/src/appsec/templates/blocked.json +0 -8
  179. package/scripts/junit_report.js +0 -25
  180. package/scripts/tdd.js +0 -34
@@ -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
  }
@@ -9,7 +9,6 @@ const coalesce = require('koalas')
9
9
  const tagger = require('./tagger')
10
10
  const { isTrue, isFalse } = require('./util')
11
11
  const uuid = require('crypto-randomuuid')
12
- const path = require('path')
13
12
 
14
13
  const fromEntries = Object.fromEntries || (entries =>
15
14
  entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))
@@ -22,16 +21,7 @@ function maybeFile (filepath) {
22
21
  try {
23
22
  return fs.readFileSync(filepath, 'utf8')
24
23
  } catch (e) {
25
- return undefined
26
- }
27
- }
28
-
29
- function maybePath (filepath) {
30
- if (!filepath) return
31
- try {
32
- fs.openSync(filepath, 'r')
33
- return filepath
34
- } catch (e) {
24
+ log.error(e)
35
25
  return undefined
36
26
  }
37
27
  }
@@ -161,7 +151,7 @@ class Config {
161
151
 
162
152
  const DD_CIVISIBILITY_ITR_ENABLED = coalesce(
163
153
  process.env.DD_CIVISIBILITY_ITR_ENABLED,
164
- false
154
+ true
165
155
  )
166
156
 
167
157
  const DD_SERVICE = options.service ||
@@ -197,6 +187,10 @@ class Config {
197
187
  process.env.DD_TRACE_TELEMETRY_ENABLED,
198
188
  !process.env.AWS_LAMBDA_FUNCTION_NAME
199
189
  )
190
+ const DD_TELEMETRY_DEBUG_ENABLED = coalesce(
191
+ process.env.DD_TELEMETRY_DEBUG_ENABLED,
192
+ false
193
+ )
200
194
  const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
201
195
  options.protocolVersion,
202
196
  process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
@@ -278,6 +272,18 @@ class Config {
278
272
  false
279
273
  )
280
274
 
275
+ const DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = coalesce(
276
+ options.traceId128BitGenerationEnabled,
277
+ process.env.DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED,
278
+ false
279
+ )
280
+
281
+ const DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED = coalesce(
282
+ options.traceId128BitLoggingEnabled,
283
+ process.env.DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED,
284
+ false
285
+ )
286
+
281
287
  let appsec = options.appsec != null ? options.appsec : options.experimental && options.experimental.appsec
282
288
 
283
289
  if (typeof appsec === 'boolean') {
@@ -322,14 +328,12 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
322
328
  |[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}`
323
329
  )
324
330
  const DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML = coalesce(
325
- maybePath(appsec.blockedTemplateHtml),
326
- maybePath(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML),
327
- path.join(__dirname, 'appsec', 'templates', 'blocked.html')
331
+ maybeFile(appsec.blockedTemplateHtml),
332
+ maybeFile(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML)
328
333
  )
329
334
  const DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON = coalesce(
330
- maybePath(appsec.blockedTemplateJson),
331
- maybePath(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON),
332
- path.join(__dirname, 'appsec', 'templates', 'blocked.json')
335
+ maybeFile(appsec.blockedTemplateJson),
336
+ maybeFile(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON)
333
337
  )
334
338
 
335
339
  const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
@@ -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,12 +470,16 @@ 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 = {
463
481
  enabled: DD_APPSEC_ENABLED,
464
- rules: DD_APPSEC_RULES,
482
+ rules: DD_APPSEC_RULES ? safeJsonParse(maybeFile(DD_APPSEC_RULES)) : require('./appsec/recommended.json'),
465
483
  rateLimit: DD_APPSEC_TRACE_RATE_LIMIT,
466
484
  wafTimeout: DD_APPSEC_WAF_TIMEOUT,
467
485
  obfuscatorKeyRegex: DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
@@ -477,19 +495,23 @@ 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)
491
510
  }
492
511
 
512
+ this.traceId128BitGenerationEnabled = isTrue(DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
513
+ this.traceId128BitLoggingEnabled = isTrue(DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
514
+
493
515
  tagger.add(this.tags, {
494
516
  service: this.service,
495
517
  env: this.env,
@@ -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, bytes] = decodeUvarint64(b)
20
+ if (low === undefined || high === undefined) {
21
+ return [undefined, bytes]
22
+ }
23
+ const positive = (low & 1) === 0
24
+ const abs = (low >>> 1) + high * 0x80000000
25
+ return [positive ? abs : -abs, bytes]
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, bytes.slice(bytes.length)]
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, bytes]
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
+ }
@@ -0,0 +1,51 @@
1
+ 'use strict'
2
+
3
+ const dc = require('diagnostics_channel')
4
+
5
+ const CHANNEL_PREFIX = 'dd-trace:bundledModuleLoadStart'
6
+
7
+ if (!dc.subscribe) {
8
+ dc.subscribe = (channel, cb) => {
9
+ dc.channel(channel).subscribe(cb)
10
+ }
11
+ }
12
+ if (!dc.unsubscribe) {
13
+ dc.unsubscribe = (channel, cb) => {
14
+ if (dc.channel(channel).hasSubscribers) {
15
+ dc.channel(channel).unsubscribe(cb)
16
+ }
17
+ }
18
+ }
19
+
20
+ module.exports = DcitmHook
21
+
22
+ /**
23
+ * This allows for listening to diagnostic channel events when a module is loaded.
24
+ * Currently it's intended use is for situations like when code runs through a bundler.
25
+ *
26
+ * Unlike RITM and IITM, which have files available on a filesystem at runtime, DCITM
27
+ * requires access to a package's version ahead of time as the package.json file likely
28
+ * won't be available.
29
+ *
30
+ * This function runs many times at startup, once for every module that dd-trace may trace.
31
+ * As it runs on a per-module basis we're creating per-module channels.
32
+ */
33
+ function DcitmHook (moduleNames, options, onrequire) {
34
+ if (!(this instanceof DcitmHook)) return new DcitmHook(moduleNames, options, onrequire)
35
+
36
+ function onModuleLoad (payload) {
37
+ payload.module = onrequire(payload.module, payload.path, undefined, payload.version)
38
+ }
39
+
40
+ for (const moduleName of moduleNames) {
41
+ // dc.channel(`${CHANNEL_PREFIX}:${moduleName}`).subscribe(onModuleLoad)
42
+ dc.subscribe(`${CHANNEL_PREFIX}:${moduleName}`, onModuleLoad)
43
+ }
44
+
45
+ this.unhook = function dcitmUnload () {
46
+ for (const moduleName of moduleNames) {
47
+ // dc.channel(`${CHANNEL_PREFIX}:${moduleName}`).unsubscribe(onModuleLoad)
48
+ dc.unsubscribe(`${CHANNEL_PREFIX}:${moduleName}`, onModuleLoad)
49
+ }
50
+ }
51
+ }
@@ -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
  /**
@@ -14,7 +14,12 @@ class LogPropagator {
14
14
  carrier.dd = {}
15
15
 
16
16
  if (spanContext) {
17
- carrier.dd.trace_id = spanContext.toTraceId()
17
+ if (this._config.traceId128BitLoggingEnabled && spanContext._trace.tags['_dd.p.tid']) {
18
+ carrier.dd.trace_id = spanContext._trace.tags['_dd.p.tid'] + spanContext._traceId.toString(16)
19
+ } else {
20
+ carrier.dd.trace_id = spanContext.toTraceId()
21
+ }
22
+
18
23
  carrier.dd.span_id = spanContext.toSpanId()
19
24
  }
20
25
 
@@ -28,12 +33,23 @@ class LogPropagator {
28
33
  return null
29
34
  }
30
35
 
31
- const spanContext = new DatadogSpanContext({
32
- traceId: id(carrier.dd.trace_id, 10),
33
- spanId: id(carrier.dd.span_id, 10)
34
- })
35
-
36
- return spanContext
36
+ if (carrier.dd.trace_id.length === 32) {
37
+ const hi = carrier.dd.trace_id.substring(0, 16)
38
+ const lo = carrier.dd.trace_id.substring(16, 32)
39
+ const spanContext = new DatadogSpanContext({
40
+ traceId: id(lo, 16),
41
+ spanId: id(carrier.dd.span_id, 10)
42
+ })
43
+
44
+ spanContext._trace.tags['_dd.p.tid'] = hi
45
+
46
+ return spanContext
47
+ } else {
48
+ return new DatadogSpanContext({
49
+ traceId: id(carrier.dd.trace_id, 10),
50
+ spanId: id(carrier.dd.span_id, 10)
51
+ })
52
+ }
37
53
  }
38
54
  }
39
55