dd-trace 3.43.0 → 3.45.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 (52) hide show
  1. package/package.json +6 -6
  2. package/packages/datadog-instrumentations/src/child-process.js +4 -5
  3. package/packages/datadog-instrumentations/src/couchbase.js +5 -4
  4. package/packages/datadog-instrumentations/src/crypto.js +2 -1
  5. package/packages/datadog-instrumentations/src/dns.js +2 -1
  6. package/packages/datadog-instrumentations/src/helpers/hooks.js +7 -2
  7. package/packages/datadog-instrumentations/src/helpers/instrument.js +8 -3
  8. package/packages/datadog-instrumentations/src/helpers/register.js +18 -2
  9. package/packages/datadog-instrumentations/src/http/client.js +2 -2
  10. package/packages/datadog-instrumentations/src/http/server.js +7 -4
  11. package/packages/datadog-instrumentations/src/http2/client.js +3 -1
  12. package/packages/datadog-instrumentations/src/http2/server.js +3 -1
  13. package/packages/datadog-instrumentations/src/jest.js +3 -1
  14. package/packages/datadog-instrumentations/src/net.js +10 -2
  15. package/packages/datadog-plugin-cucumber/src/index.js +34 -2
  16. package/packages/datadog-plugin-cypress/src/plugin.js +60 -8
  17. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -0
  18. package/packages/datadog-plugin-jest/src/index.js +60 -6
  19. package/packages/datadog-plugin-jest/src/util.js +38 -16
  20. package/packages/datadog-plugin-mocha/src/index.js +32 -1
  21. package/packages/datadog-plugin-playwright/src/index.js +17 -1
  22. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +5 -1
  23. package/packages/dd-trace/src/appsec/remote_config/index.js +4 -0
  24. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +30 -1
  25. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +30 -1
  26. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +36 -4
  27. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +18 -1
  28. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +26 -1
  29. package/packages/dd-trace/src/ci-visibility/telemetry.js +130 -0
  30. package/packages/dd-trace/src/config.js +100 -59
  31. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +14 -1
  32. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +14 -0
  33. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +4 -0
  34. package/packages/dd-trace/src/exporters/common/form-data.js +4 -0
  35. package/packages/dd-trace/src/opentracing/tracer.js +2 -2
  36. package/packages/dd-trace/src/plugins/ci_plugin.js +44 -8
  37. package/packages/dd-trace/src/plugins/index.js +5 -0
  38. package/packages/dd-trace/src/plugins/util/exec.js +23 -2
  39. package/packages/dd-trace/src/plugins/util/git.js +94 -19
  40. package/packages/dd-trace/src/priority_sampler.js +30 -38
  41. package/packages/dd-trace/src/profiling/config.js +17 -2
  42. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -0
  43. package/packages/dd-trace/src/profiling/exporters/file.js +2 -1
  44. package/packages/dd-trace/src/profiling/profiler.js +18 -14
  45. package/packages/dd-trace/src/profiling/profilers/events.js +11 -5
  46. package/packages/dd-trace/src/profiling/profilers/shared.js +7 -1
  47. package/packages/dd-trace/src/profiling/profilers/space.js +17 -2
  48. package/packages/dd-trace/src/profiling/profilers/wall.js +34 -21
  49. package/packages/dd-trace/src/sampling_rule.js +130 -0
  50. package/packages/dd-trace/src/span_sampler.js +6 -64
  51. package/packages/dd-trace/src/telemetry/index.js +43 -5
  52. package/packages/dd-trace/src/telemetry/send-data.js +35 -16
@@ -12,10 +12,21 @@ const {
12
12
  TEST_FRAMEWORK_VERSION,
13
13
  TEST_SOURCE_START,
14
14
  TEST_ITR_UNSKIPPABLE,
15
- TEST_ITR_FORCED_RUN
15
+ TEST_ITR_FORCED_RUN,
16
+ TEST_CODE_OWNERS
16
17
  } = require('../../dd-trace/src/plugins/util/test')
17
18
  const { COMPONENT } = require('../../dd-trace/src/constants')
18
19
  const id = require('../../dd-trace/src/id')
