dd-trace 4.44.0 → 4.46.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.
Files changed (108) hide show
  1. package/index.d.ts +2 -1
  2. package/package.json +5 -5
  3. package/packages/datadog-instrumentations/src/aerospike.js +1 -1
  4. package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
  5. package/packages/datadog-instrumentations/src/aws-sdk.js +4 -4
  6. package/packages/datadog-instrumentations/src/body-parser.js +17 -5
  7. package/packages/datadog-instrumentations/src/cassandra-driver.js +2 -2
  8. package/packages/datadog-instrumentations/src/child_process.js +2 -2
  9. package/packages/datadog-instrumentations/src/connect.js +4 -4
  10. package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
  11. package/packages/datadog-instrumentations/src/couchbase.js +12 -12
  12. package/packages/datadog-instrumentations/src/cucumber.js +16 -5
  13. package/packages/datadog-instrumentations/src/dns.js +10 -10
  14. package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
  15. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +3 -3
  16. package/packages/datadog-instrumentations/src/express.js +4 -4
  17. package/packages/datadog-instrumentations/src/fastify.js +6 -6
  18. package/packages/datadog-instrumentations/src/fetch.js +1 -1
  19. package/packages/datadog-instrumentations/src/find-my-way.js +2 -2
  20. package/packages/datadog-instrumentations/src/fs.js +2 -2
  21. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +2 -2
  22. package/packages/datadog-instrumentations/src/grpc/client.js +4 -6
  23. package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
  24. package/packages/datadog-instrumentations/src/hapi.js +10 -13
  25. package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -2
  26. package/packages/datadog-instrumentations/src/helpers/register.js +9 -2
  27. package/packages/datadog-instrumentations/src/http/client.js +3 -3
  28. package/packages/datadog-instrumentations/src/jest.js +5 -4
  29. package/packages/datadog-instrumentations/src/knex.js +2 -2
  30. package/packages/datadog-instrumentations/src/koa.js +5 -5
  31. package/packages/datadog-instrumentations/src/ldapjs.js +1 -1
  32. package/packages/datadog-instrumentations/src/mariadb.js +8 -8
  33. package/packages/datadog-instrumentations/src/memcached.js +2 -2
  34. package/packages/datadog-instrumentations/src/microgateway-core.js +4 -4
  35. package/packages/datadog-instrumentations/src/mocha/common.js +1 -1
  36. package/packages/datadog-instrumentations/src/mocha/main.js +91 -70
  37. package/packages/datadog-instrumentations/src/mocha/utils.js +2 -3
  38. package/packages/datadog-instrumentations/src/mocha.js +4 -0
  39. package/packages/datadog-instrumentations/src/moleculer/server.js +2 -2
  40. package/packages/datadog-instrumentations/src/mongodb-core.js +7 -7
  41. package/packages/datadog-instrumentations/src/mongoose.js +5 -6
  42. package/packages/datadog-instrumentations/src/mysql.js +3 -3
  43. package/packages/datadog-instrumentations/src/mysql2.js +6 -6
  44. package/packages/datadog-instrumentations/src/net.js +2 -2
  45. package/packages/datadog-instrumentations/src/next.js +5 -5
  46. package/packages/datadog-instrumentations/src/nyc.js +23 -0
  47. package/packages/datadog-instrumentations/src/openai.js +58 -69
  48. package/packages/datadog-instrumentations/src/oracledb.js +8 -8
  49. package/packages/datadog-instrumentations/src/passport-http.js +1 -1
  50. package/packages/datadog-instrumentations/src/passport-local.js +1 -1
  51. package/packages/datadog-instrumentations/src/passport-utils.js +1 -1
  52. package/packages/datadog-instrumentations/src/pg.js +1 -1
  53. package/packages/datadog-instrumentations/src/pino.js +4 -4
  54. package/packages/datadog-instrumentations/src/playwright.js +6 -4
  55. package/packages/datadog-instrumentations/src/redis.js +2 -2
  56. package/packages/datadog-instrumentations/src/restify.js +4 -4
  57. package/packages/datadog-instrumentations/src/rhea.js +4 -4
  58. package/packages/datadog-instrumentations/src/router.js +5 -5
  59. package/packages/datadog-instrumentations/src/sharedb.js +2 -2
  60. package/packages/datadog-instrumentations/src/vitest.js +22 -5
  61. package/packages/datadog-instrumentations/src/winston.js +2 -3
  62. package/packages/datadog-plugin-cucumber/src/index.js +12 -2
  63. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +21 -10
  64. package/packages/datadog-plugin-hapi/src/index.js +2 -2
  65. package/packages/datadog-plugin-jest/src/index.js +18 -4
  66. package/packages/datadog-plugin-mocha/src/index.js +25 -6
  67. package/packages/datadog-plugin-nyc/src/index.js +35 -0
  68. package/packages/datadog-plugin-openai/src/index.js +58 -47
  69. package/packages/datadog-plugin-playwright/src/index.js +9 -4
  70. package/packages/datadog-plugin-vitest/src/index.js +30 -4
  71. package/packages/datadog-shimmer/src/shimmer.js +144 -10
  72. package/packages/dd-trace/src/appsec/blocking.js +23 -17
  73. package/packages/dd-trace/src/appsec/graphql.js +3 -1
  74. package/packages/dd-trace/src/appsec/iast/iast-log.js +2 -1
  75. package/packages/dd-trace/src/appsec/remote_config/manager.js +4 -1
  76. package/packages/dd-trace/src/appsec/rule_manager.js +8 -0
  77. package/packages/dd-trace/src/appsec/telemetry.js +3 -3
  78. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +40 -1
  79. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -4
  80. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -4
  81. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +2 -1
  82. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +8 -7
  83. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -4
  84. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -4
  85. package/packages/dd-trace/src/ci-visibility/telemetry.js +29 -2
  86. package/packages/dd-trace/src/config.js +157 -142
  87. package/packages/dd-trace/src/lambda/handler.js +1 -0
  88. package/packages/dd-trace/src/lambda/index.js +12 -1
  89. package/packages/dd-trace/src/opentelemetry/context_manager.js +22 -39
  90. package/packages/dd-trace/src/opentelemetry/span_context.js +2 -2
  91. package/packages/dd-trace/src/opentelemetry/tracer.js +23 -14
  92. package/packages/dd-trace/src/opentelemetry/tracer_provider.js +9 -1
  93. package/packages/dd-trace/src/opentracing/propagation/log.js +1 -1
  94. package/packages/dd-trace/src/opentracing/propagation/text_map.js +61 -6
  95. package/packages/dd-trace/src/opentracing/span_context.js +1 -0
  96. package/packages/dd-trace/src/plugins/ci_plugin.js +2 -2
  97. package/packages/dd-trace/src/plugins/index.js +1 -0
  98. package/packages/dd-trace/src/plugins/util/git.js +14 -1
  99. package/packages/dd-trace/src/plugins/util/test.js +1 -5
  100. package/packages/dd-trace/src/profiler.js +15 -5
  101. package/packages/dd-trace/src/profiling/config.js +2 -4
  102. package/packages/dd-trace/src/profiling/exporter_cli.js +13 -1
  103. package/packages/dd-trace/src/profiling/exporters/agent.js +7 -1
  104. package/packages/dd-trace/src/profiling/profiler.js +0 -9
  105. package/packages/dd-trace/src/profiling/ssi-heuristics.js +49 -58
  106. package/packages/dd-trace/src/proxy.js +21 -21
  107. package/packages/dd-trace/src/telemetry/index.js +24 -7
  108. package/packages/dd-trace/src/telemetry/logs/index.js +20 -0
