dd-trace 5.51.0 → 5.53.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/README.md +5 -0
- package/index.d.ts +88 -6
- package/package.json +3 -9
- package/packages/datadog-instrumentations/src/amqplib.js +8 -5
- package/packages/datadog-instrumentations/src/child_process.js +2 -1
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +406 -0
- package/packages/datadog-instrumentations/src/couchbase.js +2 -1
- package/packages/datadog-instrumentations/src/cucumber.js +43 -45
- package/packages/datadog-instrumentations/src/dns.js +16 -14
- package/packages/datadog-instrumentations/src/express.js +2 -6
- package/packages/datadog-instrumentations/src/fs.js +43 -51
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +17 -12
- package/packages/datadog-instrumentations/src/http/client.js +2 -1
- package/packages/datadog-instrumentations/src/iovalkey.js +51 -0
- package/packages/datadog-instrumentations/src/jest.js +53 -40
- package/packages/datadog-instrumentations/src/kafkajs.js +21 -8
- package/packages/datadog-instrumentations/src/mocha/main.js +33 -46
- package/packages/datadog-instrumentations/src/mocha/utils.js +76 -74
- package/packages/datadog-instrumentations/src/mysql2.js +3 -1
- package/packages/datadog-instrumentations/src/net.js +27 -29
- package/packages/datadog-instrumentations/src/next.js +6 -14
- package/packages/datadog-instrumentations/src/pg.js +15 -7
- package/packages/datadog-instrumentations/src/playwright.js +64 -67
- package/packages/datadog-instrumentations/src/url.js +9 -17
- package/packages/datadog-instrumentations/src/vitest.js +66 -72
- 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 +32 -18
- 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-iovalkey/src/index.js +18 -0
- package/packages/datadog-plugin-jest/src/index.js +17 -8
- 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 +12 -5
- 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 +58 -35
- 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 +29 -20
- package/packages/datadog-plugin-redis/src/index.js +8 -3
- package/packages/datadog-plugin-vitest/src/index.js +67 -44
- package/packages/datadog-shimmer/src/shimmer.js +164 -33
- package/packages/dd-trace/src/appsec/api_security_sampler.js +20 -12
- package/packages/dd-trace/src/appsec/graphql.js +2 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +14 -9
- package/packages/dd-trace/src/appsec/index.js +15 -12
- package/packages/dd-trace/src/appsec/rasp/index.js +4 -2
- package/packages/dd-trace/src/appsec/rasp/utils.js +11 -6
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
- package/packages/dd-trace/src/appsec/telemetry/index.js +1 -2
- package/packages/dd-trace/src/appsec/telemetry/rasp.js +0 -9
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -6
- 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 +14 -2
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +61 -7
- package/packages/dd-trace/src/debugger/devtools_client/index.js +10 -26
- package/packages/dd-trace/src/debugger/devtools_client/send.js +8 -7
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +15 -7
- package/packages/dd-trace/src/debugger/devtools_client/state.js +22 -2
- package/packages/dd-trace/src/dogstatsd.js +2 -0
- 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/tagger.js +3 -3
- 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 +4 -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 -4
- package/packages/dd-trace/src/serverless.js +0 -48
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/standalone/product.js +3 -5
|
@@ -149,11 +149,9 @@ addHook({ name: 'express', versions: ['>=4.3.0 <5.0.0'] }, express => {
|
|
|
149
149
|
const queryReadCh = channel('datadog:express:query:finish')
|
|
150
150
|
|
|
151
151
|
addHook({ name: 'express', file: ['lib/request.js'], versions: ['>=5.0.0'] }, request => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
shimmer.wrap(requestDescriptor, 'get', function (originalGet) {
|
|
152
|
+
shimmer.wrap(request, 'query', function (originalGet) {
|
|
155
153
|
return function wrappedGet () {
|
|
156
|
-
const query = originalGet.
|
|
154
|
+
const query = originalGet.call(this)
|
|
157
155
|
|
|
158
156
|
if (queryReadCh.hasSubscribers && query) {
|
|
159
157
|
queryReadCh.publish({ query })
|
|
@@ -163,7 +161,5 @@ addHook({ name: 'express', file: ['lib/request.js'], versions: ['>=5.0.0'] }, re
|
|
|
163
161
|
}
|
|
164
162
|
})
|
|
165
163
|
|
|
166
|
-
Object.defineProperty(request, 'query', requestDescriptor)
|
|
167
|
-
|
|
168
164
|
return request
|
|
169
165
|
})
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
|
|
5
|
-
addHook,
|
|
6
|
-
AsyncResource
|
|
7
|
-
} = require('./helpers/instrument')
|
|
3
|
+
const { errorMonitor } = require('events')
|
|
4
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
8
5
|
const shimmer = require('../../datadog-shimmer')
|
|
9
6
|
|
|
10
7
|
const startChannel = channel('apm:fs:operation:start')
|
|
@@ -191,35 +188,34 @@ function wrapCreateStream (original) {
|
|
|
191
188
|
return function (path, options) {
|
|
192
189
|
if (!startChannel.hasSubscribers) return original.apply(this, arguments)
|
|
193
190
|
|
|
194
|
-
const
|
|
195
|
-
const message = getMessage(name, ['path', 'options'], arguments)
|
|
196
|
-
|
|
197
|
-
return innerResource.runInAsyncScope(() => {
|
|
198
|
-
startChannel.publish(message)
|
|
191
|
+
const ctx = getMessage(name, ['path', 'options'], arguments)
|
|
199
192
|
|
|
193
|
+
return startChannel.runStores(ctx, () => {
|
|
200
194
|
try {
|
|
201
195
|
const stream = original.apply(this, arguments)
|
|
202
|
-
const onError =
|
|
203
|
-
|
|
196
|
+
const onError = error => {
|
|
197
|
+
ctx.error = error
|
|
198
|
+
errorChannel.publish(ctx)
|
|
204
199
|
onFinish()
|
|
205
|
-
}
|
|
206
|
-
const onFinish =
|
|
207
|
-
finishChannel.
|
|
208
|
-
stream.
|
|
209
|
-
stream.
|
|
210
|
-
stream.
|
|
211
|
-
stream.
|
|
212
|
-
}
|
|
200
|
+
}
|
|
201
|
+
const onFinish = () => {
|
|
202
|
+
finishChannel.runStores(ctx, () => {})
|
|
203
|
+
stream.removeListener('close', onFinish)
|
|
204
|
+
stream.removeListener('end', onFinish)
|
|
205
|
+
stream.removeListener('finish', onFinish)
|
|
206
|
+
stream.removeListener(errorMonitor, onError)
|
|
207
|
+
}
|
|
213
208
|
|
|
214
209
|
stream.once('close', onFinish)
|
|
215
210
|
stream.once('end', onFinish)
|
|
216
211
|
stream.once('finish', onFinish)
|
|
217
|
-
stream.once(
|
|
212
|
+
stream.once(errorMonitor, onError)
|
|
218
213
|
|
|
219
214
|
return stream
|
|
220
215
|
} catch (error) {
|
|
221
|
-
|
|
222
|
-
|
|
216
|
+
ctx.error = error
|
|
217
|
+
errorChannel.publish(ctx)
|
|
218
|
+
finishChannel.runStores(ctx, () => {})
|
|
223
219
|
}
|
|
224
220
|
})
|
|
225
221
|
}
|
|
@@ -239,17 +235,16 @@ function createWatchWrapFunction (override = '') {
|
|
|
239
235
|
const operation = name
|
|
240
236
|
return function () {
|
|
241
237
|
if (!startChannel.hasSubscribers) return original.apply(this, arguments)
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
return innerResource.runInAsyncScope(() => {
|
|
245
|
-
startChannel.publish(message)
|
|
238
|
+
const ctx = getMessage(method, watchMethods[operation], arguments, this)
|
|
239
|
+
return startChannel.runStores(ctx, () => {
|
|
246
240
|
try {
|
|
247
241
|
const result = original.apply(this, arguments)
|
|
248
|
-
finishChannel.
|
|
242
|
+
finishChannel.runStores(ctx, () => {})
|
|
249
243
|
return result
|
|
250
244
|
} catch (error) {
|
|
251
|
-
|
|
252
|
-
|
|
245
|
+
ctx.error = error
|
|
246
|
+
errorChannel.publish(ctx)
|
|
247
|
+
finishChannel.runStores(ctx, () => {})
|
|
253
248
|
throw error
|
|
254
249
|
}
|
|
255
250
|
})
|
|
@@ -268,30 +263,25 @@ function createWrapFunction (prefix = '', override = '') {
|
|
|
268
263
|
|
|
269
264
|
const lastIndex = arguments.length - 1
|
|
270
265
|
const cb = typeof arguments[lastIndex] === 'function' && arguments[lastIndex]
|
|
271
|
-
const innerResource = new AsyncResource('bound-anonymous-fn')
|
|
272
266
|
const params = getMethodParamsRelationByPrefix(prefix)[operation]
|
|
273
267
|
const abortController = new AbortController()
|
|
274
|
-
const
|
|
268
|
+
const ctx = { ...getMessage(method, params, arguments, this), abortController }
|
|
275
269
|
|
|
276
|
-
const finish =
|
|
270
|
+
const finish = function (error, cb = () => {}) {
|
|
277
271
|
if (error !== null && typeof error === 'object') { // fs.exists receives a boolean
|
|
278
|
-
|
|
272
|
+
ctx.error = error
|
|
273
|
+
errorChannel.publish(ctx)
|
|
279
274
|
}
|
|
280
|
-
finishChannel.
|
|
281
|
-
}
|
|
275
|
+
return finishChannel.runStores(ctx, cb)
|
|
276
|
+
}
|
|
282
277
|
|
|
283
278
|
if (cb) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
finish(e)
|
|
288
|
-
return outerResource.runInAsyncScope(() => cb.apply(this, arguments))
|
|
289
|
-
}))
|
|
279
|
+
arguments[lastIndex] = shimmer.wrapFunction(cb, cb => function (e) {
|
|
280
|
+
return finish(e, () => cb.apply(this, arguments))
|
|
281
|
+
})
|
|
290
282
|
}
|
|
291
283
|
|
|
292
|
-
return
|
|
293
|
-
startChannel.publish(message)
|
|
294
|
-
|
|
284
|
+
return startChannel.runStores(ctx, () => {
|
|
295
285
|
if (abortController.signal.aborted) {
|
|
296
286
|
const error = abortController.signal.reason || new Error('Aborted')
|
|
297
287
|
|
|
@@ -318,23 +308,25 @@ function createWrapFunction (prefix = '', override = '') {
|
|
|
318
308
|
if (isFirstMethodReturningFileHandle(original)) {
|
|
319
309
|
wrapFileHandle(value)
|
|
320
310
|
}
|
|
321
|
-
finishChannel.
|
|
311
|
+
finishChannel.runStores(ctx, () => {})
|
|
322
312
|
return value
|
|
323
313
|
},
|
|
324
314
|
error => {
|
|
325
|
-
|
|
326
|
-
|
|
315
|
+
ctx.error = error
|
|
316
|
+
errorChannel.publish(ctx)
|
|
317
|
+
finishChannel.runStores(ctx, () => {})
|
|
327
318
|
throw error
|
|
328
319
|
}
|
|
329
320
|
)
|
|
330
321
|
}
|
|
331
322
|
|
|
332
|
-
finishChannel.
|
|
323
|
+
finishChannel.runStores(ctx, () => {})
|
|
333
324
|
|
|
334
325
|
return result
|
|
335
326
|
} catch (error) {
|
|
336
|
-
|
|
337
|
-
|
|
327
|
+
ctx.error = error
|
|
328
|
+
errorChannel.publish(ctx)
|
|
329
|
+
finishChannel.runStores(ctx, () => {})
|
|
338
330
|
throw error
|
|
339
331
|
}
|
|
340
332
|
})
|
|
@@ -61,6 +61,7 @@ module.exports = {
|
|
|
61
61
|
http2: () => require('../http2'),
|
|
62
62
|
https: () => require('../http'),
|
|
63
63
|
ioredis: () => require('../ioredis'),
|
|
64
|
+
iovalkey: () => require('../iovalkey'),
|
|
64
65
|
'jest-circus': () => require('../jest'),
|
|
65
66
|
'jest-config': () => require('../jest'),
|
|
66
67
|
'jest-environment-node': () => require('../jest'),
|
|
@@ -70,6 +71,7 @@ module.exports = {
|
|
|
70
71
|
knex: () => require('../knex'),
|
|
71
72
|
koa: () => require('../koa'),
|
|
72
73
|
'koa-router': () => require('../koa'),
|
|
74
|
+
'@confluentinc/kafka-javascript': () => require('../confluentinc-kafka-javascript'),
|
|
73
75
|
kafkajs: () => require('../kafkajs'),
|
|
74
76
|
langchain: () => require('../langchain'),
|
|
75
77
|
ldapjs: () => require('../ldapjs'),
|
|
@@ -43,7 +43,7 @@ if (!disabledInstrumentations.has('process')) {
|
|
|
43
43
|
require('../process')
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const HOOK_SYMBOL = Symbol('
|
|
46
|
+
const HOOK_SYMBOL = Symbol('hookExportsSet')
|
|
47
47
|
|
|
48
48
|
if (DD_TRACE_DEBUG && DD_TRACE_DEBUG.toLowerCase() !== 'false') {
|
|
49
49
|
checkRequireCache.checkForRequiredModules()
|
|
@@ -89,12 +89,13 @@ for (const packageName of names) {
|
|
|
89
89
|
fullFilePattern = filename(name, fullFilePattern)
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
// Create a
|
|
92
|
+
// Create a WeakSet associated with the hook function so that patches on the same moduleExport only happens once
|
|
93
93
|
// for example by instrumenting both dns and node:dns double the spans would be created
|
|
94
|
-
// since they both patch the same moduleExport, this
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
// since they both patch the same moduleExport, this WeakSet is used to mitigate that
|
|
95
|
+
// TODO(BridgeAR): Instead of using a WeakSet here, why not just use aliases for the hook in register?
|
|
96
|
+
// That way it would also not be duplicated. The actual name being used has to be identified else wise.
|
|
97
|
+
// Maybe it is also not important to know what name was actually used?
|
|
98
|
+
hook[HOOK_SYMBOL] ??= new WeakSet()
|
|
98
99
|
let matchesFile = false
|
|
99
100
|
|
|
100
101
|
matchesFile = moduleName === fullFilename
|
|
@@ -114,7 +115,7 @@ for (const packageName of names) {
|
|
|
114
115
|
log.error('Error getting version for "%s": %s', name, e.message, e)
|
|
115
116
|
continue
|
|
116
117
|
}
|
|
117
|
-
if (
|
|
118
|
+
if (namesAndSuccesses[`${name}@${version}`] === undefined) {
|
|
118
119
|
// TODO If `file` is present, we might elsewhere instrument the result of the module
|
|
119
120
|
// for a version range that actually matches, so we can't assume that we're _not_
|
|
120
121
|
// going to instrument that. However, the way the data model around instrumentation
|
|
@@ -140,12 +141,16 @@ for (const packageName of names) {
|
|
|
140
141
|
loadChannel.publish({ name, version, file })
|
|
141
142
|
// Send the name and version of the module back to the callback because now addHook
|
|
142
143
|
// takes in an array of names so by passing the name the callback will know which module name is being used
|
|
143
|
-
|
|
144
|
-
//
|
|
145
|
-
|
|
144
|
+
// TODO(BridgeAR): This is only true in case the name is identical
|
|
145
|
+
// in all loads. If they deviate, the deviating name would not be
|
|
146
|
+
// picked up due to the unification. Check what modules actually use the name.
|
|
147
|
+
// TODO(BridgeAR): Only replace moduleExports if the hook returns a new value.
|
|
148
|
+
// This allows to reduce the instrumentation code (no return needed).
|
|
149
|
+
moduleExports = hook(moduleExports, version, name) ?? moduleExports
|
|
150
|
+
// Set the moduleExports in the hooks WeakSet
|
|
151
|
+
hook[HOOK_SYMBOL].add(moduleExports)
|
|
146
152
|
} catch (e) {
|
|
147
|
-
log.info('Error during ddtrace instrumentation of application, aborting.')
|
|
148
|
-
log.info(e)
|
|
153
|
+
log.info('Error during ddtrace instrumentation of application, aborting.', e)
|
|
149
154
|
telemetry('error', [
|
|
150
155
|
`error_type:${e.constructor.name}`,
|
|
151
156
|
`integration:${name}`,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
/* eslint-disable no-fallthrough */
|
|
4
4
|
|
|
5
5
|
const url = require('url')
|
|
6
|
+
const { errorMonitor } = require('events')
|
|
6
7
|
const { channel, addHook } = require('../helpers/instrument')
|
|
7
8
|
const shimmer = require('../../../datadog-shimmer')
|
|
8
9
|
|
|
@@ -88,7 +89,7 @@ function patch (http, methodName) {
|
|
|
88
89
|
const res = arg
|
|
89
90
|
ctx.res = res
|
|
90
91
|
res.on('end', finish)
|
|
91
|
-
res.on(
|
|
92
|
+
res.on(errorMonitor, finish)
|
|
92
93
|
break
|
|
93
94
|
}
|
|
94
95
|
case 'connect':
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
const startCh = channel('apm:iovalkey:command:start')
|
|
11
|
+
const finishCh = channel('apm:iovalkey:command:finish')
|
|
12
|
+
const errorCh = channel('apm:iovalkey:command:error')
|
|
13
|
+
|
|
14
|
+
addHook({ name: 'iovalkey', versions: ['>=0.0.1'] }, Valkey => {
|
|
15
|
+
shimmer.wrap(Valkey.prototype, 'sendCommand', sendCommand => function (command, stream) {
|
|
16
|
+
if (!startCh.hasSubscribers) return sendCommand.apply(this, arguments)
|
|
17
|
+
|
|
18
|
+
if (!command?.promise) return sendCommand.apply(this, arguments)
|
|
19
|
+
|
|
20
|
+
const options = this.options || {}
|
|
21
|
+
const connectionName = options.connectionName
|
|
22
|
+
const db = options.db
|
|
23
|
+
const connectionOptions = { host: options.host, port: options.port }
|
|
24
|
+
|
|
25
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
26
|
+
return asyncResource.runInAsyncScope(() => {
|
|
27
|
+
startCh.publish({ db, command: command.name, args: command.args, connectionOptions, connectionName })
|
|
28
|
+
|
|
29
|
+
const onResolve = asyncResource.bind(() => finishCh.publish())
|
|
30
|
+
const onReject = asyncResource.bind(err => finish(finishCh, errorCh, err))
|
|
31
|
+
|
|
32
|
+
command.promise.then(onResolve, onReject)
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
return sendCommand.apply(this, arguments)
|
|
36
|
+
} catch (err) {
|
|
37
|
+
errorCh.publish(err)
|
|
38
|
+
|
|
39
|
+
throw err
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
return Valkey
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
function finish (finishCh, errorCh, error) {
|
|
47
|
+
if (error) {
|
|
48
|
+
errorCh.publish(error)
|
|
49
|
+
}
|
|
50
|
+
finishCh.publish()
|
|
51
|
+
}
|
|
@@ -41,6 +41,7 @@ const testStartCh = channel('ci:jest:test:start')
|
|
|
41
41
|
const testSkippedCh = channel('ci:jest:test:skip')
|
|
42
42
|
const testFinishCh = channel('ci:jest:test:finish')
|
|
43
43
|
const testErrCh = channel('ci:jest:test:err')
|
|
44
|
+
const testFnCh = channel('ci:jest:test:fn')
|
|
44
45
|
|
|
45
46
|
const skippableSuitesCh = channel('ci:jest:test-suite:skippable')
|
|
46
47
|
const libraryConfigurationCh = channel('ci:jest:library-configuration')
|
|
@@ -79,7 +80,7 @@ let testManagementAttemptToFixRetries = 0
|
|
|
79
80
|
|
|
80
81
|
const sessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
81
82
|
|
|
82
|
-
const
|
|
83
|
+
const testContexts = new WeakMap()
|
|
83
84
|
const originalTestFns = new WeakMap()
|
|
84
85
|
const originalHookFns = new WeakMap()
|
|
85
86
|
const retriedTestsToNumAttempts = new Map()
|
|
@@ -307,8 +308,6 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
307
308
|
const testParameters = getTestParametersString(this.nameToParams, event.test.name)
|
|
308
309
|
// Async resource for this test is created here
|
|
309
310
|
// It is used later on by the test_done handler
|
|
310
|
-
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
311
|
-
asyncResources.set(event.test, asyncResource)
|
|
312
311
|
const testName = getJestTestName(event.test)
|
|
313
312
|
const originalTestName = removeEfdStringFromTestName(removeAttemptToFixStringFromTestName(testName))
|
|
314
313
|
|
|
@@ -336,22 +335,24 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
336
335
|
}
|
|
337
336
|
|
|
338
337
|
const isJestRetry = event.test?.invocations > 1
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
338
|
+
const ctx = {
|
|
339
|
+
name: originalTestName,
|
|
340
|
+
suite: this.testSuite,
|
|
341
|
+
testSourceFile: this.testSourceFile,
|
|
342
|
+
displayName: this.displayName,
|
|
343
|
+
testParameters,
|
|
344
|
+
frameworkVersion: jestVersion,
|
|
345
|
+
isNew: isNewTest,
|
|
346
|
+
isEfdRetry: numEfdRetry > 0,
|
|
347
|
+
isAttemptToFix,
|
|
348
|
+
isAttemptToFixRetry: numOfAttemptsToFixRetries > 0,
|
|
349
|
+
isJestRetry,
|
|
350
|
+
isDisabled,
|
|
351
|
+
isQuarantined
|
|
352
|
+
}
|
|
353
|
+
testContexts.set(event.test, ctx)
|
|
354
|
+
|
|
355
|
+
testStartCh.runStores(ctx, () => {
|
|
355
356
|
for (const hook of event.test.parent.hooks) {
|
|
356
357
|
let hookFn = hook.fn
|
|
357
358
|
if (!originalHookFns.has(hook)) {
|
|
@@ -359,10 +360,21 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
359
360
|
} else {
|
|
360
361
|
hookFn = originalHookFns.get(hook)
|
|
361
362
|
}
|
|
362
|
-
|
|
363
|
+
const wrapperHook = function () {
|
|
364
|
+
return testFnCh.runStores(ctx, () => hookFn.apply(this, arguments))
|
|
365
|
+
}
|
|
366
|
+
// If we don't do this, the timeout will be not be triggered
|
|
367
|
+
Object.defineProperty(wrapperHook, 'length', { value: hookFn.length })
|
|
368
|
+
hook.fn = wrapperHook
|
|
363
369
|
}
|
|
364
|
-
|
|
365
|
-
|
|
370
|
+
const originalFn = event.test.fn
|
|
371
|
+
originalTestFns.set(event.test, originalFn)
|
|
372
|
+
const wrapper = function () {
|
|
373
|
+
return testFnCh.runStores(ctx, () => originalFn.apply(this, arguments))
|
|
374
|
+
}
|
|
375
|
+
// If we don't do this, the timeout will be not be triggered
|
|
376
|
+
Object.defineProperty(wrapper, 'length', { value: originalFn.length })
|
|
377
|
+
event.test.fn = wrapper
|
|
366
378
|
})
|
|
367
379
|
}
|
|
368
380
|
|
|
@@ -408,6 +420,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
408
420
|
event.test.fn = originalTestFns.get(event.test)
|
|
409
421
|
|
|
410
422
|
let attemptToFixPassed = false
|
|
423
|
+
let attemptToFixFailed = false
|
|
411
424
|
let failedAllTests = false
|
|
412
425
|
let isAttemptToFix = false
|
|
413
426
|
if (this.isTestManagementTestsEnabled) {
|
|
@@ -425,6 +438,9 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
425
438
|
// If it is, we'll set the failedAllTests flag to true if all the tests failed
|
|
426
439
|
// If all tests passed, we'll set the attemptToFixPassed flag to true
|
|
427
440
|
if (testStatuses.length === testManagementAttemptToFixRetries + 1) {
|
|
441
|
+
if (testStatuses.some(status => status === 'fail')) {
|
|
442
|
+
attemptToFixFailed = true
|
|
443
|
+
}
|
|
428
444
|
if (testStatuses.every(status => status === 'fail')) {
|
|
429
445
|
failedAllTests = true
|
|
430
446
|
} else if (testStatuses.every(status => status === 'pass')) {
|
|
@@ -456,16 +472,15 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
456
472
|
const willBeRetried = numRetries > 0 && numTestExecutions - 1 < numRetries
|
|
457
473
|
const mightHitBreakpoint = this.isDiEnabled && numTestExecutions >= 2
|
|
458
474
|
|
|
459
|
-
const
|
|
475
|
+
const ctx = testContexts.get(event.test)
|
|
460
476
|
|
|
461
477
|
if (status === 'fail') {
|
|
462
478
|
const shouldSetProbe = this.isDiEnabled && willBeRetried && numTestExecutions === 1
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
})
|
|
479
|
+
testErrCh.publish({
|
|
480
|
+
...ctx.currentStore,
|
|
481
|
+
error: formatJestError(event.test.errors[0]),
|
|
482
|
+
shouldSetProbe,
|
|
483
|
+
promises
|
|
469
484
|
})
|
|
470
485
|
}
|
|
471
486
|
|
|
@@ -484,14 +499,14 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
484
499
|
isAtrRetry = true
|
|
485
500
|
}
|
|
486
501
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
502
|
+
testFinishCh.publish({
|
|
503
|
+
...ctx.currentStore,
|
|
504
|
+
status,
|
|
505
|
+
testStartLine: getTestLineStart(event.test.asyncError, this.testSuite),
|
|
506
|
+
attemptToFixPassed,
|
|
507
|
+
failedAllTests,
|
|
508
|
+
attemptToFixFailed,
|
|
509
|
+
isAtrRetry
|
|
495
510
|
})
|
|
496
511
|
|
|
497
512
|
if (promises.isProbeReady) {
|
|
@@ -620,7 +635,7 @@ addHook({
|
|
|
620
635
|
})
|
|
621
636
|
|
|
622
637
|
function cliWrapper (cli, jestVersion) {
|
|
623
|
-
|
|
638
|
+
shimmer.wrap(cli, 'runCLI', runCLI => async function () {
|
|
624
639
|
let onDone
|
|
625
640
|
const configurationPromise = new Promise((resolve) => {
|
|
626
641
|
onDone = resolve
|
|
@@ -859,8 +874,6 @@ function cliWrapper (cli, jestVersion) {
|
|
|
859
874
|
return result
|
|
860
875
|
})
|
|
861
876
|
|
|
862
|
-
cli.runCLI = wrapped.runCLI
|
|
863
|
-
|
|
864
877
|
return cli
|
|
865
878
|
}
|
|
866
879
|
|
|
@@ -7,6 +7,8 @@ const {
|
|
|
7
7
|
} = require('./helpers/instrument')
|
|
8
8
|
const shimmer = require('../../datadog-shimmer')
|
|
9
9
|
|
|
10
|
+
const log = require('../../dd-trace/src/log')
|
|
11
|
+
|
|
10
12
|
const producerStartCh = channel('apm:kafkajs:produce:start')
|
|
11
13
|
const producerCommitCh = channel('apm:kafkajs:produce:commit')
|
|
12
14
|
const producerFinishCh = channel('apm:kafkajs:produce:finish')
|
|
@@ -21,6 +23,8 @@ const batchConsumerStartCh = channel('apm:kafkajs:consume-batch:start')
|
|
|
21
23
|
const batchConsumerFinishCh = channel('apm:kafkajs:consume-batch:finish')
|
|
22
24
|
const batchConsumerErrorCh = channel('apm:kafkajs:consume-batch:error')
|
|
23
25
|
|
|
26
|
+
const disabledHeaderWeakSet = new WeakSet()
|
|
27
|
+
|
|
24
28
|
function commitsFromEvent (event) {
|
|
25
29
|
const { payload: { groupId, topics } } = event
|
|
26
30
|
const commitList = []
|
|
@@ -65,15 +69,14 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
65
69
|
|
|
66
70
|
try {
|
|
67
71
|
const { topic, messages = [] } = arguments[0]
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
producerStartCh.publish({
|
|
73
|
+
topic,
|
|
74
|
+
messages,
|
|
75
|
+
bootstrapServers,
|
|
76
|
+
clusterId,
|
|
77
|
+
disableHeaderInjection: disabledHeaderWeakSet.has(producer)
|
|
78
|
+
})
|
|
75
79
|
const result = send.apply(this, arguments)
|
|
76
|
-
|
|
77
80
|
result.then(
|
|
78
81
|
innerAsyncResource.bind(res => {
|
|
79
82
|
producerFinishCh.publish(undefined)
|
|
@@ -81,6 +84,16 @@ addHook({ name: 'kafkajs', file: 'src/index.js', versions: ['>=1.4'] }, (BaseKaf
|
|
|
81
84
|
}),
|
|
82
85
|
innerAsyncResource.bind(err => {
|
|
83
86
|
if (err) {
|
|
87
|
+
// Fixes bug where we would inject message headers for kafka brokers that don't support headers
|
|
88
|
+
// (version <0.11). On the error, we disable header injection.
|
|
89
|
+
// Tnfortunately the error name / type is not more specific.
|
|
90
|
+
// This approach is implemented by other tracers as well.
|
|
91
|
+
if (err.name === 'KafkaJSProtocolError' && err.type === 'UNKNOWN') {
|
|
92
|
+
disabledHeaderWeakSet.add(producer)
|
|
93
|
+
log.error('Kafka Broker responded with UNKNOWN_SERVER_ERROR (-1). ' +
|
|
94
|
+
'Please look at broker logs for more information. ' +
|
|
95
|
+
'Tracer message header injection for Kafka is disabled.')
|
|
96
|
+
}
|
|
84
97
|
producerErrorCh.publish(err)
|
|
85
98
|
}
|
|
86
99
|
producerFinishCh.publish(undefined)
|