20
+ const {
21
+ TELEMETRY_EVENT_CREATED,
22
+ TELEMETRY_EVENT_FINISHED,
23
+ TELEMETRY_CODE_COVERAGE_STARTED,
24
+ TELEMETRY_CODE_COVERAGE_FINISHED,
25
+ TELEMETRY_ITR_FORCED_TO_RUN,
26
+ TELEMETRY_CODE_COVERAGE_EMPTY,
27
+ TELEMETRY_ITR_UNSKIPPABLE,
28
+ TELEMETRY_CODE_COVERAGE_NUM_FILES
29
+ } = require('../../dd-trace/src/ci-visibility/telemetry')
19
30
 
20
31
  const isJestWorker = !!process.env.JEST_WORKER_ID
21
32
 
@@ -27,6 +38,20 @@ class JestPlugin extends CiPlugin {
27
38
  return 'jest'
28
39
  }
29
40
 
41
+ // The lists are the same for every test suite, so we can cache them
42
+ getUnskippableSuites (unskippableSuitesList) {
43
+ if (!this.unskippableSuites) {
44
+ this.unskippableSuites = JSON.parse(unskippableSuitesList)
45
+ }
46
+ return this.unskippableSuites
47
+ }
48
+ getForcedToRunSuites (forcedToRunSuitesList) {
49
+ if (!this.forcedToRunSuites) {
50
+ this.forcedToRunSuites = JSON.parse(forcedToRunSuitesList)
51
+ }
52
+ return this.forcedToRunSuites
53
+ }
54
+
30
55
  constructor (...args) {
31
56
  super(...args)
32
57
 
@@ -81,7 +106,9 @@ class JestPlugin extends CiPlugin {
81
106
  )
82
107
 
83
108
  this.testModuleSpan.finish()
109
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
84
110
  this.testSessionSpan.finish()
111
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
85
112
  finishAllTraceSpans(this.testSessionSpan)
86
113
  this.tracer._exporter.flush()
87
114
  })
@@ -103,7 +130,8 @@ class JestPlugin extends CiPlugin {
103
130
  _ddTestCommand: testCommand,
104
131
  _ddTestModuleId: testModuleId,
105
132
  _ddForcedToRun,
106
- _ddUnskippable
133
+ _ddUnskippable,
134
+ _ddTestCodeCoverageEnabled
107
135
  } = testEnvironmentOptions
108
136
 
109
137
  const testSessionSpanContext = this.tracer.extract('text_map', {
@@ -114,9 +142,17 @@ class JestPlugin extends CiPlugin {
114
142
  const testSuiteMetadata = getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, 'jest')
115
143
 
116
144
  if (_ddUnskippable) {
117
- testSuiteMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
145
+ const unskippableSuites = this.getUnskippableSuites(_ddUnskippable)
146
+ if (unskippableSuites[testSuite]) {
147
+ this.telemetry.count(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
148
+ testSuiteMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
149
+ }
118
150
  if (_ddForcedToRun) {
119
- testSuiteMetadata[TEST_ITR_FORCED_RUN] = 'true'
151
+ const forcedToRunSuites = this.getForcedToRunSuites(_ddForcedToRun)
152
+ if (forcedToRunSuites[testSuite]) {
153
+ this.telemetry.count(TELEMETRY_ITR_FORCED_TO_RUN, { testLevel: 'suite' })
154
+ testSuiteMetadata[TEST_ITR_FORCED_RUN] = 'true'
155
+ }
120
156
  }
121
157
  }
122
158
 
@@ -128,6 +164,10 @@ class JestPlugin extends CiPlugin {
128
164
  ...testSuiteMetadata
129
165
  }
130
166
  })
167
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
168
+ if (_ddTestCodeCoverageEnabled) {
169
+ this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_STARTED, 'suite', { library: 'istanbul' })
170
+ }
131
171
  })
132
172
 
