dd-trace 5.50.0 → 5.52.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/LICENSE-3rdparty.csv +0 -6
- package/index.d.ts +35 -1
- package/package.json +3 -10
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +391 -0
- package/packages/datadog-instrumentations/src/cucumber.js +3 -0
- package/packages/datadog-instrumentations/src/dns.js +16 -14
- package/packages/datadog-instrumentations/src/fs.js +37 -46
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +10 -1
- package/packages/datadog-instrumentations/src/jest.js +19 -4
- package/packages/datadog-instrumentations/src/mocha/utils.js +5 -0
- package/packages/datadog-instrumentations/src/net.js +24 -28
- package/packages/datadog-instrumentations/src/pg.js +19 -5
- package/packages/datadog-instrumentations/src/playwright.js +6 -0
- package/packages/datadog-instrumentations/src/vitest.js +18 -4
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +11 -0
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +11 -0
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +19 -0
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +11 -0
- package/packages/datadog-plugin-cucumber/src/index.js +3 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +3 -0
- package/packages/datadog-plugin-dns/src/lookup.js +10 -5
- package/packages/datadog-plugin-dns/src/lookup_service.js +6 -2
- package/packages/datadog-plugin-dns/src/resolve.js +5 -2
- package/packages/datadog-plugin-dns/src/reverse.js +6 -2
- package/packages/datadog-plugin-fs/src/index.js +9 -2
- package/packages/datadog-plugin-jest/src/index.js +3 -0
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -1
- package/packages/datadog-plugin-kafkajs/src/consumer.js +12 -21
- package/packages/datadog-plugin-kafkajs/src/producer.js +6 -2
- package/packages/datadog-plugin-kafkajs/src/utils.js +27 -0
- package/packages/datadog-plugin-langchain/src/index.js +0 -1
- package/packages/datadog-plugin-mocha/src/index.js +3 -0
- package/packages/datadog-plugin-net/src/ipc.js +6 -4
- package/packages/datadog-plugin-net/src/tcp.js +15 -9
- package/packages/datadog-plugin-pg/src/index.js +5 -1
- package/packages/datadog-plugin-playwright/src/index.js +3 -0
- package/packages/datadog-plugin-vitest/src/index.js +15 -3
- package/packages/dd-trace/src/appsec/api_security_sampler.js +20 -12
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +14 -9
- package/packages/dd-trace/src/appsec/index.js +1 -1
- package/packages/dd-trace/src/baggage.js +36 -0
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +4 -2
- package/packages/dd-trace/src/config.js +13 -1
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -1
- package/packages/dd-trace/src/exporters/common/docker.js +13 -31
- package/packages/dd-trace/src/guardrails/telemetry.js +2 -5
- package/packages/dd-trace/src/llmobs/writers/base.js +33 -12
- package/packages/dd-trace/src/noop/proxy.js +5 -0
- package/packages/dd-trace/src/opentelemetry/context_manager.js +2 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -9
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/index.js +3 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +9 -20
- package/packages/dd-trace/src/plugins/outbound.js +11 -3
- package/packages/dd-trace/src/plugins/tracing.js +8 -4
- package/packages/dd-trace/src/plugins/util/test.js +1 -1
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +15 -14
- package/packages/dd-trace/src/proxy.js +12 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
- package/packages/dd-trace/src/standalone/product.js +3 -5
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
channel,
|
|
5
|
-
addHook,
|
|
6
|
-
AsyncResource
|
|
7
|
-
} = require('./helpers/instrument')
|
|
3
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
8
4
|
const shimmer = require('../../datadog-shimmer')
|
|
9
5
|
|
|
10
6
|
const startChannel = channel('apm:fs:operation:start')
|
|
@@ -191,25 +187,23 @@ function wrapCreateStream (original) {
|
|
|
191
187
|
return function (path, options) {
|
|
192
188
|
if (!startChannel.hasSubscribers) return original.apply(this, arguments)
|
|
193
189
|
|
|
194
|
-
const
|
|
195
|
-
const message = getMessage(name, ['path', 'options'], arguments)
|
|
196
|
-
|
|
197
|
-
return innerResource.runInAsyncScope(() => {
|
|
198
|
-
startChannel.publish(message)
|
|
190
|
+
const ctx = getMessage(name, ['path', 'options'], arguments)
|
|
199
191
|
|
|
192
|
+
return startChannel.runStores(ctx, () => {
|
|
200
193
|
try {
|
|
201
194
|
const stream = original.apply(this, arguments)
|
|
202
|
-
const onError =
|
|
203
|
-
|
|
195
|
+
const onError = error => {
|
|
196
|
+
ctx.error = error
|
|
197
|
+
errorChannel.publish(ctx)
|
|
204
198
|
onFinish()
|
|
205
|
-
}
|
|
206
|
-
const onFinish =
|
|
207
|
-
finishChannel.
|
|
199
|
+
}
|
|
200
|
+
const onFinish = () => {
|
|
201
|
+
finishChannel.runStores(ctx, () => {})
|
|
208
202
|
stream.off('close', onFinish)
|
|
209
203
|
stream.off('end', onFinish)
|
|
210
204
|
stream.off('finish', onFinish)
|
|
211
205
|
stream.off('error', onError)
|
|
212
|
-
}
|
|
206
|
+
}
|
|
213
207
|
|
|
214
208
|
stream.once('close', onFinish)
|
|
215
209
|
stream.once('end', onFinish)
|
|
@@ -218,8 +212,9 @@ function wrapCreateStream (original) {
|
|
|
218
212
|
|
|
219
213
|
return stream
|
|
220
214
|
} catch (error) {
|
|
221
|
-
|
|
222
|
-
|
|
215
|
+
ctx.error = error
|
|
216
|
+
errorChannel.publish(ctx)
|
|
217
|
+
finishChannel.runStores(ctx, () => {})
|
|
223
218
|
}
|
|
224
219
|
})
|
|
225
220
|
}
|
|
@@ -239,17 +234,16 @@ function createWatchWrapFunction (override = '') {
|
|
|
239
234
|
const operation = name
|
|
240
235
|
return function () {
|
|
241
236
|
if (!startChannel.hasSubscribers) return original.apply(this, arguments)
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
return innerResource.runInAsyncScope(() => {
|
|
245
|
-
startChannel.publish(message)
|
|
237
|
+
const ctx = getMessage(method, watchMethods[operation], arguments, this)
|
|
238
|
+
return startChannel.runStores(ctx, () => {
|
|
246
239
|
try {
|
|
247
240
|
const result = original.apply(this, arguments)
|
|
248
|
-
finishChannel.
|
|
241
|
+
finishChannel.runStores(ctx, () => {})
|
|
249
242
|
return result
|
|
250
243
|
} catch (error) {
|
|
251
|
-
|
|
252
|
-
|
|
244
|
+
ctx.error = error
|
|
245
|
+
errorChannel.publish(ctx)
|
|
246
|
+
finishChannel.runStores(ctx, () => {})
|
|
253
247
|
throw error
|
|
254
248
|
}
|
|
255
249
|
})
|
|
@@ -268,30 +262,25 @@ function createWrapFunction (prefix = '', override = '') {
|
|
|
268
262
|
|
|
269
263
|
const lastIndex = arguments.length - 1
|
|
270
264
|
const cb = typeof arguments[lastIndex] === 'function' && arguments[lastIndex]
|
|
271
|
-
const innerResource = new AsyncResource('bound-anonymous-fn')
|
|
272
265
|
const params = getMethodParamsRelationByPrefix(prefix)[operation]
|
|
273
266
|
const abortController = new AbortController()
|
|
274
|
-
const
|
|
267
|
+
const ctx = { ...getMessage(method, params, arguments, this), abortController }
|
|
275
268
|
|
|
276
|
-
const finish =
|
|
269
|
+
const finish = function (error, cb = () => {}) {
|
|
277
270
|
if (error !== null && typeof error === 'object') { // fs.exists receives a boolean
|
|
278
|
-
|
|
271
|
+
ctx.error = error
|
|
272
|
+
errorChannel.publish(ctx)
|
|
279
273
|
}
|
|
280
|
-
finishChannel.
|
|
281
|
-
}
|
|
274
|
+
return finishChannel.runStores(ctx, cb)
|
|
275
|
+
}
|
|
282
276
|
|
|
283
277
|
if (cb) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
finish(e)
|
|
288
|
-
return outerResource.runInAsyncScope(() => cb.apply(this, arguments))
|
|
289
|
-
}))
|
|
278
|
+
arguments[lastIndex] = shimmer.wrapFunction(cb, cb => function (e) {
|
|
279
|
+
return finish(e, () => cb.apply(this, arguments))
|
|
280
|
+
})
|
|
290
281
|
}
|
|
291
282
|
|
|
292
|
-
return
|
|
293
|
-
startChannel.publish(message)
|
|
294
|
-
|
|
283
|
+
return startChannel.runStores(ctx, () => {
|
|
295
284
|
if (abortController.signal.aborted) {
|
|
296
285
|
const error = abortController.signal.reason || new Error('Aborted')
|
|
297
286
|
|
|
@@ -318,23 +307,25 @@ function createWrapFunction (prefix = '', override = '') {
|
|
|
318
307
|
if (isFirstMethodReturningFileHandle(original)) {
|
|
319
308
|
wrapFileHandle(value)
|
|
320
309
|
}
|
|
321
|
-
finishChannel.
|
|
310
|
+
finishChannel.runStores(ctx, () => {})
|
|
322
311
|
return value
|
|
323
312
|
},
|
|
324
313
|
error => {
|
|
325
|
-
|
|
326
|
-
|
|
314
|
+
ctx.error = error
|
|
315
|
+
errorChannel.publish(ctx)
|
|
316
|
+
finishChannel.runStores(ctx, () => {})
|
|
327
317
|
throw error
|
|
328
318
|
}
|
|
329
319
|
)
|
|
330
320
|
}
|
|
331
321
|
|
|
332
|
-
finishChannel.
|
|
322
|
+
finishChannel.runStores(ctx, () => {})
|
|
333
323
|
|
|
334
324
|
return result
|
|
335
325
|
} catch (error) {
|
|
336
|
-
|
|
337
|
-
|
|
326
|
+
ctx.error = error
|
|
327
|
+
errorChannel.publish(ctx)
|
|
328
|
+
finishChannel.runStores(ctx, () => {})
|
|
338
329
|
throw error
|
|
339
330
|
}
|
|
340
331
|
})
|
|
@@ -70,6 +70,7 @@ module.exports = {
|
|
|
70
70
|
knex: () => require('../knex'),
|
|
71
71
|
koa: () => require('../koa'),
|
|
72
72
|
'koa-router': () => require('../koa'),
|
|
73
|
+
'@confluentinc/kafka-javascript': () => require('../confluentinc-kafka-javascript'),
|
|
73
74
|
kafkajs: () => require('../kafkajs'),
|
|
74
75
|
langchain: () => require('../langchain'),
|
|
75
76
|
ldapjs: () => require('../ldapjs'),
|
|
@@ -115,7 +115,16 @@ for (const packageName of names) {
|
|
|
115
115
|
continue
|
|
116
116
|
}
|
|
117
117
|
if (typeof namesAndSuccesses[`${name}@${version}`] === 'undefined') {
|
|
118
|
-
|
|
118
|
+
// TODO If `file` is present, we might elsewhere instrument the result of the module
|
|
119
|
+
// for a version range that actually matches, so we can't assume that we're _not_
|
|
120
|
+
// going to instrument that. However, the way the data model around instrumentation
|
|
121
|
+
// works, we can't know either way just yet, so to avoid false positives, we'll just
|
|
122
|
+
// ignore this if there is a `file` in the hook. The thing to do here is rework
|
|
123
|
+
// everything so that we can be sure that there are _no_ instrumentations that it
|
|
124
|
+
// could match.
|
|
125
|
+
if (!file) {
|
|
126
|
+
namesAndSuccesses[`${name}@${version}`] = false
|
|
127
|
+
}
|
|
119
128
|
}
|
|
120
129
|
|
|
121
130
|
if (matchVersion(version, versions)) {
|
|
@@ -81,6 +81,7 @@ const sessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
|
81
81
|
|
|
82
82
|
const asyncResources = new WeakMap()
|
|
83
83
|
const originalTestFns = new WeakMap()
|
|
84
|
+
const originalHookFns = new WeakMap()
|
|
84
85
|
const retriedTestsToNumAttempts = new Map()
|
|
85
86
|
const newTestsTestStatuses = new Map()
|
|
86
87
|
const attemptToFixRetriedTestsStatuses = new Map()
|
|
@@ -154,7 +155,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
154
155
|
const hasKnownTests = !!knownTests?.jest
|
|
155
156
|
earlyFlakeDetectionNumRetries = this.testEnvironmentOptions._ddEarlyFlakeDetectionNumRetries
|
|
156
157
|
this.knownTestsForThisSuite = hasKnownTests
|
|
157
|
-
? (knownTests?.jest[this.testSuite] || [])
|
|
158
|
+
? (knownTests?.jest?.[this.testSuite] || [])
|
|
158
159
|
: this.getKnownTestsForSuite(this.testEnvironmentOptions._ddKnownTests)
|
|
159
160
|
} catch (e) {
|
|
160
161
|
// If there has been an error parsing the tests, we'll disable Early Flake Deteciton
|
|
@@ -172,10 +173,10 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
172
173
|
|
|
173
174
|
if (this.isTestManagementTestsEnabled) {
|
|
174
175
|
try {
|
|
175
|
-
const hasTestManagementTests = !!testManagementTests
|
|
176
|
+
const hasTestManagementTests = !!testManagementTests?.jest
|
|
176
177
|
testManagementAttemptToFixRetries = this.testEnvironmentOptions._ddTestManagementAttemptToFixRetries
|
|
177
178
|
this.testManagementTestsForThisSuite = hasTestManagementTests
|
|
178
|
-
? this.getTestManagementTestsForSuite(testManagementTests
|
|
179
|
+
? this.getTestManagementTestsForSuite(testManagementTests?.jest?.suites?.[this.testSuite]?.tests)
|
|
179
180
|
: this.getTestManagementTestsForSuite(this.testEnvironmentOptions._ddTestManagementTests)
|
|
180
181
|
} catch (e) {
|
|
181
182
|
log.error('Error parsing test management tests', e)
|
|
@@ -351,6 +352,15 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
351
352
|
isDisabled,
|
|
352
353
|
isQuarantined
|
|
353
354
|
})
|
|
355
|
+
for (const hook of event.test.parent.hooks) {
|
|
356
|
+
let hookFn = hook.fn
|
|
357
|
+
if (!originalHookFns.has(hook)) {
|
|
358
|
+
originalHookFns.set(hook, hookFn)
|
|
359
|
+
} else {
|
|
360
|
+
hookFn = originalHookFns.get(hook)
|
|
361
|
+
}
|
|
362
|
+
hook.fn = asyncResource.bind(hookFn)
|
|
363
|
+
}
|
|
354
364
|
originalTestFns.set(event.test, event.test.fn)
|
|
355
365
|
event.test.fn = asyncResource.bind(event.test.fn)
|
|
356
366
|
})
|
|
@@ -398,6 +408,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
398
408
|
event.test.fn = originalTestFns.get(event.test)
|
|
399
409
|
|
|
400
410
|
let attemptToFixPassed = false
|
|
411
|
+
let attemptToFixFailed = false
|
|
401
412
|
let failedAllTests = false
|
|
402
413
|
let isAttemptToFix = false
|
|
403
414
|
if (this.isTestManagementTestsEnabled) {
|
|
@@ -415,6 +426,9 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
415
426
|
// If it is, we'll set the failedAllTests flag to true if all the tests failed
|
|
416
427
|
// If all tests passed, we'll set the attemptToFixPassed flag to true
|
|
417
428
|
if (testStatuses.length === testManagementAttemptToFixRetries + 1) {
|
|
429
|
+
if (testStatuses.some(status => status === 'fail')) {
|
|
430
|
+
attemptToFixFailed = true
|
|
431
|
+
}
|
|
418
432
|
if (testStatuses.every(status => status === 'fail')) {
|
|
419
433
|
failedAllTests = true
|
|
420
434
|
} else if (testStatuses.every(status => status === 'pass')) {
|
|
@@ -480,6 +494,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
480
494
|
testStartLine: getTestLineStart(event.test.asyncError, this.testSuite),
|
|
481
495
|
attemptToFixPassed,
|
|
482
496
|
failedAllTests,
|
|
497
|
+
attemptToFixFailed,
|
|
483
498
|
isAtrRetry
|
|
484
499
|
})
|
|
485
500
|
})
|
|
@@ -1186,7 +1201,7 @@ addHook({
|
|
|
1186
1201
|
const testSuite = getTestSuitePath(testSuiteAbsolutePath, globalConfig.rootDir || process.cwd())
|
|
1187
1202
|
const suiteKnownTests = knownTests?.jest?.[testSuite] || []
|
|
1188
1203
|
|
|
1189
|
-
const suiteTestManagementTests = testManagementTests
|
|
1204
|
+
const suiteTestManagementTests = testManagementTests?.jest?.suites?.[testSuite]?.tests || {}
|
|
1190
1205
|
|
|
1191
1206
|
args[0].config = {
|
|
1192
1207
|
...config,
|
|
@@ -265,6 +265,7 @@ function getOnTestEndHandler (config) {
|
|
|
265
265
|
|
|
266
266
|
let hasFailedAllRetries = false
|
|
267
267
|
let attemptToFixPassed = false
|
|
268
|
+
let attemptToFixFailed = false
|
|
268
269
|
|
|
269
270
|
const testName = getTestFullName(test)
|
|
270
271
|
|
|
@@ -278,6 +279,9 @@ function getOnTestEndHandler (config) {
|
|
|
278
279
|
const isLastAttempt = testStatuses.length === config.testManagementAttemptToFixRetries + 1
|
|
279
280
|
|
|
280
281
|
if (test._ddIsAttemptToFix && isLastAttempt) {
|
|
282
|
+
if (testStatuses.some(status => status === 'fail')) {
|
|
283
|
+
attemptToFixFailed = true
|
|
284
|
+
}
|
|
281
285
|
if (testStatuses.every(status => status === 'fail')) {
|
|
282
286
|
hasFailedAllRetries = true
|
|
283
287
|
} else if (testStatuses.every(status => status === 'pass')) {
|
|
@@ -299,6 +303,7 @@ function getOnTestEndHandler (config) {
|
|
|
299
303
|
isLastRetry: getIsLastRetry(test),
|
|
300
304
|
hasFailedAllRetries,
|
|
301
305
|
attemptToFixPassed,
|
|
306
|
+
attemptToFixFailed,
|
|
302
307
|
isAttemptToFixRetry,
|
|
303
308
|
isAtrRetry
|
|
304
309
|
})
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
channel,
|
|
5
|
-
addHook,
|
|
6
|
-
AsyncResource
|
|
7
|
-
} = require('./helpers/instrument')
|
|
3
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
8
4
|
const shimmer = require('../../datadog-shimmer')
|
|
9
5
|
|
|
10
6
|
const startICPCh = channel('apm:net:ipc:start')
|
|
@@ -15,6 +11,7 @@ const startTCPCh = channel('apm:net:tcp:start')
|
|
|
15
11
|
const finishTCPCh = channel('apm:net:tcp:finish')
|
|
16
12
|
const errorTCPCh = channel('apm:net:tcp:error')
|
|
17
13
|
|
|
14
|
+
const readyCh = channel('apm:net:tcp:ready')
|
|
18
15
|
const connectionCh = channel('apm:net:tcp:connection')
|
|
19
16
|
|
|
20
17
|
const names = ['net', 'node:net']
|
|
@@ -39,30 +36,27 @@ addHook({ name: names }, (net, version, name) => {
|
|
|
39
36
|
|
|
40
37
|
if (!options) return connect.apply(this, arguments)
|
|
41
38
|
|
|
42
|
-
const
|
|
43
|
-
const
|
|
39
|
+
const protocol = options.path ? 'ipc' : 'tcp'
|
|
40
|
+
const startCh = protocol === 'ipc' ? startICPCh : startTCPCh
|
|
41
|
+
const finishCh = protocol === 'ipc' ? finishICPCh : finishTCPCh
|
|
42
|
+
const errorCh = protocol === 'ipc' ? errorICPCh : errorTCPCh
|
|
43
|
+
const ctx = { options }
|
|
44
44
|
|
|
45
45
|
if (typeof callback === 'function') {
|
|
46
|
-
arguments[lastIndex] =
|
|
46
|
+
arguments[lastIndex] = function (...args) {
|
|
47
|
+
return finishCh.runStores(ctx, callback, this, ...args)
|
|
48
|
+
}
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return asyncResource.runInAsyncScope(() => {
|
|
52
|
-
if (protocol === 'ipc') {
|
|
53
|
-
startICPCh.publish({ options })
|
|
54
|
-
setupListeners(this, 'ipc', asyncResource)
|
|
55
|
-
} else {
|
|
56
|
-
startTCPCh.publish({ options })
|
|
57
|
-
setupListeners(this, 'tcp', asyncResource)
|
|
58
|
-
}
|
|
51
|
+
return startCh.runStores(ctx, () => {
|
|
52
|
+
setupListeners(this, protocol, ctx, finishCh, errorCh)
|
|
59
53
|
|
|
60
54
|
const emit = this.emit
|
|
61
55
|
this.emit = shimmer.wrapFunction(emit, emit => function (eventName) {
|
|
62
56
|
switch (eventName) {
|
|
63
57
|
case 'ready':
|
|
64
58
|
case 'connect':
|
|
65
|
-
return
|
|
59
|
+
return readyCh.runStores(ctx, () => {
|
|
66
60
|
return emit.apply(this, arguments)
|
|
67
61
|
})
|
|
68
62
|
default:
|
|
@@ -73,7 +67,7 @@ addHook({ name: names }, (net, version, name) => {
|
|
|
73
67
|
try {
|
|
74
68
|
return connect.apply(this, arguments)
|
|
75
69
|
} catch (err) {
|
|
76
|
-
|
|
70
|
+
errorCh.publish(err)
|
|
77
71
|
|
|
78
72
|
throw err
|
|
79
73
|
}
|
|
@@ -104,19 +98,21 @@ function getOptions (args) {
|
|
|
104
98
|
}
|
|
105
99
|
}
|
|
106
100
|
|
|
107
|
-
function setupListeners (socket, protocol,
|
|
101
|
+
function setupListeners (socket, protocol, ctx, finishCh, errorCh) {
|
|
108
102
|
const events = ['connect', 'error', 'close', 'timeout']
|
|
109
103
|
|
|
110
|
-
const wrapListener =
|
|
104
|
+
const wrapListener = function (error) {
|
|
111
105
|
if (error) {
|
|
112
|
-
|
|
106
|
+
ctx.error = error
|
|
107
|
+
errorCh.publish(ctx)
|
|
113
108
|
}
|
|
114
|
-
|
|
115
|
-
}
|
|
109
|
+
finishCh.runStores(ctx, () => {})
|
|
110
|
+
}
|
|
116
111
|
|
|
117
|
-
const localListener =
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
const localListener = function () {
|
|
113
|
+
ctx.socket = socket
|
|
114
|
+
connectionCh.publish(ctx)
|
|
115
|
+
}
|
|
120
116
|
|
|
121
117
|
const cleanupListener = function () {
|
|
122
118
|
socket.removeListener('connect', localListener)
|
|
@@ -14,6 +14,8 @@ const errorCh = channel('apm:pg:query:error')
|
|
|
14
14
|
const startPoolQueryCh = channel('datadog:pg:pool:query:start')
|
|
15
15
|
const finishPoolQueryCh = channel('datadog:pg:pool:query:finish')
|
|
16
16
|
|
|
17
|
+
const { errorMonitor } = require('node:events')
|
|
18
|
+
|
|
17
19
|
addHook({ name: 'pg', versions: ['>=8.0.3'] }, pg => {
|
|
18
20
|
shimmer.wrap(pg.Client.prototype, 'query', query => wrapQuery(query))
|
|
19
21
|
shimmer.wrap(pg.Pool.prototype, 'query', query => wrapPoolQuery(query))
|
|
@@ -39,13 +41,15 @@ function wrapQuery (query) {
|
|
|
39
41
|
? arguments[0]
|
|
40
42
|
: { text: arguments[0] }
|
|
41
43
|
|
|
42
|
-
const
|
|
44
|
+
const textPropObj = pgQuery.cursor ?? pgQuery
|
|
45
|
+
const textProp = Object.getOwnPropertyDescriptor(textPropObj, 'text')
|
|
46
|
+
const stream = typeof textPropObj.read === 'function'
|
|
43
47
|
|
|
44
48
|
// Only alter `text` property if safe to do so.
|
|
45
49
|
if (!textProp || textProp.configurable) {
|
|
46
|
-
const originalText =
|
|
50
|
+
const originalText = textPropObj.text
|
|
47
51
|
|
|
48
|
-
Object.defineProperty(
|
|
52
|
+
Object.defineProperty(textPropObj, 'text', {
|
|
49
53
|
get () {
|
|
50
54
|
return this?.__ddInjectableQuery || originalText
|
|
51
55
|
}
|
|
@@ -57,9 +61,10 @@ function wrapQuery (query) {
|
|
|
57
61
|
|
|
58
62
|
startCh.publish({
|
|
59
63
|
params: this.connectionParameters,
|
|
60
|
-
query:
|
|
64
|
+
query: textPropObj,
|
|
61
65
|
processId,
|
|
62
|
-
abortController
|
|
66
|
+
abortController,
|
|
67
|
+
stream
|
|
63
68
|
})
|
|
64
69
|
|
|
65
70
|
const finish = asyncResource.bind(function (error, res) {
|
|
@@ -130,6 +135,15 @@ function wrapQuery (query) {
|
|
|
130
135
|
newQuery.then((res) => finish(null, res), finish)
|
|
131
136
|
}
|
|
132
137
|
|
|
138
|
+
if (stream) {
|
|
139
|
+
newQuery.on('end', () => {
|
|
140
|
+
finish(null, [])
|
|
141
|
+
})
|
|
142
|
+
newQuery.on(errorMonitor, (err) => {
|
|
143
|
+
finish(err)
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
|
|
133
147
|
try {
|
|
134
148
|
return retval
|
|
135
149
|
} catch (err) {
|
|
@@ -337,6 +337,9 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
|
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
if (testStatuses.length === testManagementAttemptToFixRetries + 1) {
|
|
340
|
+
if (testStatuses.some(status => status === 'fail')) {
|
|
341
|
+
test._ddHasFailedAttemptToFixRetries = true
|
|
342
|
+
}
|
|
340
343
|
if (testStatuses.every(status => status === 'fail')) {
|
|
341
344
|
test._ddHasFailedAllRetries = true
|
|
342
345
|
} else if (testStatuses.every(status => status === 'pass')) {
|
|
@@ -366,6 +369,7 @@ function testEndHandler (test, annotations, testStatus, error, isTimeout, isMain
|
|
|
366
369
|
isEfdRetry: test._ddIsEfdRetry,
|
|
367
370
|
hasFailedAllRetries: test._ddHasFailedAllRetries,
|
|
368
371
|
hasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
|
|
372
|
+
hasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
|
|
369
373
|
isAtrRetry
|
|
370
374
|
})
|
|
371
375
|
})
|
|
@@ -492,6 +496,7 @@ function dispatcherHookNew (dispatcherExport, runWrapper) {
|
|
|
492
496
|
_ddIsEfdRetry: test._ddIsEfdRetry,
|
|
493
497
|
_ddHasFailedAllRetries: test._ddHasFailedAllRetries,
|
|
494
498
|
_ddHasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
|
|
499
|
+
_ddHasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
|
|
495
500
|
_ddIsAtrRetry: isAtrRetry
|
|
496
501
|
}
|
|
497
502
|
})
|
|
@@ -986,6 +991,7 @@ addHook({
|
|
|
986
991
|
isAttemptToFixRetry: test._ddIsAttemptToFixRetry,
|
|
987
992
|
hasFailedAllRetries: test._ddHasFailedAllRetries,
|
|
988
993
|
hasPassedAttemptToFixRetries: test._ddHasPassedAttemptToFixRetries,
|
|
994
|
+
hasFailedAttemptToFixRetries: test._ddHasFailedAttemptToFixRetries,
|
|
989
995
|
isAtrRetry: test._ddIsAtrRetry,
|
|
990
996
|
onDone
|
|
991
997
|
})
|
|
@@ -614,17 +614,22 @@ addHook({
|
|
|
614
614
|
}
|
|
615
615
|
|
|
616
616
|
let attemptToFixPassed = false
|
|
617
|
+
let attemptToFixFailed = false
|
|
617
618
|
if (attemptToFixTasks.has(task)) {
|
|
618
619
|
const statuses = taskToStatuses.get(task)
|
|
619
|
-
if (statuses.length === testManagementAttemptToFixRetries
|
|
620
|
-
|
|
620
|
+
if (statuses.length === testManagementAttemptToFixRetries) {
|
|
621
|
+
if (statuses.every(status => status === 'pass')) {
|
|
622
|
+
attemptToFixPassed = true
|
|
623
|
+
} else if (statuses.some(status => status === 'fail')) {
|
|
624
|
+
attemptToFixFailed = true
|
|
625
|
+
}
|
|
621
626
|
}
|
|
622
627
|
}
|
|
623
628
|
|
|
624
629
|
if (asyncResource) {
|
|
625
630
|
// We don't finish here because the test might fail in a later hook (afterEach)
|
|
626
631
|
asyncResource.runInAsyncScope(() => {
|
|
627
|
-
testFinishTimeCh.publish({ status, task, attemptToFixPassed })
|
|
632
|
+
testFinishTimeCh.publish({ status, task, attemptToFixPassed, attemptToFixFailed })
|
|
628
633
|
})
|
|
629
634
|
}
|
|
630
635
|
|
|
@@ -776,8 +781,12 @@ addHook({
|
|
|
776
781
|
}
|
|
777
782
|
|
|
778
783
|
let hasFailedAllRetries = false
|
|
784
|
+
let attemptToFixFailed = false
|
|
779
785
|
if (attemptToFixTasks.has(task)) {
|
|
780
786
|
const statuses = taskToStatuses.get(task)
|
|
787
|
+
if (statuses.some(status => status === 'fail')) {
|
|
788
|
+
attemptToFixFailed = true
|
|
789
|
+
}
|
|
781
790
|
if (statuses.every(status => status === 'fail')) {
|
|
782
791
|
hasFailedAllRetries = true
|
|
783
792
|
}
|
|
@@ -787,7 +796,12 @@ addHook({
|
|
|
787
796
|
const isRetry = task.result?.retryCount > 0
|
|
788
797
|
// `duration` is the duration of all the retries, so it can't be used if there are retries
|
|
789
798
|
testAsyncResource.runInAsyncScope(() => {
|
|
790
|
-
testErrorCh.publish({
|
|
799
|
+
testErrorCh.publish({
|
|
800
|
+
duration: !isRetry ? duration : undefined,
|
|
801
|
+
error: testError,
|
|
802
|
+
hasFailedAllRetries,
|
|
803
|
+
attemptToFixFailed
|
|
804
|
+
})
|
|
791
805
|
})
|
|
792
806
|
}
|
|
793
807
|
if (errors?.length) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const KafkajsBatchConsumerPlugin = require('../../datadog-plugin-kafkajs/src/batch-consumer')
|
|
4
|
+
|
|
5
|
+
class ConfluentKafkaJsBatchConsumerPlugin extends KafkajsBatchConsumerPlugin {
|
|
6
|
+
static get id () {
|
|
7
|
+
return '@confluentinc/kafka-javascript'
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = ConfluentKafkaJsBatchConsumerPlugin
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const KafkajsConsumerPlugin = require('../../datadog-plugin-kafkajs/src/consumer')
|
|
4
|
+
|
|
5
|
+
class ConfluentKafkaJsConsumerPlugin extends KafkajsConsumerPlugin {
|
|
6
|
+
static get id () {
|
|
7
|
+
return '@confluentinc/kafka-javascript'
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = ConfluentKafkaJsConsumerPlugin
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const ProducerPlugin = require('./producer')
|
|
4
|
+
const ConsumerPlugin = require('./consumer')
|
|
5
|
+
const BatchConsumerPlugin = require('./batch-consumer')
|
|
6
|
+
const KafkajsPlugin = require('../../datadog-plugin-kafkajs/src/index')
|
|
7
|
+
|
|
8
|
+
class ConfluentKafkaJsPlugin extends KafkajsPlugin {
|
|
9
|
+
static get id () { return '@confluentinc/kafka-javascript' }
|
|
10
|
+
static get plugins () {
|
|
11
|
+
return {
|
|
12
|
+
producer: ProducerPlugin,
|
|
13
|
+
consumer: ConsumerPlugin,
|
|
14
|
+
batchConsumer: BatchConsumerPlugin
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = ConfluentKafkaJsPlugin
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const KafkajsProducerPlugin = require('../../datadog-plugin-kafkajs/src/producer')
|
|
4
|
+
|
|
5
|
+
class ConfluentKafkaJsProducerPlugin extends KafkajsProducerPlugin {
|
|
6
|
+
static get id () {
|
|
7
|
+
return '@confluentinc/kafka-javascript'
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = ConfluentKafkaJsProducerPlugin
|
|
@@ -341,6 +341,7 @@ class CucumberPlugin extends CiPlugin {
|
|
|
341
341
|
isAttemptToFixRetry,
|
|
342
342
|
hasFailedAllRetries,
|
|
343
343
|
hasPassedAllRetries,
|
|
344
|
+
hasFailedAttemptToFix,
|
|
344
345
|
isDisabled,
|
|
345
346
|
isQuarantined
|
|
346
347
|
}) => {
|
|
@@ -385,6 +386,8 @@ class CucumberPlugin extends CiPlugin {
|
|
|
385
386
|
span.setTag(TEST_RETRY_REASON, TEST_RETRY_REASON_TYPES.atf)
|
|
386
387
|
if (hasPassedAllRetries) {
|
|
387
388
|
span.setTag(TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED, 'true')
|
|
389
|
+
} else if (hasFailedAttemptToFix) {
|
|
390
|
+
span.setTag(TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED, 'false')
|
|
388
391
|
}
|
|
389
392
|
}
|
|
390
393
|
|
|
@@ -838,6 +838,9 @@ class CypressPlugin {
|
|
|
838
838
|
}
|
|
839
839
|
const isLastAttempt = testStatuses.length === this.testManagementAttemptToFixRetries + 1
|
|
840
840
|
if (isLastAttempt) {
|
|
841
|
+
if (testStatuses.some(status => status === 'fail')) {
|
|
842
|
+
this.activeTestSpan.setTag(TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED, 'false')
|
|
843
|
+
}
|
|
841
844
|
if (testStatuses.every(status => status === 'fail')) {
|
|
842
845
|
this.activeTestSpan.setTag(TEST_HAS_FAILED_ALL_RETRIES, 'true')
|
|
843
846
|
} else if (testStatuses.every(status => status === 'pass')) {
|
|
@@ -6,7 +6,9 @@ class DNSLookupPlugin extends ClientPlugin {
|
|
|
6
6
|
static get id () { return 'dns' }
|
|
7
7
|
static get operation () { return 'lookup' }
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
bindStart (ctx) {
|
|
10
|
+
const [hostname] = ctx.args
|
|
11
|
+
|
|
10
12
|
this.startSpan('dns.lookup', {
|
|
11
13
|
service: this.config.service,
|
|
12
14
|
resource: hostname,
|
|
@@ -16,11 +18,14 @@ class DNSLookupPlugin extends ClientPlugin {
|
|
|
16
18
|
'dns.address': '',
|
|
17
19
|
'dns.addresses': ''
|
|
18
20
|
}
|
|
19
|
-
})
|
|
21
|
+
}, ctx)
|
|
22
|
+
|
|
23
|
+
return ctx.currentStore
|
|
20
24
|
}
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
const span =
|
|
26
|
+
bindFinish (ctx) {
|
|
27
|
+
const span = ctx.currentStore.span
|
|
28
|
+
const result = ctx.result
|
|
24
29
|
|
|
25
30
|
if (Array.isArray(result)) {
|
|
26
31
|
const addresses = Array.isArray(result)
|
|
@@ -33,7 +38,7 @@ class DNSLookupPlugin extends ClientPlugin {
|
|
|
33
38
|
span.setTag('dns.address', result)
|
|
34
39
|
}
|
|
35
40
|
|
|
36
|
-
|
|
41
|
+
return ctx.parentStore
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
44
|
|