dd-trace 3.3.1 → 3.12.1

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 (198) hide show
  1. package/LICENSE-3rdparty.csv +8 -0
  2. package/README.md +108 -43
  3. package/ci/init.js +6 -1
  4. package/ext/exporters.d.ts +2 -1
  5. package/ext/exporters.js +2 -1
  6. package/index.d.ts +129 -36
  7. package/package.json +18 -9
  8. package/packages/datadog-instrumentations/src/body-parser.js +26 -0
  9. package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
  10. package/packages/datadog-instrumentations/src/child-process.js +30 -0
  11. package/packages/datadog-instrumentations/src/connect.js +15 -15
  12. package/packages/datadog-instrumentations/src/cucumber.js +1 -3
  13. package/packages/datadog-instrumentations/src/elasticsearch.js +51 -47
  14. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +1 -1
  15. package/packages/datadog-instrumentations/src/helpers/hooks.js +9 -0
  16. package/packages/datadog-instrumentations/src/helpers/register.js +5 -0
  17. package/packages/datadog-instrumentations/src/http/server.js +20 -12
  18. package/packages/datadog-instrumentations/src/http2/server.js +67 -1
  19. package/packages/datadog-instrumentations/src/jest.js +182 -25
  20. package/packages/datadog-instrumentations/src/koa.js +32 -32
  21. package/packages/datadog-instrumentations/src/ldapjs.js +91 -0
  22. package/packages/datadog-instrumentations/src/mariadb.js +63 -0
  23. package/packages/datadog-instrumentations/src/memcached.js +1 -4
  24. package/packages/datadog-instrumentations/src/mocha.js +135 -24
  25. package/packages/datadog-instrumentations/src/next.js +10 -2
  26. package/packages/datadog-instrumentations/src/opensearch.js +10 -0
  27. package/packages/datadog-instrumentations/src/oracledb.js +8 -8
  28. package/packages/datadog-instrumentations/src/pg.js +7 -3
  29. package/packages/datadog-instrumentations/src/qs.js +24 -0
  30. package/packages/datadog-instrumentations/src/redis.js +12 -3
  31. package/packages/datadog-instrumentations/src/restify.js +5 -1
  32. package/packages/datadog-instrumentations/src/rhea.js +29 -15
  33. package/packages/datadog-instrumentations/src/router.js +23 -23
  34. package/packages/datadog-plugin-amqp10/src/consumer.js +32 -0
  35. package/packages/datadog-plugin-amqp10/src/index.js +11 -101
  36. package/packages/datadog-plugin-amqp10/src/producer.js +34 -0
  37. package/packages/datadog-plugin-amqp10/src/util.js +15 -0
  38. package/packages/datadog-plugin-amqplib/src/client.js +38 -0
  39. package/packages/datadog-plugin-amqplib/src/consumer.js +40 -0
  40. package/packages/datadog-plugin-amqplib/src/index.js +14 -102
  41. package/packages/datadog-plugin-amqplib/src/producer.js +37 -0
  42. package/packages/datadog-plugin-amqplib/src/util.js +14 -0
  43. package/packages/datadog-plugin-cassandra-driver/src/index.js +22 -60
  44. package/packages/datadog-plugin-cucumber/src/index.js +14 -33
  45. package/packages/datadog-plugin-cypress/src/plugin.js +2 -1
  46. package/packages/datadog-plugin-dns/src/index.js +16 -91
  47. package/packages/datadog-plugin-dns/src/lookup.js +40 -0
  48. package/packages/datadog-plugin-dns/src/lookup_service.js +24 -0
  49. package/packages/datadog-plugin-dns/src/resolve.js +24 -0
  50. package/packages/datadog-plugin-dns/src/reverse.js +21 -0
  51. package/packages/datadog-plugin-elasticsearch/src/index.js +24 -60
  52. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +24 -0
  53. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +41 -0
  54. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +14 -99
  55. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +33 -0
  56. package/packages/datadog-plugin-graphql/src/execute.js +73 -0
  57. package/packages/datadog-plugin-graphql/src/index.js +14 -176
  58. package/packages/datadog-plugin-graphql/src/parse.js +32 -0
  59. package/packages/datadog-plugin-graphql/src/resolve.js +70 -76
  60. package/packages/datadog-plugin-graphql/src/validate.js +28 -0
  61. package/packages/datadog-plugin-grpc/src/client.js +46 -55
  62. package/packages/datadog-plugin-grpc/src/index.js +7 -24
  63. package/packages/datadog-plugin-grpc/src/server.js +50 -52
  64. package/packages/datadog-plugin-grpc/src/util.js +15 -14
  65. package/packages/datadog-plugin-http/src/client.js +15 -5
  66. package/packages/datadog-plugin-http/src/index.js +7 -22
  67. package/packages/datadog-plugin-http/src/server.js +19 -3
  68. package/packages/datadog-plugin-http2/src/client.js +20 -1
  69. package/packages/datadog-plugin-http2/src/index.js +8 -26
  70. package/packages/datadog-plugin-http2/src/server.js +44 -0
  71. package/packages/datadog-plugin-jest/src/index.js +41 -65
  72. package/packages/datadog-plugin-kafkajs/src/consumer.js +42 -0
  73. package/packages/datadog-plugin-kafkajs/src/index.js +11 -87
  74. package/packages/datadog-plugin-kafkajs/src/producer.js +31 -0
  75. package/packages/datadog-plugin-mariadb/src/index.js +10 -0
  76. package/packages/datadog-plugin-memcached/src/index.js +17 -52
  77. package/packages/datadog-plugin-mocha/src/index.js +40 -60
  78. package/packages/datadog-plugin-moleculer/src/client.js +22 -36
  79. package/packages/datadog-plugin-moleculer/src/index.js +8 -26
  80. package/packages/datadog-plugin-moleculer/src/server.js +18 -30
  81. package/packages/datadog-plugin-mongodb-core/src/index.js +23 -51
  82. package/packages/datadog-plugin-mysql/src/index.js +23 -52
  83. package/packages/datadog-plugin-mysql2/src/index.js +1 -3
  84. package/packages/datadog-plugin-net/src/index.js +4 -0
  85. package/packages/datadog-plugin-net/src/ipc.js +21 -0
  86. package/packages/datadog-plugin-net/src/tcp.js +46 -0
  87. package/packages/datadog-plugin-next/src/index.js +3 -0
  88. package/packages/datadog-plugin-opensearch/src/index.js +11 -0
  89. package/packages/datadog-plugin-oracledb/src/index.js +29 -55
  90. package/packages/datadog-plugin-pg/src/index.js +27 -51
  91. package/packages/datadog-plugin-redis/src/index.js +29 -60
  92. package/packages/datadog-plugin-rhea/src/consumer.js +55 -0
  93. package/packages/datadog-plugin-rhea/src/index.js +11 -96
  94. package/packages/datadog-plugin-rhea/src/producer.js +45 -0
  95. package/packages/datadog-plugin-router/src/index.js +13 -2
  96. package/packages/datadog-plugin-sharedb/src/index.js +22 -39
  97. package/packages/datadog-plugin-tedious/src/index.js +20 -41
  98. package/packages/dd-trace/src/appsec/addresses.js +3 -1
  99. package/packages/dd-trace/src/appsec/blocking.js +44 -0
  100. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +8 -6
  101. package/packages/dd-trace/src/appsec/gateway/engine/engine.js +1 -1
  102. package/packages/dd-trace/src/appsec/gateway/engine/index.js +7 -2
  103. package/packages/dd-trace/src/appsec/gateway/engine/runner.js +0 -1
  104. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +4 -1
  105. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +11 -0
  106. package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +19 -0
  107. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +11 -0
  108. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +13 -0
  109. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +43 -5
  110. package/packages/dd-trace/src/appsec/iast/iast-context.js +3 -1
  111. package/packages/dd-trace/src/appsec/iast/index.js +24 -8
  112. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +20 -1
  113. package/packages/dd-trace/src/appsec/iast/path-line.js +17 -6
  114. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +17 -0
  115. package/packages/dd-trace/src/appsec/iast/taint-tracking/filter.js +16 -0
  116. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +18 -0
  117. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +98 -0
  118. package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +4 -0
  119. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +38 -0
  120. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +67 -0
  121. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +103 -0
  122. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +98 -30
  123. package/packages/dd-trace/src/appsec/index.js +79 -25
  124. package/packages/dd-trace/src/{plugins/util → appsec}/ip_blocklist.js +0 -0
  125. package/packages/dd-trace/src/appsec/ip_extractor.js +98 -0
  126. package/packages/dd-trace/src/appsec/recommended.json +134 -53
  127. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +7 -0
  128. package/packages/dd-trace/src/appsec/remote_config/index.js +56 -0
  129. package/packages/dd-trace/src/appsec/remote_config/manager.js +264 -0
  130. package/packages/dd-trace/src/{exporters → appsec/remote_config}/scheduler.js +9 -9
  131. package/packages/dd-trace/src/appsec/rule_manager.js +61 -1
  132. package/packages/dd-trace/src/appsec/templates/blocked.html +99 -0
  133. package/packages/dd-trace/src/appsec/templates/blocked.json +8 -0
  134. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +66 -0
  135. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +9 -5
  136. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +19 -51
  137. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +10 -5
  138. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +202 -0
  139. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +51 -62
  140. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +89 -0
  141. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +82 -0
  142. package/packages/dd-trace/src/config.js +119 -35
  143. package/packages/dd-trace/src/constants.js +9 -1
  144. package/packages/dd-trace/src/dogstatsd.js +42 -10
  145. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +10 -2
  146. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
  147. package/packages/dd-trace/src/exporter.js +3 -0
  148. package/packages/dd-trace/src/exporters/agent/index.js +10 -2
  149. package/packages/dd-trace/src/exporters/agent/writer.js +2 -9
  150. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +82 -0
  151. package/packages/dd-trace/src/exporters/common/request.js +51 -1
  152. package/packages/dd-trace/src/exporters/span-stats/index.js +6 -2
  153. package/packages/dd-trace/src/format.js +29 -10
  154. package/packages/dd-trace/src/lambda/handler.js +72 -0
  155. package/packages/dd-trace/src/lambda/index.js +5 -0
  156. package/packages/dd-trace/src/lambda/runtime/errors.js +20 -0
  157. package/packages/dd-trace/src/lambda/runtime/patch.js +74 -0
  158. package/packages/dd-trace/src/lambda/runtime/ritm.js +138 -0
  159. package/packages/dd-trace/src/metrics.js +15 -2
  160. package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -5
  161. package/packages/dd-trace/src/opentracing/span.js +2 -1
  162. package/packages/dd-trace/src/opentracing/span_context.js +9 -0
  163. package/packages/dd-trace/src/plugin_manager.js +11 -17
  164. package/packages/dd-trace/src/plugins/cache.js +9 -0
  165. package/packages/dd-trace/src/plugins/ci_plugin.js +97 -0
  166. package/packages/dd-trace/src/plugins/client.js +9 -0
  167. package/packages/dd-trace/src/plugins/composite.js +26 -0
  168. package/packages/dd-trace/src/plugins/consumer.js +9 -0
  169. package/packages/dd-trace/src/plugins/database.js +55 -0
  170. package/packages/dd-trace/src/plugins/incoming.js +7 -0
  171. package/packages/dd-trace/src/plugins/index.js +3 -0
  172. package/packages/dd-trace/src/plugins/log_plugin.js +2 -2
  173. package/packages/dd-trace/src/plugins/outgoing.js +31 -0
  174. package/packages/dd-trace/src/plugins/plugin.js +3 -0
  175. package/packages/dd-trace/src/plugins/producer.js +9 -0
  176. package/packages/dd-trace/src/plugins/server.js +9 -0
  177. package/packages/dd-trace/src/plugins/storage.js +21 -0
  178. package/packages/dd-trace/src/plugins/tracing.js +94 -0
  179. package/packages/dd-trace/src/plugins/util/ci.js +40 -4
  180. package/packages/dd-trace/src/plugins/util/git.js +58 -18
  181. package/packages/dd-trace/src/plugins/util/test.js +71 -8
  182. package/packages/dd-trace/src/plugins/util/user-provided-git.js +14 -1
  183. package/packages/dd-trace/src/plugins/util/web.js +11 -114
  184. package/packages/dd-trace/src/priority_sampler.js +6 -2
  185. package/packages/dd-trace/src/profiling/config.js +11 -6
  186. package/packages/dd-trace/src/profiling/exporters/agent.js +4 -0
  187. package/packages/dd-trace/src/profiling/index.js +2 -2
  188. package/packages/dd-trace/src/profiling/profiler.js +43 -7
  189. package/packages/dd-trace/src/proxy.js +8 -16
  190. package/packages/dd-trace/src/ritm.js +25 -14
  191. package/packages/dd-trace/src/span_processor.js +17 -0
  192. package/packages/dd-trace/src/span_sampler.js +77 -0
  193. package/packages/dd-trace/src/span_stats.js +2 -2
  194. package/packages/dd-trace/src/telemetry/dependencies.js +21 -7
  195. package/packages/dd-trace/src/telemetry/index.js +7 -1
  196. package/packages/dd-trace/src/telemetry/send-data.js +3 -1
  197. package/packages/dd-trace/src/tracer.js +10 -5
  198. package/packages/dd-trace/src/util.js +43 -1