133
173
  this.addSub('ci:jest:worker-report:trace', traces => {
@@ -164,6 +204,7 @@ class JestPlugin extends CiPlugin {
164
204
  this.testSuiteSpan.setTag('error', new Error(errorMessage))
165
205
  }
166
206
  this.testSuiteSpan.finish()
207
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
167
208
  // Suites potentially run in a different process than the session,
168
209
  // so calling finishAllTraceSpans on the session span is not enough
169
210
  finishAllTraceSpans(this.testSuiteSpan)
@@ -180,14 +221,22 @@ class JestPlugin extends CiPlugin {
180
221
  * because this subscription happens in a different process from the one
181
222
  * fetching the ITR config.
182
223
  */
183
- this.addSub('ci:jest:test-suite:code-coverage', (coverageFiles) => {
224
+ this.addSub('ci:jest:test-suite:code-coverage', ({ coverageFiles, testSuite }) => {
225
+ if (!coverageFiles.length) {
226
+ this.telemetry.count(TELEMETRY_CODE_COVERAGE_EMPTY)
227
+ }
228
+ const files = [...coverageFiles, testSuite]
229
+
184
230
  const { _traceId, _spanId } = this.testSuiteSpan.context()
185
231
  const formattedCoverage = {
186
232
  sessionId: _traceId,
187
233
  suiteId: _spanId,
188
- files: coverageFiles
234
+ files
189
235
  }
236
+
190
237
  this.tracer._exporter.exportCoverage(formattedCoverage)
238
+ this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_FINISHED, 'suite', { library: 'istanbul' })
239
+ this.telemetry.distribution(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, files.length)
191
240
  })
192
241
 
193
242
  this.addSub('ci:jest:test:start', (test) => {
@@ -204,6 +253,11 @@ class JestPlugin extends CiPlugin {
204
253
  span.setTag(TEST_SOURCE_START, testStartLine)
205
254
  }
206
255
  span.finish()
256
+ this.telemetry.ciVisEvent(
257
+ TELEMETRY_EVENT_FINISHED,
258
+ 'test',
259
+ { hasCodeOwners: !!span.context()._tags[TEST_CODE_OWNERS] }
260
+ )
207
261
  finishAllTraceSpans(span)
208
262
  })
209
263
 
@@ -77,30 +77,52 @@ function isMarkedAsUnskippable (test) {
77
77
  }
78
78
 
79
79
  function getJestSuitesToRun (skippableSuites, originalTests, rootDir) {
80
- return originalTests.reduce((acc, test) => {
80
+ const unskippableSuites = {}
81
+ const forcedToRunSuites = {}
82
+
83
+ const skippedSuites = []
84
+ const suitesToRun = []
85
+
86
+ for (const test of originalTests) {
81
87
  const relativePath = getTestSuitePath(test.path, rootDir)
82
88
  const shouldBeSkipped = skippableSuites.includes(relativePath)
83
-
84
89
  if (isMarkedAsUnskippable(test)) {
85
- acc.suitesToRun.push(test)
86
- if (test?.context?.config?.testEnvironmentOptions) {
87
- test.context.config.testEnvironmentOptions['_ddUnskippable'] = true
88
- acc.hasUnskippableSuites = true
89
- if (shouldBeSkipped) {
90
- test.context.config.testEnvironmentOptions['_ddForcedToRun'] = true
91
- acc.hasForcedToRunSuites = true
92
- }
90
+ suitesToRun.push(test)
91
+ unskippableSuites[relativePath] = true
92
+ if (shouldBeSkipped) {
93
+ forcedToRunSuites[relativePath] = true
93
94
  }
94
- return acc
95
+ continue
95
96
  }
96
-
97
97
  if (shouldBeSkipped) {
98
- acc.skippedSuites.push(relativePath)
98
+ skippedSuites.push(relativePath)
99
99
  } else {
100
- acc.suitesToRun.push(test)
100
+ suitesToRun.push(test)
101
101
  }
102
- return acc
103
- }, { skippedSuites: [], suitesToRun: [], hasUnskippableSuites: false, hasForcedToRunSuites: false })
102
+ }
103
+
104
+ const hasUnskippableSuites = Object.keys(unskippableSuites).length > 0
105
+ const hasForcedToRunSuites = Object.keys(forcedToRunSuites).length > 0
106
+
107
+ if (originalTests.length) {
108
+ // The config object is shared by all tests, so we can just take the first one
109
+ const [test] = originalTests
110
+ if (test?.context?.config?.testEnvironmentOptions) {
111
+ if (hasUnskippableSuites) {
112
+ test.context.config.testEnvironmentOptions._ddUnskippable = JSON.stringify(unskippableSuites)
113
+ }
114
+ if (hasForcedToRunSuites) {
115
+ test.context.config.testEnvironmentOptions._ddForcedToRun = JSON.stringify(forcedToRunSuites)
116
+ }
117
+ }
118
+ }
119
+
120
+ return {
121
+ skippedSuites,
122
+ suitesToRun,
123
+ hasUnskippableSuites,
124
+ hasForcedToRunSuites
125
+ }
104
126
  }
105
127
 
106
128
  module.exports = { getFormattedJestTestParameters, getJestTestName, getJestSuitesToRun, isMarkedAsUnskippable }
@@ -13,9 +13,20 @@ const {
13
13
  addIntelligentTestRunnerSpanTags,
14
14
  TEST_SOURCE_START,
15
15
  TEST_ITR_UNSKIPPABLE,
16
- TEST_ITR_FORCED_RUN
16
+ TEST_ITR_FORCED_RUN,
17
+ TEST_CODE_OWNERS
17
18
  } = require('../../dd-trace/src/plugins/util/test')
18
19
  const { COMPONENT } = require('../../dd-trace/src/constants')
20
+ const {
21
+ TELEMETRY_EVENT_CREATED,
22
+ TELEMETRY_EVENT_FINISHED,
23
+ TELEMETRY_CODE_COVERAGE_STARTED,
24
+ TELEMETRY_CODE_COVERAGE_FINISHED,
25
+ TELEMETRY_ITR_FORCED_TO_RUN,
26
+ TELEMETRY_CODE_COVERAGE_EMPTY,
27
+ TELEMETRY_ITR_UNSKIPPABLE,
28
+ TELEMETRY_CODE_COVERAGE_NUM_FILES
29
+ } = require('../../dd-trace/src/ci-visibility/telemetry')
19
30
 
20
31
  class MochaPlugin extends CiPlugin {
21
32
  static get id () {
@@ -35,6 +46,10 @@ class MochaPlugin extends CiPlugin {
35
46
  }
36
47
  const testSuiteSpan = this._testSuites.get(suiteFile)
37
48
 
49
+ if (!coverageFiles.length) {
50
+ this.telemetry.count(TELEMETRY_CODE_COVERAGE_EMPTY)
51
+ }
52
+
38
53
  const relativeCoverageFiles = [...coverageFiles, suiteFile]
39
54
  .map(filename => getTestSuitePath(filename, this.sourceRoot))
40
55
 
@@ -47,6 +62,8 @@ class MochaPlugin extends CiPlugin {
47
62
  }
48
63
 
49
64
  this.tracer._exporter.exportCoverage(formattedCoverage)
65
+ this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_FINISHED, 'suite', { library: 'istanbul' })
66
+ this.telemetry.distribution(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)
50
67
  })
51
68
 
52
69
  this.addSub('ci:mocha:test-suite:start', ({ testSuite, isUnskippable, isForcedToRun }) => {
@@ -59,9 +76,11 @@ class MochaPlugin extends CiPlugin {
59
76
  )
60
77
  if (isUnskippable) {
61
78
  testSuiteMetadata[TEST_ITR_UNSKIPPABLE] = 'true'
79
+ this.telemetry.count(TELEMETRY_ITR_UNSKIPPABLE, { testLevel: 'suite' })
62
80
  }
63
81
  if (isForcedToRun) {
64
82
  testSuiteMetadata[TEST_ITR_FORCED_RUN] = 'true'
83
+ this.telemetry.count(TELEMETRY_ITR_FORCED_TO_RUN, { testLevel: 'suite' })
65
84
  }
66
85
 
67
86
  const testSuiteSpan = this.tracer.startSpan('mocha.test_suite', {
@@ -72,6 +91,10 @@ class MochaPlugin extends CiPlugin {
72
91
  ...testSuiteMetadata
73
92
  }
74
93
  })
94
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
95
+ if (this.itrConfig?.isCodeCoverageEnabled) {
96
+ this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_STARTED, 'suite', { library: 'istanbul' })
97
+ }
75
98
  this.enter(testSuiteSpan, store)
76
99
  this._testSuites.set(testSuite, testSuiteSpan)
77
100
  })
@@ -85,6 +108,7 @@ class MochaPlugin extends CiPlugin {
85
108
  span.setTag(TEST_STATUS, status)
86
109
  }
87
110
  span.finish()
111
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
88
112
  }
89
113
  })
