dd-trace 5.34.0 → 5.36.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 (97) hide show
  1. package/index.d.ts +3 -7
  2. package/package.json +4 -4
  3. package/packages/datadog-core/index.js +1 -1
  4. package/packages/datadog-core/src/storage.js +76 -31
  5. package/packages/datadog-instrumentations/src/aws-sdk.js +16 -0
  6. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  7. package/packages/datadog-instrumentations/src/jest.js +3 -7
  8. package/packages/datadog-instrumentations/src/passport.js +45 -0
  9. package/packages/datadog-plugin-aerospike/src/index.js +1 -1
  10. package/packages/datadog-plugin-apollo/src/gateway/fetch.js +1 -1
  11. package/packages/datadog-plugin-apollo/src/gateway/index.js +1 -1
  12. package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -1
  13. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -3
  14. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +33 -6
  15. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -4
  16. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -2
  17. package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
  18. package/packages/datadog-plugin-couchbase/src/index.js +2 -2
  19. package/packages/datadog-plugin-cucumber/src/index.js +11 -11
  20. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +6 -1
  21. package/packages/datadog-plugin-cypress/src/support.js +36 -29
  22. package/packages/datadog-plugin-dd-trace-api/src/index.js +120 -0
  23. package/packages/datadog-plugin-grpc/src/client.js +1 -1
  24. package/packages/datadog-plugin-grpc/src/server.js +1 -1
  25. package/packages/datadog-plugin-hapi/src/index.js +1 -1
  26. package/packages/datadog-plugin-http/src/client.js +1 -1
  27. package/packages/datadog-plugin-http/src/server.js +1 -1
  28. package/packages/datadog-plugin-http2/src/client.js +3 -3
  29. package/packages/datadog-plugin-http2/src/server.js +1 -1
  30. package/packages/datadog-plugin-jest/src/index.js +6 -11
  31. package/packages/datadog-plugin-langchain/src/tracing.js +1 -1
  32. package/packages/datadog-plugin-mariadb/src/index.js +3 -3
  33. package/packages/datadog-plugin-mocha/src/index.js +13 -13
  34. package/packages/datadog-plugin-next/src/index.js +4 -4
  35. package/packages/datadog-plugin-openai/src/tracing.js +1 -1
  36. package/packages/datadog-plugin-playwright/src/index.js +4 -4
  37. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  38. package/packages/datadog-plugin-router/src/index.js +2 -2
  39. package/packages/datadog-plugin-selenium/src/index.js +1 -1
  40. package/packages/datadog-plugin-vitest/src/index.js +11 -11
  41. package/packages/dd-trace/src/appsec/blocking.js +4 -1
  42. package/packages/dd-trace/src/appsec/channels.js +1 -0
  43. package/packages/dd-trace/src/appsec/graphql.js +6 -6
  44. package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +1 -1
  45. package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +6 -6
  46. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +2 -2
  47. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +5 -5
  48. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +2 -2
  49. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +2 -1
  50. package/packages/dd-trace/src/appsec/iast/context/context-plugin.js +2 -2
  51. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +2 -2
  52. package/packages/dd-trace/src/appsec/iast/index.js +2 -2
  53. package/packages/dd-trace/src/appsec/iast/taint-tracking/constants.js +6 -0
  54. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +8 -8
  55. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +1 -1
  56. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +65 -0
  57. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +14 -5
  58. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +80 -2
  59. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
  60. package/packages/dd-trace/src/appsec/index.js +20 -3
  61. package/packages/dd-trace/src/appsec/rasp/command_injection.js +1 -1
  62. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +5 -5
  63. package/packages/dd-trace/src/appsec/rasp/lfi.js +1 -1
  64. package/packages/dd-trace/src/appsec/rasp/sql_injection.js +2 -2
  65. package/packages/dd-trace/src/appsec/rasp/ssrf.js +1 -1
  66. package/packages/dd-trace/src/appsec/reporter.js +3 -3
  67. package/packages/dd-trace/src/appsec/sdk/set_user.js +9 -0
  68. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -1
  69. package/packages/dd-trace/src/appsec/telemetry.js +10 -0
  70. package/packages/dd-trace/src/appsec/user_tracking.js +32 -6
  71. package/packages/dd-trace/src/appsec/waf/index.js +1 -1
  72. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +2 -0
  73. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +17 -10
  74. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +3 -3
  75. package/packages/dd-trace/src/config.js +2 -0
  76. package/packages/dd-trace/src/data_streams_context.js +2 -2
  77. package/packages/dd-trace/src/debugger/devtools_client/state.js +8 -3
  78. package/packages/dd-trace/src/exporters/common/agents.js +1 -1
  79. package/packages/dd-trace/src/exporters/common/request.js +3 -3
  80. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +49 -4
  81. package/packages/dd-trace/src/log/writer.js +3 -3
  82. package/packages/dd-trace/src/noop/span.js +1 -1
  83. package/packages/dd-trace/src/opentracing/propagation/text_map.js +5 -4
  84. package/packages/dd-trace/src/opentracing/span.js +1 -1
  85. package/packages/dd-trace/src/plugin_manager.js +6 -1
  86. package/packages/dd-trace/src/plugins/apollo.js +1 -1
  87. package/packages/dd-trace/src/plugins/ci_plugin.js +35 -1
  88. package/packages/dd-trace/src/plugins/index.js +1 -0
  89. package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
  90. package/packages/dd-trace/src/plugins/plugin.js +8 -8
  91. package/packages/dd-trace/src/plugins/tracing.js +3 -3
  92. package/packages/dd-trace/src/plugins/util/git.js +3 -3
  93. package/packages/dd-trace/src/plugins/util/test.js +5 -1
  94. package/packages/dd-trace/src/profiling/exporters/agent.js +3 -3
  95. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
  96. package/packages/dd-trace/src/scope.js +5 -5
  97. package/packages/dd-trace/src/tracer.js +0 -14