@@ -1,9 +1,9 @@
1
1
 
2
2
  const fs = require('fs')
3
- const https = require('https')
4
3
  const path = require('path')
5
4
 
6
5
  const FormData = require('../../../exporters/common/form-data')
6
+ const request = require('../../../exporters/common/request')
7
7
 
8
8
  const log = require('../../../log')
9
9
  const {
@@ -18,7 +18,7 @@ const isValidSha = (sha) => /[0-9a-f]{40}/.test(sha)
18
18
  function sanitizeCommits (commits) {
19
19
  return commits.map(({ id: commitSha, type }) => {
20
20
  if (type !== 'commit') {
21
- throw new Error('Invalid commit response')
21
+ throw new Error('Invalid commit type response')
22
22
  }
23
23
  const sanitizedCommit = commitSha.replace(/[^0-9a-f]+/g, '')
24
24
  if (sanitizedCommit !== commitSha || !isValidSha(sanitizedCommit)) {
@@ -35,9 +35,7 @@ function getCommonRequestOptions (url) {
35
35
  'dd-api-key': process.env.DATADOG_API_KEY || process.env.DD_API_KEY
36
36
  },
37
37
  timeout: 15000,
38
- protocol: url.protocol,
39
- hostname: url.hostname,
40
- port: url.port
38
+ url
41
39
  }
42
40
  }
43
41
 
@@ -46,7 +44,7 @@ function getCommonRequestOptions (url) {
46
44
  * The response are the commits for which the backend already has information
47
45
  * This response is used to know which commits can be ignored from there on
48
46
  */
49
- function getCommitsToExclude ({ url, repositoryUrl }, callback) {
47
+ function getCommitsToExclude ({ url, isEvpProxy, repositoryUrl }, callback) {
50
48
  const latestCommits = getLatestCommits()
51
49
  const [headCommit] = latestCommits
52
50
 
@@ -61,6 +59,12 @@ function getCommitsToExclude ({ url, repositoryUrl }, callback) {
61
59
  path: '/api/v2/git/repository/search_commits'
62
60
  }
63
61
 
62
+ if (isEvpProxy) {
63
+ options.path = '/evp_proxy/v2/api/v2/git/repository/search_commits'
64
+ options.headers['X-Datadog-EVP-Subdomain'] = 'api'
65
+ delete options.headers['dd-api-key']
66
+ }
67
+
64
68
  const localCommitData = JSON.stringify({
65
69
  meta: {
66
70
  repository_url: repositoryUrl
@@ -71,39 +75,25 @@ function getCommitsToExclude ({ url, repositoryUrl }, callback) {
71
75
  }))
72
76
  })
73
77
 
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
- })
78
+ request(localCommitData, options, (err, response) => {
79
+ if (err) {
80
+ const error = new Error(`Error fetching commits to exclude: ${err.message}`)
81
+ return callback(error)
82
+ }
83
+ let commitsToExclude
84
+ try {
85
+ commitsToExclude = sanitizeCommits(JSON.parse(response).data)
86
+ } catch (e) {
87
+ return callback(new Error(`Can't parse commits to exclude response: ${e.message}`))
88
+ }
89
+ callback(null, commitsToExclude, headCommit)
93
90
  })
94
-
95
- request.write(localCommitData)
96
- request.on('error', callback)
97
-
98
- request.end()
99
-
100
- return request
101
91
  }
102
92
 
103
93
  /**
104
94
  * This function uploads a git packfile
105
95
  */
106
- function uploadPackFile ({ url, packFileToUpload, repositoryUrl, headCommit }, callback) {
96
+ function uploadPackFile ({ url, isEvpProxy, packFileToUpload, repositoryUrl, headCommit }, callback) {
107
97
  const form = new FormData()
108
98
 
109
99
  const pushedSha = JSON.stringify({
@@ -127,7 +117,7 @@ function uploadPackFile ({ url, packFileToUpload, repositoryUrl, headCommit }, c
127
117
  contentType: 'application/octet-stream'
128
118
  })
129
119
  } catch (e) {
130
- callback(new Error(`Error reading packfile: ${packFileToUpload}`))
120
+ callback(new Error(`Could not read "${packFileToUpload}"`))
131
121
  return
132
122
  }
133
123
 
@@ -142,60 +132,58 @@ function uploadPackFile ({ url, packFileToUpload, repositoryUrl, headCommit }, c
142
132
  }
143
133
  }
144
134
 
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
- })
135
+ if (isEvpProxy) {
136
+ options.path = '/evp_proxy/v2/api/v2/git/repository/packfile'
137
+ options.headers['X-Datadog-EVP-Subdomain'] = 'api'
138
+ delete options.headers['dd-api-key']
139
+ }
158
140
 
159
- req.on('error', err => {
160
- callback(err)
141
+ request(form, options, (err, _, statusCode) => {
142
+ if (err) {
143
+ const error = new Error(`Could not upload packfiles: status code ${statusCode}: ${err.message}`)
144
+ return callback(error)
145
+ }
146
+ callback(null)
161
147
  })
162
- form.pipe(req)
163
148
  }
164
149
 
165
150
  /**
166
151
  * This function uploads git metadata to CI Visibility's backend.
167
152
  */
168
- function sendGitMetadata (site, callback) {
169
- const url = new URL(`https://api.${site}`)
170
-
153
+ function sendGitMetadata (url, isEvpProxy, callback) {
171
154
  const repositoryUrl = getRepositoryUrl()
172
155
 
173
- getCommitsToExclude({ url, repositoryUrl }, (err, commitsToExclude, headCommit) => {
156
+ if (!repositoryUrl) {
157
+ return callback(new Error('Repository URL is empty'))
158
+ }
159
+
160
+ getCommitsToExclude({ url, repositoryUrl, isEvpProxy }, (err, commitsToExclude, headCommit) => {
174
161
  if (err) {
175
- callback(err)
176
- return
162
+ return callback(err)
177
163
  }
178
164
  const commitsToUpload = getCommitsToUpload(commitsToExclude)
179
165
 
180
166
  if (!commitsToUpload.length) {
181
167
  log.debug('No commits to upload')
182
- callback(null)
183
- return
168
+ return callback(null)
184
169
  }
185
-
186
170
  const packFilesToUpload = generatePackFilesForCommits(commitsToUpload)
187
171
 
172
+ if (!packFilesToUpload.length) {
173
+ return callback(new Error('Failed to generate packfiles'))
174
+ }
175
+
188
176
  let packFileIndex = 0
189
177
  // This uploads packfiles sequentially
190
178
  const uploadPackFileCallback = (err) => {
191
179
  if (err || packFileIndex === packFilesToUpload.length) {
192
- callback(err)
193
- return
180
+ return callback(err)
194
181
  }
195
182
  return uploadPackFile(
196
183
  {
197
184
  packFileToUpload: packFilesToUpload[packFileIndex++],
198
185
  url,
186
+ isEvpProxy,
199
187
  repositoryUrl,
200
188
  headCommit
201
189
  },
@@ -205,8 +193,9 @@ function sendGitMetadata (site, callback) {
205
193
 
206
194
  uploadPackFile(
207
195
  {
208
- url,
209
196
  packFileToUpload: packFilesToUpload[packFileIndex++],
197
+ url,
198
+ isEvpProxy,
210
199
  repositoryUrl,
211
200
  headCommit
212
201
  },
@@ -0,0 +1,89 @@
1
+ const request = require('../../exporters/common/request')
2
+ const id = require('../../id')
3
+
4
+ function getItrConfiguration ({
5
+ url,
6
+ isEvpProxy,
7
+ env,
8
+ service,
9
+ repositoryUrl,
10
+ sha,
11
+ osVersion,
12
+ osPlatform,
13
+ osArchitecture,
14
+ runtimeName,
15
+ runtimeVersion,
16
+ branch
17
+ }, done) {
18
+ const options = {
19
+ path: '/api/v2/libraries/tests/services/setting',
20
+ method: 'POST',
21
+ headers: {
22
+ 'Content-Type': 'application/json'
23
+ },
24
+ url
25
+ }
26
+
27
+ if (isEvpProxy) {
28
+ options.path = '/evp_proxy/v2/api/v2/libraries/tests/services/setting'
29
+ options.headers['X-Datadog-EVP-Subdomain'] = 'api'
30
+ options.headers['X-Datadog-NeedsAppKey'] = 'true'
31
+ } else {
32
+ const apiKey = process.env.DATADOG_API_KEY || process.env.DD_API_KEY
33
+ const appKey = process.env.DATADOG_APP_KEY ||
34
+ process.env.DD_APP_KEY ||
35
+ process.env.DATADOG_APPLICATION_KEY ||
36
+ process.env.DD_APPLICATION_KEY
37
+
38
+ if (!apiKey || !appKey) {
39
+ return done(new Error('App key or API key undefined'))
40
+ }
41
+ options.headers['dd-api-key'] = apiKey
42
+ options.headers['dd-application-key'] = appKey
43
+ }
44
+
45
+ const data = JSON.stringify({
46
+ data: {
47
+ id: id().toString(10),
48
+ type: 'ci_app_test_service_libraries_settings',
49
+ attributes: {
50
+ test_level: 'suite',
51
+ configurations: {
52
+ 'os.platform': osPlatform,
53
+ 'os.version': osVersion,
54
+ 'os.architecture': osArchitecture,
55
+ 'runtime.name': runtimeName,
56
+ 'runtime.version': runtimeVersion
57
+ },
58
+ service,
59
+ env,
60
+ repository_url: repositoryUrl,
61
+ sha,
62
+ branch
63
+ }
64
+ }
65
+ })
66
+
67
+ request(data, options, (err, res) => {
68
+ if (err) {
69
+ done(err)
70
+ } else {
71
+ try {
72
+ const {
73
+ data: {
74
+ attributes: {
75
+ code_coverage: isCodeCoverageEnabled,
76
+ tests_skipping: isSuitesSkippingEnabled
77
+ }
78
+ }
79
+ } = JSON.parse(res)
80
+
81
+ done(null, { isCodeCoverageEnabled, isSuitesSkippingEnabled })
82
+ } catch (err) {
83
+ done(err)
84
+ }
85
+ }
86
+ })
87
+ }
88
+
89
+ module.exports = { getItrConfiguration }
@@ -0,0 +1,82 @@
1
+ const request = require('../../exporters/common/request')
2
+
3
+ function getSkippableSuites ({
4
+ url,
5
+ isEvpProxy,
6
+ env,
7
+ service,
8
+ repositoryUrl,
9
+ sha,
10
+ osVersion,
11
+ osPlatform,
12
+ osArchitecture,
13
+ runtimeName,
14
+ runtimeVersion
15
+ }, done) {
16
+ const options = {
17
+ path: '/api/v2/ci/tests/skippable',
18
+ method: 'POST',
19
+ headers: {
20
+ 'Content-Type': 'application/json'
21
+ },
22
+ timeout: 15000,
23
+ url
24
+ }
25
+
26
+ if (isEvpProxy) {
27
+ options.path = '/evp_proxy/v2/api/v2/ci/tests/skippable'
28
+ options.headers['X-Datadog-EVP-Subdomain'] = 'api'
29
+ options.headers['X-Datadog-NeedsAppKey'] = 'true'
30
+ } else {
31
+ const apiKey = process.env.DATADOG_API_KEY || process.env.DD_API_KEY
32
+ const appKey = process.env.DATADOG_APP_KEY ||
33
+ process.env.DD_APP_KEY ||
34
+ process.env.DATADOG_APPLICATION_KEY ||
35
+ process.env.DD_APPLICATION_KEY
36
+
37
+ if (!apiKey || !appKey) {
38
+ return done(new Error('App key or API key undefined'))
39
+ }
40
+ options.headers['dd-api-key'] = apiKey
41
+ options.headers['dd-application-key'] = appKey
42
+ }
43
+
44
+ const data = JSON.stringify({
45
+ data: {
46
+ type: 'test_params',
47
+ attributes: {
48
+ test_level: 'suite',
49
+ configurations: {
50
+ 'os.platform': osPlatform,
51
+ 'os.version': osVersion,
52
+ 'os.architecture': osArchitecture,
53
+ 'runtime.name': runtimeName,
54
+ 'runtime.version': runtimeVersion
55
+ },
56
+ service,
57
+ env,
58
+ repository_url: repositoryUrl,
59
+ sha
60
+ }
61
+ }
62
+ })
63
+
64
+ request(data, options, (err, res) => {
65
+ if (err) {
66
+ done(err)
67
+ } else {
68
+ let skippableSuites = []
69
+ try {
70
+ skippableSuites = JSON.parse(res)
71
+ .data
72
+ .filter(({ type }) => type === 'suite')
73
+ .map(({ attributes: { suite } }) => suite)
74
+ done(null, skippableSuites)
75
+ } catch (err) {
76
+ done(err)
77
+ }
78
+ }
79
+ })
80
+ }
81
+
82
+ module.exports = { getSkippableSuites }
@@ -3,12 +3,13 @@
3
3
  const fs = require('fs')
4
4
  const os = require('os')
5
5
  const URL = require('url').URL
6
- const path = require('path')
6
+ const log = require('./log')
7
7
  const pkg = require('./pkg')
8
8
  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')
12
13
 
13
14
  const fromEntries = Object.fromEntries || (entries =>
14
15
  entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))
@@ -16,6 +17,25 @@ const fromEntries = Object.fromEntries || (entries =>
16
17
  // eslint-disable-next-line max-len
17
18
  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
 
20
+ function maybeFile (filepath) {
21
+ if (!filepath) return
22
+ try {
23
+ return fs.readFileSync(filepath, 'utf8')
24
+ } 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) {
35
+ return undefined
36
+ }
37
+ }
38
+
19
39
  function safeJsonParse (input) {
20
40
  try {
21
41
  return JSON.parse(input)
@@ -38,6 +58,21 @@ class Config {
38
58
  constructor (options) {
39
59
  options = options || {}
40
60
 
61
+ // Configure the logger first so it can be used to warn about other configs
62
+ this.debug = isTrue(coalesce(
63
+ process.env.DD_TRACE_DEBUG,
64
+ false
65
+ ))
66
+ this.logger = options.logger
67
+ this.logLevel = coalesce(
68
+ options.logLevel,
69
+ process.env.DD_TRACE_LOG_LEVEL,
70
+ 'debug'
71
+ )
72
+
73
+ log.use(this.logger)
74
+ log.toggle(this.debug, this.logLevel, this)
75
+
41
76
  this.tags = {}
42
77
 
43
78
  tagger.add(this.tags, process.env.DD_TAGS)
@@ -70,6 +105,11 @@ class Config {
70
105
  process.env.DD_RUNTIME_METRICS_ENABLED,
71
106
  false
72
107
  )
108
+ const DD_DBM_PROPAGATION_MODE = coalesce(
109
+ options.dbmPropagationMode,
110
+ process.env.DD_DBM_PROPAGATION_MODE,
111
+ 'disabled'
112
+ )
73
113
  const DD_AGENT_HOST = coalesce(
74
114
  options.hostname,
75
115
  process.env.DD_AGENT_HOST,
@@ -87,6 +127,10 @@ class Config {
87
127
  process.env.DD_TRACE_URL,
88
128
  null
89
129
  )
130
+ const DD_IS_CIVISIBILITY = coalesce(
131
+ options.isCiVisibility,
132
+ false
133
+ )
90
134
  const DD_CIVISIBILITY_AGENTLESS_URL = process.env.DD_CIVISIBILITY_AGENTLESS_URL
91
135
 
92
136
  const DD_CIVISIBILITY_ITR_ENABLED = coalesce(
@@ -101,7 +145,12 @@ class Config {
101
145
  process.env.AWS_LAMBDA_FUNCTION_NAME ||
102
146
  pkg.name ||
103
147
  'node'
104
- const DD_SERVICE_MAPPING = process.env.DD_SERVICE_MAPPING || ''
148
+ const DD_SERVICE_MAPPING = coalesce(
149
+ options.serviceMapping,
150
+ process.env.DD_SERVICE_MAPPING ? fromEntries(
151
+ process.env.DD_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
152
+ ) : {}
153
+ )
105
154
  const DD_ENV = coalesce(
106
155
  options.env,
107
156
  process.env.DD_ENV,
@@ -122,10 +171,6 @@ class Config {
122
171
  process.env.DD_TRACE_TELEMETRY_ENABLED,
123
172
  !process.env.AWS_LAMBDA_FUNCTION_NAME
124
173
  )
125
- const DD_TRACE_DEBUG = coalesce(
126
- process.env.DD_TRACE_DEBUG,
127
- false
128
- )
129
174
  const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
130
175
  options.protocolVersion,
131
176
  process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
@@ -140,10 +185,6 @@ class Config {
140
185
  process.env.DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP,
141
186
  qsRegex
142
187
  )
143
- const DD_TRACE_CLIENT_IP_HEADER_DISABLED = coalesce(
144
- process.env.DD_TRACE_CLIENT_IP_HEADER_DISABLED,
145
- false
146
- )
147
188
  const DD_TRACE_CLIENT_IP_HEADER = coalesce(
148
189
  process.env.DD_TRACE_CLIENT_IP_HEADER,
149
190
  null
@@ -184,20 +225,24 @@ class Config {
184
225
  false
185
226
  )
186
227
 
187
- let appsec = options.appsec || (options.experimental && options.experimental.appsec)
228
+ let appsec = options.appsec != null ? options.appsec : options.experimental && options.experimental.appsec
229
+
230
+ if (typeof appsec === 'boolean') {
231
+ appsec = {
232
+ enabled: appsec
233
+ }
234
+ } else if (appsec == null) {
235
+ appsec = {}
236
+ }
188
237
 
189
238
  const DD_APPSEC_ENABLED = coalesce(
190
- appsec && (appsec === true || appsec.enabled === true), // TODO: remove when enabled by default
191
- process.env.DD_APPSEC_ENABLED,
192
- false
239
+ appsec.enabled,
240
+ process.env.DD_APPSEC_ENABLED && isTrue(process.env.DD_APPSEC_ENABLED)
193
241
  )
194
242
 
195
- appsec = appsec || {}
196
-
197
243
  const DD_APPSEC_RULES = coalesce(
198
244
  appsec.rules,
199
- process.env.DD_APPSEC_RULES,
200
- path.join(__dirname, 'appsec', 'recommended.json')
245
+ process.env.DD_APPSEC_RULES
201
246
  )
202
247
  const DD_APPSEC_TRACE_RATE_LIMIT = coalesce(
203
248
  parseInt(appsec.rateLimit),
@@ -223,6 +268,29 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
223
268
  \\s+[a-z0-9\\._\\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\\w=-]+\\.ey[I-L][\\w=-]+(?:\\.[\\w.+\\/=-]+)?\
224
269
  |[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}`
225
270
  )
271
+ const DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML = coalesce(
272
+ maybePath(appsec.blockedTemplateHtml),
273
+ maybePath(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML),
274
+ path.join(__dirname, 'appsec', 'templates', 'blocked.html')
275
+ )
276
+ const DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON = coalesce(
277
+ maybePath(appsec.blockedTemplateJson),
278
+ maybePath(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON),
279
+ path.join(__dirname, 'appsec', 'templates', 'blocked.json')
280
+ )
281
+
282
+ const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
283
+
284
+ const remoteConfigOptions = options.remoteConfig || {}
285
+ const DD_REMOTE_CONFIGURATION_ENABLED = coalesce(
286
+ process.env.DD_REMOTE_CONFIGURATION_ENABLED && isTrue(process.env.DD_REMOTE_CONFIGURATION_ENABLED),
287
+ !inAWSLambda
288
+ )
289
+ const DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS = coalesce(
290
+ parseInt(remoteConfigOptions.pollInterval),
291
+ parseInt(process.env.DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS),
292
+ 5 // seconds
293
+ )
226
294
 
227
295
  const iastOptions = options.experimental && options.experimental.iast
228
296
  const DD_IAST_ENABLED = coalesce(
@@ -267,18 +335,32 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
267
335
  ingestion.sampleRate
268
336
  ),
269
337
  rateLimit: coalesce(options.rateLimit, process.env.DD_TRACE_RATE_LIMIT, ingestion.rateLimit),
270
- rules: coalesce(options.samplingRules, safeJsonParse(process.env.DD_TRACE_SAMPLING_RULES), []).map(rule => {
338
+ rules: coalesce(
339
+ options.samplingRules,
340
+ safeJsonParse(process.env.DD_TRACE_SAMPLING_RULES),
341
+ []
342
+ ).map(rule => {
271
343
  return remapify(rule, {
272
344
  sample_rate: 'sampleRate'
273
345
  })
346
+ }),
347
+ spanSamplingRules: coalesce(
348
+ options.spanSamplingRules,
349
+ safeJsonParse(maybeFile(process.env.DD_SPAN_SAMPLING_RULES_FILE)),
350
+ safeJsonParse(process.env.DD_SPAN_SAMPLING_RULES),
351
+ []
352
+ ).map(rule => {
353
+ return remapify(rule, {
354
+ sample_rate: 'sampleRate',
355
+ max_per_second: 'maxPerSecond'
356
+ })
274
357
  })
275
358
  }
276
359
 
277
- const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
278
360
  const defaultFlushInterval = inAWSLambda ? 0 : 2000
279
361
 
280
362
  this.tracing = !isFalse(DD_TRACING_ENABLED)
281
- this.debug = isTrue(DD_TRACE_DEBUG)
363
+ this.dbmPropagationMode = DD_DBM_PROPAGATION_MODE
282
364
  this.logInjection = isTrue(DD_LOGS_INJECTION)
283
365
  this.env = DD_ENV
284
366
  this.url = DD_CIVISIBILITY_AGENTLESS_URL ? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
@@ -290,14 +372,10 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
290
372
  this.flushMinSpans = DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
291
373
  this.sampleRate = coalesce(Math.min(Math.max(sampler.sampleRate, 0), 1), 1)
292
374
  this.queryStringObfuscation = DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP
293
- this.clientIpHeaderDisabled = isTrue(DD_TRACE_CLIENT_IP_HEADER_DISABLED)
294
375
  this.clientIpHeader = DD_TRACE_CLIENT_IP_HEADER
295
- this.logger = options.logger
296
376
  this.plugins = !!coalesce(options.plugins, true)
297
377
  this.service = DD_SERVICE
298
- this.serviceMapping = DD_SERVICE_MAPPING.length ? fromEntries(
299
- DD_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
300
- ) : {}
378
+ this.serviceMapping = DD_SERVICE_MAPPING
301
379
  this.version = DD_VERSION
302
380
  this.dogstatsd = {
303
381
  hostname: coalesce(dogstatsd.hostname, process.env.DD_DOGSTATSD_HOSTNAME, this.hostname),
@@ -314,11 +392,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
314
392
  this.sampler = sampler
315
393
  this.reportHostname = isTrue(coalesce(options.reportHostname, process.env.DD_TRACE_REPORT_HOSTNAME, false))
316
394
  this.scope = process.env.DD_TRACE_SCOPE
317
- this.logLevel = coalesce(
318
- options.logLevel,
319
- process.env.DD_TRACE_LOG_LEVEL,
320
- 'debug'
321
- )
322
395
  this.profiling = {
323
396
  enabled: isTrue(DD_PROFILING_ENABLED),
324
397
  sourceMap: !isFalse(DD_PROFILING_SOURCE_MAP),
@@ -331,12 +404,18 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
331
404
  this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
332
405
  this.tagsHeaderMaxLength = parseInt(DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
333
406
  this.appsec = {
334
- enabled: isTrue(DD_APPSEC_ENABLED),
407
+ enabled: DD_APPSEC_ENABLED,
335
408
  rules: DD_APPSEC_RULES,
336
409
  rateLimit: DD_APPSEC_TRACE_RATE_LIMIT,
337
410
  wafTimeout: DD_APPSEC_WAF_TIMEOUT,
338
411
  obfuscatorKeyRegex: DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
339
- obfuscatorValueRegex: DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP
412
+ obfuscatorValueRegex: DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP,
413
+ blockedTemplateHtml: DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML,
414
+ blockedTemplateJson: DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON
415
+ }
416
+ this.remoteConfig = {
417
+ enabled: DD_REMOTE_CONFIGURATION_ENABLED,
418
+ pollInterval: DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS
340
419
  }
341
420
  this.iast = {
342
421
  enabled: isTrue(DD_IAST_ENABLED),
@@ -344,8 +423,13 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
344
423
  maxConcurrentRequests: DD_IAST_MAX_CONCURRENT_REQUESTS,
345
424
  maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS
346
425
  }
347
- this.isGitUploadEnabled = isTrue(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED)
348
- this.isIntelligentTestRunnerEnabled = isTrue(DD_CIVISIBILITY_ITR_ENABLED)
426
+
427
+ this.isCiVisibility = isTrue(DD_IS_CIVISIBILITY)
428
+
429
+ this.isIntelligentTestRunnerEnabled = this.isCiVisibility && isTrue(DD_CIVISIBILITY_ITR_ENABLED)
430
+ this.isGitUploadEnabled = this.isCiVisibility &&
431
+ (this.isIntelligentTestRunnerEnabled || isTrue(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED))
432
+
349
433
  this.stats = {
350
434
  enabled: isTrue(DD_TRACE_STATS_COMPUTATION_ENABLED)
351
435
  }
@@ -15,6 +15,14 @@ module.exports = {
15
15
  SAMPLING_MECHANISM_MANUAL: 4,
16
16
  SAMPLING_MECHANISM_APPSEC: 5,
17
17
  SAMPLING_MECHANISM_SPAN: 8,
18
+ SPAN_SAMPLING_MECHANISM: '_dd.span_sampling.mechanism',
19
+ SPAN_SAMPLING_RULE_RATE: '_dd.span_sampling.rule_rate',
20
+ SPAN_SAMPLING_MAX_PER_SECOND: '_dd.span_sampling.max_per_second',
18
21
  DATADOG_LAMBDA_EXTENSION_PATH: '/opt/extensions/datadog-agent',
19
- DECISION_MAKER_KEY: '_dd.p.dm'
22
+ DECISION_MAKER_KEY: '_dd.p.dm',
23
+ PROCESS_ID: 'process_id',
24
+ ERROR_TYPE: 'error.type',
25
+ ERROR_MESSAGE: 'error.message',
26
+ ERROR_STACK: 'error.stack',
27
+ COMPONENT: 'component'
20
28
  }