90
114
 
@@ -113,6 +137,11 @@ class MochaPlugin extends CiPlugin {
113
137
  span.setTag(TEST_STATUS, status)
114
138
 
115
139
  span.finish()
140
+ this.telemetry.ciVisEvent(
141
+ TELEMETRY_EVENT_FINISHED,
142
+ 'test',
143
+ { hasCodeOwners: !!span.context()._tags[TEST_CODE_OWNERS] }
144
+ )
116
145
  finishAllTraceSpans(span)
117
146
  }
118
147
  })
@@ -179,7 +208,9 @@ class MochaPlugin extends CiPlugin {
179
208
  )
180
209
 
181
210
  this.testModuleSpan.finish()
211
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
182
212
  this.testSessionSpan.finish()
213
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
183
214
  finishAllTraceSpans(this.testSessionSpan)
184
215
  }
185
216
  this.itrConfig = null
@@ -8,10 +8,15 @@ const {
8
8
  finishAllTraceSpans,
9
9
  getTestSuitePath,
10
10
  getTestSuiteCommonTags,
11
- TEST_SOURCE_START
11
+ TEST_SOURCE_START,
12
+ TEST_CODE_OWNERS
12
13
  } = require('../../dd-trace/src/plugins/util/test')
13
14
  const { RESOURCE_NAME } = require('../../../ext/tags')
