dd-trace 5.59.0 → 5.61.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 (68) hide show
  1. package/index.d.ts +6 -0
  2. package/package.json +7 -7
  3. package/packages/datadog-code-origin/index.js +3 -0
  4. package/packages/datadog-instrumentations/src/apollo-server.js +14 -3
  5. package/packages/datadog-instrumentations/src/azure-functions.js +5 -0
  6. package/packages/datadog-instrumentations/src/azure-service-bus.js +38 -0
  7. package/packages/datadog-instrumentations/src/fastify.js +17 -0
  8. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  9. package/packages/datadog-instrumentations/src/next.js +17 -18
  10. package/packages/datadog-instrumentations/src/openai.js +13 -114
  11. package/packages/datadog-instrumentations/src/sequelize.js +4 -14
  12. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +6 -38
  13. package/packages/datadog-plugin-azure-functions/src/index.js +57 -28
  14. package/packages/datadog-plugin-azure-service-bus/src/index.js +15 -0
  15. package/packages/datadog-plugin-azure-service-bus/src/producer.js +36 -0
  16. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +24 -23
  17. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +3 -155
  18. package/packages/datadog-plugin-langchain/src/handlers/default.js +0 -18
  19. package/packages/datadog-plugin-langchain/src/handlers/embedding.js +0 -48
  20. package/packages/datadog-plugin-langchain/src/handlers/language_models.js +18 -0
  21. package/packages/datadog-plugin-langchain/src/tracing.js +5 -17
  22. package/packages/datadog-plugin-openai/src/stream-helpers.js +114 -0
  23. package/packages/datadog-plugin-openai/src/tracing.js +38 -0
  24. package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +8 -1
  25. package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +2 -2
  26. package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +11 -10
  27. package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +25 -18
  28. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +13 -5
  29. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +5 -1
  30. package/packages/dd-trace/src/appsec/iast/analyzers/xcontenttype-header-missing-analyzer.js +2 -2
  31. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +4 -0
  32. package/packages/dd-trace/src/appsec/iast/index.js +25 -7
  33. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +79 -21
  34. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -3
  35. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +0 -4
  36. package/packages/dd-trace/src/appsec/reporter.js +3 -15
  37. package/packages/dd-trace/src/appsec/waf/index.js +20 -1
  38. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +2 -1
  39. package/packages/dd-trace/src/config.js +0 -16
  40. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +4 -8
  41. package/packages/dd-trace/src/datastreams/schemas/schema_sampler.js +2 -4
  42. package/packages/dd-trace/src/debugger/config.js +16 -0
  43. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +1 -1
  44. package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -6
  45. package/packages/dd-trace/src/debugger/devtools_client/index.js +1 -1
  46. package/packages/dd-trace/src/debugger/devtools_client/log.js +19 -0
  47. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +1 -1
  48. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -1
  49. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +1 -1
  50. package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -1
  51. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
  52. package/packages/dd-trace/src/debugger/index.js +13 -3
  53. package/packages/dd-trace/src/plugins/index.js +1 -0
  54. package/packages/dd-trace/src/plugins/util/ci.js +23 -7
  55. package/packages/dd-trace/src/plugins/util/git.js +53 -18
  56. package/packages/dd-trace/src/plugins/util/tags.js +8 -6
  57. package/packages/dd-trace/src/profiling/profilers/events.js +3 -3
  58. package/packages/dd-trace/src/profiling/profilers/space.js +4 -3
  59. package/packages/dd-trace/src/profiling/profilers/wall.js +5 -4
  60. package/packages/dd-trace/src/remote_config/capabilities.js +2 -1
  61. package/packages/dd-trace/src/remote_config/index.js +2 -0
  62. package/packages/dd-trace/src/remote_config/scheduler.js +2 -1
  63. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +4 -0
  64. package/packages/dd-trace/src/supported-configurations.json +1 -0
  65. package/packages/datadog-plugin-langchain/src/handlers/chain.js +0 -50
  66. package/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js +0 -101
  67. package/packages/datadog-plugin-langchain/src/handlers/language_models/index.js +0 -48
  68. package/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js +0 -58