@@ -92,7 +92,7 @@ function wrapUnifiedCommand (command, operation, name) {
92
92
  }
93
93
  return instrument(operation, command, this, arguments, server, ns, ops, { name })
94
94
  }
95
- return shimmer.wrap(command, wrapped)
95
+ return wrapped
96
96
  }
97
97
 
98
98
  function wrapConnectionCommand (command, operation, name, instrumentFn = instrument) {
@@ -109,7 +109,7 @@ function wrapConnectionCommand (command, operation, name, instrumentFn = instrum
109
109
  ns = `${ns.db}.${ns.collection}`
110
110
  return instrumentFn(operation, command, this, arguments, topology, ns, ops, { name })
111
111
  }
112
- return shimmer.wrap(command, wrapped)
112
+ return wrapped
113
113
  }
114
114
 
115
115
  function wrapQuery (query, operation, name) {
@@ -123,7 +123,7 @@ function wrapQuery (query, operation, name) {
123
123
  return instrument(operation, query, this, arguments, pool, ns, ops)
124
124
  }
125
125
 
126
- return shimmer.wrap(query, wrapped)
126
+ return wrapped
127
127
  }
128
128
 
129
129
  function wrapCursor (cursor, operation, name) {
@@ -135,7 +135,7 @@ function wrapCursor (cursor, operation, name) {
135
135
  const ns = this.ns
136
136
  return instrument(operation, cursor, this, arguments, pool, ns, {}, { name })
137
137
  }
138
- return shimmer.wrap(cursor, wrapped)
138
+ return wrapped
139
139
  }
140
140
 