14
15
  const { COMPONENT } = require('../../dd-trace/src/constants')
16
+ const {
17
+ TELEMETRY_EVENT_CREATED,
18
+ TELEMETRY_EVENT_FINISHED
19
+ } = require('../../dd-trace/src/ci-visibility/telemetry')
15
20
 
16
21
  class PlaywrightPlugin extends CiPlugin {
17
22
  static get id () {
@@ -28,7 +33,9 @@ class PlaywrightPlugin extends CiPlugin {
28
33
  this.testSessionSpan.setTag(TEST_STATUS, status)
29
34
 
30
35
  this.testModuleSpan.finish()
36
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
31
37
  this.testSessionSpan.finish()
38
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session')
32
39
  finishAllTraceSpans(this.testSessionSpan)
33
40
  this.tracer._exporter.flush(onDone)
34
41
  })
@@ -52,6 +59,7 @@ class PlaywrightPlugin extends CiPlugin {
52
59
  ...testSuiteMetadata
53
60
  }
54
61
  })
62
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite')
55
63
  this.enter(testSuiteSpan, store)
56
64
 
57
65
  this._testSuites.set(testSuite, testSuiteSpan)
@@ -63,6 +71,7 @@ class PlaywrightPlugin extends CiPlugin {
63
71
  if (!span) return
64
72
  span.setTag(TEST_STATUS, status)
65
73
  span.finish()
74
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
66
75
  })
67
76
 
68
77
  this.addSub('ci:playwright:test:start', ({ testName, testSuiteAbsolutePath, testSourceLine }) => {
@@ -104,6 +113,13 @@ class PlaywrightPlugin extends CiPlugin {
104
113
  })
105
114
 
106
115
  span.finish()
116
+
117
+ this.telemetry.ciVisEvent(
118
+ TELEMETRY_EVENT_FINISHED,
119
+ 'test',
120
+ { hasCodeOwners: !!span.context()._tags[TEST_CODE_OWNERS] }
121
+ )
122
+
107
123
  finishAllTraceSpans(span)
108
124
  })
109
125
  }
@@ -10,5 +10,9 @@ module.exports = {
10
10
  ASM_CUSTOM_RULES: 1n << 8n,
11
11
  ASM_CUSTOM_BLOCKING_RESPONSE: 1n << 9n,
12
12
  ASM_TRUSTED_IPS: 1n << 10n,
13
- ASM_API_SECURITY_SAMPLE_RATE: 1n << 11n
13
+ ASM_API_SECURITY_SAMPLE_RATE: 1n << 11n,
14
+ APM_TRACING_SAMPLE_RATE: 1n << 12n,
15
+ APM_TRACING_LOGS_INJECTION: 1n << 13n,
16
+ APM_TRACING_HTTP_HEADER_TAGS: 1n << 14n,
17
+ APM_TRACING_CUSTOM_TAGS: 1n << 15n
14
18
  }
@@ -10,6 +10,10 @@ let rc
10
10
 
11
11
  function enable (config) {
12
12
  rc = new RemoteConfigManager(config)
13
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_CUSTOM_TAGS, true)
14
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_HTTP_HEADER_TAGS, true)
15
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_LOGS_INJECTION, true)
16
+ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RATE, true)
13
17
 
14
18
  const activation = Activation.fromConfig(config)
15
19
 
