dd-trace 5.106.0 → 5.107.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/index.d.ts +20 -1
- package/package.json +5 -7
- package/packages/datadog-core/src/storage.js +47 -48
- package/packages/datadog-esbuild/index.js +6 -1
- package/packages/datadog-instrumentations/src/ai.js +12 -3
- package/packages/datadog-instrumentations/src/body-parser.js +5 -2
- package/packages/datadog-instrumentations/src/connect.js +3 -2
- package/packages/datadog-instrumentations/src/cookie-parser.js +3 -2
- package/packages/datadog-instrumentations/src/cucumber.js +7 -0
- package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +7 -5
- package/packages/datadog-instrumentations/src/express-session.js +12 -11
- package/packages/datadog-instrumentations/src/express.js +24 -20
- package/packages/datadog-instrumentations/src/fastify.js +18 -6
- package/packages/datadog-instrumentations/src/helpers/openai-ai-guard.js +27 -12
- package/packages/datadog-instrumentations/src/http/client.js +9 -12
- package/packages/datadog-instrumentations/src/http/server.js +30 -16
- package/packages/datadog-instrumentations/src/http2/client.js +15 -12
- package/packages/datadog-instrumentations/src/http2/server.js +15 -8
- package/packages/datadog-instrumentations/src/jest/bail-reporter.js +42 -0
- package/packages/datadog-instrumentations/src/jest.js +143 -73
- package/packages/datadog-instrumentations/src/mocha/main.js +43 -8
- package/packages/datadog-instrumentations/src/mocha/utils.js +128 -17
- package/packages/datadog-instrumentations/src/multer.js +3 -2
- package/packages/datadog-instrumentations/src/mysql2.js +34 -0
- package/packages/datadog-instrumentations/src/net.js +8 -6
- package/packages/datadog-instrumentations/src/openai.js +19 -7
- package/packages/datadog-instrumentations/src/pg.js +19 -0
- package/packages/datadog-instrumentations/src/router.js +12 -10
- package/packages/datadog-instrumentations/src/vitest.js +29 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +0 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +62 -11
- package/packages/datadog-plugin-cucumber/src/index.js +2 -0
- package/packages/datadog-plugin-cypress/src/support.js +31 -1
- package/packages/datadog-plugin-http/src/client.js +0 -3
- package/packages/datadog-plugin-http/src/server.js +11 -1
- package/packages/datadog-plugin-mocha/src/index.js +2 -0
- package/packages/datadog-plugin-pg/src/index.js +10 -0
- package/packages/dd-trace/src/aiguard/index.js +34 -15
- package/packages/dd-trace/src/aiguard/sdk.js +34 -3
- package/packages/dd-trace/src/aiguard/tags.js +6 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -1
- package/packages/dd-trace/src/config/defaults.js +14 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +1 -1
- package/packages/dd-trace/src/config/helper.js +1 -0
- package/packages/dd-trace/src/config/index.js +5 -9
- package/packages/dd-trace/src/config/parsers.js +8 -0
- package/packages/dd-trace/src/config/supported-configurations.json +13 -6
- package/packages/dd-trace/src/crashtracking/crashtracker.js +2 -2
- package/packages/dd-trace/src/datastreams/writer.js +1 -2
- package/packages/dd-trace/src/debugger/config.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/config.js +3 -2
- package/packages/dd-trace/src/debugger/index.js +1 -2
- package/packages/dd-trace/src/dogstatsd.js +2 -3
- package/packages/dd-trace/src/encode/0.4.js +49 -41
- package/packages/dd-trace/src/encode/agentless-json.js +5 -1
- package/packages/dd-trace/src/encode/tags-processors.js +14 -0
- package/packages/dd-trace/src/exporters/agent/index.js +1 -2
- package/packages/dd-trace/src/exporters/agentless/index.js +6 -10
- package/packages/dd-trace/src/exporters/common/buffering-exporter.js +1 -2
- package/packages/dd-trace/src/exporters/common/request.js +26 -0
- package/packages/dd-trace/src/exporters/span-stats/index.js +1 -2
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +4 -0
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +45 -0
- package/packages/dd-trace/src/llmobs/sdk.js +4 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +17 -1
- package/packages/dd-trace/src/llmobs/tagger.js +5 -3
- package/packages/dd-trace/src/llmobs/util.js +54 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +1 -2
- package/packages/dd-trace/src/llmobs/writers/util.js +1 -2
- package/packages/dd-trace/src/openfeature/writers/base.js +1 -10
- package/packages/dd-trace/src/openfeature/writers/util.js +1 -2
- package/packages/dd-trace/src/opentelemetry/metrics/instruments.js +26 -13
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +7 -10
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +92 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +3 -2
- package/packages/dd-trace/src/opentracing/span.js +23 -18
- package/packages/dd-trace/src/opentracing/tracer.js +16 -12
- package/packages/dd-trace/src/plugins/ci_plugin.js +131 -46
- package/packages/dd-trace/src/priority_sampler.js +6 -5
- package/packages/dd-trace/src/profiling/config.js +1 -2
- package/packages/dd-trace/src/proxy.js +13 -10
- package/packages/dd-trace/src/remote_config/index.js +1 -2
- package/packages/dd-trace/src/runtime_metrics/client.js +30 -0
- package/packages/dd-trace/src/runtime_metrics/index.js +12 -2
- package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +284 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +2 -11
- package/packages/dd-trace/src/service-naming/source-resolver.js +5 -1
- package/packages/dd-trace/src/span_format.js +33 -25
- package/packages/dd-trace/src/span_stats.js +1 -1
- package/packages/dd-trace/src/startup-log.js +1 -2
- package/packages/dd-trace/src/telemetry/send-data.js +1 -1
- package/packages/dd-trace/src/tracer.js +1 -1
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +2 -2
- package/vendor/dist/shell-quote/index.js +1 -1
- package/packages/dd-trace/src/agent/url.js +0 -28
- package/scripts/preinstall.js +0 -34
|
@@ -15,8 +15,8 @@ const aiguardChannel = dc.channel('dd-trace:ai:aiguard')
|
|
|
15
15
|
* @typedef {object} ResourceHandler
|
|
16
16
|
* @property {(callArgs: object) => (Array<object>|undefined)} getInputMessages
|
|
17
17
|
* @property {(body: object) => Array<object>} getOutputMessages
|
|
18
|
-
* @property {(inputMessages: Array<object>, outputMessages: Array<object
|
|
19
|
-
* publishOutputEvaluation
|
|
18
|
+
* @property {(inputMessages: Array<object>, outputMessages: Array<object>, parentSpan?: object)
|
|
19
|
+
* => Promise<unknown>} publishOutputEvaluation
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -24,17 +24,29 @@ const aiguardChannel = dc.channel('dd-trace:ai:aiguard')
|
|
|
24
24
|
* @property {ResourceHandler} handler
|
|
25
25
|
* @property {Array<object>} inputMessages
|
|
26
26
|
* @property {() => Promise<void>} getInputEval
|
|
27
|
+
* @property {object} [parentSpan] - LLM span (`openai.request`) to nest `ai_guard` spans under.
|
|
28
|
+
* Set by the instrumentation once the LLM span is active.
|
|
27
29
|
*/
|
|
28
30
|
|
|
29
31
|
/**
|
|
30
32
|
* Publishes already-converted AI-style messages to the AI Guard evaluation channel.
|
|
31
33
|
*
|
|
34
|
+
* Subscribers push async work into `pending` and abort `abortController` to block.
|
|
35
|
+
*
|
|
32
36
|
* @param {Array<object>} messages - AI-style messages to evaluate.
|
|
37
|
+
* @param {object} [parentSpan] - LLM span to use as the `ai_guard` span's parent.
|
|
33
38
|
* @returns {Promise<void>}
|
|
34
39
|
*/
|
|
35
|
-
function publishEvaluation (messages) {
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
function publishEvaluation (messages, parentSpan) {
|
|
41
|
+
const abortController = new AbortController()
|
|
42
|
+
const ctx = { messages, integration: 'openai', parentSpan, abortController, pending: [] }
|
|
43
|
+
|
|
44
|
+
aiguardChannel.publish(ctx)
|
|
45
|
+
|
|
46
|
+
return Promise.all(ctx.pending).then(() => {
|
|
47
|
+
if (abortController.signal.aborted) {
|
|
48
|
+
throw abortController.signal.reason
|
|
49
|
+
}
|
|
38
50
|
})
|
|
39
51
|
}
|
|
40
52
|
|
|
@@ -84,12 +96,13 @@ function getChatCompletionsOutputMessages (body) {
|
|
|
84
96
|
*
|
|
85
97
|
* @param {Array<object>} inputMessages
|
|
86
98
|
* @param {Array<object>} outputMessages - One entry per choice
|
|
99
|
+
* @param {object} [parentSpan]
|
|
87
100
|
* @returns {Promise<Array<void>>}
|
|
88
101
|
*/
|
|
89
|
-
function publishChatCompletionsOutputEvaluation (inputMessages, outputMessages) {
|
|
102
|
+
function publishChatCompletionsOutputEvaluation (inputMessages, outputMessages, parentSpan) {
|
|
90
103
|
const evals = []
|
|
91
104
|
for (const message of outputMessages) {
|
|
92
|
-
evals.push(publishEvaluation([...inputMessages, message]))
|
|
105
|
+
evals.push(publishEvaluation([...inputMessages, message], parentSpan))
|
|
93
106
|
}
|
|
94
107
|
return Promise.all(evals)
|
|
95
108
|
}
|
|
@@ -157,10 +170,11 @@ function getResponsesOutputMessages (body) {
|
|
|
157
170
|
*
|
|
158
171
|
* @param {Array<object>} inputMessages
|
|
159
172
|
* @param {Array<object>} outputMessages
|
|
173
|
+
* @param {object} [parentSpan]
|
|
160
174
|
* @returns {Promise<void>}
|
|
161
175
|
*/
|
|
162
|
-
function publishResponsesOutputEvaluation (inputMessages, outputMessages) {
|
|
163
|
-
return publishEvaluation([...inputMessages, ...outputMessages])
|
|
176
|
+
function publishResponsesOutputEvaluation (inputMessages, outputMessages, parentSpan) {
|
|
177
|
+
return publishEvaluation([...inputMessages, ...outputMessages], parentSpan)
|
|
164
178
|
}
|
|
165
179
|
|
|
166
180
|
/**
|
|
@@ -215,8 +229,9 @@ function createGuard (baseResource, callArgs, stream) {
|
|
|
215
229
|
if (!inputMessages) return null
|
|
216
230
|
|
|
217
231
|
let inputEvalPromise
|
|
218
|
-
const
|
|
219
|
-
|
|
232
|
+
const guard = { handler, inputMessages, parentSpan: undefined }
|
|
233
|
+
guard.getInputEval = () => (inputEvalPromise ??= publishEvaluation(inputMessages, guard.parentSpan))
|
|
234
|
+
return guard
|
|
220
235
|
}
|
|
221
236
|
|
|
222
237
|
/**
|
|
@@ -257,7 +272,7 @@ function gateParse (parsedPromise, guard) {
|
|
|
257
272
|
function evaluateOutput (guard, body) {
|
|
258
273
|
const outputMessages = guard.handler.getOutputMessages(body)
|
|
259
274
|
if (!outputMessages.length) return Promise.resolve()
|
|
260
|
-
return guard.handler.publishOutputEvaluation(guard.inputMessages, outputMessages)
|
|
275
|
+
return guard.handler.publishOutputEvaluation(guard.inputMessages, outputMessages, guard.parentSpan)
|
|
261
276
|
}
|
|
262
277
|
|
|
263
278
|
module.exports = {
|
|
@@ -219,7 +219,9 @@ function patch (http, methodName) {
|
|
|
219
219
|
return setTimeout.apply(this, args)
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
req.emit = function (
|
|
222
|
+
req.emit = function (...args) {
|
|
223
|
+
const eventName = args[0]
|
|
224
|
+
const arg = args[1]
|
|
223
225
|
switch (eventName) {
|
|
224
226
|
case 'response': {
|
|
225
227
|
const res = arg
|
|
@@ -233,7 +235,7 @@ function patch (http, methodName) {
|
|
|
233
235
|
break
|
|
234
236
|
}
|
|
235
237
|
|
|
236
|
-
const result =
|
|
238
|
+
const result = Reflect.apply(emit, this, args)
|
|
237
239
|
|
|
238
240
|
instrumentation.finalizeIfNeeded()
|
|
239
241
|
|
|
@@ -254,7 +256,7 @@ function patch (http, methodName) {
|
|
|
254
256
|
finish()
|
|
255
257
|
}
|
|
256
258
|
|
|
257
|
-
return
|
|
259
|
+
return Reflect.apply(emit, this, args)
|
|
258
260
|
}
|
|
259
261
|
|
|
260
262
|
if (abortController.signal.aborted) {
|
|
@@ -292,17 +294,12 @@ function patch (http, methodName) {
|
|
|
292
294
|
|
|
293
295
|
function normalizeOptions (inputURL) {
|
|
294
296
|
if (typeof inputURL === 'string') {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
// eslint-disable-next-line n/no-deprecated-api
|
|
299
|
-
return url.parse(inputURL)
|
|
300
|
-
}
|
|
301
|
-
} else if (inputURL instanceof url.URL) {
|
|
297
|
+
return urlToOptions(new url.URL(inputURL))
|
|
298
|
+
}
|
|
299
|
+
if (inputURL instanceof url.URL) {
|
|
302
300
|
return urlToOptions(inputURL)
|
|
303
|
-
} else {
|
|
304
|
-
return inputURL
|
|
305
301
|
}
|
|
302
|
+
return inputURL
|
|
306
303
|
}
|
|
307
304
|
|
|
308
305
|
function urlToOptions (url) {
|
|
@@ -37,28 +37,35 @@ addHook({ name: 'https' }, http => {
|
|
|
37
37
|
return http
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
function wrapResponseEmit (
|
|
41
|
-
|
|
40
|
+
function wrapResponseEmit (originalEmit) {
|
|
41
|
+
// Named `emit` mirrors the response method so the one-time prototype wrap
|
|
42
|
+
// skips its name rewrite; rest params keep the per-event forwarding
|
|
43
|
+
// allocation-free.
|
|
44
|
+
return function emit (...args) {
|
|
42
45
|
if (!finishServerCh.hasSubscribers) {
|
|
43
|
-
return
|
|
46
|
+
return Reflect.apply(originalEmit, this, args)
|
|
44
47
|
}
|
|
45
48
|
|
|
49
|
+
const eventName = args[0]
|
|
46
50
|
if ((eventName === 'finish' || eventName === 'close') && !requestFinishedSet.has(this)) {
|
|
47
51
|
finishServerCh.publish({ req: this.req })
|
|
48
52
|
requestFinishedSet.add(this)
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
return
|
|
55
|
+
return Reflect.apply(originalEmit, this, args)
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
function wrapEmit (
|
|
56
|
-
return function (
|
|
59
|
+
function wrapEmit (originalEmit) {
|
|
60
|
+
return function emit (...args) {
|
|
57
61
|
if (!startServerCh.hasSubscribers) {
|
|
58
|
-
return
|
|
62
|
+
return Reflect.apply(originalEmit, this, args)
|
|
59
63
|
}
|
|
60
64
|
|
|
65
|
+
const eventName = args[0]
|
|
61
66
|
if (eventName === 'request') {
|
|
67
|
+
const req = args[1]
|
|
68
|
+
const res = args[2]
|
|
62
69
|
res.req = req
|
|
63
70
|
|
|
64
71
|
const abortController = new AbortController()
|
|
@@ -75,7 +82,7 @@ function wrapEmit (emit) {
|
|
|
75
82
|
return this.listenerCount(eventName) > 0
|
|
76
83
|
}
|
|
77
84
|
|
|
78
|
-
return
|
|
85
|
+
return Reflect.apply(originalEmit, this, args)
|
|
79
86
|
} catch (err) {
|
|
80
87
|
errorServerCh.publish(err)
|
|
81
88
|
|
|
@@ -84,16 +91,23 @@ function wrapEmit (emit) {
|
|
|
84
91
|
exitServerCh.publish(ctx)
|
|
85
92
|
}
|
|
86
93
|
}
|
|
87
|
-
return
|
|
94
|
+
return Reflect.apply(originalEmit, this, args)
|
|
88
95
|
}
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
function wrapWriteHead (writeHead) {
|
|
92
|
-
|
|
99
|
+
// Rest params + Reflect.apply instead of named formals + `arguments`: naming
|
|
100
|
+
// params while reading `arguments` makes V8 materialise the mapped arguments
|
|
101
|
+
// object on every call, including the no-subscriber fast path.
|
|
102
|
+
return function wrappedWriteHead (...args) {
|
|
93
103
|
if (!startWriteHeadCh.hasSubscribers) {
|
|
94
|
-
return
|
|
104
|
+
return Reflect.apply(writeHead, this, args)
|
|
95
105
|
}
|
|
96
106
|
|
|
107
|
+
const statusCode = args[0]
|
|
108
|
+
const reason = args[1]
|
|
109
|
+
let obj = args[2]
|
|
110
|
+
|
|
97
111
|
const abortController = new AbortController()
|
|
98
112
|
|
|
99
113
|
if (typeof reason !== 'string') {
|
|
@@ -126,7 +140,7 @@ function wrapWriteHead (writeHead) {
|
|
|
126
140
|
return this
|
|
127
141
|
}
|
|
128
142
|
|
|
129
|
-
return
|
|
143
|
+
return Reflect.apply(writeHead, this, args)
|
|
130
144
|
}
|
|
131
145
|
}
|
|
132
146
|
|
|
@@ -157,9 +171,9 @@ function wrapWrite (write) {
|
|
|
157
171
|
}
|
|
158
172
|
|
|
159
173
|
function wrapSetHeader (setHeader) {
|
|
160
|
-
return function wrappedSetHeader (
|
|
174
|
+
return function wrappedSetHeader (...args) {
|
|
161
175
|
if (!startSetHeaderCh.hasSubscribers && !finishSetHeaderCh.hasSubscribers) {
|
|
162
|
-
return
|
|
176
|
+
return Reflect.apply(setHeader, this, args)
|
|
163
177
|
}
|
|
164
178
|
|
|
165
179
|
if (startSetHeaderCh.hasSubscribers) {
|
|
@@ -171,10 +185,10 @@ function wrapSetHeader (setHeader) {
|
|
|
171
185
|
}
|
|
172
186
|
}
|
|
173
187
|
|
|
174
|
-
const setHeaderResult =
|
|
188
|
+
const setHeaderResult = Reflect.apply(setHeader, this, args)
|
|
175
189
|
|
|
176
190
|
if (finishSetHeaderCh.hasSubscribers) {
|
|
177
|
-
finishSetHeaderCh.publish({ name, value, res: this })
|
|
191
|
+
finishSetHeaderCh.publish({ name: args[0], value: args[1], res: this })
|
|
178
192
|
}
|
|
179
193
|
|
|
180
194
|
return setHeaderResult
|
|
@@ -11,14 +11,16 @@ const asyncEndChannel = channel('apm:http2:client:request:asyncEnd')
|
|
|
11
11
|
const errorChannel = channel('apm:http2:client:request:error')
|
|
12
12
|
|
|
13
13
|
function createWrapEmit (ctx) {
|
|
14
|
-
return function wrapEmit (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
return function wrapEmit (originalEmit) {
|
|
15
|
+
// Named `emit`/arity-1 mirrors the request method so the per-request wrap
|
|
16
|
+
// skips its name/length rewrite.
|
|
17
|
+
return function emit (eventName) {
|
|
18
|
+
ctx.eventName = eventName
|
|
19
|
+
ctx.eventData = arguments[1]
|
|
18
20
|
|
|
19
21
|
return asyncStartChannel.runStores(ctx, () => {
|
|
20
22
|
try {
|
|
21
|
-
return
|
|
23
|
+
return Reflect.apply(originalEmit, this, arguments)
|
|
22
24
|
} finally {
|
|
23
25
|
asyncEndChannel.publish(ctx)
|
|
24
26
|
}
|
|
@@ -29,14 +31,14 @@ function createWrapEmit (ctx) {
|
|
|
29
31
|
|
|
30
32
|
function createWrapRequest (authority, options) {
|
|
31
33
|
return function wrapRequest (request) {
|
|
32
|
-
return function (
|
|
33
|
-
if (!startChannel.hasSubscribers) return
|
|
34
|
+
return function (...args) {
|
|
35
|
+
if (!startChannel.hasSubscribers) return Reflect.apply(request, this, args)
|
|
34
36
|
|
|
35
|
-
const ctx = { headers, authority, options }
|
|
37
|
+
const ctx = { headers: args[0], authority, options }
|
|
36
38
|
|
|
37
39
|
return startChannel.runStores(ctx, () => {
|
|
38
40
|
try {
|
|
39
|
-
const req =
|
|
41
|
+
const req = Reflect.apply(request, this, args)
|
|
40
42
|
|
|
41
43
|
shimmer.wrap(req, 'emit', createWrapEmit(ctx))
|
|
42
44
|
|
|
@@ -54,13 +56,14 @@ function createWrapRequest (authority, options) {
|
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
function wrapConnect (connect) {
|
|
57
|
-
return function (
|
|
59
|
+
return function (...args) {
|
|
60
|
+
const authority = args[0]
|
|
58
61
|
if (connectChannel.hasSubscribers) {
|
|
59
62
|
connectChannel.publish({ authority })
|
|
60
63
|
}
|
|
61
|
-
const session =
|
|
64
|
+
const session = Reflect.apply(connect, this, args)
|
|
62
65
|
|
|
63
|
-
shimmer.wrap(session, 'request', createWrapRequest(authority,
|
|
66
|
+
shimmer.wrap(session, 'request', createWrapRequest(authority, args[1]))
|
|
64
67
|
|
|
65
68
|
return session
|
|
66
69
|
}
|
|
@@ -26,21 +26,28 @@ function wrapCreateServer (createServer) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function wrapResponseEmit (
|
|
30
|
-
|
|
29
|
+
function wrapResponseEmit (originalEmit, ctx) {
|
|
30
|
+
// Named `emit`/arity-1 mirrors the response method so the per-response wrap
|
|
31
|
+
// skips its name/length rewrite.
|
|
32
|
+
return function emit (eventName) {
|
|
31
33
|
ctx.req = this.req
|
|
32
34
|
ctx.eventName = eventName
|
|
33
|
-
return emitCh.runStores(ctx,
|
|
35
|
+
return emitCh.runStores(ctx, originalEmit, this, ...arguments)
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
function wrapEmit (
|
|
38
|
-
|
|
39
|
+
function wrapEmit (originalEmit) {
|
|
40
|
+
// Named `emit` mirrors the server method so the one-time wrap skips its name
|
|
41
|
+
// rewrite; rest params keep the per-event forwarding allocation-free.
|
|
42
|
+
return function emit (...args) {
|
|
39
43
|
if (!startServerCh.hasSubscribers) {
|
|
40
|
-
return
|
|
44
|
+
return Reflect.apply(originalEmit, this, args)
|
|
41
45
|
}
|
|
42
46
|
|
|
47
|
+
const eventName = args[0]
|
|
43
48
|
if (eventName === 'request') {
|
|
49
|
+
const req = args[1]
|
|
50
|
+
const res = args[2]
|
|
44
51
|
res.req = req
|
|
45
52
|
|
|
46
53
|
const ctx = { req, res }
|
|
@@ -48,7 +55,7 @@ function wrapEmit (emit) {
|
|
|
48
55
|
shimmer.wrap(res, 'emit', emit => wrapResponseEmit(emit, ctx))
|
|
49
56
|
|
|
50
57
|
try {
|
|
51
|
-
return
|
|
58
|
+
return Reflect.apply(originalEmit, this, args)
|
|
52
59
|
} catch (error) {
|
|
53
60
|
ctx.error = error
|
|
54
61
|
errorServerCh.publish(ctx)
|
|
@@ -57,6 +64,6 @@ function wrapEmit (emit) {
|
|
|
57
64
|
}
|
|
58
65
|
})
|
|
59
66
|
}
|
|
60
|
-
return
|
|
67
|
+
return Reflect.apply(originalEmit, this, args)
|
|
61
68
|
}
|
|
62
69
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const JEST_SESSION_STATE = Symbol.for('dd-trace:jest:session')
|
|
4
|
+
|
|
5
|
+
class DatadogJestBailReporter {
|
|
6
|
+
/**
|
|
7
|
+
* @param {{ bail?: number, collectCoverage?: boolean, coverage?: boolean }} globalConfig
|
|
8
|
+
*/
|
|
9
|
+
constructor (globalConfig) {
|
|
10
|
+
this.globalConfig = globalConfig
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {Set<object>} _testContexts
|
|
15
|
+
* @param {{ numFailedTests?: number, numFailedTestSuites?: number, numRuntimeErrorTestSuites?: number }} results
|
|
16
|
+
* @returns {Promise<void> | void}
|
|
17
|
+
*/
|
|
18
|
+
onRunComplete (_testContexts, results) {
|
|
19
|
+
const numBailFailures = getNumBailFailures(results)
|
|
20
|
+
if (
|
|
21
|
+
!this.globalConfig.bail ||
|
|
22
|
+
this.globalConfig.collectCoverage ||
|
|
23
|
+
this.globalConfig.coverage ||
|
|
24
|
+
numBailFailures < this.globalConfig.bail
|
|
25
|
+
) {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return globalThis[JEST_SESSION_STATE]?.finishBailTestSession?.(results)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function getNumBailFailures (results) {
|
|
34
|
+
const numFailedTests = results?.numFailedTests || 0
|
|
35
|
+
const numFailedSuites = results?.numRuntimeErrorTestSuites === undefined
|
|
36
|
+
? (numFailedTests === 0 ? results?.numFailedTestSuites || 0 : 0)
|
|
37
|
+
: results.numRuntimeErrorTestSuites
|
|
38
|
+
|
|
39
|
+
return numFailedTests + numFailedSuites
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = DatadogJestBailReporter
|