dd-trace 4.18.0 → 5.6.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 (209) hide show
  1. package/CONTRIBUTING.md +98 -0
  2. package/LICENSE-3rdparty.csv +4 -5
  3. package/MIGRATING.md +15 -0
  4. package/README.md +20 -140
  5. package/ci/cypress/after-run.js +1 -0
  6. package/ci/cypress/after-spec.js +1 -0
  7. package/ci/init.js +1 -4
  8. package/ext/kinds.d.ts +1 -0
  9. package/ext/kinds.js +2 -1
  10. package/ext/tags.d.ts +2 -1
  11. package/ext/tags.js +6 -1
  12. package/index.d.ts +1523 -1460
  13. package/package.json +19 -19
  14. package/packages/datadog-core/src/storage/async_resource.js +1 -1
  15. package/packages/datadog-core/src/utils/src/get.js +11 -0
  16. package/packages/datadog-core/src/utils/src/has.js +14 -0
  17. package/packages/datadog-core/src/utils/src/kebabcase.js +16 -0
  18. package/packages/datadog-core/src/utils/src/pick.js +11 -0
  19. package/packages/datadog-core/src/utils/src/set.js +16 -0
  20. package/packages/datadog-core/src/utils/src/uniq.js +5 -0
  21. package/packages/datadog-esbuild/index.js +1 -20
  22. package/packages/datadog-instrumentations/src/aerospike.js +47 -0
  23. package/packages/datadog-instrumentations/src/amqplib.js +2 -2
  24. package/packages/datadog-instrumentations/src/apollo-server-core.js +41 -0
  25. package/packages/datadog-instrumentations/src/apollo-server.js +83 -0
  26. package/packages/datadog-instrumentations/src/child_process.js +150 -0
  27. package/packages/datadog-instrumentations/src/couchbase.js +5 -4
  28. package/packages/datadog-instrumentations/src/crypto.js +2 -1
  29. package/packages/datadog-instrumentations/src/cucumber.js +163 -46
  30. package/packages/datadog-instrumentations/src/dns.js +2 -1
  31. package/packages/datadog-instrumentations/src/express.js +20 -0
  32. package/packages/datadog-instrumentations/src/graphql.js +18 -4
  33. package/packages/datadog-instrumentations/src/grpc/client.js +56 -36
  34. package/packages/datadog-instrumentations/src/grpc/server.js +3 -1
  35. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +1 -2
  36. package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -3
  37. package/packages/datadog-instrumentations/src/helpers/instrument.js +9 -4
  38. package/packages/datadog-instrumentations/src/helpers/register.js +19 -3
  39. package/packages/datadog-instrumentations/src/http/client.js +12 -2
  40. package/packages/datadog-instrumentations/src/http/server.js +7 -4
  41. package/packages/datadog-instrumentations/src/http2/client.js +3 -1
  42. package/packages/datadog-instrumentations/src/http2/server.js +3 -1
  43. package/packages/datadog-instrumentations/src/jest.js +239 -52
  44. package/packages/datadog-instrumentations/src/kafkajs.js +27 -0
  45. package/packages/datadog-instrumentations/src/mocha.js +154 -18
  46. package/packages/datadog-instrumentations/src/mongodb-core.js +34 -3
  47. package/packages/datadog-instrumentations/src/mongoose.js +23 -10
  48. package/packages/datadog-instrumentations/src/mquery.js +65 -0
  49. package/packages/datadog-instrumentations/src/net.js +10 -2
  50. package/packages/datadog-instrumentations/src/next.js +35 -9
  51. package/packages/datadog-instrumentations/src/playwright.js +110 -16
  52. package/packages/datadog-instrumentations/src/restify.js +14 -1
  53. package/packages/datadog-instrumentations/src/rhea.js +15 -9
  54. package/packages/datadog-plugin-aerospike/src/index.js +113 -0
  55. package/packages/datadog-plugin-amqplib/src/consumer.js +14 -1
  56. package/packages/datadog-plugin-amqplib/src/producer.js +13 -1
  57. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
  58. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +163 -27
  59. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +46 -8
  60. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +129 -22
  61. package/packages/datadog-plugin-child_process/src/index.js +91 -0
  62. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +125 -0
  63. package/packages/datadog-plugin-cucumber/src/index.js +70 -13
  64. package/packages/datadog-plugin-cypress/src/after-run.js +3 -0
  65. package/packages/datadog-plugin-cypress/src/after-spec.js +3 -0
  66. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +625 -0
  67. package/packages/datadog-plugin-cypress/src/plugin.js +6 -454
  68. package/packages/datadog-plugin-cypress/src/support.js +50 -3
  69. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -0
  70. package/packages/datadog-plugin-graphql/src/index.js +1 -6
  71. package/packages/datadog-plugin-graphql/src/resolve.js +28 -18
  72. package/packages/datadog-plugin-grpc/src/client.js +16 -2
  73. package/packages/datadog-plugin-grpc/src/util.js +1 -1
  74. package/packages/datadog-plugin-http/src/client.js +19 -2
  75. package/packages/datadog-plugin-jest/src/index.js +118 -12
  76. package/packages/datadog-plugin-jest/src/util.js +38 -16
  77. package/packages/datadog-plugin-kafkajs/src/consumer.js +76 -6
  78. package/packages/datadog-plugin-kafkajs/src/producer.js +64 -8
  79. package/packages/datadog-plugin-mocha/src/index.js +87 -17
  80. package/packages/datadog-plugin-next/src/index.js +40 -14
  81. package/packages/datadog-plugin-playwright/src/index.js +71 -8
  82. package/packages/datadog-plugin-rhea/src/consumer.js +16 -1
  83. package/packages/datadog-plugin-rhea/src/producer.js +10 -0
  84. package/packages/dd-trace/src/appsec/activation.js +29 -0
  85. package/packages/dd-trace/src/appsec/addresses.js +5 -1
  86. package/packages/dd-trace/src/appsec/api_security_sampler.js +61 -0
  87. package/packages/dd-trace/src/appsec/blocked_templates.js +4 -1
  88. package/packages/dd-trace/src/appsec/blocking.js +95 -43
  89. package/packages/dd-trace/src/appsec/channels.js +7 -3
  90. package/packages/dd-trace/src/appsec/graphql.js +146 -0
  91. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +2 -0
  92. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +1 -1
  93. package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +105 -0
  94. package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +22 -17
  95. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +7 -28
  96. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +10 -6
  97. package/packages/dd-trace/src/appsec/iast/analyzers/weak-randomness-analyzer.js +19 -0
  98. package/packages/dd-trace/src/appsec/iast/context/context-plugin.js +90 -0
  99. package/packages/dd-trace/src/appsec/iast/context/kafka-ctx-plugin.js +14 -0
  100. package/packages/dd-trace/src/appsec/iast/iast-log.js +1 -1
  101. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +13 -2
  102. package/packages/dd-trace/src/appsec/iast/index.js +15 -5
  103. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
  104. package/packages/dd-trace/src/appsec/iast/path-line.js +1 -1
  105. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +2 -0
  106. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +10 -0
  107. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +53 -0
  108. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +10 -46
  109. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +13 -9
  110. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +47 -0
  111. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +19 -6
  112. package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +3 -1
  113. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +41 -3
  114. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/constants.js +7 -0
  115. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +12 -19
  116. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +20 -0
  117. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/json-sensitive-analyzer.js +6 -10
  118. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +18 -25
  119. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +79 -85
  120. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +27 -36
  121. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +14 -11
  122. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
  123. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +2 -0
  124. package/packages/dd-trace/src/appsec/index.js +49 -33
  125. package/packages/dd-trace/src/appsec/recommended.json +1763 -106
  126. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +7 -1
  127. package/packages/dd-trace/src/appsec/remote_config/index.js +42 -16
  128. package/packages/dd-trace/src/appsec/remote_config/manager.js +9 -8
  129. package/packages/dd-trace/src/appsec/reporter.js +51 -34
  130. package/packages/dd-trace/src/appsec/rule_manager.js +11 -8
  131. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
  132. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +28 -13
  133. package/packages/dd-trace/src/appsec/waf/waf_manager.js +0 -1
  134. package/packages/dd-trace/src/ci-visibility/{intelligent-test-runner/get-itr-configuration.js → early-flake-detection/get-known-tests.js} +17 -22
  135. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +25 -6
  136. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +30 -1
  137. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +2 -0
  138. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +30 -1
  139. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +95 -37
  140. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +134 -61
  141. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +37 -4
  142. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +131 -0
  143. package/packages/dd-trace/src/ci-visibility/telemetry.js +130 -0
  144. package/packages/dd-trace/src/config.js +561 -470
  145. package/packages/dd-trace/src/data_streams_context.js +1 -1
  146. package/packages/dd-trace/src/datastreams/pathway.js +58 -1
  147. package/packages/dd-trace/src/datastreams/processor.js +196 -27
  148. package/packages/dd-trace/src/datastreams/writer.js +11 -5
  149. package/packages/dd-trace/src/dogstatsd.js +3 -5
  150. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +44 -6
  151. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +14 -0
  152. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +4 -0
  153. package/packages/dd-trace/src/exporters/common/form-data.js +4 -0
  154. package/packages/dd-trace/src/exporters/common/request.js +21 -3
  155. package/packages/dd-trace/src/format.js +30 -2
  156. package/packages/dd-trace/src/id.js +12 -0
  157. package/packages/dd-trace/src/iitm.js +1 -1
  158. package/packages/dd-trace/src/log/channels.js +1 -1
  159. package/packages/dd-trace/src/noop/proxy.js +4 -0
  160. package/packages/dd-trace/src/noop/span.js +1 -0
  161. package/packages/dd-trace/src/opentelemetry/span.js +104 -4
  162. package/packages/dd-trace/src/opentelemetry/tracer.js +9 -10
  163. package/packages/dd-trace/src/opentracing/propagation/text_map.js +16 -7
  164. package/packages/dd-trace/src/opentracing/span.js +48 -4
  165. package/packages/dd-trace/src/opentracing/span_context.js +15 -6
  166. package/packages/dd-trace/src/opentracing/tracer.js +4 -3
  167. package/packages/dd-trace/src/plugin_manager.js +1 -1
  168. package/packages/dd-trace/src/plugins/ci_plugin.js +78 -19
  169. package/packages/dd-trace/src/plugins/database.js +1 -1
  170. package/packages/dd-trace/src/plugins/index.js +7 -0
  171. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  172. package/packages/dd-trace/src/plugins/util/ci.js +6 -19
  173. package/packages/dd-trace/src/plugins/util/git.js +104 -22
  174. package/packages/dd-trace/src/plugins/util/ip_extractor.js +7 -6
  175. package/packages/dd-trace/src/plugins/util/test.js +60 -10
  176. package/packages/dd-trace/src/plugins/util/url.js +26 -0
  177. package/packages/dd-trace/src/plugins/util/user-provided-git.js +4 -16
  178. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  179. package/packages/dd-trace/src/priority_sampler.js +30 -38
  180. package/packages/dd-trace/src/profiler.js +5 -3
  181. package/packages/dd-trace/src/profiling/config.js +77 -24
  182. package/packages/dd-trace/src/profiling/exporters/agent.js +77 -31
  183. package/packages/dd-trace/src/profiling/exporters/file.js +2 -1
  184. package/packages/dd-trace/src/profiling/profiler.js +33 -22
  185. package/packages/dd-trace/src/profiling/profilers/events.js +270 -0
  186. package/packages/dd-trace/src/profiling/profilers/shared.js +45 -0
  187. package/packages/dd-trace/src/profiling/profilers/space.js +18 -2
  188. package/packages/dd-trace/src/profiling/profilers/wall.js +146 -70
  189. package/packages/dd-trace/src/proxy.js +56 -24
  190. package/packages/dd-trace/src/ritm.js +1 -1
  191. package/packages/dd-trace/src/sampling_rule.js +130 -0
  192. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +5 -0
  193. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
  194. package/packages/dd-trace/src/span_processor.js +9 -1
  195. package/packages/dd-trace/src/span_sampler.js +6 -64
  196. package/packages/dd-trace/src/spanleak.js +98 -0
  197. package/packages/dd-trace/src/startup-log.js +7 -1
  198. package/packages/dd-trace/src/telemetry/dependencies.js +56 -10
  199. package/packages/dd-trace/src/telemetry/index.js +182 -53
  200. package/packages/dd-trace/src/telemetry/logs/index.js +2 -2
  201. package/packages/dd-trace/src/telemetry/send-data.js +65 -7
  202. package/packages/dd-trace/src/tracer.js +12 -5
  203. package/register.js +4 -0
  204. package/scripts/install_plugin_modules.js +11 -3
  205. package/scripts/st.js +105 -0
  206. package/packages/datadog-instrumentations/src/child-process.js +0 -30
  207. package/packages/dd-trace/src/plugins/util/exec.js +0 -13
  208. package/packages/diagnostics_channel/index.js +0 -3
  209. package/packages/diagnostics_channel/src/index.js +0 -121