@@ -5,6 +5,16 @@ const { safeJSONStringify } = require('../../../exporters/common/util')
5
5
 
6
6
  const { CoverageCIVisibilityEncoder } = require('../../../encode/coverage-ci-visibility')
7
7
  const BaseWriter = require('../../../exporters/common/writer')
8
+ const {
9
+ incrementCountMetric,
10
+ distributionMetric,
11
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS,
12
+ TELEMETRY_ENDPOINT_PAYLOAD_BYTES,
13
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_MS,
14
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_ERRORS,
15
+ TELEMETRY_ENDPOINT_PAYLOAD_DROPPED,
16
+ getErrorTypeFromStatusCode
17
+ } = require('../../../ci-visibility/telemetry')
8
18
 
9
19
  class Writer extends BaseWriter {
10
20
  constructor ({ url, evpProxyPrefix = '' }) {
@@ -34,8 +44,27 @@ class Writer extends BaseWriter {
34
44
 
35
45
  log.debug(() => `Request to the intake: ${safeJSONStringify(options)}`)
36
46
 
37
- request(form, options, (err, res) => {
47
+ const startRequestTime = Date.now()
48
+
49
+ incrementCountMetric(TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS, { endpoint: 'code_coverage' })
50
+ distributionMetric(TELEMETRY_ENDPOINT_PAYLOAD_BYTES, { endpoint: 'code_coverage' }, form.size())
51
+
52
+ request(form, options, (err, res, statusCode) => {
53
+ distributionMetric(
54
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_MS,
55
+ { endpoint: 'code_coverage' },
56
+ Date.now() - startRequestTime
57
+ )
38
58
  if (err) {
59
+ const errorType = getErrorTypeFromStatusCode(statusCode)
60
+ incrementCountMetric(
61
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_ERRORS,
62
+ { endpoint: 'code_coverage', errorType }
63
+ )
64
+ incrementCountMetric(
65
+ TELEMETRY_ENDPOINT_PAYLOAD_DROPPED,
66
+ { endpoint: 'code_coverage' }
67
+ )
39
68
  log.error(err)
40
69
  done()
41
70
  return
@@ -5,6 +5,16 @@ const log = require('../../../log')
5
5
 
6
6
  const { AgentlessCiVisibilityEncoder } = require('../../../encode/agentless-ci-visibility')
7
7
  const BaseWriter = require('../../../exporters/common/writer')
8
+ const {
9
+ incrementCountMetric,
10
+ distributionMetric,
11
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS,
12
+ TELEMETRY_ENDPOINT_PAYLOAD_BYTES,
13
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_MS,
14
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_ERRORS,
15
+ TELEMETRY_ENDPOINT_PAYLOAD_DROPPED,
16
+ getErrorTypeFromStatusCode
17
+ } = require('../../../ci-visibility/telemetry')
8
18
 
9
19
  class Writer extends BaseWriter {
10
20
  constructor ({ url, tags, evpProxyPrefix = '' }) {
@@ -35,8 +45,27 @@ class Writer extends BaseWriter {
35
45
 
36
46
  log.debug(() => `Request to the intake: ${safeJSONStringify(options)}`)
37
47
 
38
- request(data, options, (err, res) => {
48
+ const startRequestTime = Date.now()
49
+
50
+ incrementCountMetric(TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS, { endpoint: 'test_cycle' })
51
+ distributionMetric(TELEMETRY_ENDPOINT_PAYLOAD_BYTES, { endpoint: 'test_cycle' }, data.length)
52
+
53
+ request(data, options, (err, res, statusCode) => {
54
+ distributionMetric(
55
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_MS,
56
+ { endpoint: 'test_cycle' },
57
+ Date.now() - startRequestTime
58
+ )
39
59
  if (err) {
60
+ const errorType = getErrorTypeFromStatusCode(statusCode)
61
+ incrementCountMetric(
62
+ TELEMETRY_ENDPOINT_PAYLOAD_REQUESTS_ERRORS,
63
+ { endpoint: 'test_cycle', errorType }
64
+ )
65
+ incrementCountMetric(
66
+ TELEMETRY_ENDPOINT_PAYLOAD_DROPPED,
67
+ { endpoint: 'test_cycle' }
68
+ )
40
69
  log.error(err)
41
70
  done()
42
71
  return
@@ -15,6 +15,20 @@ const {
15
15
  unshallowRepository
16
16
  } = require('../../../plugins/util/git')
17
17
 
18
+ const {
19
+ incrementCountMetric,
20
+ distributionMetric,
21
+ TELEMETRY_GIT_REQUESTS_SEARCH_COMMITS,
22
+ TELEMETRY_GIT_REQUESTS_SEARCH_COMMITS_MS,
23
+ TELEMETRY_GIT_REQUESTS_SEARCH_COMMITS_ERRORS,
24
+ TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES_NUM,
25
+ TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES,
26
+ TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES_MS,
27
+ TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES_ERRORS,
28
+ TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES_BYTES,
29
+ getErrorTypeFromStatusCode
30
+ } = require('../../../ci-visibility/telemetry')
31
+
18
32
  const isValidSha1 = (sha) => /^[0-9a-f]{40}$/.test(sha)
19
33
  const isValidSha256 = (sha) => /^[0-9a-f]{64}$/.test(sha)
20
34
 
@@ -74,8 +88,13 @@ function getCommitsToUpload ({ url, repositoryUrl, latestCommits, isEvpProxy },
74
88
  }))
75
89
  })
76
90
 
77
- request(localCommitData, options, (err, response) => {
91
+ incrementCountMetric(TELEMETRY_GIT_REQUESTS_SEARCH_COMMITS)
92
+ const startTime = Date.now()
93
+ request(localCommitData, options, (err, response, statusCode) => {
94
+ distributionMetric(TELEMETRY_GIT_REQUESTS_SEARCH_COMMITS_MS, {}, Date.now() - startTime)
78
95
  if (err) {
96
+ const errorType = getErrorTypeFromStatusCode(statusCode)
97
+ incrementCountMetric(TELEMETRY_GIT_REQUESTS_SEARCH_COMMITS_ERRORS, { errorType })
79
98
  const error = new Error(`Error fetching commits to exclude: ${err.message}`)
80
99
  return callback(error)
81
100
  }
@@ -83,6 +102,7 @@ function getCommitsToUpload ({ url, repositoryUrl, latestCommits, isEvpProxy },
83
102
  try {
84
103
  alreadySeenCommits = validateCommits(JSON.parse(response).data)
85
104
  } catch (e) {
105
+ incrementCountMetric(TELEMETRY_GIT_REQUESTS_SEARCH_COMMITS_ERRORS, { errorType: 'network' })
86
106
  return callback(new Error(`Can't parse commits to exclude response: ${e.message}`))
87
107
  }
88
108
  log.debug(`There are ${alreadySeenCommits.length} commits to exclude.`)
@@ -147,12 +167,20 @@ function uploadPackFile ({ url, isEvpProxy, packFileToUpload, repositoryUrl, hea
147
167
  delete options.headers['dd-api-key']
148
168
  }
149
169
 
170
+ incrementCountMetric(TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES)
171
+
172
+ const uploadSize = form.size()
173
+
174
+ const startTime = Date.now()
150
175
  request(form, options, (err, _, statusCode) => {
176
+ distributionMetric(TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES_MS, {}, Date.now() - startTime)
151
177
  if (err) {
178
+ const errorType = getErrorTypeFromStatusCode(statusCode)
179
+ incrementCountMetric(TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES_ERRORS, { errorType })
152
180
  const error = new Error(`Could not upload packfiles: status code ${statusCode}: ${err.message}`)
153
- return callback(error)
181
+ return callback(error, uploadSize)
154
182
  }
155
- callback(null)
183
+ callback(null, uploadSize)
156
184
  })
157
185
  }
158
186
 
@@ -173,10 +201,14 @@ function generateAndUploadPackFiles ({
173
201
  return callback(new Error('Failed to generate packfiles'))
174
202
  }
175
203
 
204
+ distributionMetric(TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES_NUM, {}, packFilesToUpload.length)
176
205
  let packFileIndex = 0
206
+ let totalUploadedBytes = 0
177
207
  // This uploads packfiles sequentially
178
- const uploadPackFileCallback = (err) => {
208
+ const uploadPackFileCallback = (err, byteLength) => {
209
+ totalUploadedBytes += byteLength
179
210
  if (err || packFileIndex === packFilesToUpload.length) {
211
+ distributionMetric(TELEMETRY_GIT_REQUESTS_OBJECT_PACKFILES_BYTES, {}, totalUploadedBytes)
180
212
  return callback(err)
181
213
  }
182
214
  return uploadPackFile(
@@ -1,6 +1,15 @@
1
1
  const request = require('../../exporters/common/request')
2
2
  const id = require('../../id')
3
3
  const log = require('../../log')
4
+ const {
5
+ incrementCountMetric,
6
+ distributionMetric,
7
+ TELEMETRY_GIT_REQUESTS_SETTINGS,
8
+ TELEMETRY_GIT_REQUESTS_SETTINGS_MS,
9
+ TELEMETRY_GIT_REQUESTS_SETTINGS_ERRORS,
10
+ TELEMETRY_GIT_REQUESTS_SETTINGS_RESPONSE,
11
+ getErrorTypeFromStatusCode
12
+ } = require('../../ci-visibility/telemetry')
4
13
 
5
14
  function getItrConfiguration ({
6
15
  url,
@@ -62,8 +71,14 @@ function getItrConfiguration ({
62
71
  }
63
72
  })
64
73
 
65
- request(data, options, (err, res) => {
74
+ incrementCountMetric(TELEMETRY_GIT_REQUESTS_SETTINGS)
75
+
76
+ const startTime = Date.now()
77
+ request(data, options, (err, res, statusCode) => {
78
+ distributionMetric(TELEMETRY_GIT_REQUESTS_SETTINGS_MS, {}, Date.now() - startTime)
66
79
  if (err) {
80
+ const errorType = getErrorTypeFromStatusCode(statusCode)
81
+ incrementCountMetric(TELEMETRY_GIT_REQUESTS_SETTINGS_ERRORS, { errorType })
67
82
  done(err)
68
83
  } else {
69
84
  try {
@@ -91,6 +106,8 @@ function getItrConfiguration ({
91
106
  log.debug(() => 'Dangerously set test skipping to true')
92
107
  }
93
108
 
109
+ incrementCountMetric(TELEMETRY_GIT_REQUESTS_SETTINGS_RESPONSE, settings)
110
+
94
111
  done(null, settings)
95
112
  } catch (err) {
96
113
  done(err)
@@ -1,5 +1,16 @@
1
1
  const request = require('../../exporters/common/request')
2
2
  const log = require('../../log')
3
+ const {
4
+ incrementCountMetric,
5
+ distributionMetric,
6
+ TELEMETRY_ITR_SKIPPABLE_TESTS,
7
+ TELEMETRY_ITR_SKIPPABLE_TESTS_MS,
8
+ TELEMETRY_ITR_SKIPPABLE_TESTS_ERRORS,
9
+ TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_SUITES,
10
+ TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_TESTS,
11
+ TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_BYTES,
12
+ getErrorTypeFromStatusCode
13
+ } = require('../../ci-visibility/telemetry')
3
14
 
4
15
  function getSkippableSuites ({
5
16
  url,
@@ -59,8 +70,15 @@ function getSkippableSuites ({
59
70
  }
60
71
  })
61
72
 
62
- request(data, options, (err, res) => {
73
+ incrementCountMetric(TELEMETRY_ITR_SKIPPABLE_TESTS)
74
+
75
+ const startTime = Date.now()
76
+
77
+ request(data, options, (err, res, statusCode) => {
78
+ distributionMetric(TELEMETRY_ITR_SKIPPABLE_TESTS_MS, {}, Date.now() - startTime)
63
79
  if (err) {
80
+ const errorType = getErrorTypeFromStatusCode(statusCode)
81
+ incrementCountMetric(TELEMETRY_ITR_SKIPPABLE_TESTS_ERRORS, { errorType })
64
82
  done(err)
65
83
  } else {
66
84
  let skippableSuites = []
@@ -74,6 +92,13 @@ function getSkippableSuites ({
74
92
  }
75
93
  return { suite, name }
76
94
  })
95
+ incrementCountMetric(
96
+ testLevel === 'test'
97
+ ? TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_TESTS : TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_SUITES,
98
+ {},
99
+ skippableSuites.length
100
+ )
101
+ distributionMetric(TELEMETRY_ITR_SKIPPABLE_TESTS_RESPONSE_BYTES, {}, res.length)
77
102
  log.debug(() => `Number of received skippable ${testLevel}s: ${skippableSuites.length}`)
78
103
  done(null, skippableSuites)
79
104
  } catch (err) {