dd-trace 2.12.1 → 3.2.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 (107) hide show
  1. package/LICENSE-3rdparty.csv +3 -2
  2. package/MIGRATING.md +119 -0
  3. package/ci/init.js +2 -27
  4. package/ext/formats.js +3 -5
  5. package/ext/tags.d.ts +2 -1
  6. package/ext/tags.js +2 -1
  7. package/index.d.ts +44 -38
  8. package/package.json +9 -8
  9. package/packages/datadog-core/src/storage/async_resource.js +19 -1
  10. package/packages/datadog-core/src/storage/index.js +1 -1
  11. package/packages/datadog-instrumentations/index.js +1 -52
  12. package/packages/datadog-instrumentations/src/connect.js +1 -1
  13. package/packages/datadog-instrumentations/src/crypto.js +30 -0
  14. package/packages/datadog-instrumentations/src/cucumber.js +15 -0
  15. package/packages/datadog-instrumentations/src/grpc/client.js +2 -2
  16. package/packages/datadog-instrumentations/src/grpc/server.js +1 -1
  17. package/packages/datadog-instrumentations/src/hapi.js +3 -31
  18. package/packages/datadog-instrumentations/src/helpers/hooks.js +69 -0
  19. package/packages/datadog-instrumentations/src/helpers/instrument.js +5 -34
  20. package/packages/datadog-instrumentations/src/helpers/instrumentations.js +7 -0
  21. package/packages/datadog-instrumentations/src/helpers/register.js +59 -0
  22. package/packages/datadog-instrumentations/src/http/server.js +1 -1
  23. package/packages/datadog-instrumentations/src/jest.js +33 -11
  24. package/packages/datadog-instrumentations/src/koa.js +1 -1
  25. package/packages/datadog-instrumentations/src/mocha.js +4 -1
  26. package/packages/datadog-instrumentations/src/net.js +13 -0
  27. package/packages/datadog-instrumentations/src/pg.js +2 -2
  28. package/packages/datadog-instrumentations/src/restify.js +27 -5
  29. package/packages/datadog-instrumentations/src/router.js +1 -1
  30. package/packages/datadog-plugin-aws-sdk/src/base.js +1 -2
  31. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
  32. package/packages/datadog-plugin-cucumber/src/index.js +4 -0
  33. package/packages/datadog-plugin-grpc/src/client.js +2 -2
  34. package/packages/datadog-plugin-grpc/src/server.js +2 -2
  35. package/packages/datadog-plugin-http/src/client.js +1 -1
  36. package/packages/datadog-plugin-http/src/server.js +1 -1
  37. package/packages/datadog-plugin-http2/src/client.js +1 -1
  38. package/packages/datadog-plugin-jest/src/index.js +25 -4
  39. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  40. package/packages/datadog-plugin-mongodb-core/src/index.js +32 -8
  41. package/packages/datadog-plugin-oracledb/src/index.js +12 -4
  42. package/packages/datadog-plugin-restify/src/index.js +7 -0
  43. package/packages/dd-trace/index.js +1 -1
  44. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +3 -0
  45. package/packages/dd-trace/src/appsec/iast/analyzers/index.js +20 -0
  46. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +48 -0
  47. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +24 -0
  48. package/packages/dd-trace/src/appsec/iast/iast-context.js +50 -0
  49. package/packages/dd-trace/src/appsec/iast/index.js +59 -0
  50. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +94 -0
  51. package/packages/dd-trace/src/appsec/iast/path-line.js +70 -0
  52. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +113 -0
  53. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +50 -0
  54. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +53 -8
  55. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +23 -24
  56. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +220 -0
  57. package/packages/dd-trace/src/config.js +97 -10
  58. package/packages/dd-trace/src/constants.js +9 -1
  59. package/packages/dd-trace/src/encode/0.4.js +55 -58
  60. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +13 -34
  61. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +84 -0
  62. package/packages/dd-trace/src/encode/span-stats.js +155 -0
  63. package/packages/dd-trace/src/exporters/agent/index.js +25 -7
  64. package/packages/dd-trace/src/exporters/agent/writer.js +7 -4
  65. package/packages/dd-trace/src/{profiling/exporters → exporters/common}/form-data.js +0 -0
  66. package/packages/dd-trace/src/exporters/common/request.js +69 -39
  67. package/packages/dd-trace/src/exporters/common/writer.js +16 -6
  68. package/packages/dd-trace/src/exporters/span-stats/index.js +20 -0
  69. package/packages/dd-trace/src/exporters/span-stats/writer.js +54 -0
  70. package/packages/dd-trace/src/format.js +2 -0
  71. package/packages/dd-trace/src/id.js +16 -13
  72. package/packages/dd-trace/src/iitm.js +12 -1
  73. package/packages/dd-trace/src/index.js +10 -0
  74. package/packages/dd-trace/src/noop/proxy.js +77 -0
  75. package/packages/dd-trace/src/noop/scope.js +2 -6
  76. package/packages/dd-trace/src/noop/span.js +12 -12
  77. package/packages/dd-trace/src/noop/tracer.js +8 -9
  78. package/packages/dd-trace/src/opentracing/propagation/text_map.js +77 -6
  79. package/packages/dd-trace/src/opentracing/span.js +63 -49
  80. package/packages/dd-trace/src/opentracing/span_context.js +1 -5
  81. package/packages/dd-trace/src/opentracing/tracer.js +32 -37
  82. package/packages/dd-trace/src/plugin_manager.js +111 -64
  83. package/packages/dd-trace/src/plugins/index.js +57 -45
  84. package/packages/dd-trace/src/plugins/log_plugin.js +16 -9
  85. package/packages/dd-trace/src/plugins/util/ci.js +34 -9
  86. package/packages/dd-trace/src/plugins/util/git.js +52 -2
  87. package/packages/dd-trace/src/plugins/util/ip_blocklist.js +25 -0
  88. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  89. package/packages/dd-trace/src/plugins/util/web.js +149 -6
  90. package/packages/dd-trace/src/priority_sampler.js +36 -1
  91. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  92. package/packages/dd-trace/src/profiling/profilers/cpu.js +3 -3
  93. package/packages/dd-trace/src/proxy.js +21 -90
  94. package/packages/dd-trace/src/ritm.js +10 -1
  95. package/packages/dd-trace/src/scope.js +2 -184
  96. package/packages/dd-trace/src/span_processor.js +7 -1
  97. package/packages/dd-trace/src/span_stats.js +210 -0
  98. package/packages/dd-trace/src/startup-log.js +8 -19
  99. package/packages/dd-trace/src/telemetry/dependencies.js +83 -0
  100. package/packages/dd-trace/src/{telemetry.js → telemetry/index.js} +11 -79
  101. package/packages/dd-trace/src/telemetry/send-data.js +35 -0
  102. package/packages/dd-trace/src/tracer.js +0 -4
  103. package/scripts/install_plugin_modules.js +17 -26
  104. package/ci/jest/env.js +0 -39
  105. package/cypress/plugin.js +0 -5
  106. package/cypress/support.js +0 -1
  107. package/packages/datadog-plugin-fs/src/index.js +0 -548