@@ -15,11 +15,20 @@ const {
15
15
  TEST_MODULE,
16
16
  getTestSuiteCommonTags,
17
17
  TEST_STATUS,
18
- TEST_SKIPPED_BY_ITR
18
+ TEST_SKIPPED_BY_ITR,
19
+ ITR_CORRELATION_ID
19
20
  } = require('./util/test')
20
21
  const Plugin = require('./plugin')
21
22
  const { COMPONENT } = require('../constants')
22
23
  const log = require('../log')
24
+ const {
25
+ incrementCountMetric,
26
+ distributionMetric,
27
+ TELEMETRY_EVENT_CREATED,
28
+ TELEMETRY_ITR_SKIPPED
29
+ } = require('../ci-visibility/telemetry')
30
+ const { CI_PROVIDER_NAME, GIT_REPOSITORY_URL, GIT_COMMIT_SHA, GIT_BRANCH, CI_WORKSPACE_PATH } = require('./util/tags')
31
+ const { OS_VERSION, OS_PLATFORM, OS_ARCHITECTURE, RUNTIME_NAME, RUNTIME_VERSION } = require('./util/env')
23
32
 
24
33
  module.exports = class CiPlugin extends Plugin {
25
34
  constructor (...args) {
@@ -27,29 +36,31 @@ module.exports = class CiPlugin extends Plugin {
27
36
 
28
37
  this.rootDir = process.cwd() // fallback in case :session:start events are not emitted
29
38
 
30
- this.addSub(`ci:${this.constructor.id}:itr-configuration`, ({ onDone }) => {
31
- if (!this.tracer._exporter || !this.tracer._exporter.getItrConfiguration) {
39
+ this.addSub(`ci:${this.constructor.id}:library-configuration`, ({ onDone }) => {
40
+ if (!this.tracer._exporter || !this.tracer._exporter.getLibraryConfiguration) {
32
41
  return onDone({ err: new Error('CI Visibility was not initialized correctly') })
33
42
  }
34
- this.tracer._exporter.getItrConfiguration(this.testConfiguration, (err, itrConfig) => {
43
+ this.tracer._exporter.getLibraryConfiguration(this.testConfiguration, (err, libraryConfig) => {
35
44
  if (err) {
36
45
  log.error(`Intelligent Test Runner configuration could not be fetched. ${err.message}`)
37
46
  } else {
38
- this.itrConfig = itrConfig
47
+ this.libraryConfig = libraryConfig
39
48
  }
40
- onDone({ err, itrConfig })
49
+ onDone({ err, libraryConfig })
41
50
  })
42
51
  })
43
52
 
44
53
  this.addSub(`ci:${this.constructor.id}:test-suite:skippable`, ({ onDone }) => {
45
- if (!this.tracer._exporter || !this.tracer._exporter.getSkippableSuites) {
54
+ if (!this.tracer._exporter?.getSkippableSuites) {
46
55
  return onDone({ err: new Error('CI Visibility was not initialized correctly') })
47
56
  }
48
- this.tracer._exporter.getSkippableSuites(this.testConfiguration, (err, skippableSuites) => {
57
+ this.tracer._exporter.getSkippableSuites(this.testConfiguration, (err, skippableSuites, itrCorrelationId) => {
49
58
  if (err) {
50
59
  log.error(`Skippable suites could not be fetched. ${err.message}`)
60
+ } else {
61
+ this.itrCorrelationId = itrCorrelationId
51
62
  }
52
- onDone({ err, skippableSuites })
63
+ onDone({ err, skippableSuites, itrCorrelationId })
53
64
  })
54
65
  })
55
66
 
@@ -71,6 +82,7 @@ module.exports = class CiPlugin extends Plugin {
71
82
  ...testSessionSpanMetadata
72
83
  }
73
84
  })
85
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'session')
74
86
  this.testModuleSpan = this.tracer.startSpan(`${this.constructor.id}.test_module`, {
75
87
  childOf: this.testSessionSpan,
76
88
  tags: {
@@ -79,12 +91,16 @@ module.exports = class CiPlugin extends Plugin {
79
91
  ...testModuleSpanMetadata
80
92
  }
81
93
  })
94
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'module')
82
95
  })
83
96
 
84
97
  this.addSub(`ci:${this.constructor.id}:itr:skipped-suites`, ({ skippedSuites, frameworkVersion }) => {
85
98
  const testCommand = this.testSessionSpan.context()._tags[TEST_COMMAND]
86
99
  skippedSuites.forEach((testSuite) => {
87
100
  const testSuiteMetadata = getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, this.constructor.id)
101
+ if (this.itrCorrelationId) {
102
+ testSuiteMetadata[ITR_CORRELATION_ID] = this.itrCorrelationId
103
+ }
88
104
 
89
105
  this.tracer.startSpan(`${this.constructor.id}.test_suite`, {
90
106
  childOf: this.testModuleSpan,
@@ -97,25 +113,65 @@ module.exports = class CiPlugin extends Plugin {
97
113
  }
98
114
  }).finish()
99
115
  })
116
+ this.telemetry.count(TELEMETRY_ITR_SKIPPED, { testLevel: 'suite' }, skippedSuites.length)
117
+ })
118
+
119
+ this.addSub(`ci:${this.constructor.id}:known-tests`, ({ onDone }) => {
120
+ if (!this.tracer._exporter?.getKnownTests) {
121
+ return onDone({ err: new Error('CI Visibility was not initialized correctly') })
122
+ }
123
+ this.tracer._exporter.getKnownTests(this.testConfiguration, (err, knownTests) => {
124
+ if (err) {
125
+ log.error(`Known tests could not be fetched. ${err.message}`)
126
+ }
127
+ onDone({ err, knownTests })
128
+ })
100
129
  })
101
130
  }
102
131
 
132
+ get telemetry () {
133
+ const testFramework = this.constructor.id
134
+ return {
135
+ ciVisEvent: function (name, testLevel, tags = {}) {
136
+ incrementCountMetric(name, {
137
+ testLevel,
138
+ testFramework,
139
+ isUnsupportedCIProvider: this.isUnsupportedCIProvider,
140
+ ...tags
141
+ })
142
+ },
143
+ count: function (name, tags, value = 1) {
144
+ incrementCountMetric(name, tags, value)
145
+ },
146
+ distribution: function (name, tags, measure) {
147
+ distributionMetric(name, tags, measure)
148
+ }
149
+ }
150
+ }
151
+
103
152
  configure (config) {
104
153
  super.configure(config)
105
154
  this.testEnvironmentMetadata = getTestEnvironmentMetadata(this.constructor.id, this.config)
106
- this.codeOwnersEntries = getCodeOwnersFileEntries()
107
155
 
108
156
  const {
109
- 'git.repository_url': repositoryUrl,
110
- 'git.commit.sha': sha,
111
- 'os.version': osVersion,
112
- 'os.platform': osPlatform,
113
- 'os.architecture': osArchitecture,
114
- 'runtime.name': runtimeName,
115
- 'runtime.version': runtimeVersion,
116
- 'git.branch': branch
157
+ [GIT_REPOSITORY_URL]: repositoryUrl,
158
+ [GIT_COMMIT_SHA]: sha,
159
+ [OS_VERSION]: osVersion,
160
+ [OS_PLATFORM]: osPlatform,
161
+ [OS_ARCHITECTURE]: osArchitecture,
162
+ [RUNTIME_NAME]: runtimeName,
163
+ [RUNTIME_VERSION]: runtimeVersion,
164
+ [GIT_BRANCH]: branch,
165
+ [CI_PROVIDER_NAME]: ciProviderName,
166
+ [CI_WORKSPACE_PATH]: repositoryRoot
117
167
  } = this.testEnvironmentMetadata
118
168
 
169
+ this.repositoryRoot = repositoryRoot || process.cwd()
170
+
171
+ this.codeOwnersEntries = getCodeOwnersFileEntries(repositoryRoot)
172
+
173
+ this.isUnsupportedCIProvider = !ciProviderName
174
+
119
175
  this.testConfiguration = {
120
176
  repositoryUrl,
121
177
  sha,
@@ -124,7 +180,8 @@ module.exports = class CiPlugin extends Plugin {
124
180
  osArchitecture,
125
181
  runtimeName,
126
182
  runtimeVersion,
127
- branch
183
+ branch,
184
+ testLevel: 'suite'
128
185
  }
129
186
  }
130
187
 
@@ -169,6 +226,8 @@ module.exports = class CiPlugin extends Plugin {
169
226
  }
170
227
  }
171
228
 
229
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'test', { hasCodeOwners: !!codeOwners })
230
+
172
231
  const testSpan = this.tracer
173
232
  .startSpan(`${this.constructor.id}.test`, {
174
233
  childOf,
@@ -36,7 +36,7 @@ class DatabasePlugin extends StoragePlugin {
36
36
  const { encodedDddbs, encodedDde, encodedDdps, encodedDdpv } = this.serviceTags
37
37
 
38
38
  return `dddbs='${encodedDddbs}',dde='${encodedDde}',` +
39
- `ddps='${encodedDdps}',ddpv='${encodedDdpv}'`
39
+ `ddps='${encodedDdps}',ddpv='${encodedDdpv}'`
40
40
  }
41
41
 
42
42
  getDbmServiceName (span, tracerService) {
@@ -17,11 +17,13 @@ module.exports = {
17
17
  get '@opensearch-project/opensearch' () { return require('../../../datadog-plugin-opensearch/src') },
18
18
  get '@redis/client' () { return require('../../../datadog-plugin-redis/src') },
19
19
  get '@smithy/smithy-client' () { return require('../../../datadog-plugin-aws-sdk/src') },
20
+ get 'aerospike' () { return require('../../../datadog-plugin-aerospike/src') },
20
21
  get 'amqp10' () { return require('../../../datadog-plugin-amqp10/src') },
21
22
  get 'amqplib' () { return require('../../../datadog-plugin-amqplib/src') },
22
23
  get 'aws-sdk' () { return require('../../../datadog-plugin-aws-sdk/src') },
23
24
  get 'bunyan' () { return require('../../../datadog-plugin-bunyan/src') },
24
25
  get 'cassandra-driver' () { return require('../../../datadog-plugin-cassandra-driver/src') },
26
+ get 'child_process' () { return require('../../../datadog-plugin-child_process/src') },
25
27
  get 'connect' () { return require('../../../datadog-plugin-connect/src') },
26
28
  get 'couchbase' () { return require('../../../datadog-plugin-couchbase/src') },
27
29
  get 'cypress' () { return require('../../../datadog-plugin-cypress/src') },
@@ -58,6 +60,11 @@ module.exports = {
58
60
  get 'mysql2' () { return require('../../../datadog-plugin-mysql2/src') },
59
61
  get 'net' () { return require('../../../datadog-plugin-net/src') },
60
62
  get 'next' () { return require('../../../datadog-plugin-next/src') },
63
+ get 'node:dns' () { return require('../../../datadog-plugin-dns/src') },
64
+ get 'node:http' () { return require('../../../datadog-plugin-http/src') },
65
+ get 'node:http2' () { return require('../../../datadog-plugin-http2/src') },
66
+ get 'node:https' () { return require('../../../datadog-plugin-http/src') },
67
+ get 'node:net' () { return require('../../../datadog-plugin-net/src') },
61
68
  get 'oracledb' () { return require('../../../datadog-plugin-oracledb/src') },
62
69
  get 'openai' () { return require('../../../datadog-plugin-openai/src') },
63
70
  get 'paperplane' () { return require('../../../datadog-plugin-paperplane/src') },
@@ -2,7 +2,7 @@
2
2
 
3
3
  // TODO: move anything related to tracing to TracingPlugin instead
4
4
 
5
- const dc = require('../../../diagnostics_channel')
5
+ const dc = require('dc-polyfill')
6
6
  const { storage } = require('../../../datadog-core')
7
7
 
8
8
  class Subscription {
@@ -1,5 +1,3 @@
1
- const URL = require('url').URL
2
-
3
1
  const {
4
2
  GIT_BRANCH,
5
3
  GIT_COMMIT_SHA,
@@ -24,6 +22,7 @@ const {
24
22
  CI_NODE_LABELS,
25
23
  CI_NODE_NAME
26
24
  } = require('./tags')
25
+ const { filterSensitiveInfoFromRepository } = require('./url')
27
26
 
28
27
  // Receives a string with the form 'John Doe <john.doe@gmail.com>'
29
28
  // and returns { name: 'John Doe', email: 'john.doe@gmail.com' }
@@ -67,20 +66,6 @@ function normalizeRef (ref) {
67
66
  return ref.replace(/origin\/|refs\/heads\/|tags\//gm, '')
68
67
  }
69
68
 
70
- function filterSensitiveInfoFromRepository (repositoryUrl) {
71
- if (repositoryUrl.startsWith('git@')) {
72
- return repositoryUrl
73
- }
74
-
75
- try {
76
- const { protocol, hostname, pathname } = new URL(repositoryUrl)
77
-
78
- return `${protocol}//${hostname}${pathname}`
79
- } catch (e) {
80
- return ''
81
- }
82
- }
83
-
84
69
  function resolveTilde (filePath) {
85
70
  if (!filePath || typeof filePath !== 'string') {
86
71
  return ''
@@ -271,20 +256,22 @@ module.exports = {
271
256
  const ref = GITHUB_HEAD_REF || GITHUB_REF || ''
272
257
  const refKey = ref.includes('tags/') ? GIT_TAG : GIT_BRANCH
273
258
 
259
+ // Both pipeline URL and job URL include GITHUB_SERVER_URL, which can include user credentials,
260
+ // so we pass them through `filterSensitiveInfoFromRepository`.
274
261
  tags = {
275
262
  [CI_PIPELINE_ID]: GITHUB_RUN_ID,
276
263
  [CI_PIPELINE_NAME]: GITHUB_WORKFLOW,
277
264
  [CI_PIPELINE_NUMBER]: GITHUB_RUN_NUMBER,
278
- [CI_PIPELINE_URL]: pipelineURL,
265
+ [CI_PIPELINE_URL]: filterSensitiveInfoFromRepository(pipelineURL),
279
266
  [CI_PROVIDER_NAME]: 'github',
280
267
  [GIT_COMMIT_SHA]: GITHUB_SHA,
281
268
  [GIT_REPOSITORY_URL]: repositoryURL,
282
- [CI_JOB_URL]: jobUrl,
269
+ [CI_JOB_URL]: filterSensitiveInfoFromRepository(jobUrl),
283
270
  [CI_JOB_NAME]: GITHUB_JOB,
284
271
  [CI_WORKSPACE_PATH]: GITHUB_WORKSPACE,
285
272
  [refKey]: ref,
286
273
  [CI_ENV_VARS]: JSON.stringify({
287
- GITHUB_SERVER_URL,
274
+ GITHUB_SERVER_URL: filterSensitiveInfoFromRepository(GITHUB_SERVER_URL),
288
275
  GITHUB_REPOSITORY,
289
276
  GITHUB_RUN_ID,
290
277
  GITHUB_RUN_ATTEMPT
@@ -1,10 +1,9 @@
1
- const { execFileSync } = require('child_process')
1
+ const cp = require('child_process')
2
2
  const os = require('os')
3
3
  const path = require('path')
4
4
  const fs = require('fs')
5
5
 
6
6
  const log = require('../../log')
7
- const { sanitizedExec } = require('./exec')
8
7
  const {
9
8
  GIT_COMMIT_SHA,
10
9
  GIT_BRANCH,
@@ -19,9 +18,52 @@ const {
19
18
  GIT_COMMIT_AUTHOR_NAME,
20
19
  CI_WORKSPACE_PATH
21
20
  } = require('./tags')
21
+ const {
22
+ incrementCountMetric,
23
+ distributionMetric,
24
+ TELEMETRY_GIT_COMMAND,
25
+ TELEMETRY_GIT_COMMAND_MS,
26
+ TELEMETRY_GIT_COMMAND_ERRORS
27
+ } = require('../../ci-visibility/telemetry')
28
+ const { filterSensitiveInfoFromRepository } = require('./url')
29
+ const { storage } = require('../../../../datadog-core')
22
30
 
23
31
  const GIT_REV_LIST_MAX_BUFFER = 8 * 1024 * 1024 // 8MB
24
32
 
33
+ function sanitizedExec (
34
+ cmd,
35
+ flags,
36
+ operationMetric,
37
+ durationMetric,
38
+ errorMetric
39
+ ) {
40
+ const store = storage.getStore()
41
+ storage.enterWith({ noop: true })
42
+
43
+ let startTime
44
+ if (operationMetric) {
45
+ incrementCountMetric(operationMetric.name, operationMetric.tags)
46
+ }
47
+ if (durationMetric) {
48
+ startTime = Date.now()
49
+ }
50
+ try {
51
+ const result = cp.execFileSync(cmd, flags, { stdio: 'pipe' }).toString().replace(/(\r\n|\n|\r)/gm, '')
52
+ if (durationMetric) {
53
+ distributionMetric(durationMetric.name, durationMetric.tags, Date.now() - startTime)
54
+ }
55
+ return result
56
+ } catch (e) {
57
+ if (errorMetric) {
58
+ incrementCountMetric(errorMetric.name, { ...errorMetric.tags, exitCode: e.status })
59
+ }
60
+ log.error(e)
61
+ return ''
62
+ } finally {
63
+ storage.enterWith(store)
64
+ }
65
+ }
66
+
25
67
  function isDirectory (path) {
26
68
  try {
27
69
  const stats = fs.statSync(path)
@@ -32,7 +74,13 @@ function isDirectory (path) {
32
74
  }
33
75
 
34
76
  function isShallowRepository () {
35
- return sanitizedExec('git', ['rev-parse', '--is-shallow-repository']) === 'true'
77
+ return sanitizedExec(
78
+ 'git',
79
+ ['rev-parse', '--is-shallow-repository'],
80
+ { name: TELEMETRY_GIT_COMMAND, tags: { command: 'check_shallow' } },
81
+ { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'check_shallow' } },
82
+ { name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'check_shallow' } }
83
+ ) === 'true'
36
84
  }
37
85
 
38
86
  function getGitVersion () {
@@ -71,50 +119,76 @@ function unshallowRepository () {
71
119
  defaultRemoteName
72
120
  ]
73
121
 
122
+ incrementCountMetric(TELEMETRY_GIT_COMMAND, { command: 'unshallow' })
123
+ const start = Date.now()
74
124
  try {
75
- execFileSync('git', [
125
+ cp.execFileSync('git', [
76
126
  ...baseGitOptions,
77
127
  revParseHead
78
128
  ], { stdio: 'pipe' })
79
- } catch (e) {
129
+ } catch (err) {
80
130
  // If the local HEAD is a commit that has not been pushed to the remote, the above command will fail.
81
- log.error(e)
131
+ log.error(err)
132
+ incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'unshallow', exitCode: err.status })
82
133
  const upstreamRemote = sanitizedExec('git', ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}'])
83
134
  try {
84
- execFileSync('git', [
135
+ cp.execFileSync('git', [
85
136
  ...baseGitOptions,
86
137
  upstreamRemote
87
138
  ], { stdio: 'pipe' })
88
- } catch (e) {
139
+ } catch (err) {
89
140
  // If the CI is working on a detached HEAD or branch tracking hasn’t been set up, the above command will fail.
90
- log.error(e)
141
+ log.error(err)
142
+ incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'unshallow', exitCode: err.status })
91
143
  // We use sanitizedExec here because if this last option fails, we'll give up.
92
- sanitizedExec('git', baseGitOptions)
144
+ sanitizedExec(
145
+ 'git',
146
+ baseGitOptions,
147
+ null,
148
+ null,
149
+ { name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'unshallow' } } // we log the error in sanitizedExec
150
+ )
93
151
  }
94
152
  }
153
+ distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'unshallow' }, Date.now() - start)
95
154
  }
96
155
 
97
156
  function getRepositoryUrl () {
98
- return sanitizedExec('git', ['config', '--get', 'remote.origin.url'])
157
+ return sanitizedExec(
158
+ 'git',
159
+ ['config', '--get', 'remote.origin.url'],
160
+ { name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_repository' } },
161
+ { name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_repository' } },
162
+ { name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'get_repository' } }
163
+ )
99
164
  }
100
165
 
101
166
  function getLatestCommits () {
167
+ incrementCountMetric(TELEMETRY_GIT_COMMAND, { command: 'get_local_commits' })
168
+ const startTime = Date.now()
102
169
  try {
103
- return execFileSync('git', ['log', '--format=%H', '-n 1000', '--since="1 month ago"'], { stdio: 'pipe' })
170
+ const result = cp.execFileSync('git', ['log', '--format=%H', '-n 1000', '--since="1 month ago"'], { stdio: 'pipe' })
104
171
  .toString()
105
172
  .split('\n')
106
173
  .filter(commit => commit)
174
+ distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'get_local_commits' }, Date.now() - startTime)
175
+ return result
107
176
  } catch (err) {
108
177
  log.error(`Get latest commits failed: ${err.message}`)
178
+ incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'get_local_commits', errorType: err.status })
109
179
  return []
110
180
  }
111
181
  }
112
182
 
113
- function getCommitsToUpload (commitsToExclude, commitsToInclude) {
183
+ function getCommitsRevList (commitsToExclude, commitsToInclude) {
184
+ let result = []
185
+
114
186
  const commitsToExcludeString = commitsToExclude.map(commit => `^${commit}`)
115
187
 
188
+ incrementCountMetric(TELEMETRY_GIT_COMMAND, { command: 'get_objects' })
189
+ const startTime = Date.now()
116
190
  try {
117
- return execFileSync(
191
+ result = cp.execFileSync(
118
192
  'git',
119
193
  [
120
194
  'rev-list',
@@ -131,11 +205,14 @@ function getCommitsToUpload (commitsToExclude, commitsToInclude) {
131
205
  .filter(commit => commit)
132
206
  } catch (err) {
133
207
  log.error(`Get commits to upload failed: ${err.message}`)
134
- return []
208
+ incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'get_objects', errorType: err.status })
135
209
  }
210
+ distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'get_objects' }, Date.now() - startTime)
211
+ return result
136
212
  }
137
213
 
138
214
  function generatePackFilesForCommits (commitsToUpload) {
215
+ let result = []
139
216
  const tmpFolder = os.tmpdir()
140
217
 
141
218
  if (!isDirectory(tmpFolder)) {
@@ -147,10 +224,12 @@ function generatePackFilesForCommits (commitsToUpload) {
147
224
  const temporaryPath = path.join(tmpFolder, randomPrefix)
148
225
  const cwdPath = path.join(process.cwd(), randomPrefix)
149
226
 
227
+ incrementCountMetric(TELEMETRY_GIT_COMMAND, { command: 'pack_objects' })
228
+ const startTime = Date.now()
150
229
  // Generates pack files to upload and
151
230
  // returns the ordered list of packfiles' paths
152
231
  function execGitPackObjects (targetPath) {
153
- return execFileSync(
232
+ return cp.execFileSync(
154
233
  'git',
155
234
  [
156
235
  'pack-objects',
@@ -163,9 +242,10 @@ function generatePackFilesForCommits (commitsToUpload) {
163
242
  }
164
243
 
165
244
  try {
166
- return execGitPackObjects(temporaryPath)
245
+ result = execGitPackObjects(temporaryPath)
167
246
  } catch (err) {
168
247
  log.error(err)
248
+ incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'pack_objects', errorType: err.status })
169
249
  /**
170
250
  * The generation of pack files in the temporary folder (from `os.tmpdir()`)
171
251
  * sometimes fails in certain CI setups with the error message
@@ -179,13 +259,15 @@ function generatePackFilesForCommits (commitsToUpload) {
179
259
  * TODO: fix issue and remove workaround.
180
260
  */
181
261
  try {
182
- return execGitPackObjects(cwdPath)
262
+ result = execGitPackObjects(cwdPath)
183
263
  } catch (err) {
184
264
  log.error(err)
265
+ incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'pack_objects', errorType: err.status })
185
266
  }
186
-
187
- return []
188
267
  }
268
+ distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'pack_objects' }, Date.now() - startTime)
269
+
270
+ return result
189
271
  }
190
272
 
191
273
  // If there is ciMetadata, it takes precedence.
@@ -214,7 +296,7 @@ function getGitMetadata (ciMetadata) {
214
296
 
215
297
  return {
216
298
  [GIT_REPOSITORY_URL]:
217
- repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url']),
299
+ filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url'])),
218
300
  [GIT_COMMIT_MESSAGE]:
219
301
  commitMessage || sanitizedExec('git', ['show', '-s', '--format=%s']),
220
302
  [GIT_COMMIT_AUTHOR_DATE]: authorDate,
@@ -235,7 +317,7 @@ module.exports = {
235
317
  getLatestCommits,
236
318
  getRepositoryUrl,
237
319
  generatePackFilesForCommits,
238
- getCommitsToUpload,
320
+ getCommitsRevList,
239
321
  GIT_REV_LIST_MAX_BUFFER,
240
322
  isShallowRepository,
241
323
  unshallowRepository
@@ -48,8 +48,8 @@ function extractIp (config, req) {
48
48
 
49
49
  let firstPrivateIp
50
50
  if (headers) {
51
- for (let i = 0; i < ipHeaderList.length; i++) {
52
- const firstIp = findFirstIp(headers[ipHeaderList[i]])
51
+ for (const ipHeaderName of ipHeaderList) {
52
+ const firstIp = findFirstIp(headers[ipHeaderName])
53
53
 
54
54
  if (firstIp.public) {
55
55
  return firstIp.public
@@ -59,7 +59,7 @@ function extractIp (config, req) {
59
59
  }
60
60
  }
61
61
 
62
- return firstPrivateIp || (req.socket && req.socket.remoteAddress)
62
+ return firstPrivateIp || req.socket?.remoteAddress
63
63
  }
64
64
 
65
65
  function findFirstIp (str) {
@@ -68,8 +68,8 @@ function findFirstIp (str) {
68
68
 
69
69
  const splitted = str.split(',')
70
70
 
71
- for (let i = 0; i < splitted.length; i++) {
72
- const chunk = splitted[i].trim()
71
+ for (const part of splitted) {
72
+ const chunk = part.trim()
73
73
 
74
74
  // TODO: strip port and interface data ?
75
75
 
@@ -90,5 +90,6 @@ function findFirstIp (str) {
90
90
  }
91
91
 
92
92
  module.exports = {
93
- extractIp
93
+ extractIp,
94
+ ipHeaderList
94
95
  }