dd-trace 6.9.0 → 6.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/ci/vitest-no-worker-init-setup.mjs +112 -10
- package/index.d.ts +42 -0
- package/package.json +4 -3
- package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +111 -6
- package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +629 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +81 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +83 -1
- package/packages/datadog-instrumentations/src/jest.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -8
- package/packages/datadog-instrumentations/src/mysql.js +45 -15
- package/packages/datadog-instrumentations/src/mysql2.js +119 -18
- package/packages/datadog-instrumentations/src/path-to-regexp.js +67 -1
- package/packages/datadog-instrumentations/src/pg.js +116 -92
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +43 -4
- package/packages/datadog-instrumentations/src/vitest-main.js +169 -17
- package/packages/datadog-instrumentations/src/vitest-util.js +64 -5
- package/packages/datadog-instrumentations/src/vitest-worker.js +150 -25
- package/packages/datadog-instrumentations/src/webdriverio.js +31 -17
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +12 -6
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -5
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -5
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +31 -17
- package/packages/datadog-plugin-jest/src/index.js +5 -4
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +2 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -2
- package/packages/datadog-plugin-kafkajs/src/utils.js +65 -7
- package/packages/datadog-plugin-mocha/src/index.js +550 -39
- package/packages/datadog-plugin-mysql/src/index.js +37 -0
- package/packages/datadog-plugin-next/src/index.js +1 -19
- package/packages/datadog-plugin-openai-agents/src/integration.js +278 -69
- package/packages/datadog-plugin-openai-agents/src/processor.js +16 -4
- package/packages/datadog-plugin-pg/src/index.js +1 -0
- package/packages/datadog-plugin-vitest/src/index.js +8 -20
- package/packages/datadog-plugin-ws/src/util.js +2 -1
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +453 -0
- package/packages/dd-trace/src/appsec/handlers/http-request.js +13 -0
- package/packages/dd-trace/src/carrier.js +356 -0
- package/packages/dd-trace/src/config/generated-config-types.d.ts +3 -0
- package/packages/dd-trace/src/config/supported-configurations.json +10 -0
- package/packages/dd-trace/src/datastreams/context.js +6 -1
- package/packages/dd-trace/src/datastreams/manager.js +5 -1
- package/packages/dd-trace/src/datastreams/pathway.js +23 -22
- package/packages/dd-trace/src/datastreams/processor.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +5 -0
- package/packages/dd-trace/src/llmobs/index.js +34 -2
- package/packages/dd-trace/src/llmobs/span_processor.js +16 -0
- package/packages/dd-trace/src/llmobs/tagger.js +96 -0
- package/packages/dd-trace/src/llmobs/util.js +78 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +126 -120
- package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +4 -8
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/{datadog-plugin-jest/src/util.js → dd-trace/src/plugins/util/jest.js} +1 -62
- package/packages/dd-trace/src/plugins/util/test.js +84 -5
- package/packages/dd-trace/src/plugins/util/web.js +53 -2
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { errorMonitor } = require('node:events')
|
|
4
|
+
const { performance } = require('node:perf_hooks')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('node:diagnostics_channel').Channel} Channel
|
|
8
|
+
* @typedef {{ length: number, [index: number]: unknown } & Iterable<unknown>} ArgumentsLike
|
|
9
|
+
* @typedef {{
|
|
10
|
+
* acquired?: boolean,
|
|
11
|
+
* callback?: Function,
|
|
12
|
+
* conf?: Record<string, unknown>,
|
|
13
|
+
* errorReported?: boolean,
|
|
14
|
+
* key?: object,
|
|
15
|
+
* observesError?: boolean,
|
|
16
|
+
* start?: number
|
|
17
|
+
* }} ClusterAcquire
|
|
18
|
+
* @typedef {{ _freeConnections?: { length: number } }} Pool
|
|
19
|
+
* @typedef {{ deferred: boolean }} PoolWaitTransfer
|
|
20
|
+
* @typedef {{ transfer: PoolWaitTransfer, waitTime: number }} DeferredPoolWait
|
|
21
|
+
* @typedef {{ pending: boolean, pool: object }} DeferredPoolQueryAcquire
|
|
22
|
+
* @typedef {{
|
|
23
|
+
* connectionFinishCh: Channel,
|
|
24
|
+
* acquireStartCh: Channel,
|
|
25
|
+
* acquireFinishCh: Channel
|
|
26
|
+
* }} AcquireErrorChannels
|
|
27
|
+
* @typedef {{
|
|
28
|
+
* connectionStartCh: Channel,
|
|
29
|
+
* connectionFinishCh: Channel,
|
|
30
|
+
* acquireStartCh: Channel,
|
|
31
|
+
* acquireFinishCh: Channel,
|
|
32
|
+
* reentersQueuedCallbacks?: boolean
|
|
33
|
+
* }} AcquireChannels
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
const poolQueryAcquire = {}
|
|
37
|
+
|
|
38
|
+
/** @type {ClusterAcquire | typeof poolQueryAcquire | undefined} */
|
|
39
|
+
let currentPoolQueryAcquire
|
|
40
|
+
|
|
41
|
+
/** @type {import('node:async_hooks').AsyncLocalStorage<DeferredPoolQueryAcquire>|undefined} */
|
|
42
|
+
let deferredPoolQueryAcquireStorage
|
|
43
|
+
|
|
44
|
+
/** @type {WeakMap<object, ClusterAcquire>} */
|
|
45
|
+
const deferredClusterAcquires = new WeakMap()
|
|
46
|
+
|
|
47
|
+
// Keep synchronous wait handoff allocation-free; a delayed consumer promotes only its pool wrapper.
|
|
48
|
+
const poolWaitConnections = []
|
|
49
|
+
const poolWaitTimes = []
|
|
50
|
+
|
|
51
|
+
/** @type {WeakMap<object, DeferredPoolWait>} */
|
|
52
|
+
const deferredPoolWaitTimes = new WeakMap()
|
|
53
|
+
let deferredPoolWaitCount = 0
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {Function} method
|
|
57
|
+
* @param {Channel} connectionStartCh
|
|
58
|
+
* @param {boolean} [deferred]
|
|
59
|
+
* @returns {Function}
|
|
60
|
+
*/
|
|
61
|
+
function wrapPoolQueryMethod (method, connectionStartCh, deferred) {
|
|
62
|
+
if (deferred) {
|
|
63
|
+
return function () {
|
|
64
|
+
if (!connectionStartCh.hasSubscribers) return method.apply(this, arguments)
|
|
65
|
+
|
|
66
|
+
const storage = getDeferredPoolQueryAcquireStorage()
|
|
67
|
+
return storage.run({ pending: true, pool: this }, () => method.apply(this, arguments))
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return function () {
|
|
72
|
+
if (!connectionStartCh.hasSubscribers) return method.apply(this, arguments)
|
|
73
|
+
return runWithPoolQueryAcquire(poolQueryAcquire, method, this, arguments)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {Function} method
|
|
79
|
+
* @param {Function} inactiveMethod
|
|
80
|
+
* @param {Channel} connectionStartCh
|
|
81
|
+
* @param {boolean} deferred
|
|
82
|
+
* @returns {Function}
|
|
83
|
+
*/
|
|
84
|
+
function wrapPoolAcquireCarrier (method, inactiveMethod, connectionStartCh, deferred) {
|
|
85
|
+
if (!deferred) return method
|
|
86
|
+
|
|
87
|
+
return function (callback) {
|
|
88
|
+
if (!connectionStartCh.hasSubscribers) return inactiveMethod.apply(this, arguments)
|
|
89
|
+
if (typeof callback !== 'function' || !takeDeferredPoolQueryAcquire(this)) {
|
|
90
|
+
return method.apply(this, arguments)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return runWithPoolQueryAcquire(poolQueryAcquire, method, this, arguments)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {Function} method
|
|
99
|
+
* @param {AcquireChannels} channels
|
|
100
|
+
* @returns {Function}
|
|
101
|
+
*/
|
|
102
|
+
function wrapPoolClusterQueryMethod (method, channels) {
|
|
103
|
+
return function () {
|
|
104
|
+
if (!channels.connectionStartCh.hasSubscribers) return method.apply(this, arguments)
|
|
105
|
+
|
|
106
|
+
const key = arguments[0]
|
|
107
|
+
const acquire = takeClusterAcquire(key) ?? {}
|
|
108
|
+
const result = runWithPoolQueryAcquire(acquire, method, this, arguments)
|
|
109
|
+
|
|
110
|
+
if (isWeakKey(result)) acquire.key = result
|
|
111
|
+
if (!acquire.observesError) {
|
|
112
|
+
const callback = result?._callback
|
|
113
|
+
if (typeof callback === 'function') {
|
|
114
|
+
acquire.observesError = true
|
|
115
|
+
result._callback = wrapClusterQueryCallback(callback, acquire, channels)
|
|
116
|
+
} else if (typeof result?.once === 'function') {
|
|
117
|
+
acquire.observesError = true
|
|
118
|
+
result.once(errorMonitor, error => reportClusterAcquireError(acquire, error, channels))
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return result
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @param {Function} method
|
|
127
|
+
* @param {Channel} connectionStartCh
|
|
128
|
+
* @returns {Function}
|
|
129
|
+
*/
|
|
130
|
+
function wrapPoolClusterMethod (method, connectionStartCh) {
|
|
131
|
+
return function () {
|
|
132
|
+
if (!connectionStartCh.hasSubscribers) return method.apply(this, arguments)
|
|
133
|
+
return runWithPoolQueryAcquire({}, method, this, arguments)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @param {Function} method
|
|
139
|
+
* @param {AcquireChannels} channels
|
|
140
|
+
* @returns {Function}
|
|
141
|
+
*/
|
|
142
|
+
function wrapPoolClusterGetConnection (method, channels) {
|
|
143
|
+
return function (callback) {
|
|
144
|
+
if (!channels.connectionStartCh.hasSubscribers) return method.apply(this, arguments)
|
|
145
|
+
|
|
146
|
+
const previous = currentPoolQueryAcquire
|
|
147
|
+
const acquire = isClusterAcquire(previous) && previous.key === undefined
|
|
148
|
+
? previous
|
|
149
|
+
: takeClusterAcquire(callback)
|
|
150
|
+
|
|
151
|
+
if (acquire === undefined && previous === undefined) return method.apply(this, arguments)
|
|
152
|
+
if (acquire !== undefined) {
|
|
153
|
+
if (acquire.callback === undefined) {
|
|
154
|
+
acquire.callback = wrapClusterAcquireCallback(callback, acquire, channels)
|
|
155
|
+
}
|
|
156
|
+
arguments[0] = acquire.callback
|
|
157
|
+
acquire.key = acquire.callback
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return runWithPoolQueryAcquire(acquire, method, this, arguments)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @param {Function} getConnection
|
|
166
|
+
* @param {AcquireChannels} channels
|
|
167
|
+
* @param {boolean} [deferred]
|
|
168
|
+
* @returns {Function}
|
|
169
|
+
*/
|
|
170
|
+
function wrapPoolGetConnection (getConnection, channels, deferred) {
|
|
171
|
+
const wrapped = wrapSynchronousPoolGetConnection(getConnection, channels)
|
|
172
|
+
return wrapPoolAcquireCarrier(wrapped, getConnection, channels.connectionStartCh, deferred === true)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @param {Function} getConnection
|
|
177
|
+
* @param {AcquireChannels} channels
|
|
178
|
+
* @returns {Function}
|
|
179
|
+
*/
|
|
180
|
+
function wrapSynchronousPoolGetConnection (getConnection, channels) {
|
|
181
|
+
const {
|
|
182
|
+
connectionStartCh,
|
|
183
|
+
connectionFinishCh,
|
|
184
|
+
acquireStartCh,
|
|
185
|
+
acquireFinishCh,
|
|
186
|
+
} = channels
|
|
187
|
+
const poolWaitTransfer = { deferred: false }
|
|
188
|
+
const queuedCallbacks = channels.reentersQueuedCallbacks ? new WeakSet() : undefined
|
|
189
|
+
|
|
190
|
+
return function (callback) {
|
|
191
|
+
if (!connectionStartCh.hasSubscribers || queuedCallbacks?.has(callback)) {
|
|
192
|
+
return getConnection.apply(this, arguments)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const pool = this
|
|
196
|
+
const ctx = {}
|
|
197
|
+
const acquire = currentPoolQueryAcquire
|
|
198
|
+
const acquireCtx = acquire === undefined && acquireStartCh.hasSubscribers
|
|
199
|
+
? { conf: pool.config.connectionConfig }
|
|
200
|
+
: undefined
|
|
201
|
+
const start = acquireStart(pool, acquire)
|
|
202
|
+
|
|
203
|
+
if (acquireCtx !== undefined) acquireStartCh.publish(acquireCtx)
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @param {unknown} error
|
|
207
|
+
* @param {object|undefined} connection
|
|
208
|
+
* @returns {unknown}
|
|
209
|
+
*/
|
|
210
|
+
const wrappedCallback = function (error, connection) {
|
|
211
|
+
if (acquire === undefined) {
|
|
212
|
+
if (!error && connection !== undefined) clearPoolWaitTime(connection)
|
|
213
|
+
if (acquireCtx !== undefined) {
|
|
214
|
+
acquireCtx.error = error
|
|
215
|
+
acquireCtx.poolWaitTime = acquireWait(start)
|
|
216
|
+
acquireFinishCh.publish(acquireCtx)
|
|
217
|
+
}
|
|
218
|
+
return connectionFinishCh.runStores(ctx, callback, this, ...arguments)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return runPoolQueryConnectionCallback(
|
|
222
|
+
poolWaitTransfer,
|
|
223
|
+
acquire,
|
|
224
|
+
start,
|
|
225
|
+
error,
|
|
226
|
+
connection,
|
|
227
|
+
pool,
|
|
228
|
+
channels,
|
|
229
|
+
ctx,
|
|
230
|
+
callback,
|
|
231
|
+
this,
|
|
232
|
+
arguments
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
if (queuedCallbacks !== undefined) queuedCallbacks.add(wrappedCallback)
|
|
236
|
+
arguments[0] = wrappedCallback
|
|
237
|
+
|
|
238
|
+
connectionStartCh.publish(ctx)
|
|
239
|
+
if (acquire !== undefined) {
|
|
240
|
+
return runWithPoolQueryAcquire(undefined, getConnection, pool, arguments)
|
|
241
|
+
}
|
|
242
|
+
if (acquireCtx !== undefined) {
|
|
243
|
+
return getConnectionForAcquire(getConnection, pool, arguments, acquireCtx, start, acquireFinishCh)
|
|
244
|
+
}
|
|
245
|
+
return getConnection.apply(pool, arguments)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* @param {Function} getConnection
|
|
251
|
+
* @param {object} pool
|
|
252
|
+
* @param {ArgumentsLike} args
|
|
253
|
+
* @param {Record<string, unknown>} acquireCtx
|
|
254
|
+
* @param {number|undefined} start
|
|
255
|
+
* @param {Channel} acquireFinishCh
|
|
256
|
+
* @returns {unknown}
|
|
257
|
+
*/
|
|
258
|
+
function getConnectionForAcquire (getConnection, pool, args, acquireCtx, start, acquireFinishCh) {
|
|
259
|
+
try {
|
|
260
|
+
return getConnection.apply(pool, args)
|
|
261
|
+
} catch (error) {
|
|
262
|
+
if (acquireCtx.poolWaitTime === undefined) {
|
|
263
|
+
acquireCtx.error = error
|
|
264
|
+
acquireCtx.poolWaitTime = acquireWait(start)
|
|
265
|
+
acquireFinishCh.publish(acquireCtx)
|
|
266
|
+
}
|
|
267
|
+
throw error
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* @returns {boolean}
|
|
273
|
+
*/
|
|
274
|
+
function isPoolQueryAcquire () {
|
|
275
|
+
return currentPoolQueryAcquire !== undefined
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @param {Function} method
|
|
280
|
+
* @param {object} receiver
|
|
281
|
+
* @param {ArgumentsLike} args
|
|
282
|
+
* @returns {unknown}
|
|
283
|
+
*/
|
|
284
|
+
function runOutsidePoolQueryAcquire (method, receiver, args) {
|
|
285
|
+
return runWithPoolQueryAcquire(undefined, method, receiver, args)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* @param {ClusterAcquire | typeof poolQueryAcquire | undefined} acquire
|
|
290
|
+
* @param {Function} method
|
|
291
|
+
* @param {unknown} receiver
|
|
292
|
+
* @param {ArgumentsLike} args
|
|
293
|
+
* @returns {unknown}
|
|
294
|
+
*/
|
|
295
|
+
function runWithPoolQueryAcquire (acquire, method, receiver, args) {
|
|
296
|
+
const previous = currentPoolQueryAcquire
|
|
297
|
+
currentPoolQueryAcquire = acquire
|
|
298
|
+
try {
|
|
299
|
+
return method.apply(receiver, args)
|
|
300
|
+
} finally {
|
|
301
|
+
currentPoolQueryAcquire = previous
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* @param {object} pool
|
|
307
|
+
* @returns {boolean}
|
|
308
|
+
*/
|
|
309
|
+
function takeDeferredPoolQueryAcquire (pool) {
|
|
310
|
+
const acquire = deferredPoolQueryAcquireStorage?.getStore()
|
|
311
|
+
if (acquire === undefined || acquire.pool !== pool || !acquire.pending) return false
|
|
312
|
+
|
|
313
|
+
acquire.pending = false
|
|
314
|
+
return true
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* @returns {import('node:async_hooks').AsyncLocalStorage<DeferredPoolQueryAcquire>}
|
|
319
|
+
*/
|
|
320
|
+
function getDeferredPoolQueryAcquireStorage () {
|
|
321
|
+
if (deferredPoolQueryAcquireStorage === undefined) {
|
|
322
|
+
const { AsyncLocalStorage } = require('node:async_hooks')
|
|
323
|
+
deferredPoolQueryAcquireStorage = new AsyncLocalStorage()
|
|
324
|
+
}
|
|
325
|
+
return deferredPoolQueryAcquireStorage
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* @param {Function} method
|
|
330
|
+
* @param {Record<string, unknown>} receiver
|
|
331
|
+
* @param {string} acquireMethod
|
|
332
|
+
* @param {unknown[]} args
|
|
333
|
+
* @returns {boolean}
|
|
334
|
+
*/
|
|
335
|
+
function dispatchesAcquireSynchronously (method, receiver, acquireMethod, args) {
|
|
336
|
+
let dispatched = false
|
|
337
|
+
// Prevent an async probe from executing beyond its fake acquisition.
|
|
338
|
+
// eslint-disable-next-line unicorn/no-thenable
|
|
339
|
+
const pending = { then () {} }
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
if (method.constructor.name === 'AsyncFunction') return false
|
|
343
|
+
|
|
344
|
+
receiver[acquireMethod] = () => {
|
|
345
|
+
dispatched = true
|
|
346
|
+
return pending
|
|
347
|
+
}
|
|
348
|
+
method.apply(receiver, args)
|
|
349
|
+
} catch {
|
|
350
|
+
return false
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return dispatched
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* @param {Pool} pool
|
|
358
|
+
* @param {ClusterAcquire | typeof poolQueryAcquire} [acquire]
|
|
359
|
+
* @returns {number|undefined}
|
|
360
|
+
*/
|
|
361
|
+
function acquireStart (pool, acquire) {
|
|
362
|
+
if (isClusterAcquire(acquire) && acquire.start !== undefined) return acquire.start
|
|
363
|
+
if (pool._freeConnections?.length > 0) return
|
|
364
|
+
|
|
365
|
+
const start = performance.now()
|
|
366
|
+
if (isClusterAcquire(acquire)) acquire.start = start
|
|
367
|
+
return start
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* @param {number|undefined} start
|
|
372
|
+
* @returns {number}
|
|
373
|
+
*/
|
|
374
|
+
function acquireWait (start) {
|
|
375
|
+
return start === undefined ? 0 : performance.now() - start
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* @param {object} connection
|
|
380
|
+
* @returns {number|undefined}
|
|
381
|
+
*/
|
|
382
|
+
function takePoolWaitTime (connection) {
|
|
383
|
+
for (let i = poolWaitConnections.length - 1; i >= 0; i--) {
|
|
384
|
+
if (poolWaitConnections[i] === connection) {
|
|
385
|
+
poolWaitConnections[i] = undefined
|
|
386
|
+
return poolWaitTimes[i]
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (deferredPoolWaitCount !== 0) {
|
|
391
|
+
const candidate = deferredPoolWaitTimes.get(connection)
|
|
392
|
+
if (candidate !== undefined) {
|
|
393
|
+
deferredPoolWaitTimes.delete(connection)
|
|
394
|
+
deferredPoolWaitCount--
|
|
395
|
+
candidate.transfer.deferred = true
|
|
396
|
+
return candidate.waitTime
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* @param {PoolWaitTransfer} transfer
|
|
403
|
+
* @param {object} connection
|
|
404
|
+
* @param {number} waitTime
|
|
405
|
+
* @param {Channel} channel
|
|
406
|
+
* @param {object} ctx
|
|
407
|
+
* @param {Function} callback
|
|
408
|
+
* @param {unknown} thisArg
|
|
409
|
+
* @param {ArgumentsLike} args
|
|
410
|
+
* @returns {unknown}
|
|
411
|
+
*/
|
|
412
|
+
function runWithPoolWait (transfer, connection, waitTime, channel, ctx, callback, thisArg, args) {
|
|
413
|
+
clearPoolWaitTime(connection)
|
|
414
|
+
|
|
415
|
+
if (transfer.deferred) {
|
|
416
|
+
deferPoolWaitTime(transfer, connection, waitTime)
|
|
417
|
+
return channel.runStores(ctx, callback, thisArg, ...args)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const index = poolWaitConnections.length
|
|
421
|
+
poolWaitConnections.push(connection)
|
|
422
|
+
poolWaitTimes.push(waitTime)
|
|
423
|
+
try {
|
|
424
|
+
return channel.runStores(ctx, callback, thisArg, ...args)
|
|
425
|
+
} finally {
|
|
426
|
+
if (poolWaitConnections[index] !== undefined) deferPoolWaitTime(transfer, connection, waitTime)
|
|
427
|
+
poolWaitConnections.pop()
|
|
428
|
+
poolWaitTimes.pop()
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* @param {object} connection
|
|
434
|
+
*/
|
|
435
|
+
function clearPoolWaitTime (connection) {
|
|
436
|
+
if (deferredPoolWaitCount !== 0 && deferredPoolWaitTimes.delete(connection)) deferredPoolWaitCount--
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* @param {PoolWaitTransfer} transfer
|
|
441
|
+
* @param {object} connection
|
|
442
|
+
* @param {number} waitTime
|
|
443
|
+
*/
|
|
444
|
+
function deferPoolWaitTime (transfer, connection, waitTime) {
|
|
445
|
+
if (!deferredPoolWaitTimes.has(connection)) deferredPoolWaitCount++
|
|
446
|
+
deferredPoolWaitTimes.set(connection, { transfer, waitTime })
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* @param {PoolWaitTransfer} poolWaitTransfer
|
|
451
|
+
* @param {ClusterAcquire | typeof poolQueryAcquire} acquire
|
|
452
|
+
* @param {number|undefined} start
|
|
453
|
+
* @param {unknown} error
|
|
454
|
+
* @param {object|undefined} connection
|
|
455
|
+
* @param {{ config: { connectionConfig: Record<string, unknown> } }} pool
|
|
456
|
+
* @param {AcquireChannels} channels
|
|
457
|
+
* @param {object} ctx
|
|
458
|
+
* @param {Function} callback
|
|
459
|
+
* @param {unknown} thisArg
|
|
460
|
+
* @param {ArgumentsLike} args
|
|
461
|
+
* @returns {unknown}
|
|
462
|
+
*/
|
|
463
|
+
function runPoolQueryConnectionCallback (
|
|
464
|
+
poolWaitTransfer,
|
|
465
|
+
acquire,
|
|
466
|
+
start,
|
|
467
|
+
error,
|
|
468
|
+
connection,
|
|
469
|
+
pool,
|
|
470
|
+
channels,
|
|
471
|
+
ctx,
|
|
472
|
+
callback,
|
|
473
|
+
thisArg,
|
|
474
|
+
args
|
|
475
|
+
) {
|
|
476
|
+
if (error || connection === undefined) {
|
|
477
|
+
const conf = pool.config.connectionConfig
|
|
478
|
+
if (error && isClusterAcquire(acquire)) {
|
|
479
|
+
acquire.conf = conf
|
|
480
|
+
if (acquire.key !== undefined) deferredClusterAcquires.set(acquire.key, acquire)
|
|
481
|
+
return channels.connectionFinishCh.runStores(ctx, callback, thisArg, ...args)
|
|
482
|
+
}
|
|
483
|
+
if (error && channels.acquireStartCh.hasSubscribers) {
|
|
484
|
+
return runPoolAcquireError(
|
|
485
|
+
start,
|
|
486
|
+
error,
|
|
487
|
+
{ conf },
|
|
488
|
+
channels,
|
|
489
|
+
ctx,
|
|
490
|
+
callback,
|
|
491
|
+
thisArg,
|
|
492
|
+
args
|
|
493
|
+
)
|
|
494
|
+
}
|
|
495
|
+
return channels.connectionFinishCh.runStores(ctx, callback, thisArg, ...args)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (isClusterAcquire(acquire)) {
|
|
499
|
+
if (acquire.key !== undefined) deferredClusterAcquires.delete(acquire.key)
|
|
500
|
+
acquire.acquired = true
|
|
501
|
+
acquire.key = undefined
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return runWithPoolWait(
|
|
505
|
+
poolWaitTransfer,
|
|
506
|
+
connection,
|
|
507
|
+
acquireWait(start),
|
|
508
|
+
channels.connectionFinishCh,
|
|
509
|
+
ctx,
|
|
510
|
+
callback,
|
|
511
|
+
thisArg,
|
|
512
|
+
args
|
|
513
|
+
)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* @param {number|undefined} start
|
|
518
|
+
* @param {unknown} error
|
|
519
|
+
* @param {Record<string, unknown>} acquireCtx
|
|
520
|
+
* @param {AcquireErrorChannels} channels
|
|
521
|
+
*/
|
|
522
|
+
function reportPoolAcquireError (start, error, acquireCtx, channels) {
|
|
523
|
+
acquireCtx.error = error
|
|
524
|
+
acquireCtx.poolWaitTime = acquireWait(start)
|
|
525
|
+
if (start !== undefined) acquireCtx.startTime = performance.timeOrigin + start
|
|
526
|
+
channels.acquireStartCh.publish(acquireCtx)
|
|
527
|
+
channels.acquireFinishCh.publish(acquireCtx)
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* @param {number|undefined} start
|
|
532
|
+
* @param {unknown} error
|
|
533
|
+
* @param {Record<string, unknown>} acquireCtx
|
|
534
|
+
* @param {AcquireErrorChannels} channels
|
|
535
|
+
* @param {object} connectionCtx
|
|
536
|
+
* @param {Function} callback
|
|
537
|
+
* @param {unknown} thisArg
|
|
538
|
+
* @param {ArgumentsLike} args
|
|
539
|
+
* @returns {unknown}
|
|
540
|
+
*/
|
|
541
|
+
function runPoolAcquireError (start, error, acquireCtx, channels, connectionCtx, callback, thisArg, args) {
|
|
542
|
+
return channels.connectionFinishCh.runStores(connectionCtx, () => {
|
|
543
|
+
reportPoolAcquireError(start, error, acquireCtx, channels)
|
|
544
|
+
return callback.apply(thisArg, args)
|
|
545
|
+
})
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* @param {Function} callback
|
|
550
|
+
* @param {ClusterAcquire} acquire
|
|
551
|
+
* @param {AcquireChannels} channels
|
|
552
|
+
* @returns {Function}
|
|
553
|
+
*/
|
|
554
|
+
function wrapClusterAcquireCallback (callback, acquire, channels) {
|
|
555
|
+
return function (error) {
|
|
556
|
+
if (error) reportClusterAcquireError(acquire, error, channels)
|
|
557
|
+
if (currentPoolQueryAcquire !== undefined) {
|
|
558
|
+
return runWithPoolQueryAcquire(undefined, callback, this, arguments)
|
|
559
|
+
}
|
|
560
|
+
return callback.apply(this, arguments)
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* @param {Function} callback
|
|
566
|
+
* @param {ClusterAcquire} acquire
|
|
567
|
+
* @param {AcquireChannels} channels
|
|
568
|
+
* @returns {Function}
|
|
569
|
+
*/
|
|
570
|
+
function wrapClusterQueryCallback (callback, acquire, channels) {
|
|
571
|
+
return function (error) {
|
|
572
|
+
if (error) reportClusterAcquireError(acquire, error, channels)
|
|
573
|
+
return callback.apply(this, arguments)
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* @param {ClusterAcquire} acquire
|
|
579
|
+
* @param {unknown} error
|
|
580
|
+
* @param {AcquireChannels} channels
|
|
581
|
+
*/
|
|
582
|
+
function reportClusterAcquireError (acquire, error, channels) {
|
|
583
|
+
if (acquire.acquired || acquire.errorReported || !channels.acquireStartCh.hasSubscribers) return
|
|
584
|
+
acquire.errorReported = true
|
|
585
|
+
reportPoolAcquireError(acquire.start, error, { conf: acquire.conf ?? {} }, channels)
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* @param {unknown} value
|
|
590
|
+
* @returns {value is ClusterAcquire}
|
|
591
|
+
*/
|
|
592
|
+
function isClusterAcquire (value) {
|
|
593
|
+
return value !== undefined && value !== poolQueryAcquire
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* @param {unknown} value
|
|
598
|
+
* @returns {value is object}
|
|
599
|
+
*/
|
|
600
|
+
function isWeakKey (value) {
|
|
601
|
+
return (typeof value === 'object' && value !== null) || typeof value === 'function'
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* @param {unknown} key
|
|
606
|
+
* @returns {ClusterAcquire|undefined}
|
|
607
|
+
*/
|
|
608
|
+
function takeClusterAcquire (key) {
|
|
609
|
+
if (!isWeakKey(key)) return
|
|
610
|
+
const acquire = deferredClusterAcquires.get(key)
|
|
611
|
+
if (acquire !== undefined) deferredClusterAcquires.delete(key)
|
|
612
|
+
return acquire
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
module.exports = {
|
|
616
|
+
clearPoolWaitTime,
|
|
617
|
+
dispatchesAcquireSynchronously,
|
|
618
|
+
isPoolQueryAcquire,
|
|
619
|
+
runOutsidePoolQueryAcquire,
|
|
620
|
+
runPoolAcquireError,
|
|
621
|
+
runWithPoolWait,
|
|
622
|
+
takePoolWaitTime,
|
|
623
|
+
wrapPoolAcquireCarrier,
|
|
624
|
+
wrapPoolClusterGetConnection,
|
|
625
|
+
wrapPoolClusterMethod,
|
|
626
|
+
wrapPoolClusterQueryMethod,
|
|
627
|
+
wrapPoolGetConnection,
|
|
628
|
+
wrapPoolQueryMethod,
|
|
629
|
+
}
|
|
@@ -7,7 +7,7 @@ const log = require('../../../../dd-trace/src/log')
|
|
|
7
7
|
const { create } = require('../../../../../vendor/dist/@apm-js-collab/code-transformer')
|
|
8
8
|
const instrumentations = require('./instrumentations')
|
|
9
9
|
const { getRewriteTarget } = require('./targets')
|
|
10
|
-
const { waitForAsyncEnd } = require('./transforms')
|
|
10
|
+
const { awaitContextCallback, waitForAsyncEnd } = require('./transforms')
|
|
11
11
|
|
|
12
12
|
// `dc-polyfill` is referenced from injected `require()` (CJS) and `import`
|
|
13
13
|
// (ESM) statements that the transformer splices into the rewritten module.
|
|
@@ -35,6 +35,7 @@ const matcherCjs = create(instrumentations, dcPolyfillCjs)
|
|
|
35
35
|
const matcherEsm = create(instrumentations, dcPolyfillEsm)
|
|
36
36
|
|
|
37
37
|
for (const matcher of [matcherCjs, matcherEsm]) {
|
|
38
|
+
matcher.addTransform('awaitContextCallback', awaitContextCallback)
|
|
38
39
|
matcher.addTransform('waitForAsyncEnd', waitForAsyncEnd)
|
|
39
40
|
}
|
|
40
41
|
|