@@ -2,30 +2,75 @@
2
2
 
3
3
  const URL = require('url').URL
4
4
  const Writer = require('./writer')
5
- const Scheduler = require('../../../exporters/scheduler')
5
+ const CoverageWriter = require('./coverage-writer')
6
+
7
+ const log = require('../../../log')
6
8
 
7
9
  class AgentlessCiVisibilityExporter {
8
10
  constructor (config) {
9
- const { flushInterval, tags, site, url } = config
11
+ this._config = config
12
+ const { tags, site, url, isIntelligentTestRunnerEnabled } = config
13
+ this._isIntelligentTestRunnerEnabled = isIntelligentTestRunnerEnabled
10
14
  this._url = url || new URL(`https://citestcycle-intake.${site}`)
11
15
  this._writer = new Writer({ url: this._url, tags })
16
+ this._timer = undefined
17
+ this._coverageTimer = undefined
18
+
19
+ this._coverageUrl = url || new URL(`https://event-platform-intake.${site}`)
20
+ this._coverageWriter = new CoverageWriter({ url: this._coverageUrl })
21
+
22
+ process.once('beforeExit', () => {
23
+ this._writer.flush()
24
+ this._coverageWriter.flush()
25
+ })
26
+ }
12
27
 
13
- if (flushInterval > 0) {
14
- this._scheduler = new Scheduler(() => this._writer.flush(), flushInterval)
28
+ exportCoverage ({ testSpan, coverageFiles }) {
29
+ const formattedCoverage = {
30
+ traceId: testSpan.context()._traceId,
31
+ spanId: testSpan.context()._spanId,
32
+ files: coverageFiles
33
+ }
34
+ this._coverageWriter.append(formattedCoverage)
35
+
36
+ const { flushInterval } = this._config
37
+
38
+ if (flushInterval === 0) {
39
+ this._coverageWriter.flush()
40
+ } else if (flushInterval > 0 && !this._coverageTimer) {
41
+ this._coverageTimer = setTimeout(() => {
42
+ this._coverageWriter.flush()
43
+ this._coverageTimer = clearTimeout(this._coverageTimer)
44
+ }, flushInterval).unref()
15
45
  }
16
- this._scheduler && this._scheduler.start()
17
46
  }
18
47
 
19
48
  export (trace) {
20
49
  this._writer.append(trace)
21
50
 
22
- if (!this._scheduler) {
51
+ const { flushInterval } = this._config
52
+
53
+ if (flushInterval === 0) {
23
54
  this._writer.flush()
55
+ } else if (flushInterval > 0 && !this._timer) {
56
+ this._timer = setTimeout(() => {
57
+ this._writer.flush()
58
+ this._timer = clearTimeout(this._timer)
59
+ }, flushInterval).unref()
24
60
  }
25
61
  }
26
62
 
27
- flush () {
28
- this._writer.flush()
63
+ setUrl (url, coverageUrl = url) {
64
+ try {
65
+ url = new URL(url)
66
+ coverageUrl = new URL(coverageUrl)
67
+ this._url = url
68
+ this._coverageUrl = coverageUrl
69
+ this._writer.setUrl(url)
70
+ this._coverageWriter.setUrl(coverageUrl)
71
+ } catch (e) {
72
+ log.error(e)
73
+ }
29
74
  }
30
75
  }
31
76
 
@@ -5,16 +5,37 @@ const log = require('../../../log')
5
5
  const { AgentlessCiVisibilityEncoder } = require('../../../encode/agentless-ci-visibility')
6
6
  const BaseWriter = require('../../../exporters/common/writer')
7
7
 
8
+ function safeJSONStringify (value) {
9
+ return JSON.stringify(value, (key, value) =>
10
+ key !== 'dd-api-key' ? value : undefined
11
+ )
12
+ }
13
+
8
14
  class Writer extends BaseWriter {
9
15
  constructor ({ url, tags }) {
10
16
  super(...arguments)
11
17
  const { 'runtime-id': runtimeId, env, service } = tags
12
18
  this._url = url
13
- this._encoder = new AgentlessCiVisibilityEncoder({ runtimeId, env, service })
19
+ this._encoder = new AgentlessCiVisibilityEncoder(this, { runtimeId, env, service })
14
20
  }
15
21
 
16
22
  _sendPayload (data, _, done) {
17
- makeRequest(data, this._url, (err, res) => {
23
+ const options = {
24
+ path: '/api/v2/citestcycle',
25
+ method: 'POST',
26
+ headers: {
27
+ 'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY,
28
+ 'Content-Type': 'application/msgpack'
29
+ },
30
+ timeout: 15000
31
+ }
32
+
33
+ options.protocol = this._url.protocol
34
+ options.hostname = this._url.hostname
35
+ options.port = this._url.port
36
+
37
+ log.debug(() => `Request to the intake: ${safeJSONStringify(options)}`)
38
+ request(data, options, (err, res) => {
18
39
  if (err) {
19
40
  log.error(err)
20
41
  done()
@@ -26,26 +47,4 @@ class Writer extends BaseWriter {
26
47
  }
27
48
  }
28
49
 
29
- function makeRequest (data, url, cb) {
30
- const options = {
31
- path: '/api/v2/citestcycle',
32
- method: 'POST',
33
- headers: {
34
- 'Content-Type': 'application/msgpack',
35
- 'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY
36
- },
37
- timeout: 15000
38
- }
39
-
40
- options.protocol = url.protocol
41
- options.hostname = url.hostname
42
- options.port = url.port
43
-
44
- log.debug(() => `Request to the intake: ${JSON.stringify(options)}`)
45
-
46
- request(data, options, false, (err, res) => {
47
- cb(err, res)
48
- })
49
- }
50
-
51
50
  module.exports = Writer
@@ -0,0 +1,220 @@
1
+
2
+ const fs = require('fs')
3
+ const https = require('https')
4
+ const path = require('path')
5
+
6
+ const FormData = require('../../../exporters/common/form-data')
7
+
8
+ const log = require('../../../log')
9
+ const {
10
+ getLatestCommits,
11
+ getRepositoryUrl,
12
+ generatePackFilesForCommits,
13
+ getCommitsToUpload
14
+ } = require('../../../plugins/util/git')
15
+
16
+ const isValidSha = (sha) => /[0-9a-f]{40}/.test(sha)
17
+
18
+ function sanitizeCommits (commits) {
19
+ return commits.map(({ id: commitSha, type }) => {
20
+ if (type !== 'commit') {
21
+ throw new Error('Invalid commit response')
22
+ }
23
+ const sanitizedCommit = commitSha.replace(/[^0-9a-f]+/g, '')
24
+ if (sanitizedCommit !== commitSha || !isValidSha(sanitizedCommit)) {
25
+ throw new Error('Invalid commit format')
26
+ }
27
+ return sanitizedCommit
28
+ })
29
+ }
30
+
31
+ function getCommonRequestOptions (url) {
32
+ return {
33
+ method: 'POST',
34
+ headers: {
35
+ 'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY
36
+ },
37
+ timeout: 15000,
38
+ protocol: url.protocol,
39
+ hostname: url.hostname,
40
+ port: url.port
41
+ }
42
+ }
43
+
44
+ /**
45
+ * This function posts the SHAs of the commits of the last month
46
+ * The response are the commits for which the backend already has information
47
+ * This response is used to know which commits can be ignored from there on
48
+ */
49
+ function getCommitsToExclude ({ url, repositoryUrl }, callback) {
50
+ const latestCommits = getLatestCommits()
51
+ const [headCommit] = latestCommits
52
+
53
+ const commonOptions = getCommonRequestOptions(url)
54
+
55
+ const options = {
56
+ ...commonOptions,
57
+ headers: {
58
+ ...commonOptions.headers,
59
+ 'Content-Type': 'application/json'
60
+ },
61
+ path: '/api/v2/git/repository/search_commits'
62
+ }
63
+
64
+ const localCommitData = JSON.stringify({
65
+ meta: {
66
+ repository_url: repositoryUrl
67
+ },
68
+ data: latestCommits.map(commit => ({
69
+ id: commit,
70
+ type: 'commit'
71
+ }))
72
+ })
73
+
74
+ const request = https.request(options, (res) => {
75
+ let responseData = ''
76
+
77
+ res.on('data', chunk => { responseData += chunk })
78
+ res.on('end', () => {
79
+ if (res.statusCode === 200) {
80
+ let commitsToExclude
81
+ try {
82
+ commitsToExclude = sanitizeCommits(JSON.parse(responseData).data)
83
+ } catch (e) {
84
+ callback(new Error(`Can't parse response: ${e.message}`))
85
+ return
86
+ }
87
+ callback(null, commitsToExclude, headCommit)
88
+ } else {
89
+ const error = new Error(`Error getting commits: ${res.statusCode} ${res.statusMessage}`)
90
+ callback(error)
91
+ }
92
+ })
93
+ })
94
+
95
+ request.write(localCommitData)
96
+ request.on('error', callback)
97
+
98
+ request.end()
99
+
100
+ return request
101
+ }
102
+
103
+ /**
104
+ * This function uploads a git packfile
105
+ */
106
+ function uploadPackFile ({ url, packFileToUpload, repositoryUrl, headCommit }, callback) {
107
+ const form = new FormData()
108
+
109
+ const pushedSha = JSON.stringify({
110
+ data: {
111
+ id: headCommit,
112
+ type: 'commit'
113
+ },
114
+ meta: {
115
+ repository_url: repositoryUrl
116
+ }
117
+ })
118
+
119
+ form.append('pushedSha', pushedSha, { contentType: 'application/json' })
120
+
121
+ try {
122
+ const packFileContent = fs.readFileSync(packFileToUpload)
123
+ // The original filename includes a random prefix, so we remove it here
124
+ const [, filename] = path.basename(packFileToUpload).split('-')
125
+ form.append('packfile', packFileContent, {
126
+ filename,
127
+ contentType: 'application/octet-stream'
128
+ })
129
+ } catch (e) {
130
+ callback(new Error(`Error reading packfile: ${packFileToUpload}`))
131
+ return
132
+ }
133
+
134
+ const commonOptions = getCommonRequestOptions(url)
135
+
136
+ const options = {
137
+ ...commonOptions,
138
+ path: '/api/v2/git/repository/packfile',
139
+ headers: {
140
+ ...commonOptions.headers,
141
+ ...form.getHeaders()
142
+ }
143
+ }
144
+
145
+ const req = https.request(options, res => {
146
+ res.on('data', () => {})
147
+ res.on('end', () => {
148
+ if (res.statusCode === 204) {
149
+ callback(null)
150
+ } else {
151
+ const error = new Error(`Error uploading packfiles: ${res.statusCode} ${res.statusMessage}`)
152
+ error.status = res.statusCode
153
+
154
+ callback(error)
155
+ }
156
+ })
157
+ })
158
+
159
+ req.on('error', err => {
160
+ callback(err)
161
+ })
162
+ form.pipe(req)
163
+ }
164
+
165
+ /**
166
+ * This function uploads git metadata to CI Visibility's backend.
167
+ */
168
+ function sendGitMetadata (site, callback) {
169
+ const url = new URL(`https://api.${site}`)
170
+
171
+ const repositoryUrl = getRepositoryUrl()
172
+
173
+ getCommitsToExclude({ url, repositoryUrl }, (err, commitsToExclude, headCommit) => {
174
+ if (err) {
175
+ callback(err)
176
+ return
177
+ }
178
+ const commitsToUpload = getCommitsToUpload(commitsToExclude)
179
+
180
+ if (!commitsToUpload.length) {
181
+ log.debug('No commits to upload')
182
+ callback(null)
183
+ return
184
+ }
185
+
186
+ const packFilesToUpload = generatePackFilesForCommits(commitsToUpload)
187
+
188
+ let packFileIndex = 0
189
+ // This uploads packfiles sequentially
190
+ const uploadPackFileCallback = (err) => {
191
+ if (err || packFileIndex === packFilesToUpload.length) {
192
+ callback(err)
193
+ return
194
+ }
195
+ return uploadPackFile(
196
+ {
197
+ packFileToUpload: packFilesToUpload[packFileIndex++],
198
+ url,
199
+ repositoryUrl,
200
+ headCommit
201
+ },
202
+ uploadPackFileCallback
203
+ )
204
+ }
205
+
206
+ uploadPackFile(
207
+ {
208
+ url,
209
+ packFileToUpload: packFilesToUpload[packFileIndex++],
210
+ repositoryUrl,
211
+ headCommit
212
+ },
213
+ uploadPackFileCallback
214
+ )
215
+ })
216
+ }
217
+
218
+ module.exports = {
219
+ sendGitMetadata
220
+ }
@@ -13,6 +13,17 @@ const uuid = require('crypto-randomuuid')
13
13
  const fromEntries = Object.fromEntries || (entries =>
14
14
  entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))
15
15
 
16
+ // eslint-disable-next-line max-len
17
+ const qsRegex = '(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\\s|%20)*(?::|%3A)(?:\\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|bearer(?:\\s|%20)+[a-z0-9\\._\\-]|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\\w=-]|%3D)+\\.ey[I-L](?:[\\w=-]|%3D)+(?:\\.(?:[\\w.+\\/=-]|%3D|%2F|%2B)+)?|[\\-]{5}BEGIN(?:[a-z\\s]|%20)+PRIVATE(?:\\s|%20)KEY[\\-]{5}[^\\-]+[\\-]{5}END(?:[a-z\\s]|%20)+PRIVATE(?:\\s|%20)KEY|ssh-rsa(?:\\s|%20)*(?:[a-z0-9\\/\\.+]|%2F|%5C|%2B){100,}'
18
+
19
+ function safeJsonParse (input) {
20
+ try {
21
+ return JSON.parse(input)
22
+ } catch (err) {
23
+ return undefined
24
+ }
25
+ }
26
+
16
27
  class Config {
17
28
  constructor (options) {
18
29
  options = options || {}
@@ -67,6 +78,12 @@ class Config {
67
78
  null
68
79
  )
69
80
  const DD_CIVISIBILITY_AGENTLESS_URL = process.env.DD_CIVISIBILITY_AGENTLESS_URL
81
+
82
+ const DD_CIVISIBILITY_ITR_ENABLED = coalesce(
83
+ process.env.DD_CIVISIBILITY_ITR_ENABLED,
84
+ false
85
+ )
86
+
70
87
  const DD_SERVICE = options.service ||
71
88
  process.env.DD_SERVICE ||
72
89
  process.env.DD_SERVICE_NAME ||
@@ -109,6 +126,18 @@ class Config {
109
126
  parseInt(process.env.DD_TRACE_PARTIAL_FLUSH_MIN_SPANS),
110
127
  1000
111
128
  )
129
+ const DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP = coalesce(
130
+ process.env.DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP,
131
+ qsRegex
132
+ )
133
+ const DD_TRACE_CLIENT_IP_HEADER_DISABLED = coalesce(
134
+ process.env.DD_TRACE_CLIENT_IP_HEADER_DISABLED,
135
+ false
136
+ )
137
+ const DD_TRACE_CLIENT_IP_HEADER = coalesce(
138
+ process.env.DD_TRACE_CLIENT_IP_HEADER,
139
+ null
140
+ )
112
141
  const DD_TRACE_B3_ENABLED = coalesce(
113
142
  options.experimental && options.experimental.b3,
114
143
  process.env.DD_TRACE_EXPERIMENTAL_B3_ENABLED,
@@ -134,6 +163,17 @@ class Config {
134
163
  false
135
164
  )
136
165
 
166
+ const DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH = coalesce(
167
+ process.env.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
168
+ '512'
169
+ )
170
+
171
+ const DD_TRACE_STATS_COMPUTATION_ENABLED = coalesce(
172
+ options.stats,
173
+ process.env.DD_TRACE_STATS_COMPUTATION_ENABLED,
174
+ false
175
+ )
176
+
137
177
  let appsec = options.appsec || (options.experimental && options.experimental.appsec)
138
178
 
139
179
  const DD_APPSEC_ENABLED = coalesce(
@@ -174,19 +214,51 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
174
214
  |[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}`
175
215
  )
176
216
 
177
- const sampler = (options.experimental && options.experimental.sampler) || {}
217
+ const iastOptions = options.experimental && options.experimental.iast
218
+ const DD_IAST_ENABLED = coalesce(
219
+ iastOptions &&
220
+ (iastOptions === true || iastOptions.enabled === true),
221
+ process.env.DD_IAST_ENABLED,
222
+ false
223
+ )
224
+
225
+ const defaultIastRequestSampling = 30
226
+ const iastRequestSampling = coalesce(
227
+ parseInt(iastOptions && iastOptions.requestSampling),
228
+ parseInt(process.env.DD_IAST_REQUEST_SAMPLING),
229
+ defaultIastRequestSampling
230
+ )
231
+ const DD_IAST_REQUEST_SAMPLING = iastRequestSampling < 0 ||
232
+ iastRequestSampling > 100 ? defaultIastRequestSampling : iastRequestSampling
233
+
234
+ const DD_IAST_MAX_CONCURRENT_REQUESTS = coalesce(
235
+ parseInt(iastOptions && iastOptions.maxConcurrentRequests),
236
+ parseInt(process.env.DD_IAST_MAX_CONCURRENT_REQUESTS),
237
+ 2
238
+ )
239
+
240
+ const DD_IAST_MAX_CONTEXT_OPERATIONS = coalesce(
241
+ parseInt(iastOptions && iastOptions.maxContextOperations),
242
+ parseInt(process.env.DD_IAST_MAX_CONTEXT_OPERATIONS),
243
+ 2
244
+ )
245
+
246
+ const DD_CIVISIBILITY_GIT_UPLOAD_ENABLED = coalesce(
247
+ process.env.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED,
248
+ false
249
+ )
250
+
178
251
  const ingestion = options.ingestion || {}
179
252
  const dogstatsd = coalesce(options.dogstatsd, {})
180
-
181
- Object.assign(sampler, {
253
+ const sampler = {
182
254
  sampleRate: coalesce(
183
255
  options.sampleRate,
184
- ingestion.sampleRate,
185
- sampler.sampleRate,
186
- process.env.DD_TRACE_SAMPLE_RATE
256
+ process.env.DD_TRACE_SAMPLE_RATE,
257
+ ingestion.sampleRate
187
258
  ),
188
- rateLimit: coalesce(ingestion.rateLimit, sampler.rateLimit, process.env.DD_TRACE_RATE_LIMIT)
189
- })
259
+ rateLimit: coalesce(options.rateLimit, process.env.DD_TRACE_RATE_LIMIT, ingestion.rateLimit),
260
+ rules: coalesce(options.samplingRules, safeJsonParse(process.env.DD_TRACE_SAMPLING_RULES), [])
261
+ }
190
262
 
191
263
  const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
192
264
  const defaultFlushInterval = inAWSLambda ? 0 : 2000
@@ -203,6 +275,9 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
203
275
  this.flushInterval = coalesce(parseInt(options.flushInterval, 10), defaultFlushInterval)
204
276
  this.flushMinSpans = DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
205
277
  this.sampleRate = coalesce(Math.min(Math.max(sampler.sampleRate, 0), 1), 1)
278
+ this.queryStringObfuscation = DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP
279
+ this.clientIpHeaderDisabled = isTrue(DD_TRACE_CLIENT_IP_HEADER_DISABLED)
280
+ this.clientIpHeader = DD_TRACE_CLIENT_IP_HEADER
206
281
  this.logger = options.logger
207
282
  this.plugins = !!coalesce(options.plugins, true)
208
283
  this.service = DD_SERVICE
@@ -220,9 +295,9 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
220
295
  traceparent: isTrue(DD_TRACE_TRACEPARENT_ENABLED),
221
296
  runtimeId: isTrue(DD_TRACE_RUNTIME_ID_ENABLED),
222
297
  exporter: DD_TRACE_EXPORTER,
223
- enableGetRumData: isTrue(DD_TRACE_GET_RUM_DATA_ENABLED),
224
- sampler
298
+ enableGetRumData: isTrue(DD_TRACE_GET_RUM_DATA_ENABLED)
225
299
  }
300
+ this.sampler = sampler
226
301
  this.reportHostname = isTrue(coalesce(options.reportHostname, process.env.DD_TRACE_REPORT_HOSTNAME, false))
227
302
  this.scope = process.env.DD_TRACE_SCOPE
228
303
  this.logLevel = coalesce(
@@ -240,6 +315,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
240
315
  // Disabled for CI Visibility's agentless
241
316
  this.telemetryEnabled = DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_TRACE_TELEMETRY_ENABLED)
242
317
  this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
318
+ this.tagsHeaderMaxLength = parseInt(DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
243
319
  this.appsec = {
244
320
  enabled: isTrue(DD_APPSEC_ENABLED),
245
321
  rules: DD_APPSEC_RULES,
@@ -248,6 +324,17 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
248
324
  obfuscatorKeyRegex: DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
249
325
  obfuscatorValueRegex: DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP
250
326
  }
327
+ this.iast = {
328
+ enabled: isTrue(DD_IAST_ENABLED),
329
+ requestSampling: DD_IAST_REQUEST_SAMPLING,
330
+ maxConcurrentRequests: DD_IAST_MAX_CONCURRENT_REQUESTS,
331
+ maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS
332
+ }
333
+ this.isGitUploadEnabled = isTrue(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED)
334
+ this.isIntelligentTestRunnerEnabled = isTrue(DD_CIVISIBILITY_ITR_ENABLED)
335
+ this.stats = {
336
+ enabled: isTrue(DD_TRACE_STATS_COMPUTATION_ENABLED)
337
+ }
251
338
 
252
339
  tagger.add(this.tags, {
253
340
  service: this.service,
@@ -5,8 +5,16 @@ module.exports = {
5
5
  ANALYTICS_KEY: '_dd1.sr.eausr',
6
6
  ORIGIN_KEY: '_dd.origin',
7
7
  HOSTNAME_KEY: '_dd.hostname',
8
+ TOP_LEVEL_KEY: '_dd.top_level',
8
9
  SAMPLING_RULE_DECISION: '_dd.rule_psr',
9
10
  SAMPLING_LIMIT_DECISION: '_dd.limit_psr',
10
11
  SAMPLING_AGENT_DECISION: '_dd.agent_psr',
11
- DATADOG_LAMBDA_EXTENSION_PATH: '/opt/extensions/datadog-agent'
12
+ SAMPLING_MECHANISM_DEFAULT: 0,
13
+ SAMPLING_MECHANISM_AGENT: 1,
14
+ SAMPLING_MECHANISM_RULE: 3,
15
+ SAMPLING_MECHANISM_MANUAL: 4,
16
+ SAMPLING_MECHANISM_APPSEC: 5,
17
+ SAMPLING_MECHANISM_SPAN: 8,
18
+ DATADOG_LAMBDA_EXTENSION_PATH: '/opt/extensions/datadog-agent',
19
+ DECISION_MAKER_KEY: '_dd.p.dm'
12
20
  }