dd-trace 5.9.0 → 5.10.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.
- package/package.json +2 -2
- package/packages/datadog-instrumentations/src/jest.js +84 -4
- package/packages/datadog-instrumentations/src/kafkajs.js +4 -7
- package/packages/datadog-instrumentations/src/oracledb.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +6 -2
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +9 -2
- package/packages/dd-trace/src/config.js +3 -1
- package/packages/dd-trace/src/plugins/util/git.js +33 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"node": ">=18"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@datadog/native-appsec": "7.1.
|
|
72
|
+
"@datadog/native-appsec": "7.1.1",
|
|
73
73
|
"@datadog/native-iast-rewriter": "2.3.0",
|
|
74
74
|
"@datadog/native-iast-taint-tracking": "1.7.0",
|
|
75
75
|
"@datadog/native-metrics": "^2.0.0",
|
|
@@ -44,11 +44,14 @@ const knownTestsCh = channel('ci:jest:known-tests')
|
|
|
44
44
|
|
|
45
45
|
const itrSkippedSuitesCh = channel('ci:jest:itr:skipped-suites')
|
|
46
46
|
|
|
47
|
+
// Message sent by jest's main process to workers to run a test suite (=test file)
|
|
48
|
+
// https://github.com/jestjs/jest/blob/1d682f21c7a35da4d3ab3a1436a357b980ebd0fa/packages/jest-worker/src/types.ts#L37
|
|
49
|
+
const CHILD_MESSAGE_CALL = 1
|
|
47
50
|
// Maximum time we'll wait for the tracer to flush
|
|
48
51
|
const FLUSH_TIMEOUT = 10000
|
|
49
52
|
|
|
50
53
|
let skippableSuites = []
|
|
51
|
-
let knownTests =
|
|
54
|
+
let knownTests = {}
|
|
52
55
|
let isCodeCoverageEnabled = false
|
|
53
56
|
let isSuitesSkippingEnabled = false
|
|
54
57
|
let isUserCodeCoverageEnabled = false
|
|
@@ -73,6 +76,7 @@ const specStatusToTestStatus = {
|
|
|
73
76
|
const asyncResources = new WeakMap()
|
|
74
77
|
const originalTestFns = new WeakMap()
|
|
75
78
|
const retriedTestsToNumAttempts = new Map()
|
|
79
|
+
const newTestsTestStatuses = new Map()
|
|
76
80
|
|
|
77
81
|
// based on https://github.com/facebook/jest/blob/main/packages/jest-circus/src/formatNodeAssertErrors.ts#L41
|
|
78
82
|
function formatJestError (errors) {
|
|
@@ -101,6 +105,13 @@ function getTestEnvironmentOptions (config) {
|
|
|
101
105
|
return {}
|
|
102
106
|
}
|
|
103
107
|
|
|
108
|
+
function getEfdStats (testStatuses) {
|
|
109
|
+
return testStatuses.reduce((acc, testStatus) => {
|
|
110
|
+
acc[testStatus]++
|
|
111
|
+
return acc
|
|
112
|
+
}, { pass: 0, fail: 0 })
|
|
113
|
+
}
|
|
114
|
+
|
|
104
115
|
function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
105
116
|
return class DatadogEnvironment extends BaseEnvironment {
|
|
106
117
|
constructor (config, context) {
|
|
@@ -123,9 +134,12 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
123
134
|
this.isEarlyFlakeDetectionEnabled = this.testEnvironmentOptions._ddIsEarlyFlakeDetectionEnabled
|
|
124
135
|
|
|
125
136
|
if (this.isEarlyFlakeDetectionEnabled) {
|
|
137
|
+
const hasKnownTests = !!knownTests.jest
|
|
126
138
|
earlyFlakeDetectionNumRetries = this.testEnvironmentOptions._ddEarlyFlakeDetectionNumRetries
|
|
127
139
|
try {
|
|
128
|
-
this.knownTestsForThisSuite =
|
|
140
|
+
this.knownTestsForThisSuite = hasKnownTests
|
|
141
|
+
? (knownTests.jest[this.testSuite] || [])
|
|
142
|
+
: this.getKnownTestsForSuite(this.testEnvironmentOptions._ddKnownTests)
|
|
129
143
|
} catch (e) {
|
|
130
144
|
// If there has been an error parsing the tests, we'll disable Early Flake Deteciton
|
|
131
145
|
this.isEarlyFlakeDetectionEnabled = false
|
|
@@ -145,7 +159,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
145
159
|
if (typeof knownTestsForSuite === 'string') {
|
|
146
160
|
knownTestsForSuite = JSON.parse(knownTestsForSuite)
|
|
147
161
|
}
|
|
148
|
-
return knownTestsForSuite
|
|
162
|
+
return knownTestsForSuite
|
|
149
163
|
}
|
|
150
164
|
|
|
151
165
|
// Add the `add_test` event we don't have the test object yet, so
|
|
@@ -242,6 +256,19 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
242
256
|
})
|
|
243
257
|
// restore in case it is retried
|
|
244
258
|
event.test.fn = originalTestFns.get(event.test)
|
|
259
|
+
// We'll store the test statuses of the retries
|
|
260
|
+
if (this.isEarlyFlakeDetectionEnabled) {
|
|
261
|
+
const testName = getJestTestName(event.test)
|
|
262
|
+
const originalTestName = removeEfdStringFromTestName(testName)
|
|
263
|
+
const isNewTest = retriedTestsToNumAttempts.has(originalTestName)
|
|
264
|
+
if (isNewTest) {
|
|
265
|
+
if (newTestsTestStatuses.has(originalTestName)) {
|
|
266
|
+
newTestsTestStatuses.get(originalTestName).push(status)
|
|
267
|
+
} else {
|
|
268
|
+
newTestsTestStatuses.set(originalTestName, [status])
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
245
272
|
})
|
|
246
273
|
}
|
|
247
274
|
if (event.name === 'test_skip' || event.name === 'test_todo') {
|
|
@@ -508,6 +535,28 @@ function cliWrapper (cli, jestVersion) {
|
|
|
508
535
|
|
|
509
536
|
numSkippedSuites = 0
|
|
510
537
|
|
|
538
|
+
/**
|
|
539
|
+
* If Early Flake Detection (EFD) is enabled the logic is as follows:
|
|
540
|
+
* - If all attempts for a test are failing, the test has failed and we will let the test process fail.
|
|
541
|
+
* - If just a single attempt passes, we will prevent the test process from failing.
|
|
542
|
+
* The rationale behind is the following: you may still be able to block your CI pipeline by gating
|
|
543
|
+
* on flakiness (the test will be considered flaky), but you may choose to unblock the pipeline too.
|
|
544
|
+
*/
|
|
545
|
+
|
|
546
|
+
if (isEarlyFlakeDetectionEnabled) {
|
|
547
|
+
let numFailedTestsToIgnore = 0
|
|
548
|
+
for (const testStatuses of newTestsTestStatuses.values()) {
|
|
549
|
+
const { pass, fail } = getEfdStats(testStatuses)
|
|
550
|
+
if (pass > 0) { // as long as one passes, we'll consider the test passed
|
|
551
|
+
numFailedTestsToIgnore += fail
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// If every test that failed was an EFD retry, we'll consider the suite passed
|
|
555
|
+
if (numFailedTestsToIgnore !== 0 && result.results.numFailedTests === numFailedTestsToIgnore) {
|
|
556
|
+
result.results.success = true
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
511
560
|
return result
|
|
512
561
|
})
|
|
513
562
|
|
|
@@ -619,7 +668,6 @@ function configureTestEnvironment (readConfigsResult) {
|
|
|
619
668
|
// because `jestAdapterWrapper` runs in a different process. We have to go through `testEnvironmentOptions`
|
|
620
669
|
configs.forEach(config => {
|
|
621
670
|
config.testEnvironmentOptions._ddTestCodeCoverageEnabled = isCodeCoverageEnabled
|
|
622
|
-
config.testEnvironmentOptions._ddKnownTests = knownTests
|
|
623
671
|
})
|
|
624
672
|
|
|
625
673
|
isUserCodeCoverageEnabled = !!readConfigsResult.globalConfig.collectCoverage
|
|
@@ -795,6 +843,38 @@ addHook({
|
|
|
795
843
|
file: 'build/workers/ChildProcessWorker.js'
|
|
796
844
|
}, (childProcessWorker) => {
|
|
797
845
|
const ChildProcessWorker = childProcessWorker.default
|
|
846
|
+
shimmer.wrap(ChildProcessWorker.prototype, 'send', send => function (request) {
|
|
847
|
+
if (!isEarlyFlakeDetectionEnabled) {
|
|
848
|
+
return send.apply(this, arguments)
|
|
849
|
+
}
|
|
850
|
+
const [type] = request
|
|
851
|
+
// eslint-disable-next-line
|
|
852
|
+
// https://github.com/jestjs/jest/blob/1d682f21c7a35da4d3ab3a1436a357b980ebd0fa/packages/jest-worker/src/workers/ChildProcessWorker.ts#L424
|
|
853
|
+
if (type === CHILD_MESSAGE_CALL) {
|
|
854
|
+
// This is the message that the main process sends to the worker to run a test suite (=test file).
|
|
855
|
+
// In here we modify the config.testEnvironmentOptions to include the known tests for the suite.
|
|
856
|
+
// This way the suite only knows about the tests that are part of it.
|
|
857
|
+
const args = request[request.length - 1]
|
|
858
|
+
if (args.length > 1) {
|
|
859
|
+
return send.apply(this, arguments)
|
|
860
|
+
}
|
|
861
|
+
if (!args[0]?.config) {
|
|
862
|
+
return send.apply(this, arguments)
|
|
863
|
+
}
|
|
864
|
+
const [{ globalConfig, config, path: testSuiteAbsolutePath }] = args
|
|
865
|
+
const testSuite = getTestSuitePath(testSuiteAbsolutePath, globalConfig.rootDir || process.cwd())
|
|
866
|
+
const suiteKnownTests = knownTests.jest?.[testSuite] || []
|
|
867
|
+
args[0].config = {
|
|
868
|
+
...config,
|
|
869
|
+
testEnvironmentOptions: {
|
|
870
|
+
...config.testEnvironmentOptions,
|
|
871
|
+
_ddKnownTests: suiteKnownTests
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
return send.apply(this, arguments)
|
|
877
|
+
})
|
|
798
878
|
shimmer.wrap(ChildProcessWorker.prototype, '_onMessage', _onMessage => function () {
|
|
799
879
|
const [code, data] = arguments[0]
|
|
800
880
|
if (code === JEST_WORKER_TRACE_PAYLOAD_CODE) { // datadog trace payload
|
|
@@ -68,7 +68,10 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
68
68
|
const result = send.apply(this, arguments)
|
|
69
69
|
|
|
70
70
|
result.then(
|
|
71
|
-
innerAsyncResource.bind(
|
|
71
|
+
innerAsyncResource.bind(res => {
|
|
72
|
+
producerFinishCh.publish(undefined)
|
|
73
|
+
producerCommitCh.publish(res)
|
|
74
|
+
}),
|
|
72
75
|
innerAsyncResource.bind(err => {
|
|
73
76
|
if (err) {
|
|
74
77
|
producerErrorCh.publish(err)
|
|
@@ -77,12 +80,6 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
77
80
|
})
|
|
78
81
|
)
|
|
79
82
|
|
|
80
|
-
result.then(res => {
|
|
81
|
-
if (producerCommitCh.hasSubscribers) {
|
|
82
|
-
producerCommitCh.publish(res)
|
|
83
|
-
}
|
|
84
|
-
})
|
|
85
|
-
|
|
86
83
|
return result
|
|
87
84
|
} catch (e) {
|
|
88
85
|
producerErrorCh.publish(e)
|
|
@@ -21,7 +21,7 @@ function finish (err) {
|
|
|
21
21
|
finishChannel.publish(undefined)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
addHook({ name: 'oracledb', versions: ['5'] }, oracledb => {
|
|
24
|
+
addHook({ name: 'oracledb', versions: ['>=5'] }, oracledb => {
|
|
25
25
|
shimmer.wrap(oracledb.Connection.prototype, 'execute', execute => {
|
|
26
26
|
return function wrappedExecute (dbQuery, ...args) {
|
|
27
27
|
if (!startChannel.hasSubscribers) {
|
|
@@ -20,11 +20,15 @@ const EXCLUDED_LOCATIONS = getNodeModulesPaths(
|
|
|
20
20
|
'pusher/lib/utils.js',
|
|
21
21
|
'redlock/dist/cjs',
|
|
22
22
|
'sqreen/lib/package-reader/index.js',
|
|
23
|
-
'ws/lib/websocket-server.js'
|
|
23
|
+
'ws/lib/websocket-server.js',
|
|
24
|
+
'google-gax/build/src/grpc.js',
|
|
25
|
+
'cookie-signature/index.js'
|
|
24
26
|
)
|
|
25
27
|
|
|
26
28
|
const EXCLUDED_PATHS_FROM_STACK = [
|
|
27
|
-
path.join('node_modules', 'object-hash', path.sep)
|
|
29
|
+
path.join('node_modules', 'object-hash', path.sep),
|
|
30
|
+
path.join('node_modules', 'aws-sdk', 'lib', 'util.js'),
|
|
31
|
+
path.join('node_modules', 'keygrip', path.sep)
|
|
28
32
|
]
|
|
29
33
|
class WeakHashAnalyzer extends Analyzer {
|
|
30
34
|
constructor () {
|
|
@@ -114,6 +114,10 @@ function getCommitsToUpload ({ url, repositoryUrl, latestCommits, isEvpProxy, ev
|
|
|
114
114
|
|
|
115
115
|
const commitsToUpload = getCommitsRevList(alreadySeenCommits, commitsToInclude)
|
|
116
116
|
|
|
117
|
+
if (commitsToUpload === null) {
|
|
118
|
+
return callback(new Error('git rev-list failed'))
|
|
119
|
+
}
|
|
120
|
+
|
|
117
121
|
callback(null, commitsToUpload)
|
|
118
122
|
})
|
|
119
123
|
}
|
|
@@ -252,9 +256,8 @@ function sendGitMetadata (url, { isEvpProxy, evpProxyPrefix }, configRepositoryU
|
|
|
252
256
|
return callback(new Error('Repository URL is empty'))
|
|
253
257
|
}
|
|
254
258
|
|
|
255
|
-
|
|
259
|
+
let latestCommits = getLatestCommits()
|
|
256
260
|
log.debug(`There were ${latestCommits.length} commits since last month.`)
|
|
257
|
-
const [headCommit] = latestCommits
|
|
258
261
|
|
|
259
262
|
const getOnFinishGetCommitsToUpload = (hasCheckedShallow) => (err, commitsToUpload) => {
|
|
260
263
|
if (err) {
|
|
@@ -268,6 +271,7 @@ function sendGitMetadata (url, { isEvpProxy, evpProxyPrefix }, configRepositoryU
|
|
|
268
271
|
|
|
269
272
|
// If it has already unshallowed or the clone is not shallow, we move on
|
|
270
273
|
if (hasCheckedShallow || !isShallowRepository()) {
|
|
274
|
+
const [headCommit] = latestCommits
|
|
271
275
|
return generateAndUploadPackFiles({
|
|
272
276
|
url,
|
|
273
277
|
isEvpProxy,
|
|
@@ -280,6 +284,9 @@ function sendGitMetadata (url, { isEvpProxy, evpProxyPrefix }, configRepositoryU
|
|
|
280
284
|
// Otherwise we unshallow and get commits to upload again
|
|
281
285
|
log.debug('It is shallow clone, unshallowing...')
|
|
282
286
|
unshallowRepository()
|
|
287
|
+
|
|
288
|
+
// The latest commits change after unshallowing
|
|
289
|
+
latestCommits = getLatestCommits()
|
|
283
290
|
getCommitsToUpload({
|
|
284
291
|
url,
|
|
285
292
|
repositoryUrl,
|
|
@@ -27,6 +27,7 @@ const qsRegex = '(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private
|
|
|
27
27
|
const defaultWafObfuscatorKeyRegex = '(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?)key)|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization'
|
|
28
28
|
// eslint-disable-next-line max-len
|
|
29
29
|
const defaultWafObfuscatorValueRegex = '(?i)(?: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*=[^;]|"\\s*:\\s*"[^"]+")|bearer\\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.+\\/=-]+)?|[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}'
|
|
30
|
+
const runtimeId = uuid()
|
|
30
31
|
|
|
31
32
|
function maybeFile (filepath) {
|
|
32
33
|
if (!filepath) return
|
|
@@ -291,7 +292,7 @@ class Config {
|
|
|
291
292
|
service: this.service,
|
|
292
293
|
env: this.env,
|
|
293
294
|
version: this.version,
|
|
294
|
-
'runtime-id':
|
|
295
|
+
'runtime-id': runtimeId
|
|
295
296
|
})
|
|
296
297
|
|
|
297
298
|
if (this.isCiVisibility) {
|
|
@@ -823,6 +824,7 @@ class Config {
|
|
|
823
824
|
: undefined
|
|
824
825
|
|
|
825
826
|
tagger.add(tags, options.tracing_tags)
|
|
827
|
+
if (Object.keys(tags).length) tags['runtime-id'] = runtimeId
|
|
826
828
|
|
|
827
829
|
this._setUnit(opts, 'sampleRate', options.tracing_sampling_rate)
|
|
828
830
|
this._setBoolean(opts, 'logInjection', options.log_injection_enabled)
|
|
@@ -28,7 +28,7 @@ const {
|
|
|
28
28
|
const { filterSensitiveInfoFromRepository } = require('./url')
|
|
29
29
|
const { storage } = require('../../../../datadog-core')
|
|
30
30
|
|
|
31
|
-
const GIT_REV_LIST_MAX_BUFFER =
|
|
31
|
+
const GIT_REV_LIST_MAX_BUFFER = 12 * 1024 * 1024 // 12MB
|
|
32
32
|
|
|
33
33
|
function sanitizedExec (
|
|
34
34
|
cmd,
|
|
@@ -53,11 +53,15 @@ function sanitizedExec (
|
|
|
53
53
|
distributionMetric(durationMetric.name, durationMetric.tags, Date.now() - startTime)
|
|
54
54
|
}
|
|
55
55
|
return result
|
|
56
|
-
} catch (
|
|
56
|
+
} catch (err) {
|
|
57
57
|
if (errorMetric) {
|
|
58
|
-
incrementCountMetric(errorMetric.name, {
|
|
58
|
+
incrementCountMetric(errorMetric.name, {
|
|
59
|
+
...errorMetric.tags,
|
|
60
|
+
errorType: err.code,
|
|
61
|
+
exitCode: err.status || err.errno
|
|
62
|
+
})
|
|
59
63
|
}
|
|
60
|
-
log.error(
|
|
64
|
+
log.error(err)
|
|
61
65
|
return ''
|
|
62
66
|
} finally {
|
|
63
67
|
storage.enterWith(store)
|
|
@@ -129,7 +133,10 @@ function unshallowRepository () {
|
|
|
129
133
|
} catch (err) {
|
|
130
134
|
// If the local HEAD is a commit that has not been pushed to the remote, the above command will fail.
|
|
131
135
|
log.error(err)
|
|
132
|
-
incrementCountMetric(
|
|
136
|
+
incrementCountMetric(
|
|
137
|
+
TELEMETRY_GIT_COMMAND_ERRORS,
|
|
138
|
+
{ command: 'unshallow', errorType: err.code, exitCode: err.status || err.errno }
|
|
139
|
+
)
|
|
133
140
|
const upstreamRemote = sanitizedExec('git', ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}'])
|
|
134
141
|
try {
|
|
135
142
|
cp.execFileSync('git', [
|
|
@@ -139,7 +146,10 @@ function unshallowRepository () {
|
|
|
139
146
|
} catch (err) {
|
|
140
147
|
// If the CI is working on a detached HEAD or branch tracking hasn’t been set up, the above command will fail.
|
|
141
148
|
log.error(err)
|
|
142
|
-
incrementCountMetric(
|
|
149
|
+
incrementCountMetric(
|
|
150
|
+
TELEMETRY_GIT_COMMAND_ERRORS,
|
|
151
|
+
{ command: 'unshallow', errorType: err.code, exitCode: err.status || err.errno }
|
|
152
|
+
)
|
|
143
153
|
// We use sanitizedExec here because if this last option fails, we'll give up.
|
|
144
154
|
sanitizedExec(
|
|
145
155
|
'git',
|
|
@@ -175,13 +185,16 @@ function getLatestCommits () {
|
|
|
175
185
|
return result
|
|
176
186
|
} catch (err) {
|
|
177
187
|
log.error(`Get latest commits failed: ${err.message}`)
|
|
178
|
-
incrementCountMetric(
|
|
188
|
+
incrementCountMetric(
|
|
189
|
+
TELEMETRY_GIT_COMMAND_ERRORS,
|
|
190
|
+
{ command: 'get_local_commits', errorType: err.status }
|
|
191
|
+
)
|
|
179
192
|
return []
|
|
180
193
|
}
|
|
181
194
|
}
|
|
182
195
|
|
|
183
196
|
function getCommitsRevList (commitsToExclude, commitsToInclude) {
|
|
184
|
-
let result =
|
|
197
|
+
let result = null
|
|
185
198
|
|
|
186
199
|
const commitsToExcludeString = commitsToExclude.map(commit => `^${commit}`)
|
|
187
200
|
|
|
@@ -205,7 +218,10 @@ function getCommitsRevList (commitsToExclude, commitsToInclude) {
|
|
|
205
218
|
.filter(commit => commit)
|
|
206
219
|
} catch (err) {
|
|
207
220
|
log.error(`Get commits to upload failed: ${err.message}`)
|
|
208
|
-
incrementCountMetric(
|
|
221
|
+
incrementCountMetric(
|
|
222
|
+
TELEMETRY_GIT_COMMAND_ERRORS,
|
|
223
|
+
{ command: 'get_objects', errorType: err.code, exitCode: err.status || err.errno } // err.status might be null
|
|
224
|
+
)
|
|
209
225
|
}
|
|
210
226
|
distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'get_objects' }, Date.now() - startTime)
|
|
211
227
|
return result
|
|
@@ -245,7 +261,10 @@ function generatePackFilesForCommits (commitsToUpload) {
|
|
|
245
261
|
result = execGitPackObjects(temporaryPath)
|
|
246
262
|
} catch (err) {
|
|
247
263
|
log.error(err)
|
|
248
|
-
incrementCountMetric(
|
|
264
|
+
incrementCountMetric(
|
|
265
|
+
TELEMETRY_GIT_COMMAND_ERRORS,
|
|
266
|
+
{ command: 'pack_objects', exitCode: err.status || err.errno, errorType: err.code }
|
|
267
|
+
)
|
|
249
268
|
/**
|
|
250
269
|
* The generation of pack files in the temporary folder (from `os.tmpdir()`)
|
|
251
270
|
* sometimes fails in certain CI setups with the error message
|
|
@@ -262,7 +281,10 @@ function generatePackFilesForCommits (commitsToUpload) {
|
|
|
262
281
|
result = execGitPackObjects(cwdPath)
|
|
263
282
|
} catch (err) {
|
|
264
283
|
log.error(err)
|
|
265
|
-
incrementCountMetric(
|
|
284
|
+
incrementCountMetric(
|
|
285
|
+
TELEMETRY_GIT_COMMAND_ERRORS,
|
|
286
|
+
{ command: 'pack_objects', exitCode: err.status || err.errno, errorType: err.code }
|
|
287
|
+
)
|
|
266
288
|
}
|
|
267
289
|
}
|
|
268
290
|
distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'pack_objects' }, Date.now() - startTime)
|