141
141
  function wrapCommand (command, operation, name) {
@@ -145,7 +145,7 @@ function wrapCommand (command, operation, name) {
145
145
  }
146
146
  return instrument(operation, command, this, arguments, this, ns, ops, { name })
147
147
  }
148
- return shimmer.wrap(command, wrapped)
148
+ return wrapped
149
149
  }
150
150
 
151
151
  function instrument (operation, command, ctx, args, server, ns, ops, options = {}) {
@@ -164,7 +164,7 @@ function instrument (operation, command, ctx, args, server, ns, ops, options = {
164
164
  return asyncResource.runInAsyncScope(() => {
165
165
  startCh.publish({ ns, ops, options: serverInfo, name })
166
166
 
167
- args[index] = asyncResource.bind(function (err, res) {
167
+ args[index] = shimmer.wrapFunction(callback, callback => asyncResource.bind(function (err, res) {
168
168
  if (err) {
169
169
  errorCh.publish(err)
170
170
  }
@@ -174,7 +174,7 @@ function instrument (operation, command, ctx, args, server, ns, ops, options = {
174
174
  if (callback) {
175
175
  return callback.apply(this, arguments)
176
176
  }
177
- })
177
+ }))
178
178
 
179
179
  try {
180
180
  return command.apply(ctx, args)
@@ -128,22 +128,21 @@ addHook({
128
128
  const resolve = arguments[0]
129
129
  const reject = arguments[1]
130
130
 
131
- // not using shimmer here because resolve/reject could be empty
132
- arguments[0] = function wrappedResolve () {
131
+ arguments[0] = shimmer.wrapFunction(resolve, resolve => function wrappedResolve () {
133
132
  finish()
134
133
 
135
134
  if (resolve) {
136
135
  return resolve.apply(this, arguments)
137
136
  }
138
- }
137
+ })
139
138
 
140
- arguments[1] = function wrappedReject () {
139
+ arguments[1] = shimmer.wrapFunction(reject, reject => function wrappedReject () {
141
140
  finish()
142
141
 
143
142
  if (reject) {
144
143
  return reject.apply(this, arguments)
145
144
  }
146
- }
145
+ })
147
146
 
148
147
  return originalThen.apply(this, arguments)
149
148
  }
@@ -169,7 +168,7 @@ addHook({
169
168
  versions: ['6', '>=7'],
170
169
  file: 'lib/helpers/query/sanitizeFilter.js'
171
170
  }, sanitizeFilter => {
172
- return shimmer.wrap(sanitizeFilter, function wrappedSanitizeFilter () {
171
+ return shimmer.wrapFunction(sanitizeFilter, sanitizeFilter => function wrappedSanitizeFilter () {
173
172
  const sanitizedObject = sanitizeFilter.apply(this, arguments)
174
173
 
175
174
  if (sanitizeFilterFinishCh.hasSubscribers) {
@@ -37,14 +37,14 @@ addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connect
37
37
 
38
38
  if (res._callback) {
39
39
  const cb = callbackResource.bind(res._callback)
40
- res._callback = asyncResource.bind(function (error, result) {
40
+ res._callback = shimmer.wrapFunction(cb, cb => asyncResource.bind(function (error, result) {
41
41
  if (error) {
42
42
  errorCh.publish(error)
43
43
  }
44
44
  finishCh.publish(result)
45
45
 
46
46
  return cb.apply(this, arguments)
47
- })
47
+ }))
48
48
  } else {
49
49
  const cb = asyncResource.bind(function () {
50
50
  finishCh.publish(undefined)
@@ -92,7 +92,7 @@ addHook({ name: 'mysql', file: 'lib/Pool.js', versions: ['>=2'] }, Pool => {
92
92
 
93
93
  const cb = arguments[arguments.length - 1]
94
94
  if (typeof cb === 'function') {
95
- arguments[arguments.length - 1] = shimmer.wrap(cb, function () {
95
+ arguments[arguments.length - 1] = shimmer.wrapFunction(cb, cb => function () {
96
96
  finish()
97
97
  return cb.apply(this, arguments)
98
98
  })
@@ -31,19 +31,19 @@ addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connec
31
31
  return Connection
32
32
 
33
33
  function bindExecute (cmd, execute, asyncResource) {
34
- return asyncResource.bind(function executeWithTrace (packet, connection) {
34
+ return shimmer.wrapFunction(execute, execute => asyncResource.bind(function executeWithTrace (packet, connection) {
35
35
  if (this.onResult) {
36
36
  this.onResult = asyncResource.bind(this.onResult)
37
37
  }
38
38
 
39
39
  return execute.apply(this, arguments)
40
- }, cmd)
40
+ }, cmd))
41
41
  }
42
42
 
43
43
  function wrapExecute (cmd, execute, asyncResource, config) {
44
44
  const callbackResource = new AsyncResource('bound-anonymous-fn')
45
45
 
46
- return asyncResource.bind(function executeWithTrace (packet, connection) {
46
+ return shimmer.wrapFunction(execute, execute => asyncResource.bind(function executeWithTrace (packet, connection) {
47
47
  const sql = cmd.statement ? cmd.statement.query : cmd.sql
48
48
  const payload = { sql, conf: config }
49
49
  startCh.publish(payload)
@@ -57,13 +57,13 @@ addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connec
57
57
  if (this.onResult) {
58
58
  const onResult = callbackResource.bind(this.onResult)
59
59
 
60
- this.onResult = asyncResource.bind(function (error) {
60
+ this.onResult = shimmer.wrapFunction(onResult, onResult => asyncResource.bind(function (error) {
61
61
  if (error) {
62
62
  errorCh.publish(error)
63
63
  }
64
64
  finishCh.publish(undefined)
65
65
  onResult.apply(this, arguments)
66
- }, 'bound-anonymous-fn', this)
66
+ }, 'bound-anonymous-fn', this))
67
67
  } else {
68
68
  this.on('error', asyncResource.bind(error => errorCh.publish(error)))
69
69
  this.on('end', asyncResource.bind(() => finishCh.publish(undefined)))
@@ -76,6 +76,6 @@ addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connec
76
76
  } catch (err) {
77
77
  errorCh.publish(err)
78
78
  }
79
- }, cmd)
79
+ }, cmd))
80
80
  }
81
81
  })
@@ -58,7 +58,7 @@ addHook({ name: names }, (net, version, name) => {
58
58
  }
59
59
 
60
60
  const emit = this.emit
61
- this.emit = function (eventName) {
61
+ this.emit = shimmer.wrapFunction(emit, emit => function (eventName) {
62
62
  switch (eventName) {
63
63
  case 'ready':
64
64
  case 'connect':
@@ -68,7 +68,7 @@ addHook({ name: names }, (net, version, name) => {
68
68
  default:
69
69
  return emit.apply(this, arguments)
70
70
  }
71
- }
71
+ })
72
72
 
73
73
  try {
74
74
  return connect.apply(this, arguments)
@@ -188,7 +188,7 @@ function finish (ctx, result, err) {
188
188
  // however, it is not provided as a class function or exported property
189
189
  addHook({
190
190
  name: 'next',
191
- versions: ['>=13.3.0'],
191
+ versions: ['>=13.3.0 <14.2.7'],
192
192
  file: 'dist/server/web/spec-extension/adapters/next-request.js'
193
193
  }, NextRequestAdapter => {
194
194
  shimmer.wrap(NextRequestAdapter.NextRequestAdapter, 'fromNodeNextRequest', fromNodeNextRequest => {
@@ -203,7 +203,7 @@ addHook({
203
203
 
204
204
  addHook({
205
205
  name: 'next',
206
- versions: ['>=11.1'],
206
+ versions: ['>=11.1 <14.2.7'],
207
207
  file: 'dist/server/serve-static.js'
208
208
  }, serveStatic => shimmer.wrap(serveStatic, 'serveStatic', wrapServeStatic))
209
209
 
@@ -213,7 +213,7 @@ addHook({
213
213
  file: 'dist/next-server/server/serve-static.js'
214
214
  }, serveStatic => shimmer.wrap(serveStatic, 'serveStatic', wrapServeStatic))
215
215
 
216
- addHook({ name: 'next', versions: ['>=11.1'], file: 'dist/server/next-server.js' }, nextServer => {
216
+ addHook({ name: 'next', versions: ['>=11.1 <14.2.7'], file: 'dist/server/next-server.js' }, nextServer => {
217
217
  const Server = nextServer.default
218
218
 
219
219
  shimmer.wrap(Server.prototype, 'handleRequest', wrapHandleRequest)
@@ -230,7 +230,7 @@ addHook({ name: 'next', versions: ['>=11.1'], file: 'dist/server/next-server.js'
230
230
  })
231
231
 
232
232
  // `handleApiRequest` changes parameters/implementation at 13.2.0
233
- addHook({ name: 'next', versions: ['>=13.2'], file: 'dist/server/next-server.js' }, nextServer => {
233
+ addHook({ name: 'next', versions: ['>=13.2 <14.2.7'], file: 'dist/server/next-server.js' }, nextServer => {
234
234
  const Server = nextServer.default
235
235
  shimmer.wrap(Server.prototype, 'handleApiRequest', wrapHandleApiRequestWithMatch)
236
236
  return nextServer
@@ -264,7 +264,7 @@ addHook({
264
264
 
265
265
  addHook({
266
266
  name: 'next',
267
- versions: ['>=13'],
267
+ versions: ['>=13 <14.2.7'],
268
268
  file: 'dist/server/web/spec-extension/request.js'
269
269
  }, request => {
270
270
  const nextUrlDescriptor = Object.getOwnPropertyDescriptor(request.NextRequest.prototype, 'nextUrl')
@@ -0,0 +1,23 @@
1
+ const { addHook, channel } = require('./helpers/instrument')
2
+ const shimmer = require('../../datadog-shimmer')
3
+
4
+ const codeCoverageWrapCh = channel('ci:nyc:wrap')
5
+
6
+ addHook({
7
+ name: 'nyc',
8
+ versions: ['>=17']
9
+ }, (nycPackage) => {
10
+ shimmer.wrap(nycPackage.prototype, 'wrap', wrap => async function () {
11
+ // Only relevant if the config `all` is set to true
12
+ try {
13
+ if (JSON.parse(process.env.NYC_CONFIG).all) {
14
+ codeCoverageWrapCh.publish(this)
15
+ }
16
+ } catch (e) {
17
+ // ignore errors
18
+ }
19
+
20
+ return wrap.apply(this, arguments)
21
+ })
22
+ return nycPackage
23
+ })
@@ -1,14 +1,10 @@
1
1
  'use strict'
2
2
 
3
- const {
4
- channel,
5
- addHook
6
- } = require('./helpers/instrument')
3
+ const { addHook } = require('./helpers/instrument')
7
4
  const shimmer = require('../../datadog-shimmer')
8
5
 
9
- const startCh = channel('apm:openai:request:start')
10
- const finishCh = channel('apm:openai:request:finish')
11
- const errorCh = channel('apm:openai:request:error')
6
+ const tracingChannel = require('dc-polyfill').tracingChannel
7
+ const ch = tracingChannel('apm:openai:request')
12
8
 
13
9
  const V4_PACKAGE_SHIMS = [
14
10
  {
@@ -110,33 +106,18 @@ addHook({ name: 'openai', file: 'dist/api.js', versions: ['>=3.0.0 <4'] }, expor
110
106
 
111
107
  for (const methodName of methodNames) {
112
108
  shimmer.wrap(exports.OpenAIApi.prototype, methodName, fn => function () {
113
- if (!startCh.hasSubscribers) {
109
+ if (!ch.start.hasSubscribers) {
114
110
  return fn.apply(this, arguments)
115
111
  }
116
112
 
117
- startCh.publish({
113
+ const ctx = {
118
114
  methodName,
119
115
  args: arguments,
120
116
  basePath: this.basePath,
121
117
  apiKey: this.configuration.apiKey
122
- })
123
-
124
- return fn.apply(this, arguments)
125
- .then((response) => {
126
- finish({
127
- headers: response.headers,
128
- body: response.data,
129
- path: response.request.path,
130
- method: response.request.method
131
- })
132
-
133
- return response
134
- })
135
- .catch(error => {
136
- finish(undefined, error)
118
+ }
137
119
 
138
- throw error
139
- })
120
+ return ch.tracePromise(fn, ctx, this, ...arguments)
140
121
  })
141
122
  }
142
123
 
@@ -213,7 +194,7 @@ function convertBufferstoObjects (chunks = []) {
213
194
  * the chunks, and let the combined content be the final response.
214
195
  * This way, spans look the same as when not streamed.
215
196
  */
216
- function wrapStreamIterator (response, options, n) {
197
+ function wrapStreamIterator (response, options, n, ctx) {
217
198
  let processChunksAsBuffers = false
218
199
  let chunks = []
219
200
  return function (itr) {
@@ -253,11 +234,13 @@ function wrapStreamIterator (response, options, n) {
253
234
  }
254
235
  }
255
236
 
256
- finish({
237
+ finish(ctx, {
257
238
  headers: response.headers,
258
- body,
259
- path: response.url,
260
- method: options.method
239
+ data: body,
240
+ request: {
241
+ path: response.url,
242
+ method: options.method
243
+ }
261
244
  })
262
245
  }
263
246
 
@@ -281,7 +264,7 @@ for (const shim of V4_PACKAGE_SHIMS) {
281
264
 
282
265
  for (const methodName of methods) {
283
266
  shimmer.wrap(targetPrototype, methodName, methodFn => function () {
284
- if (!startCh.hasSubscribers) {
267
+ if (!ch.start.hasSubscribers) {
285
268
  return methodFn.apply(this, arguments)
286
269
  }
287
270
 
@@ -303,66 +286,72 @@ for (const shim of V4_PACKAGE_SHIMS) {
303
286
 
304
287
  const client = this._client || this.client
305
288
 
306
- startCh.publish({
289
+ const ctx = {
307
290
  methodName: `${baseResource}.${methodName}`,
308
291
  args: arguments,
309
292
  basePath: client.baseURL,
310
293
  apiKey: client.apiKey
311
- })
294
+ }
312
295
 
313
- const apiProm = methodFn.apply(this, arguments)
296
+ return ch.start.runStores(ctx, () => {
297
+ const apiProm = methodFn.apply(this, arguments)
314
298
 
315
- // wrapping `parse` avoids problematic wrapping of `then` when trying to call
316
- // `withResponse` in userland code after. This way, we can return the whole `APIPromise`
317
- shimmer.wrap(apiProm, 'parse', origApiPromParse => function () {
318
- return origApiPromParse.apply(this, arguments)
299
+ // wrapping `parse` avoids problematic wrapping of `then` when trying to call
300
+ // `withResponse` in userland code after. This way, we can return the whole `APIPromise`
301
+ shimmer.wrap(apiProm, 'parse', origApiPromParse => function () {
302
+ return origApiPromParse.apply(this, arguments)
319
303
  // the original response is wrapped in a promise, so we need to unwrap it
320
- .then(body => Promise.all([this.responsePromise, body]))
321
- .then(([{ response, options }, body]) => {
322
- if (stream) {
323
- if (body.iterator) {
324
- shimmer.wrap(body, 'iterator', wrapStreamIterator(response, options, n))
304
+ .then(body => Promise.all([this.responsePromise, body]))
305
+ .then(([{ response, options }, body]) => {
306
+ if (stream) {
307
+ if (body.iterator) {
308
+ shimmer.wrap(body, 'iterator', wrapStreamIterator(response, options, n, ctx))
309
+ } else {
310
+ shimmer.wrap(
311
+ body.response.body, Symbol.asyncIterator, wrapStreamIterator(response, options, n, ctx)
312
+ )
313
+ }
325
314
  } else {
326
- shimmer.wrap(
327
- body.response.body, Symbol.asyncIterator, wrapStreamIterator(response, options, n)
328
- )
315
+ finish(ctx, {
316
+ headers: response.headers,
317
+ data: body,
318
+ request: {
319
+ path: response.url,
320
+ method: options.method
321
+ }
322
+ })
329
323
  }
330
- } else {
331
- finish({
332
- headers: response.headers,
333
- body,
334
- path: response.url,
335
- method: options.method
336
- })
337
- }
338
324
 
339
- return body
340
- })
341
- .catch(error => {
342
- finish(undefined, error)
325
+ return body
326
+ })
327
+ .catch(error => {
328
+ finish(ctx, undefined, error)
343
329
 
344
- throw error
345
- })
346
- .finally(() => {
330
+ throw error
331
+ })
332
+ .finally(() => {
347
333
  // maybe we don't want to unwrap here in case the promise is re-used?
348
334
  // other hand: we want to avoid resource leakage
349
- shimmer.unwrap(apiProm, 'parse')
350
- })
351
- })
335
+ shimmer.unwrap(apiProm, 'parse')
336
+ })
337
+ })
352
338
 
353
- return apiProm
339
+ return apiProm
340
+ })
354
341
  })
355
342
  }
356
343
  return exports
357
344
  })
358
345
  }
359
346
 
360
- function finish (response, error) {
347
+ function finish (ctx, response, error) {
361
348
  if (error) {
362
- errorCh.publish({ error })
349
+ ctx.error = error
350
+ ch.error.publish(ctx)
363
351
  }
364
352
 
365
- finishCh.publish(response)
353
+ ctx.result = response
354
+ ch.asyncEnd.publish(ctx)
366
355
  }
367
356
 
368
357
  function getOption (args, option, defaultValue) {
@@ -31,10 +31,10 @@ addHook({ name: 'oracledb', versions: ['>=5'] }, oracledb => {
31
31
  if (arguments.length && typeof arguments[arguments.length - 1] === 'function') {
32
32
  const cb = arguments[arguments.length - 1]
33
33
  const outerAr = new AsyncResource('apm:oracledb:outer-scope')
34
- arguments[arguments.length - 1] = function wrappedCb (err, result) {
34
+ arguments[arguments.length - 1] = shimmer.wrapFunction(cb, cb => function wrappedCb (err, result) {
35
35
  finish(err)
36
36
  return outerAr.runInAsyncScope(() => cb.apply(this, arguments))
37
- }
37
+ })
38
38
  }
39
39
 
40
40
  return new AsyncResource('apm:oracledb:inner-scope').runInAsyncScope(() => {
@@ -67,12 +67,12 @@ addHook({ name: 'oracledb', versions: ['>=5'] }, oracledb => {
67
67
  shimmer.wrap(oracledb, 'getConnection', getConnection => {
68
68
  return function wrappedGetConnection (connAttrs, callback) {
69
69
  if (callback) {
70
- arguments[1] = (err, connection) => {
70
+ arguments[1] = shimmer.wrapFunction(callback, callback => (err, connection) => {
71
71
  if (connection) {
72
72
  connectionAttributes.set(connection, connAttrs)
73
73
  }
74
74
  callback(err, connection)
75
- }
75
+ })
76
76
 
77
77
  getConnection.apply(this, arguments)
78
78
  } else {
@@ -86,12 +86,12 @@ addHook({ name: 'oracledb', versions: ['>=5'] }, oracledb => {
86
86
  shimmer.wrap(oracledb, 'createPool', createPool => {
87
87
  return function wrappedCreatePool (poolAttrs, callback) {
88
88
  if (callback) {
89
- arguments[1] = (err, pool) => {
89
+ arguments[1] = shimmer.wrapFunction(callback, callback => (err, pool) => {
90
90
  if (pool) {
91
91
  poolAttributes.set(pool, poolAttrs)
92
92
  }
93
93
  callback(err, pool)
94
- }
94
+ })
95
95
 
96
96
  createPool.apply(this, arguments)
97
97
  } else {
@@ -109,12 +109,12 @@ addHook({ name: 'oracledb', versions: ['>=5'] }, oracledb => {
109
109
  callback = arguments[arguments.length - 1]
110
110
  }
111
111
  if (callback) {
112
- arguments[arguments.length - 1] = (err, connection) => {
112
+ arguments[arguments.length - 1] = shimmer.wrapFunction(callback, callback => (err, connection) => {
113
113
  if (connection) {
114
114
  connectionAttributes.set(connection, poolAttributes.get(this))
115
115
  }
116
116
  callback(err, connection)
117
- }
117
+ })
118
118
  getConnection.apply(this, arguments)
119
119
  } else {
120
120
  return getConnection.apply(this, arguments).then((connection) => {
@@ -9,7 +9,7 @@ addHook({
9
9
  file: 'lib/passport-http/strategies/basic.js',
10
10
  versions: ['>=0.3.0']
11
11
  }, BasicStrategy => {
12
- return shimmer.wrap(BasicStrategy, function () {
12
+ return shimmer.wrapFunction(BasicStrategy, BasicStrategy => function () {
13
13
  const type = 'http'
14
14
 
15
15
  if (typeof arguments[0] === 'function') {
@@ -9,7 +9,7 @@ addHook({
9
9
  file: 'lib/strategy.js',
10
10
  versions: ['>=1.0.0']
11
11
  }, Strategy => {
12
- return shimmer.wrap(Strategy, function () {
12
+ return shimmer.wrapFunction(Strategy, Strategy => function () {
13
13
  const type = 'local'
14
14
 
15
15
  if (typeof arguments[0] === 'function') {
@@ -11,7 +11,7 @@ function wrapVerifiedAndPublish (username, password, verified, type) {
11
11
  }
12
12
 
13
13
  // eslint-disable-next-line n/handle-callback-err
14
- return shimmer.wrap(verified, function (err, user, info) {
14
+ return shimmer.wrapFunction(verified, verified => function (err, user, info) {
15
15
  const credentials = { type, username }
16
16
  passportVerifyChannel.publish({ credentials, user })
17
17
  return verified.apply(this, arguments)
@@ -122,7 +122,7 @@ function wrapPoolQuery (query) {
122
122
 
123
123
  const cb = arguments[arguments.length - 1]
124
124
  if (typeof cb === 'function') {
125
- arguments[arguments.length - 1] = shimmer.wrap(cb, function () {
125
+ arguments[arguments.length - 1] = shimmer.wrapFunction(cb, cb => function () {
126
126
  finish()
127
127
  return cb.apply(this, arguments)
128
128
  })
@@ -76,19 +76,19 @@ function wrapPrettyFactory (prettyFactory) {
76
76
  addHook({ name: 'pino', versions: ['2 - 3', '4', '>=5 <5.14.0'] }, pino => {
77
77
  const asJsonSym = (pino.symbols && pino.symbols.asJsonSym) || 'asJson'
78
78
 
79
- return shimmer.wrap(pino, wrapPino(asJsonSym, wrapAsJson, pino))
79
+ return shimmer.wrapFunction(pino, pino => wrapPino(asJsonSym, wrapAsJson, pino))
80
80
  })
81
81
 
82
82
  addHook({ name: 'pino', versions: ['>=5.14.0 <6.8.0'] }, pino => {
83
83
  const mixinSym = pino.symbols.mixinSym
84
84
 
85
- return shimmer.wrap(pino, wrapPino(mixinSym, wrapMixin, pino))
85
+ return shimmer.wrapFunction(pino, pino => wrapPino(mixinSym, wrapMixin, pino))
86
86
  })
87
87
 
88
88
  addHook({ name: 'pino', versions: ['>=6.8.0'] }, pino => {
89
89
  const mixinSym = pino.symbols.mixinSym
90
90
 
91
- const wrapped = shimmer.wrap(pino, wrapPino(mixinSym, wrapMixin, pino))
91
+ const wrapped = shimmer.wrapFunction(pino, pino => wrapPino(mixinSym, wrapMixin, pino))
92
92
  wrapped.pino = wrapped
93
93
  wrapped.default = wrapped
94
94
 
@@ -101,5 +101,5 @@ addHook({ name: 'pino-pretty', file: 'lib/utils.js', versions: ['>=3'] }, utils
101
101
  })
102
102
 
103
103
  addHook({ name: 'pino-pretty', versions: ['1 - 2'] }, prettyFactory => {
104
- return shimmer.wrap(prettyFactory, wrapPrettyFactory(prettyFactory))
104
+ return shimmer.wrapFunction(prettyFactory, wrapPrettyFactory)
105
105
  })
@@ -2,7 +2,7 @@ const semver = require('semver')
2
2
 
3
3
  const { addHook, channel, AsyncResource } = require('./helpers/instrument')
4
4
  const shimmer = require('../../datadog-shimmer')
5
- const { parseAnnotations, getTestSuitePath, NUM_FAILED_TEST_RETRIES } = require('../../dd-trace/src/plugins/util/test')
5
+ const { parseAnnotations, getTestSuitePath } = require('../../dd-trace/src/plugins/util/test')
6
6
  const log = require('../../dd-trace/src/log')
7
7
 
8
8
  const testStartCh = channel('ci:playwright:test:start')
@@ -36,8 +36,9 @@ const STATUS_TO_TEST_STATUS = {
36
36
 
37
37
  let remainingTestsByFile = {}
38
38
  let isEarlyFlakeDetectionEnabled = false
39
- let isFlakyTestRetriesEnabled = false
40
39
  let earlyFlakeDetectionNumRetries = 0
40
+ let isFlakyTestRetriesEnabled = false
41
+ let flakyTestRetriesCount = 0
41
42
  let knownTests = {}
42
43
  let rootDir = ''
43
44
  const MINIMUM_SUPPORTED_VERSION_EFD = '1.38.0'
@@ -407,6 +408,7 @@ function runnerHook (runnerExport, playwrightVersion) {
407
408
  isEarlyFlakeDetectionEnabled = libraryConfig.isEarlyFlakeDetectionEnabled
408
409
  earlyFlakeDetectionNumRetries = libraryConfig.earlyFlakeDetectionNumRetries
409
410
  isFlakyTestRetriesEnabled = libraryConfig.isFlakyTestRetriesEnabled
411
+ flakyTestRetriesCount = libraryConfig.flakyTestRetriesCount
410
412
  }
411
413
  } catch (e) {
412
414
  isEarlyFlakeDetectionEnabled = false
@@ -429,10 +431,10 @@ function runnerHook (runnerExport, playwrightVersion) {
429
431
 
430
432
  const projects = getProjectsFromRunner(this)
431
433
 
432
- if (isFlakyTestRetriesEnabled) {
434
+ if (isFlakyTestRetriesEnabled && flakyTestRetriesCount > 0) {
433
435
  projects.forEach(project => {
434
436
  if (project.retries === 0) { // Only if it hasn't been set by the user
435
- project.retries = NUM_FAILED_TEST_RETRIES
437
+ project.retries = flakyTestRetriesCount
436
438
  }
437
439
  })
438
440
  }
@@ -156,12 +156,12 @@ function start (client, command, args, url = {}) {
156
156
  }
157
157
 
158
158
  function wrapCallback (finishCh, errorCh, callback) {
159
- return function (err) {
159
+ return shimmer.wrapFunction(callback, callback => function (err) {
160
160
  finish(finishCh, errorCh, err)
161
161
  if (callback) {
162
162
  return callback.apply(this, arguments)
163
163
  }
164
- }
164
+ })
165
165
  }
166
166
 
167
167
  function finish (finishCh, errorCh, error) {