package/index.d.ts CHANGED
@@ -85,10 +85,6 @@ interface Tracer extends opentracing.Tracer {
85
85
  * span will finish when that callback is called.
86
86
  * * The function doesn't accept a callback and doesn't return a promise, in
87
87
  * which case the span will finish at the end of the function execution.
88
- *
89
- * If the `orphanable` option is set to false, the function will not be traced
90
- * unless there is already an active span or `childOf` option. Note that this
91
- * option is deprecated and has been removed in version 4.0.
92
88
  */
93
89
  trace<T> (name: string, fn: (span: tracer.Span) => T): T;
94
90
  trace<T> (name: string, fn: (span: tracer.Span, done: (error?: Error) => void) => T): T;
@@ -659,13 +655,13 @@ declare namespace tracer {
659
655
  * * 'anonymous': will hash user IDs and user logins before collecting them
660
656
  * * 'anon': alias for 'anonymous'
661
657
  * * 'safe': deprecated alias for 'anonymous'
662
- *
658
+ *
663
659
  * * 'identification': will collect user IDs and logins without redaction
664
660
  * * 'ident': alias for 'identification'
665
661
  * * 'extended': deprecated alias for 'identification'
666
- *
662
+ *
667
663
  * * 'disabled': will not collect user IDs and logins
668
- *
664
+ *
669
665
  * Unknown values will be considered as 'disabled'
670
666
  * @default 'identification'
671
667
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.34.0",
3
+ "version": "5.36.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -13,7 +13,7 @@
13
13
  "type:doc": "cd docs && yarn && yarn build",
14
14
  "type:test": "cd docs && yarn && yarn test",
15
15
  "lint": "node scripts/check_licenses.js && eslint . && yarn audit",
16
- "lint-fix": "node scripts/check_licenses.js && eslint . --fix && yarn audit",
16
+ "lint:fix": "node scripts/check_licenses.js && eslint . --fix && yarn audit",
17
17
  "release:proposal": "node scripts/release/proposal",
18
18
  "services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
19
19
  "test": "SERVICES=* yarn services && mocha --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
@@ -83,7 +83,7 @@
83
83
  "dependencies": {
84
84
  "@datadog/libdatadog": "^0.4.0",
85
85
  "@datadog/native-appsec": "8.4.0",
86
- "@datadog/native-iast-rewriter": "2.6.1",
86
+ "@datadog/native-iast-rewriter": "2.8.0",
87
87
  "@datadog/native-iast-taint-tracking": "3.2.0",
88
88
  "@datadog/native-metrics": "^3.1.0",
89
89
  "@datadog/pprof": "5.5.1",
@@ -117,7 +117,7 @@
117
117
  "devDependencies": {
118
118
  "@apollo/server": "^4.11.0",
119
119
  "@eslint/eslintrc": "^3.1.0",
120
- "@eslint/js": "^9.11.1",
120
+ "@eslint/js": "^8.57.1",
121
121
  "@msgpack/msgpack": "^3.0.0-beta3",
122
122
  "@stylistic/eslint-plugin-js": "^2.8.0",
123
123
  "@types/node": "^16.0.0",
@@ -1,5 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const storage = require('./src/storage')
3
+ const { storage } = require('./src/storage')
4
4
 
5
5
  module.exports = { storage }
@@ -2,66 +2,111 @@
2
2
 
3
3
  const { AsyncLocalStorage } = require('async_hooks')
4
4
 
5
- class DatadogStorage {
6
- constructor () {
7
- this._storage = new AsyncLocalStorage()
8
- }
9
-
10
- disable () {
11
- this._storage.disable()
12
- }
13
-
5
+ /**
6
+ * This is exactly the same as AsyncLocalStorage, with the exception that it
7
+ * uses a WeakMap to store the store object. This is because ALS stores the
8
+ * store object as a property of the resource object, which causes all sorts
9
+ * of problems with logging and memory. We substitute the `store` object with
10
+ * a "handle" object, which is used as a key in a WeakMap, where the values
11
+ * are the real store objects.
12
+ *
13
+ * @template T
14
+ */
15
+ class DatadogStorage extends AsyncLocalStorage {
16
+ /**
17
+ *
18
+ * @param store {DatadogStorage}
19
+ */
14
20
  enterWith (store) {
15
21
  const handle = {}
16
22
  stores.set(handle, store)
17
- this._storage.enterWith(handle)
18
- }
19
-
20
- exit (callback, ...args) {
21
- this._storage.exit(callback, ...args)
23
+ super.enterWith(handle)
22
24
  }
23
25
 
24
- // TODO: Refactor the Scope class to use a span-only store and remove this.
26
+ /**
27
+ * This is method is a passthrough to the real `getStore()`, so that, when we
28
+ * need it, we can use the handle rather than our mapped store.
29
+ *
30
+ * It's only here because stores are currently used for a bunch of things,
31
+ * and we don't want to hold on to all of them in spans
32
+ * (see opentracing/span.js). Using a namespaced storage for spans would
33
+ * solve this.
34
+ *
35
+ * TODO: Refactor the Scope class to use a span-only store and remove this.
36
+ *
37
+ * @returns {{}}
38
+ */
25
39
  getHandle () {
26
- return this._storage.getStore()
40
+ return super.getStore()
27
41
  }
28
42
 
43
+ /**
44
+ * Here, we replicate the behavior of the original `getStore()` method by
45
+ * passing in the handle, which we retrieve by calling it on super. Handles
46
+ * retrieved through `getHandle()` can also be passed in to be used as the
47
+ * key. This is useful if you've stashed a handle somewhere and want to
48
+ * retrieve the store with it.
49
+ *
50
+ * @param handle {{}}
51
+ * @returns {T | undefined}
52
+ */
29
53
  getStore (handle) {
30
54
  if (!handle) {
31
- handle = this._storage.getStore()
55
+ handle = super.getStore()
32
56
  }
33
57
 
34
58
  return stores.get(handle)
35
59
  }
36
60
 
61
+ /**
62
+ * Here, we replicate the behavior of the original `run()` method. We ensure
63
+ * that our `enterWith()` is called internally, so that the handle to the
64
+ * store is set. As an optimization, we use super for getStore and enterWith
65
+ * when dealing with the parent store, so that we don't have to access the
66
+ * WeakMap.
67
+ * @template R
68
+ * @template TArgs extends any[]
69
+ * @param store {DatadogStorage}
70
+ * @param fn {() => R}
71
+ * @param args {TArgs}
72
+ * @returns {void}
73
+ */
37
74
  run (store, fn, ...args) {
38
- const prior = this._storage.getStore()
75
+ const prior = super.getStore()
39
76
  this.enterWith(store)
40
77
  try {
41
78
  return Reflect.apply(fn, null, args)
42
79
  } finally {
43
- this._storage.enterWith(prior)
80
+ super.enterWith(prior)
44
81
  }
45
82
  }
46
83
  }
47
84
 
85
+ /**
86
+ * This is the map from handles to real stores, used in the class above.
87
+ * @template T
88
+ * @type {WeakMap<WeakKey, T>}
89
+ */
90
+ const stores = new WeakMap()
91
+
92
+ /**
93
+ * For convenience, we use the `storage` function as a registry of namespaces
94
+ * corresponding to DatadogStorage instances. This lets us have separate
95
+ * storages for separate purposes.
96
+ * @type {Map<string, DatadogStorage>}
97
+ */
48
98
  const storages = Object.create(null)
49
- const legacyStorage = new DatadogStorage()
50
99
 
51
- const storage = function (namespace) {
100
+ /**
101
+ *
102
+ * @param namespace {string} the namespace to use
103
+ * @returns {DatadogStorage}
104
+ */
105
+ function storage (namespace) {
52
106
  if (!storages[namespace]) {
53
107
  storages[namespace] = new DatadogStorage()
54
108
  }
55
109
  return storages[namespace]
56
110
  }
57
111
 
58
- storage.disable = legacyStorage.disable.bind(legacyStorage)
59
- storage.enterWith = legacyStorage.enterWith.bind(legacyStorage)
60
- storage.exit = legacyStorage.exit.bind(legacyStorage)
61
- storage.getHandle = legacyStorage.getHandle.bind(legacyStorage)
62
- storage.getStore = legacyStorage.getStore.bind(legacyStorage)
63
- storage.run = legacyStorage.run.bind(legacyStorage)
64
-
65
- const stores = new WeakMap()
66
-
67
- module.exports = storage
112
+ module.exports = { storage }
@@ -40,6 +40,18 @@ function wrapRequest (send) {
40
40
  }
41
41
  }
42
42
 
43
+ function wrapDeserialize (deserialize, channelSuffix) {
44
+ const headersCh = channel(`apm:aws:response:deserialize:${channelSuffix}`)
45
+
46
+ return function (response) {
47
+ if (headersCh.hasSubscribers) {
48
+ headersCh.publish({ headers: response.headers })
49
+ }
50
+
51
+ return deserialize.apply(this, arguments)
52
+ }
53
+ }
54
+
43
55
  function wrapSmithySend (send) {
44
56
  return function (command, ...args) {
45
57
  const cb = args[args.length - 1]
@@ -61,6 +73,10 @@ function wrapSmithySend (send) {
61
73
  const responseStartChannel = channel(`apm:aws:response:start:${channelSuffix}`)
62
74
  const responseFinishChannel = channel(`apm:aws:response:finish:${channelSuffix}`)
63
75
 
76
+ if (typeof command.deserialize === 'function') {
77
+ shimmer.wrap(command, 'deserialize', deserialize => wrapDeserialize(deserialize, channelSuffix))
78
+ }
79
+
64
80
  return innerAr.runInAsyncScope(() => {
65
81
  startCh.publish({
66
82
  serviceIdentifier,
@@ -102,6 +102,7 @@ module.exports = {
102
102
  oracledb: () => require('../oracledb'),
103
103
  openai: () => require('../openai'),
104
104
  paperplane: () => require('../paperplane'),
105
+ passport: () => require('../passport'),
105
106
  'passport-http': () => require('../passport-http'),
106
107
  'passport-local': () => require('../passport-local'),
107
108
  pg: () => require('../pg'),
@@ -313,10 +313,11 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
313
313
  const asyncResource = asyncResources.get(event.test)
314
314
 
315
315
  if (status === 'fail') {
316
+ const shouldSetProbe = this.isDiEnabled && willBeRetried && numTestExecutions === 1
316
317
  asyncResource.runInAsyncScope(() => {
317
318
  testErrCh.publish({
318
319
  error: formatJestError(event.test.errors[0]),
319
- shouldSetProbe: this.isDiEnabled && willBeRetried && numTestExecutions === 1,
320
+ shouldSetProbe,
320
321
  promises
321
322
  })
322
323
  })
@@ -336,18 +337,13 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
336
337
  testFinishCh.publish({
337
338
  status,
338
339
  testStartLine: getTestLineStart(event.test.asyncError, this.testSuite),
339
- promises,
340
- shouldRemoveProbe: this.isDiEnabled && !willBeRetried
340
+ promises
341
341
  })
342
342
  })
343
343
 
344
344
  if (promises.isProbeReady) {
345
345
  await promises.isProbeReady
346
346
  }
347
-
348
- if (promises.isProbeRemoved) {
349
- await promises.isProbeRemoved
350
- }
351
347
  }
352
348
  if (event.name === 'test_skip' || event.name === 'test_todo') {
353
349
  const asyncResource = new AsyncResource('bound-anonymous-fn')
@@ -0,0 +1,45 @@
1
+ 'use strict'
2
+
3
+ const shimmer = require('../../datadog-shimmer')
4
+ const { channel, addHook } = require('./helpers/instrument')
5
+
6
+ const onPassportDeserializeUserChannel = channel('datadog:passport:deserializeUser:finish')
7
+
8
+ function wrapDone (done) {
9
+ return function wrappedDone (err, user) {
10
+ if (!err && user) {
11
+ const abortController = new AbortController()
12
+
13
+ onPassportDeserializeUserChannel.publish({ user, abortController })
14
+
15
+ if (abortController.signal.aborted) return
16
+ }
17
+
18
+ return done.apply(this, arguments)
19
+ }
20
+ }
21
+
22
+ function wrapDeserializeUser (deserializeUser) {
23
+ return function wrappedDeserializeUser (fn, req, done) {
24
+ if (typeof fn === 'function') return deserializeUser.apply(this, arguments)
25
+
26
+ if (typeof req === 'function') {
27
+ done = req
28
+ arguments[1] = wrapDone(done)
29
+ } else {
30
+ arguments[2] = wrapDone(done)
31
+ }
32
+
33
+ return deserializeUser.apply(this, arguments)
34
+ }
35
+ }
36
+
37
+ addHook({
38
+ name: 'passport',
39
+ file: 'lib/authenticator.js',
40
+ versions: ['>=0.3.0']
41
+ }, Authenticator => {
42
+ shimmer.wrap(Authenticator.prototype, 'deserializeUser', wrapDeserializeUser)
43
+
44
+ return Authenticator
45
+ })
@@ -20,7 +20,7 @@ class AerospikePlugin extends DatabasePlugin {
20
20
  bindStart (ctx) {
21
21
  const { commandName, commandArgs } = ctx
22
22
  const resourceName = commandName.slice(0, commandName.indexOf('Command'))
23
- const store = storage.getStore()
23
+ const store = storage('legacy').getStore()
24
24
  const childOf = store ? store.span : null
25
25
  const meta = getMeta(resourceName, commandArgs)
26
26
 
@@ -10,7 +10,7 @@ class ApolloGatewayFetchPlugin extends ApolloBasePlugin {
10
10
  }
11
11
 
12
12
  bindStart (ctx) {
13
- const store = storage.getStore()
13
+ const store = storage('legacy').getStore()
14
14
  const childOf = store ? store.span : null
15
15
 
16
16
  const spanData = {
@@ -25,7 +25,7 @@ class ApolloGatewayPlugin extends CompositePlugin {
25
25
  constructor (...args) {
26
26
  super(...args)
27
27
  this.addSub('apm:apollo:gateway:general:error', (ctx) => {
28
- const store = storage.getStore()
28
+ const store = storage('legacy').getStore()
29
29
  const span = store?.span
30
30
  if (!span) return
31
31
  span.setTag('error', ctx.error)
@@ -15,7 +15,7 @@ class ApolloGatewayRequestPlugin extends ApolloBasePlugin {
15
15
  }
16
16
 
17
17
  bindStart (ctx) {
18
- const store = storage.getStore()
18
+ const store = storage('legacy').getStore()
19
19
  const childOf = store ? store.span : null
20
20
  const spanData = {
21
21
  childOf,
@@ -67,13 +67,13 @@ class BaseAwsSdkPlugin extends ClientPlugin {
67
67
  span.addTags(requestTags)
68
68
  }
69
69
 
70
- const store = storage.getStore()
70
+ const store = storage('legacy').getStore()
71
71
 
72
72
  this.enter(span, store)
73
73
  })
74
74
 
75
75
  this.addSub(`apm:aws:request:region:${this.serviceIdentifier}`, region => {
76
- const store = storage.getStore()
76
+ const store = storage('legacy').getStore()
77
77
  if (!store) return
78
78
  const { span } = store
79
79
  if (!span) return
@@ -82,7 +82,7 @@ class BaseAwsSdkPlugin extends ClientPlugin {
82
82
  })
83
83
 
84
84
  this.addSub(`apm:aws:request:complete:${this.serviceIdentifier}`, ({ response, cbExists = false }) => {
85
- const store = storage.getStore()
85
+ const store = storage('legacy').getStore()
86
86
  if (!store) return
87
87
  const { span } = store
88
88
  if (!span) return
@@ -24,11 +24,23 @@ const PROVIDER = {
24
24
  }
25
25
 
26
26
  class Generation {
27
- constructor ({ message = '', finishReason = '', choiceId = '' } = {}) {
27
+ constructor ({
28
+ message = '',
29
+ finishReason = '',
30
+ choiceId = '',
31
+ role,
32
+ inputTokens,
33
+ outputTokens
34
+ } = {}) {
28
35
  // stringify message as it could be a single generated message as well as a list of embeddings
29
36
  this.message = typeof message === 'string' ? message : JSON.stringify(message) || ''
30
37
  this.finishReason = finishReason || ''
31
38
  this.choiceId = choiceId || undefined
39
+ this.role = role
40
+ this.usage = {
41
+ inputTokens,
42
+ outputTokens
43
+ }
32
44
  }
33
45
  }
34
46
 
@@ -202,9 +214,12 @@ function extractTextAndResponseReason (response, provider, modelName) {
202
214
  if (generations.length > 0) {
203
215
  const generation = generations[0]
204
216
  return new Generation({
205
- message: generation.message,
217
+ message: generation.message.content,
206
218
  finishReason: generation.finish_reason,
207
- choiceId: shouldSetChoiceIds ? generation.id : undefined
219
+ choiceId: shouldSetChoiceIds ? generation.id : undefined,
220
+ role: generation.message.role,
221
+ inputTokens: body.usage?.prompt_tokens,
222
+ outputTokens: body.usage?.completion_tokens
208
223
  })
209
224
  }
210
225
  }
@@ -214,7 +229,9 @@ function extractTextAndResponseReason (response, provider, modelName) {
214
229
  return new Generation({
215
230
  message: completion.data?.text,
216
231
  finishReason: completion?.finishReason,
217
- choiceId: shouldSetChoiceIds ? completion?.id : undefined
232
+ choiceId: shouldSetChoiceIds ? completion?.id : undefined,
233
+ inputTokens: body.usage?.prompt_tokens,
234
+ outputTokens: body.usage?.completion_tokens
218
235
  })
219
236
  }
220
237
  return new Generation()
@@ -226,7 +243,12 @@ function extractTextAndResponseReason (response, provider, modelName) {
226
243
  const results = body.results || []
227
244
  if (results.length > 0) {
228
245
  const result = results[0]
229
- return new Generation({ message: result.outputText, finishReason: result.completionReason })
246
+ return new Generation({
247
+ message: result.outputText,
248
+ finishReason: result.completionReason,
249
+ inputTokens: body.inputTextTokenCount,
250
+ outputTokens: result.tokenCount
251
+ })
230
252
  }
231
253
  break
232
254
  }
@@ -252,7 +274,12 @@ function extractTextAndResponseReason (response, provider, modelName) {
252
274
  break
253
275
  }
254
276
  case PROVIDER.META: {
255
- return new Generation({ message: body.generation, finishReason: body.stop_reason })
277
+ return new Generation({
278
+ message: body.generation,
279
+ finishReason: body.stop_reason,
280
+ inputTokens: body.prompt_token_count,
281
+ outputTokens: body.generation_token_count
282
+ })
256
283
  }
257
284
  case PROVIDER.MISTRAL: {
258
285
  const mistralGenerations = body.outputs || []
@@ -21,7 +21,7 @@ class Kinesis extends BaseAwsSdkPlugin {
21
21
 
22
22
  this.addSub('apm:aws:response:start:kinesis', obj => {
23
23
  const { request, response } = obj
24
- const store = storage.getStore()
24
+ const store = storage('legacy').getStore()
25
25
  const plugin = this
26
26
 
27
27
  // if we have either of these operations, we want to store the streamName param
@@ -49,7 +49,7 @@ class Kinesis extends BaseAwsSdkPlugin {
49
49
  }
50
50
 
51
51
  // get the stream name that should have been stored previously
52
- const { streamName } = storage.getStore()
52
+ const { streamName } = storage('legacy').getStore()
53
53
 
54
54
  // extract DSM context after as we might not have a parent-child but may have a DSM context
55
55
  this.responseExtractDSMContext(
@@ -59,7 +59,7 @@ class Kinesis extends BaseAwsSdkPlugin {
59
59
  })
60
60
 
61
61
  this.addSub('apm:aws:response:finish:kinesis', err => {
62
- const { span } = storage.getStore()
62
+ const { span } = storage('legacy').getStore()
63
63
  this.finish(span, null, err)
64
64
  })
65
65
  }
@@ -79,7 +79,7 @@ class Kinesis extends BaseAwsSdkPlugin {
79
79
  if (!params || !params.StreamName) return
80
80
 
81
81
  const streamName = params.StreamName
82
- storage.enterWith({ ...store, streamName })
82
+ storage('legacy').enterWith({ ...store, streamName })
83
83
  }
84
84
 
85
85
  responseExtract (params, operation, response) {
@@ -20,7 +20,7 @@ class Sqs extends BaseAwsSdkPlugin {
20
20
 
21
21
  this.addSub('apm:aws:response:start:sqs', obj => {
22
22
  const { request, response } = obj
23
- const store = storage.getStore()
23
+ const store = storage('legacy').getStore()
24
24
  const plugin = this
25
25
  const contextExtraction = this.responseExtract(request.params, request.operation, response)
26
26
  let span
@@ -47,7 +47,7 @@ class Sqs extends BaseAwsSdkPlugin {
47
47
  })
48
48
 
49
49
  this.addSub('apm:aws:response:finish:sqs', err => {
50
- const { span } = storage.getStore()
50
+ const { span } = storage('legacy').getStore()
51
51
  this.finish(span, null, err)
52
52
  })
53
53
  }
@@ -24,7 +24,7 @@ class AzureFunctionsPlugin extends TracingPlugin {
24
24
 
25
25
  bindStart (ctx) {
26
26
  const { functionName, methodName } = ctx
27
- const store = storage.getStore()
27
+ const store = storage('legacy').getStore()
28
28
 
29
29
  const span = this.startSpan(this.operationName(), {
30
30
  service: this.serviceName(),
@@ -42,7 +42,7 @@ class CouchBasePlugin extends StoragePlugin {
42
42
  super(...args)
43
43
 
44
44
  this.addSubs('query', ({ resource, bucket, seedNodes }) => {
45
- const store = storage.getStore()
45
+ const store = storage('legacy').getStore()
46
46
  const span = this.startSpan(
47
47
  'query', {
48
48
  'span.type': 'sql',
@@ -64,7 +64,7 @@ class CouchBasePlugin extends StoragePlugin {
64
64
 
65
65
  _addCommandSubs (name) {
66
66
  this.addSubs(name, ({ bucket, collection, seedNodes }) => {
67
- const store = storage.getStore()
67
+ const store = storage('legacy').getStore()
68
68
  const span = this.startSpan(name, {}, store, { bucket, collection, seedNodes })
69
69
  this.enter(span, store)
70
70
  })
@@ -213,7 +213,7 @@ class CucumberPlugin extends CiPlugin {
213
213
  isParallel,
214
214
  promises
215
215
  }) => {
216
- const store = storage.getStore()
216
+ const store = storage('legacy').getStore()
217
217
  const testSuite = getTestSuitePath(testFileAbsolutePath, this.sourceRoot)
218
218
  const testSourceFile = getTestSuitePath(testFileAbsolutePath, this.repositoryRoot)
219
219
 
@@ -231,7 +231,7 @@ class CucumberPlugin extends CiPlugin {
231
231
 
232
232
  this.activeTestSpan = testSpan
233
233
  // Time we give the breakpoint to be hit
234
- if (promises && this.runningTestProbeId) {
234
+ if (promises && this.runningTestProbe) {
235
235
  promises.hitBreakpointPromise = new Promise((resolve) => {
236
236
  setTimeout(resolve, BREAKPOINT_HIT_GRACE_PERIOD_MS)
237
237
  })
@@ -239,7 +239,7 @@ class CucumberPlugin extends CiPlugin {
239
239
  })
240
240
 
241
241
  this.addSub('ci:cucumber:test:retry', ({ isFirstAttempt, error }) => {
242
- const store = storage.getStore()
242
+ const store = storage('legacy').getStore()
243
243
  const span = store.span
244
244
  if (!isFirstAttempt) {
245
245
  span.setTag(TEST_IS_RETRY, 'true')
@@ -248,8 +248,8 @@ class CucumberPlugin extends CiPlugin {
248
248
  if (isFirstAttempt && this.di && error && this.libraryConfig?.isDiEnabled) {
249
249
  const probeInformation = this.addDiProbe(error)
250
250
  if (probeInformation) {
251
- const { probeId, stackIndex } = probeInformation
252
- this.runningTestProbeId = probeId
251
+ const { file, line, stackIndex } = probeInformation
252
+ this.runningTestProbe = { file, line }
253
253
  this.testErrorStackIndex = stackIndex
254
254
  // TODO: we're not waiting for setProbePromise to be resolved, so there might be race conditions
255
255
  }
@@ -260,7 +260,7 @@ class CucumberPlugin extends CiPlugin {
260
260
  })
261
261
 
262
262
  this.addSub('ci:cucumber:test-step:start', ({ resource }) => {
263
- const store = storage.getStore()
263
+ const store = storage('legacy').getStore()
264
264
  const childOf = store ? store.span : store
265
265
  const span = this.tracer.startSpan('cucumber.step', {
266
266
  childOf,
@@ -313,7 +313,7 @@ class CucumberPlugin extends CiPlugin {
313
313
  isEfdRetry,
314
314
  isFlakyRetry
315
315
  }) => {
316
- const span = storage.getStore().span
316
+ const span = storage('legacy').getStore().span
317
317
  const statusTag = isStep ? 'step.status' : TEST_STATUS
318
318
 
319
319
  span.setTag(statusTag, status)
@@ -359,16 +359,16 @@ class CucumberPlugin extends CiPlugin {
359
359
  this.tracer._exporter.flush()
360
360
  }
361
361
  this.activeTestSpan = null
362
- if (this.runningTestProbeId) {
363
- this.removeDiProbe(this.runningTestProbeId)
364
- this.runningTestProbeId = null
362
+ if (this.runningTestProbe) {
363
+ this.removeDiProbe(this.runningTestProbe)
364
+ this.runningTestProbe = null
365
365
  }
366
366
  }
367
367
  })
368
368
 
369
369
  this.addSub('ci:cucumber:error', (err) => {
370
370
  if (err) {
371
- const span = storage.getStore().span
371
+ const span = storage('legacy').getStore().span
372
372
  span.setTag('error', err)
373
373
  }
374
374
  })
@@ -32,7 +32,8 @@ const {
32
32
  getTestSessionName,
33
33
  TEST_SESSION_NAME,
34
34
  TEST_LEVEL_EVENT_TYPES,
35
- TEST_RETRY_REASON
35
+ TEST_RETRY_REASON,
36
+ DD_TEST_IS_USER_PROVIDED_SERVICE
36
37
  } = require('../../dd-trace/src/plugins/util/test')
37
38
  const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util')
38
39
  const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
@@ -222,6 +223,10 @@ class CypressPlugin {
222
223
  this.tracer = tracer
223
224
  this.cypressConfig = cypressConfig
224
225
 
226
+ // we have to do it here because the tracer is not initialized in the constructor
227
+ this.testEnvironmentMetadata[DD_TEST_IS_USER_PROVIDED_SERVICE] =
228
+ tracer._tracer._config.isServiceUserProvided ? 'true' : 'false'
229
+
225
230
  this.libraryConfigurationPromise = getLibraryConfiguration(this.tracer, this.testConfiguration)
226
231
  .then((libraryConfigurationResponse) => {
227
232
  if (libraryConfigurationResponse.err) {