package/index.d.ts CHANGED
@@ -167,6 +167,7 @@ interface Plugins {
167
167
  "avsc": tracer.plugins.avsc;
168
168
  "aws-sdk": tracer.plugins.aws_sdk;
169
169
  "azure-functions": tracer.plugins.azure_functions;
170
+ "azure-service-bus": tracer.plugins.azure_service_bus;
170
171
  "bunyan": tracer.plugins.bunyan;
171
172
  "cassandra-driver": tracer.plugins.cassandra_driver;
172
173
  "child_process": tracer.plugins.child_process;
@@ -1381,6 +1382,11 @@ declare namespace tracer {
1381
1382
  */
1382
1383
  interface azure_functions extends Instrumentation {}
1383
1384
 
1385
+ /**
1386
+ * This plugin automatically instruments the
1387
+ * @azure/service-bus module
1388
+ */
1389
+ interface azure_service_bus extends Integration {}
1384
1390
  /**
1385
1391
  * This plugin patches the [bunyan](https://github.com/trentm/node-bunyan)
1386
1392
  * to automatically inject trace identifiers in log records when the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.59.0",
3
+ "version": "5.61.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -114,7 +114,7 @@
114
114
  ],
115
115
  "dependencies": {
116
116
  "@datadog/libdatadog": "0.7.0",
117
- "@datadog/native-appsec": "10.0.0",
117
+ "@datadog/native-appsec": "10.0.1",
118
118
  "@datadog/native-iast-taint-tracking": "4.0.0",
119
119
  "@datadog/native-metrics": "3.1.1",
120
120
  "@datadog/pprof": "5.9.0",
@@ -124,7 +124,7 @@
124
124
  "@opentelemetry/api": "1.8.0",
125
125
  "@opentelemetry/core": "^1.14.0",
126
126
  "crypto-randomuuid": "^1.0.0",
127
- "dc-polyfill": "^0.1.9",
127
+ "dc-polyfill": "^0.1.10",
128
128
  "ignore": "^7.0.5",
129
129
  "import-in-the-middle": "^1.14.2",
130
130
  "istanbul-lib-coverage": "^3.2.2",
@@ -155,7 +155,7 @@
155
155
  "@msgpack/msgpack": "^3.1.2",
156
156
  "@stylistic/eslint-plugin": "^5.0.0",
157
157
  "@types/node": "^18.19.106",
158
- "axios": "^1.10.0",
158
+ "axios": "^1.11.0",
159
159
  "benchmark": "^2.1.4",
160
160
  "body-parser": "^2.2.0",
161
161
  "chai": "^4.5.0",
@@ -165,15 +165,15 @@
165
165
  "eslint-plugin-mocha": "^10.5.0",
166
166
  "eslint-plugin-n": "^17.20.0",
167
167
  "eslint-plugin-promise": "^7.2.1",
168
- "eslint-plugin-unicorn": "^59.0.1",
168
+ "eslint-plugin-unicorn": "^60.0.0",
169
169
  "express": "^5.1.0",
170
170
  "get-port": "^5.1.1",
171
171
  "glob": "^7.2.3",
172
- "globals": "^15.15.0",
172
+ "globals": "^16.3.0",
173
173
  "graphql": "*",
174
174
  "jszip": "^3.10.1",
175
175
  "mocha": "^11.6.0",
176
- "multer": "^2.0.1",
176
+ "multer": "^2.0.2",
177
177
  "nock": "^11.9.1",
178
178
  "nyc": "^15.1.0",
179
179
  "octokit": "^5.0.3",
@@ -38,9 +38,12 @@ function exitTags (topOfStackFunc) {
38
38
  function tag (type, topOfStackFunc, limit) {
39
39
  // The `Error.prepareStackTrace` API doesn't support resolving source maps.
40
40
  // Fall back to manually parsing the stack trace.
41
+ const originalLimit = Error.stackTraceLimit
42
+ Error.stackTraceLimit = Infinity
41
43
  const dummy = {}
42
44
  Error.captureStackTrace(dummy, topOfStackFunc)
43
45
  const frames = parseUserLandFrames(dummy.stack, limit)
46
+ Error.stackTraceLimit = originalLimit
44
47
 
45
48
  const tags = {
46
49
  '_dd.code_origin.type': type
@@ -77,6 +77,17 @@ function apolloServerHook (apolloServer) {
77
77
  return apolloServer
78
78
  }
79
79
 
80
- addHook({ name: '@apollo/server', file: 'dist/cjs/ApolloServer.js', versions: ['>=4.0.0'] }, apolloServerHook)
81
- addHook({ name: '@apollo/server', file: 'dist/cjs/express4/index.js', versions: ['>=4.0.0'] }, apolloExpress4Hook)
82
- addHook({ name: '@apollo/server', file: 'dist/cjs/utils/HeaderMap.js', versions: ['>=4.0.0'] }, apolloHeaderMapHook)
80
+ addHook(
81
+ { name: '@apollo/server', file: 'dist/cjs/ApolloServer.js', versions: ['>=4.0.0 <5.0.0'] },
82
+ apolloServerHook
83
+ )
84
+
85
+ addHook(
86
+ { name: '@apollo/server', file: 'dist/cjs/express4/index.js', versions: ['>=4.0.0 <5.0.0'] },
87
+ apolloExpress4Hook
88
+ )
89
+
90
+ addHook(
91
+ { name: '@apollo/server', file: 'dist/cjs/utils/HeaderMap.js', versions: ['>=4.0.0 <5.0.0'] },
92
+ apolloHeaderMapHook
93
+ )
@@ -11,6 +11,7 @@ const azureFunctionsChannel = dc.tracingChannel('datadog:azure:functions:invoke'
11
11
  addHook({ name: '@azure/functions', versions: ['>=4'] }, azureFunction => {
12
12
  const { app } = azureFunction
13
13
 
14
+ // Http triggers
14
15
  shimmer.wrap(app, 'deleteRequest', wrapHandler)
15
16
  shimmer.wrap(app, 'http', wrapHandler)
16
17
  shimmer.wrap(app, 'get', wrapHandler)
@@ -18,6 +19,10 @@ addHook({ name: '@azure/functions', versions: ['>=4'] }, azureFunction => {
18
19
  shimmer.wrap(app, 'post', wrapHandler)
19
20
  shimmer.wrap(app, 'put', wrapHandler)
20
21
 
22
+ // Service Bus triggers
23
+ shimmer.wrap(app, 'serviceBusQueue', wrapHandler)
24
+ shimmer.wrap(app, 'serviceBusTopic', wrapHandler)
25
+
21
26
  return azureFunction
22
27
  })
23
28
 
@@ -0,0 +1,38 @@
1
+ 'use strict'
2
+
3
+ const {
4
+ channel,
5
+ addHook
6
+ } = require('./helpers/instrument')
7
+
8
+ const shimmer = require('../../datadog-shimmer')
9
+
10
+ const producerStartCh = channel('apm:azure-service-bus:send:start')
11
+ const producerErrorCh = channel('apm:azure-service-bus:send:error')
12
+ const producerFinishCh = channel('apm:azure-service-bus:send:finish')
13
+
14
+ addHook({ name: '@azure/service-bus', versions: ['>=7.9.2'] }, (obj) => {
15
+ const ServiceBusClient = obj.ServiceBusClient
16
+ shimmer.wrap(ServiceBusClient.prototype, 'createSender', createSender => function (queueOrTopicName) {
17
+ const sender = createSender.apply(this, arguments)
18
+ shimmer.wrap(sender._sender, 'send', send => function (msg) {
19
+ const ctx = { sender, msg }
20
+ return producerStartCh.runStores(ctx, () => {
21
+ return send.apply(this, arguments)
22
+ .then(
23
+ response => {
24
+ producerFinishCh.publish(ctx)
25
+ },
26
+ error => {
27
+ ctx.error = error
28
+ producerErrorCh.publish(ctx)
29
+ producerFinishCh.publish(ctx)
30
+ throw error
31
+ }
32
+ )
33
+ })
34
+ })
35
+ return sender
36
+ })
37
+ return obj
38
+ })
@@ -11,6 +11,7 @@ const queryParamsReadCh = channel('datadog:fastify:query-params:finish')
11
11
  const cookieParserReadCh = channel('datadog:fastify-cookie:read:finish')
12
12
  const responsePayloadReadCh = channel('datadog:fastify:response:finish')
13
13
  const pathParamsReadCh = channel('datadog:fastify:path-params:finish')
14
+ const finishSetHeaderCh = channel('datadog:fastify:set-header:finish')
14
15
 
15
16
  const parsingResources = new WeakMap()
16
17
  const cookiesPublished = new WeakSet()
@@ -275,3 +276,19 @@ addHook({ name: 'fastify', versions: ['2'] }, fastify => {
275
276
  addHook({ name: 'fastify', versions: ['1'] }, fastify => {
276
277
  return shimmer.wrapFunction(fastify, fastify => wrapFastify(fastify, false))
277
278
  })
279
+
280
+ function wrapReplyHeader (Reply) {
281
+ shimmer.wrap(Reply.prototype, 'header', header => function (key, value) {
282
+ const result = header.apply(this, arguments)
283
+
284
+ if (finishSetHeaderCh.hasSubscribers && key && value) {
285
+ finishSetHeaderCh.publish({ name: key, value, res: getRes(this) })
286
+ }
287
+
288
+ return result
289
+ })
290
+
291
+ return Reply
292
+ }
293
+
294
+ addHook({ name: 'fastify', file: 'lib/reply.js', versions: ['1', '2', '>=3'] }, wrapReplyHeader)
@@ -6,6 +6,7 @@ module.exports = {
6
6
  'apollo-server-core': () => require('../apollo-server-core'),
7
7
  '@aws-sdk/smithy-client': () => require('../aws-sdk'),
8
8
  '@azure/functions': () => require('../azure-functions'),
9
+ '@azure/service-bus': () => require('../azure-service-bus'),
9
10
  '@cucumber/cucumber': () => require('../cucumber'),
10
11
  '@playwright/test': () => require('../playwright'),
11
12
  '@elastic/elasticsearch': () => require('../elasticsearch'),
@@ -141,6 +141,20 @@ function instrument (req, res, handler, error) {
141
141
  requests.add(req)
142
142
 
143
143
  const ctx = { req, res }
144
+ // Parse query parameters from request URL
145
+ if (queryParsedChannel.hasSubscribers && req.url) {
146
+ // req.url is only the relative path (/foo?bar=baz) and new URL() needs a full URL
147
+ // so we give it a dummy base
148
+ const { searchParams } = new URL(req.url, 'http://dummy')
149
+ const query = {}
150
+ for (const key of searchParams.keys()) {
151
+ if (!query[key]) {
152
+ query[key] = searchParams.getAll(key)
153
+ }
154
+ }
155
+
156
+ queryParsedChannel.publish({ query })
157
+ }
144
158
 
145
159
  return startChannel.runStores(ctx, () => {
146
160
  try {
@@ -280,24 +294,9 @@ addHook({
280
294
  versions: ['>=13'],
281
295
  file: 'dist/server/web/spec-extension/request.js'
282
296
  }, request => {
283
- shimmer.wrap(request.NextRequest.prototype, 'nextUrl', function (originalGet) {
284
- return function wrappedGet () {
285
- const nextUrl = originalGet.apply(this, arguments)
286
- if (queryParsedChannel.hasSubscribers) {
287
- const query = {}
288
- for (const key of nextUrl.searchParams.keys()) {
289
- if (!query[key]) {
290
- query[key] = nextUrl.searchParams.getAll(key)
291
- }
292
- }
293
-
294
- queryParsedChannel.publish({ query })
295
- }
296
- return nextUrl
297
- }
298
- })
297
+ const requestProto = Object.getPrototypeOf(request.NextRequest.prototype)
299
298
 
300
- shimmer.massWrap(request.NextRequest.prototype, ['text', 'json'], function (originalMethod) {
299
+ shimmer.massWrap(requestProto, ['text', 'json'], function (originalMethod) {
301
300
  return async function wrappedJson () {
302
301
  const body = await originalMethod.apply(this, arguments)
303
302
 
@@ -307,7 +306,7 @@ addHook({
307
306
  }
308
307
  })
309
308
 
310
- shimmer.wrap(request.NextRequest.prototype, 'formData', function (originalFormData) {
309
+ shimmer.wrap(requestProto, 'formData', function (originalFormData) {
311
310
  return async function wrappedFormData () {
312
311
  const body = await originalFormData.apply(this, arguments)
313
312
 
@@ -5,6 +5,7 @@ const shimmer = require('../../datadog-shimmer')
5
5
 
6
6
  const dc = require('dc-polyfill')
7
7
  const ch = dc.tracingChannel('apm:openai:request')
8
+ const onStreamedChunkCh = dc.channel('apm:openai:request:chunk')
8
9
 
9
10
  const V4_PACKAGE_SHIMS = [
10
11
  {
@@ -160,79 +161,12 @@ addHook({ name: 'openai', file: 'dist/api.js', versions: ['>=3.0.0 <4'] }, expor
160
161
  return exports
161
162
  })
162
163
 
163
- function addStreamedChunk (content, chunk) {
164
- content.usage = chunk.usage // add usage if it was specified to be returned
165
- for (const choice of chunk.choices) {
166
- const choiceIdx = choice.index
167
- const oldChoice = content.choices.find(choice => choice?.index === choiceIdx)
168
- if (oldChoice) {
169
- if (!oldChoice.finish_reason) {
170
- oldChoice.finish_reason = choice.finish_reason
171
- }
172
-
173
- // delta exists on chat completions
174
- const delta = choice.delta
175
-
176
- if (delta) {
177
- const content = delta.content
178
- if (content) {
179
- if (oldChoice.delta.content) { // we don't want to append to undefined
180
- oldChoice.delta.content += content
181
- } else {
182
- oldChoice.delta.content = content
183
- }
184
- }
185
- } else {
186
- const text = choice.text
187
- if (text) {
188
- if (oldChoice.text) {
189
- oldChoice.text += text
190
- } else {
191
- oldChoice.text = text
192
- }
193
- }
194
- }
195
-
196
- // tools only exist on chat completions
197
- const tools = delta && choice.delta.tool_calls
198
-
199
- if (tools) {
200
- oldChoice.delta.tool_calls = tools.map((newTool, toolIdx) => {
201
- const oldTool = oldChoice.delta.tool_calls?.[toolIdx]
202
-
203
- if (oldTool) {
204
- oldTool.function.arguments += newTool.function.arguments
205
- return oldTool
206
- }
207
-
208
- return newTool
209
- })
210
- }
211
- } else {
212
- // we don't know which choices arrive in which order
213
- content.choices[choiceIdx] = choice
214
- }
215
- }
216
- }
217
-
218
- function convertBufferstoObjects (chunks) {
219
- return Buffer
220
- .concat(chunks) // combine the buffers
221
- .toString() // stringify
222
- .split(/(?=data:)/) // split on "data:"
223
- .map(chunk => chunk.replaceAll('\n', '').slice(6)) // remove newlines and 'data: ' from the front
224
- .slice(0, -1) // remove the last [DONE] message
225
- .map(JSON.parse) // parse all of the returned objects
226
- }
227
-
228
164
  /**
229
165
  * For streamed responses, we need to accumulate all of the content in
230
166
  * the chunks, and let the combined content be the final response.
231
167
  * This way, spans look the same as when not streamed.
232
168
  */
233
- function wrapStreamIterator (response, options, n, ctx) {
234
- let processChunksAsBuffers = false
235
- let chunks = []
169
+ function wrapStreamIterator (response, options, ctx) {
236
170
  return function (itr) {
237
171
  return function () {
238
172
  const iterator = itr.apply(this, arguments)
@@ -240,39 +174,11 @@ function wrapStreamIterator (response, options, n, ctx) {
240
174
  return next.apply(this, arguments)
241
175
  .then(res => {
242
176
  const { done, value: chunk } = res
243
-
244
- if (chunk) {
245
- chunks.push(chunk)
246
- // TODO(BridgeAR): It likely depends on the options being passed
247
- // through if the stream returns buffers or not. By reading that,
248
- // we don't have to do the instanceof check anymore, which is
249
- // relatively expensive.
250
- if (chunk instanceof Buffer) {
251
- // this operation should be safe
252
- // if one chunk is a buffer (versus a plain object), the rest should be as well
253
- processChunksAsBuffers = true
254
- }
255
- }
177
+ onStreamedChunkCh.publish({ ctx, chunk, done })
256
178
 
257
179
  if (done) {
258
- let body = {}
259
- if (processChunksAsBuffers) {
260
- chunks = convertBufferstoObjects(chunks)
261
- }
262
-
263
- if (chunks.length) {
264
- // Define the initial body having all the content outside of choices from the first chunk
265
- // this will include import data like created, id, model, etc.
266
- body = { ...chunks[0], choices: Array.from({ length: n }) }
267
- // Start from the first chunk, and add its choices into the body
268
- for (const chunk_ of chunks) {
269
- addStreamedChunk(body, chunk_)
270
- }
271
- }
272
-
273
180
  finish(ctx, {
274
181
  headers: response.headers,
275
- data: body,
276
182
  request: {
277
183
  path: response.url,
278
184
  method: options.method
@@ -312,17 +218,6 @@ for (const extension of extensions) {
312
218
  // chat.completions and completions
313
219
  const stream = streamedResponse && getOption(arguments, 'stream', false)
314
220
 
315
- // we need to compute how many prompts we are sending in streamed cases for completions
316
- // not applicable for chat completiond
317
- let n
318
- if (stream) {
319
- n = getOption(arguments, 'n', 1)
320
- const prompt = getOption(arguments, 'prompt')
321
- if (Array.isArray(prompt) && typeof prompt[0] !== 'number') {
322
- n *= prompt.length
323
- }
324
- }
325
-
326
221
  const client = this._client || this.client
327
222
 
328
223
  const ctx = {
@@ -348,7 +243,7 @@ for (const extension of extensions) {
348
243
  const parsedPromise = origApiPromParse.apply(this, arguments)
349
244
  .then(body => Promise.all([this.responsePromise, body]))
350
245
 
351
- return handleUnwrappedAPIPromise(parsedPromise, ctx, stream, n)
246
+ return handleUnwrappedAPIPromise(parsedPromise, ctx, stream)
352
247
  })
353
248
 
354
249
  return unwrappedPromise
@@ -361,7 +256,7 @@ for (const extension of extensions) {
361
256
  const parsedPromise = origApiPromParse.apply(this, arguments)
362
257
  .then(body => Promise.all([this.responsePromise, body]))
363
258
 
364
- return handleUnwrappedAPIPromise(parsedPromise, ctx, stream, n)
259
+ return handleUnwrappedAPIPromise(parsedPromise, ctx, stream)
365
260
  })
366
261
 
367
262
  ch.end.publish(ctx)
@@ -375,15 +270,15 @@ for (const extension of extensions) {
375
270
  }
376
271
  }
377
272
 
378
- function handleUnwrappedAPIPromise (apiProm, ctx, stream, n) {
273
+ function handleUnwrappedAPIPromise (apiProm, ctx, stream) {
379
274
  return apiProm
380
275
  .then(([{ response, options }, body]) => {
381
276
  if (stream) {
382
277
  if (body.iterator) {
383
- shimmer.wrap(body, 'iterator', wrapStreamIterator(response, options, n, ctx))
278
+ shimmer.wrap(body, 'iterator', wrapStreamIterator(response, options, ctx))
384
279
  } else {
385
280
  shimmer.wrap(
386
- body.response.body, Symbol.asyncIterator, wrapStreamIterator(response, options, n, ctx)
281
+ body.response.body, Symbol.asyncIterator, wrapStreamIterator(response, options, ctx)
387
282
  )
388
283
  }
389
284
  } else {
@@ -412,7 +307,11 @@ function finish (ctx, response, error) {
412
307
  ch.error.publish(ctx)
413
308
  }
414
309
 
415
- ctx.result = response
310
+ // for successful streamed responses, we've already set the result on ctx.body,
311
+ // so we don't want to override it here
312
+ ctx.result ??= {}
313
+ Object.assign(ctx.result, response)
314
+
416
315
  ch.asyncEnd.publish(ctx)
417
316
  }
418
317
 
@@ -2,8 +2,7 @@
2
2
 
3
3
  const {
4
4
  channel,
5
- addHook,
6
- AsyncResource
5
+ addHook
7
6
  } = require('./helpers/instrument')
8
7
 
9
8
  const shimmer = require('../../datadog-shimmer')
@@ -18,8 +17,6 @@ addHook({ name: 'sequelize', versions: ['>=4'] }, Sequelize => {
18
17
  return query.apply(this, arguments)
19
18
  }
20
19
 
21
- const asyncResource = new AsyncResource('bound-anonymous-fn')
22
-
23
20
  let dialect
24
21
  if (this.options && this.options.dialect) {
25
22
  dialect = this.options.dialect
@@ -33,22 +30,15 @@ addHook({ name: 'sequelize', versions: ['>=4'] }, Sequelize => {
33
30
  result = result[0]
34
31
  }
35
32
 
36
- asyncResource.bind(function () {
37
- finishCh.publish({ result })
38
- }, this).apply(this)
33
+ finishCh.runStores({ result }, () => {})
39
34
  }
40
35
 
41
- return asyncResource.bind(function () {
42
- startCh.publish({
43
- sql,
44
- dialect
45
- })
46
-
36
+ return startCh.runStores({ sql, dialect }, () => {
47
37
  const promise = query.apply(this, arguments)
48
38
  promise.then(onFinish, () => { onFinish() })
49
39
 
50
40
  return promise
51
- }, this).apply(this, arguments)
41
+ })
52
42
  }
53
43
  })
54
44
 
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const BaseAwsSdkPlugin = require('../../base')
4
- const { parseModelId, extractRequestParams, extractTextAndResponseReason } = require('./utils')
4
+ const { parseModelId } = require('./utils')
5
5
 
6
6
  const enabledOperations = new Set(['invokeModel'])
7
7
 
@@ -20,44 +20,12 @@ class BedrockRuntime extends BaseAwsSdkPlugin {
20
20
  generateTags (params, operation, response) {
21
21
  const { modelProvider, modelName } = parseModelId(params.modelId)
22
22
 
23
- const requestParams = extractRequestParams(params, modelProvider)
24
- const textAndResponseReason = extractTextAndResponseReason(response, modelProvider, modelName)
25
-
26
- const tags = buildTagsFromParams(requestParams, textAndResponseReason, modelProvider, modelName, operation)
27
-
28
- return tags
29
- }
30
- }
31
-
32
- function buildTagsFromParams (requestParams, textAndResponseReason, modelProvider, modelName, operation) {
33
- const tags = {}
34
-
35
- // add request tags
36
- tags['resource.name'] = operation
37
- tags['aws.bedrock.request.model'] = modelName
38
- tags['aws.bedrock.request.model_provider'] = modelProvider.toLowerCase()
39
- tags['aws.bedrock.request.prompt'] = requestParams.prompt
40
- tags['aws.bedrock.request.temperature'] = requestParams.temperature
41
- tags['aws.bedrock.request.top_p'] = requestParams.topP
42
- tags['aws.bedrock.request.top_k'] = requestParams.topK
43
- tags['aws.bedrock.request.max_tokens'] = requestParams.maxTokens
44
- tags['aws.bedrock.request.stop_sequences'] = requestParams.stopSequences
45
- tags['aws.bedrock.request.input_type'] = requestParams.inputType
46
- tags['aws.bedrock.request.truncate'] = requestParams.truncate
47
- tags['aws.bedrock.request.stream'] = requestParams.stream
48
- tags['aws.bedrock.request.n'] = requestParams.n
49
-
50
- // add response tags
51
- if (modelName.includes('embed')) {
52
- tags['aws.bedrock.response.embedding_length'] = textAndResponseReason.message.length
53
- }
54
- if (textAndResponseReason.choiceId) {
55
- tags['aws.bedrock.response.choices.id'] = textAndResponseReason.choiceId
23
+ return {
24
+ 'resource.name': operation,
25
+ 'aws.bedrock.request.model': modelName,
26
+ 'aws.bedrock.request.model_provider': modelProvider.toLowerCase()
27
+ }
56
28
  }
57
- tags['aws.bedrock.response.choices.text'] = textAndResponseReason.message
58
- tags['aws.bedrock.response.choices.finish_reason'] = textAndResponseReason.finishReason
59
-
60
- return tags
61
29
  }
62
30
 
63
31
  module.exports = BedrockRuntime