dd-trace 5.57.0 → 5.58.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 (56) hide show
  1. package/LICENSE-3rdparty.csv +2 -1
  2. package/init.js +1 -4
  3. package/package.json +12 -10
  4. package/packages/datadog-instrumentations/src/azure-functions.js +1 -1
  5. package/packages/datadog-instrumentations/src/child_process.js +1 -1
  6. package/packages/datadog-instrumentations/src/graphql.js +9 -0
  7. package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
  8. package/packages/datadog-instrumentations/src/jest.js +1 -1
  9. package/packages/datadog-instrumentations/src/mysql2.js +6 -6
  10. package/packages/datadog-instrumentations/src/next.js +3 -1
  11. package/packages/datadog-instrumentations/src/oracledb.js +24 -2
  12. package/packages/datadog-instrumentations/src/tedious.js +12 -17
  13. package/packages/datadog-plugin-aws-sdk/src/base.js +51 -1
  14. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -1
  15. package/packages/datadog-plugin-cypress/src/support.js +19 -25
  16. package/packages/datadog-plugin-graphql/src/tools/index.js +0 -2
  17. package/packages/datadog-plugin-graphql/src/tools/signature.js +0 -2
  18. package/packages/datadog-plugin-graphql/src/tools/transforms.js +0 -2
  19. package/packages/datadog-plugin-http/src/client.js +3 -4
  20. package/packages/datadog-plugin-http2/src/client.js +9 -8
  21. package/packages/datadog-plugin-langchain/src/handlers/chain.js +1 -1
  22. package/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js +1 -1
  23. package/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js +1 -1
  24. package/packages/datadog-plugin-oracledb/src/connection-parser.js +35 -0
  25. package/packages/datadog-plugin-oracledb/src/index.js +15 -17
  26. package/packages/datadog-plugin-tedious/src/index.js +10 -9
  27. package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +6 -4
  28. package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +9 -0
  29. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +5 -2
  30. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -0
  31. package/packages/dd-trace/src/appsec/reporter.js +61 -7
  32. package/packages/dd-trace/src/appsec/rule_manager.js +63 -171
  33. package/packages/dd-trace/src/appsec/sdk/track_event.js +3 -5
  34. package/packages/dd-trace/src/appsec/telemetry/common.js +1 -1
  35. package/packages/dd-trace/src/appsec/telemetry/index.js +8 -0
  36. package/packages/dd-trace/src/appsec/telemetry/waf.js +5 -3
  37. package/packages/dd-trace/src/appsec/waf/diagnostics.js +15 -0
  38. package/packages/dd-trace/src/appsec/waf/index.js +47 -6
  39. package/packages/dd-trace/src/appsec/waf/waf_manager.js +22 -12
  40. package/packages/dd-trace/src/config.js +11 -4
  41. package/packages/dd-trace/src/constants.js +1 -2
  42. package/packages/dd-trace/src/exporters/common/request.js +1 -1
  43. package/packages/dd-trace/src/heap_snapshots.js +58 -0
  44. package/packages/dd-trace/src/llmobs/noop.js +1 -1
  45. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  46. package/packages/dd-trace/src/log/log.js +1 -1
  47. package/packages/dd-trace/src/opentracing/span.js +1 -1
  48. package/packages/dd-trace/src/payload-tagging/index.js +1 -1
  49. package/packages/dd-trace/src/payload-tagging/tagging.js +2 -2
  50. package/packages/dd-trace/src/plugins/outbound.js +7 -0
  51. package/packages/dd-trace/src/profiling/profilers/wall.js +2 -2
  52. package/packages/dd-trace/src/proxy.js +4 -0
  53. package/packages/dd-trace/src/service-naming/schemas/definition.js +2 -9
  54. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +2 -1
  55. package/packages/dd-trace/src/supported-configurations.json +3 -0
  56. package/packages/dd-trace/src/payload-tagging/jsonpath-plus.js +0 -2094
@@ -15,6 +15,7 @@ require,ignore,MIT,Copyright 2013 Kael Zhang and contributors
15
15
  require,import-in-the-middle,Apache license 2.0,Copyright 2021 Datadog Inc.
16
16
  require,istanbul-lib-coverage,BSD-3-Clause,Copyright 2012-2015 Yahoo! Inc.
17
17
  require,jest-docblock,MIT,Copyright Meta Platforms, Inc. and affiliates.
18
+ require,jsonpath-plus,MIT,Copyright (c) 2011-2019 Stefan Goessner, Subbu Allamaraju, Mike Brevoort, Robert Krahn, Brett Zamir, Richard Schneider
18
19
  require,koalas,MIT,Copyright 2013-2017 Brian Woodward
19
20
  require,limiter,MIT,Copyright 2011 John Hurliman
20
21
  require,lodash.sortby,MIT,Copyright JS Foundation and other contributors
@@ -43,7 +44,7 @@ dev,benchmark,MIT,Copyright 2010-2016 Mathias Bynens Robert Kieffer John-David D
43
44
  dev,body-parser,MIT,Copyright 2014 Jonathan Ong 2014-2015 Douglas Christopher Wilson
44
45
  dev,chai,MIT,Copyright 2017 Chai.js Assertion Library
45
46
  dev,eslint,MIT,Copyright JS Foundation and other contributors https://js.foundation
46
- dev,eslint-config-standard,MIT,Copyright Feross Aboukhadijeh
47
+ dev,eslint-plugin-cypress,MIT,Copyright (c) 2019 Cypress.io
47
48
  dev,eslint-plugin-import,MIT,Copyright 2015 Ben Mosher
48
49
  dev,eslint-plugin-mocha,MIT,Copyright 2014 Mathias Schreck
49
50
  dev,eslint-plugin-n,MIT,Copyright 2015 Toru Nagashima
package/init.js CHANGED
@@ -5,8 +5,5 @@
5
5
  var guard = require('./packages/dd-trace/src/guardrails')
6
6
 
7
7
  module.exports = guard(function () {
8
- var INSTRUMENTED_BY_SSI = require('./packages/dd-trace/src/constants').INSTRUMENTED_BY_SSI
9
- var obj = {}
10
- obj[INSTRUMENTED_BY_SSI] = 'ssi'
11
- return require('.').init(obj)
8
+ return require('.').init()
12
9
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.57.0",
3
+ "version": "5.58.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -24,6 +24,7 @@
24
24
  "test:appsec:plugins:ci": "yarn services && nyc --no-clean --include \"packages/dd-trace/src/appsec/**/*.js\" -- npm run test:appsec:plugins",
25
25
  "test:debugger": "mocha -r 'packages/dd-trace/test/setup/mocha.js' 'packages/dd-trace/test/debugger/**/*.spec.js'",
26
26
  "test:debugger:ci": "nyc --no-clean --include 'packages/dd-trace/src/debugger/**/*.js' -- npm run test:debugger",
27
+ "test:eslint-rules": "node eslint-rules/*.test.mjs",
27
28
  "test:trace:core": "tap packages/dd-trace/test/*.spec.js \"packages/dd-trace/test/{ci-visibility,datastreams,encode,exporters,opentelemetry,opentracing,plugins,service-naming,standalone,telemetry}/**/*.spec.js\"",
28
29
  "test:trace:core:ci": "npm run test:trace:core -- --coverage --nyc-arg=--include=\"packages/dd-trace/src/**/*.js\"",
29
30
  "test:instrumentations": "mocha -r 'packages/dd-trace/test/setup/mocha.js' \"packages/datadog-instrumentations/test/@($(echo $PLUGINS)).spec.js\"",
@@ -84,13 +85,13 @@
84
85
  "node": ">=18"
85
86
  },
86
87
  "dependencies": {
87
- "@datadog/libdatadog": "^0.7.0",
88
- "@datadog/native-appsec": "^8.5.2",
89
- "@datadog/native-iast-taint-tracking": "^4.0.0",
90
- "@datadog/native-metrics": "^3.1.1",
91
- "@datadog/pprof": "^5.9.0",
92
- "@datadog/sketches-js": "^2.1.1",
93
- "@datadog/wasm-js-rewriter": "^4.0.1",
88
+ "@datadog/libdatadog": "0.7.0",
89
+ "@datadog/native-appsec": "9.0.0",
90
+ "@datadog/native-iast-taint-tracking": "4.0.0",
91
+ "@datadog/native-metrics": "3.1.1",
92
+ "@datadog/pprof": "5.9.0",
93
+ "@datadog/sketches-js": "2.1.1",
94
+ "@datadog/wasm-js-rewriter": "4.0.1",
94
95
  "@isaacs/ttlcache": "^1.4.1",
95
96
  "@opentelemetry/api": "1.8.0",
96
97
  "@opentelemetry/core": "^1.14.0",
@@ -100,6 +101,7 @@
100
101
  "import-in-the-middle": "^1.14.2",
101
102
  "istanbul-lib-coverage": "^3.2.2",
102
103
  "jest-docblock": "^29.7.0",
104
+ "jsonpath-plus": "^10.3.0",
103
105
  "koalas": "^1.0.2",
104
106
  "limiter": "^1.1.5",
105
107
  "lodash.sortby": "^4.7.0",
@@ -130,12 +132,12 @@
130
132
  "body-parser": "^2.2.0",
131
133
  "chai": "^4.5.0",
132
134
  "eslint": "^9.29.0",
133
- "eslint-config-standard": "^17.1.0",
135
+ "eslint-plugin-cypress": "^5.1.0",
134
136
  "eslint-plugin-import": "^2.32.0",
135
137
  "eslint-plugin-mocha": "^10.5.0",
136
138
  "eslint-plugin-n": "^17.20.0",
137
139
  "eslint-plugin-promise": "^7.2.1",
138
- "eslint-plugin-unicorn": "^57.0.0",
140
+ "eslint-plugin-unicorn": "^59.0.1",
139
141
  "express": "^4.21.2",
140
142
  "get-port": "^5.1.1",
141
143
  "glob": "^7.2.3",
@@ -25,7 +25,7 @@ addHook({ name: '@azure/functions', versions: ['>=4'] }, azureFunction => {
25
25
  // The arguments are either an object with a handler property or the handler function itself
26
26
  function wrapHandler (method) {
27
27
  return function (name, arg) {
28
- if (typeof arg === 'object' && arg.hasOwnProperty('handler')) {
28
+ if (arg !== null && typeof arg === 'object' && arg.hasOwnProperty('handler')) {
29
29
  const options = arg
30
30
  shimmer.wrap(options, 'handler', handler => traceHandler(handler, name, method.name))
31
31
  } else if (typeof arg === 'function') {
@@ -179,7 +179,7 @@ function wrapChildProcessCustomPromisifyMethod (customPromisifyMethod, shell) {
179
179
  return result
180
180
  }
181
181
 
182
- return Promise.prototype.then.call(result, resolve, reject)
182
+ return Promise.resolve(result).then(resolve, reject)
183
183
  }
184
184
  }
185
185
 
@@ -359,6 +359,15 @@ function finishResolvers ({ fields }) {
359
359
  })
360
360
  }
361
361
 
362
+ addHook({ name: '@graphql-tools/executor', versions: ['>=0.0.14'] }, executor => {
363
+ // graphql-yoga uses the normalizedExecutor function, so we need to wrap both. There is no risk in wrapping both
364
+ // since the functions are closely related, and our wrappedExecute function prevents double calls with the
365
+ // contexts.has(contextValue) check.
366
+ shimmer.wrap(executor, 'execute', wrapExecute(executor))
367
+ shimmer.wrap(executor, 'normalizedExecutor', wrapExecute(executor))
368
+ return executor
369
+ })
370
+
362
371
  addHook({ name: '@graphql-tools/executor', file: 'cjs/execution/execute.js', versions: ['>=0.0.14'] }, execute => {
363
372
  shimmer.wrap(execute, 'execute', wrapExecute(execute))
364
373
  return execute
@@ -72,7 +72,7 @@ for (const packageName of names) {
72
72
 
73
73
  let hook = hooks[packageName]
74
74
 
75
- if (typeof hook === 'object') {
75
+ if (hook !== null && typeof hook === 'object') {
76
76
  if (hook.serverless === false && isInServerlessEnvironment()) continue
77
77
 
78
78
  // some integrations are disabled by default, but can be enabled by setting
@@ -1071,7 +1071,7 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
1071
1071
  const adapter = jestAdapter.default ?? jestAdapter
1072
1072
  const newAdapter = shimmer.wrapFunction(adapter, adapter => function () {
1073
1073
  const environment = arguments[2]
1074
- if (!environment) {
1074
+ if (!environment || !environment.testEnvironmentOptions) {
1075
1075
  return adapter.apply(this, arguments)
1076
1076
  }
1077
1077
  testSuiteStartCh.publish({
@@ -35,7 +35,7 @@ function wrapConnection (Connection, version) {
35
35
  shimmer.wrap(Connection.prototype, 'query', query => function (sql, values, cb) {
36
36
  if (!startOuterQueryCh.hasSubscribers) return query.apply(this, arguments)
37
37
 
38
- if (typeof sql === 'object') sql = sql?.sql
38
+ if (sql !== null && typeof sql === 'object') sql = sql.sql
39
39
 
40
40
  if (!sql) return query.apply(this, arguments)
41
41
 
@@ -76,7 +76,7 @@ function wrapConnection (Connection, version) {
76
76
  shimmer.wrap(Connection.prototype, 'execute', execute => function (sql, values, cb) {
77
77
  if (!startOuterQueryCh.hasSubscribers) return execute.apply(this, arguments)
78
78
 
79
- if (typeof sql === 'object') sql = sql?.sql
79
+ if (sql !== null && typeof sql === 'object') sql = sql.sql
80
80
 
81
81
  if (!sql) return execute.apply(this, arguments)
82
82
 
@@ -167,7 +167,7 @@ function wrapPool (Pool, version) {
167
167
  shimmer.wrap(Pool.prototype, 'query', query => function (sql, values, cb) {
168
168
  if (!startOuterQueryCh.hasSubscribers) return query.apply(this, arguments)
169
169
 
170
- if (typeof sql === 'object') sql = sql?.sql
170
+ if (sql !== null && typeof sql === 'object') sql = sql.sql
171
171
 
172
172
  if (!sql) return query.apply(this, arguments)
173
173
 
@@ -206,7 +206,7 @@ function wrapPool (Pool, version) {
206
206
  shimmer.wrap(Pool.prototype, 'execute', execute => function (sql, values, cb) {
207
207
  if (!startOuterQueryCh.hasSubscribers) return execute.apply(this, arguments)
208
208
 
209
- if (typeof sql === 'object') sql = sql?.sql
209
+ if (sql !== null && typeof sql === 'object') sql = sql.sql
210
210
 
211
211
  if (!sql) return execute.apply(this, arguments)
212
212
 
@@ -239,7 +239,7 @@ function wrapPoolCluster (PoolCluster) {
239
239
 
240
240
  if (startOuterQueryCh.hasSubscribers && !wrappedPoolNamespaces.has(poolNamespace)) {
241
241
  shimmer.wrap(poolNamespace, 'query', query => function (sql, values, cb) {
242
- if (typeof sql === 'object') sql = sql?.sql
242
+ if (sql !== null && typeof sql === 'object') sql = sql.sql
243
243
 
244
244
  if (!sql) return query.apply(this, arguments)
245
245
 
@@ -274,7 +274,7 @@ function wrapPoolCluster (PoolCluster) {
274
274
  })
275
275
 
276
276
  shimmer.wrap(poolNamespace, 'execute', execute => function (sql, values, cb) {
277
- if (typeof sql === 'object') sql = sql?.sql
277
+ if (sql !== null && typeof sql === 'object') sql = sql.sql
278
278
 
279
279
  if (!sql) return execute.apply(this, arguments)
280
280
 
@@ -51,7 +51,9 @@ function wrapHandleApiRequest (handleApiRequest) {
51
51
  function wrapHandleApiRequestWithMatch (handleApiRequest) {
52
52
  return function (req, res, query, match) {
53
53
  return instrument(req, res, () => {
54
- const page = (match !== null && typeof match === 'object' && typeof match.definition === 'object')
54
+ const page = (
55
+ match !== null && typeof match === 'object' && match.definition !== null && typeof match.definition === 'object'
56
+ )
55
57
  ? match.definition.pathname
56
58
  : undefined
57
59
 
@@ -38,12 +38,34 @@ addHook({ name: 'oracledb', versions: ['>=5'] }, oracledb => {
38
38
  }
39
39
 
40
40
  return new AsyncResource('apm:oracledb:inner-scope').runInAsyncScope(() => {
41
+ // The connAttrs are used to pass through the argument to the potential
42
+ // serviceName method a user might have passed through as well as parsing
43
+ // the connection string in v5.
41
44
  const connAttrs = connectionAttributes.get(this)
42
- startChannel.publish({ query: dbQuery, connAttrs })
45
+
46
+ const details = typeof this.hostName === 'string' ? this : this._impl
47
+
48
+ let hostname
49
+ let port
50
+ let dbInstance
51
+
52
+ if (details) {
53
+ dbInstance = details.serviceName
54
+ hostname = details.hostName ?? details.nscon?.ntAdapter?.hostName
55
+ port = String(details.port ?? details.nscon?.ntAdapter?.port ?? '')
56
+ }
57
+
58
+ startChannel.publish({
59
+ query: dbQuery,
60
+ connAttrs,
61
+ dbInstance,
62
+ port,
63
+ hostname,
64
+ })
43
65
  try {
44
66
  let result = execute.apply(this, arguments)
45
67
 
46
- if (result && typeof result.then === 'function') {
68
+ if (typeof result?.then === 'function') {
47
69
  result = result.then(
48
70
  x => {
49
71
  finish()
@@ -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
  const shimmer = require('../../datadog-shimmer')
9
8
 
@@ -22,30 +21,26 @@ addHook({ name: 'tedious', versions: ['>=1.0.0'] }, tedious => {
22
21
  return makeRequest.apply(this, arguments)
23
22
  }
24
23
 
25
- const callbackResource = new AsyncResource('bound-anonymous-fn')
26
- const asyncResource = new AsyncResource('bound-anonymous-fn')
27
-
28
24
  const connectionConfig = this.config
25
+ const ctx = { queryOrProcedure, connectionConfig }
29
26
 
30
- return asyncResource.runInAsyncScope(() => {
31
- const payload = { queryOrProcedure, connectionConfig }
32
- startCh.publish(payload)
33
- queryParent[queryField] = payload.sql
27
+ return startCh.runStores(ctx, () => {
28
+ queryParent[queryField] = ctx.sql
34
29
 
35
- const cb = callbackResource.bind(request.callback, request)
36
- request.callback = asyncResource.bind(function (error) {
30
+ const cb = request.callback
31
+ request.callback = function (error, ...args) {
37
32
  if (error) {
38
- errorCh.publish(error)
33
+ ctx.error = error
34
+ errorCh.publish(ctx)
39
35
  }
40
- finishCh.publish()
41
-
42
- return cb.apply(this, arguments)
43
- }, null, request)
36
+ return finishCh.runStores(ctx, cb, this, error, ...args)
37
+ }
44
38
 
45
39
  try {
46
40
  return makeRequest.apply(this, arguments)
47
41
  } catch (error) {
48
- errorCh.publish(error)
42
+ ctx.error = error
43
+ errorCh.publish(ctx)
49
44
 
50
45
  throw error
51
46
  }
@@ -73,9 +73,25 @@ class BaseAwsSdkPlugin extends ClientPlugin {
73
73
  span.addTags(requestTags)
74
74
  }
75
75
 
76
+ this.enter(span)
76
77
  const store = storage('legacy').getStore()
77
78
 
78
- this.enter(span, store)
79
+ const peerServerlessStorage = storage('peerServerless')
80
+ if (!this._tracerConfig?._isInServerlessEnvironment()) return
81
+
82
+ // Try to resolve the hostname immediately; if not possible, keep enough
83
+ // information so the region callback can resolve it later.
84
+ const hostname = getHostname({ awsParams: request.params, awsService }, awsRegion)
85
+ const peerServerlessStore = {}
86
+ peerServerlessStorage.enterWith(peerServerlessStore)
87
+
88
+ if (hostname) {
89
+ span.setTag('peer.service', hostname)
90
+ peerServerlessStore.peerHostname = hostname
91
+ } else {
92
+ store.awsParams = request.params
93
+ store.awsService = awsService
94
+ }
79
95
  })
80
96
 
81
97
  this.addSub(`apm:aws:request:region:${this.serviceIdentifier}`, region => {
@@ -85,6 +101,17 @@ class BaseAwsSdkPlugin extends ClientPlugin {
85
101
  if (!span) return
86
102
  span.setTag('aws.region', region)
87
103
  span.setTag('region', region)
104
+
105
+ if (!this._tracerConfig?._isInServerlessEnvironment()) return
106
+
107
+ const hostname = getHostname(store, region)
108
+ if (!hostname) return
109
+
110
+ span.setTag('peer.service', hostname)
111
+ const peerServerlessStore = storage('peerServerless').getStore()
112
+ if (peerServerlessStore) {
113
+ peerServerlessStore.peerHostname = hostname
114
+ }
88
115
  })
89
116
 
90
117
  this.addSub(`apm:aws:request:complete:${this.serviceIdentifier}`, ({ response, cbExists = false }) => {
@@ -243,4 +270,27 @@ function getHooks (config) {
243
270
  return { request }
244
271
  }
245
272
 
273
+ function getHostname (store, region) {
274
+ if (!store) return
275
+ if (!region) return
276
+ const { awsParams, awsService } = store
277
+ switch (awsService) {
278
+ case 'EventBridge':
279
+ return `events.${region}.amazonaws.com`
280
+ case 'SQS':
281
+ return `sqs.${region}.amazonaws.com`
282
+ case 'SNS':
283
+ return `sns.${region}.amazonaws.com`
284
+ case 'Kinesis':
285
+ return `kinesis.${region}.amazonaws.com`
286
+ case 'DynamoDBDocument':
287
+ case 'DynamoDB':
288
+ return `dynamodb.${region}.amazonaws.com`
289
+ case 'S3':
290
+ return awsParams?.Bucket
291
+ ? `${awsParams.Bucket}.s3.${region}.amazonaws.com`
292
+ : `s3.${region}.amazonaws.com`
293
+ }
294
+ }
295
+
246
296
  module.exports = BaseAwsSdkPlugin
@@ -63,7 +63,7 @@ function scrubChildProcessCmd (expression) {
63
63
 
64
64
  if (token === null) {
65
65
  continue
66
- } else if (typeof token === 'object') {
66
+ } else if (typeof token === 'object') { // eslint-disable-line eslint-rules/eslint-safe-typeof-object
67
67
  if (token.pattern) {
68
68
  result.push(token.pattern)
69
69
  } else if (token.op) {
@@ -1,5 +1,3 @@
1
- /* eslint-disable unicorn/no-abusive-eslint-disable */
2
- /* eslint-disable */
3
1
  let isEarlyFlakeDetectionEnabled = false
4
2
  let isKnownTestsEnabled = false
5
3
  let knownTestsForSuite = []
@@ -20,7 +18,7 @@ let originalWindow
20
18
  function safeGetRum (window) {
21
19
  try {
22
20
  return window.DD_RUM
23
- } catch (e) {
21
+ } catch {
24
22
  return null
25
23
  }
26
24
  }
@@ -30,12 +28,13 @@ function isNewTest (test) {
30
28
  }
31
29
 
32
30
  function getTestProperties (testName) {
33
- // We neeed to do it in this way because of compatibility with older versions as '?' is not supported in older versions of Cypress
34
- const properties = testManagementTests[testName] && testManagementTests[testName].properties || {};
31
+ // We neeed to do it in this way because of compatibility with older versions as '?' is not supported in older
32
+ // versions of Cypress
33
+ const properties = testManagementTests[testName] && testManagementTests[testName].properties || {}
35
34
 
36
- const { attempt_to_fix: isAttemptToFix, disabled: isDisabled, quarantined: isQuarantined } = properties;
35
+ const { attempt_to_fix: isAttemptToFix, disabled: isDisabled, quarantined: isQuarantined } = properties
37
36
 
38
- return { isAttemptToFix, isDisabled, isQuarantined };
37
+ return { isAttemptToFix, isDisabled, isQuarantined }
39
38
  }
40
39
 
41
40
  function retryTest (test, suiteTests, numRetries, tags) {
@@ -63,11 +62,9 @@ Cypress.mocha.getRunner().runTests = function (suite, fn) {
63
62
 
64
63
  const { isAttemptToFix } = getTestProperties(testName)
65
64
 
66
- if (isTestManagementEnabled) {
67
- if (isAttemptToFix && !test.isPending()) {
68
- test._ddIsAttemptToFix = true
69
- retryTest(test, suite.tests, testManagementAttemptToFixRetries, ['_ddIsAttemptToFix'])
70
- }
65
+ if (isTestManagementEnabled && isAttemptToFix && !test.isPending()) {
66
+ test._ddIsAttemptToFix = true
67
+ retryTest(test, suite.tests, testManagementAttemptToFixRetries, ['_ddIsAttemptToFix'])
71
68
  }
72
69
  if (isImpactedTestsEnabled && isModifiedTest) {
73
70
  test._ddIsModified = true
@@ -80,15 +77,13 @@ Cypress.mocha.getRunner().runTests = function (suite, fn) {
80
77
  )
81
78
  }
82
79
  }
83
- if (isKnownTestsEnabled) {
84
- if (!test._ddIsNew && !test.isPending() && isNewTest(test)) {
85
- test._ddIsNew = true
86
- if (isImpactedTestsEnabled && isModifiedTest) {
87
- test._ddIsModified = true
88
- }
89
- if (isEarlyFlakeDetectionEnabled && !isAttemptToFix && !isModifiedTest) {
90
- retryTest(test, suite.tests, earlyFlakeDetectionNumRetries, ['_ddIsNew', '_ddIsEfdRetry'])
91
- }
80
+ if (isKnownTestsEnabled && !test._ddIsNew && !test.isPending() && isNewTest(test)) {
81
+ test._ddIsNew = true
82
+ if (isImpactedTestsEnabled && isModifiedTest) {
83
+ test._ddIsModified = true
84
+ }
85
+ if (isEarlyFlakeDetectionEnabled && !isAttemptToFix && !isModifiedTest) {
86
+ retryTest(test, suite.tests, earlyFlakeDetectionNumRetries, ['_ddIsNew', '_ddIsEfdRetry'])
92
87
  }
93
88
  }
94
89
  })
@@ -135,12 +130,11 @@ after(() => {
135
130
  if (safeGetRum(originalWindow)) {
136
131
  originalWindow.dispatchEvent(new Event('beforeunload'))
137
132
  }
138
- } catch (e) {
133
+ } catch {
139
134
  // ignore error. It's usually a multi origin issue.
140
135
  }
141
136
  })
142
137
 
143
-
144
138
  afterEach(function () {
145
139
  const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest
146
140
  const testInfo = {
@@ -156,7 +150,7 @@ afterEach(function () {
156
150
  }
157
151
  try {
158
152
  testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line
159
- } catch (e) {}
153
+ } catch {}
160
154
 
161
155
  if (safeGetRum(originalWindow)) {
162
156
  testInfo.isRUMActive = true
@@ -164,7 +158,7 @@ afterEach(function () {
164
158
  let coverage
165
159
  try {
166
160
  coverage = originalWindow.__coverage__
167
- } catch (e) {
161
+ } catch {
168
162
  // ignore error and continue
169
163
  }
170
164
  cy.task('dd:afterEach', { test: testInfo, coverage })
@@ -1,5 +1,3 @@
1
- /* eslint-disable unicorn/no-abusive-eslint-disable */
2
- /* eslint-disable */
3
1
  // file mostly untouched from apollo-graphql
4
2
 
5
3
  "use strict";
@@ -1,5 +1,3 @@
1
- /* eslint-disable unicorn/no-abusive-eslint-disable */
2
- /* eslint-disable */
3
1
  // file mostly untouched from apollo-graphql
4
2
 
5
3
  "use strict";
@@ -1,5 +1,3 @@
1
- /* eslint-disable unicorn/no-abusive-eslint-disable */
2
- /* eslint-disable */
3
1
  // file mostly untouched from apollo-graphql
4
2
 
5
3
  "use strict";
@@ -89,7 +89,8 @@ class HttpClientPlugin extends ClientPlugin {
89
89
  return parentStore
90
90
  }
91
91
 
92
- finish ({ req, res, span }) {
92
+ finish (ctx) {
93
+ const { req, res, span } = ctx
93
94
  if (!span) return
94
95
  if (res) {
95
96
  const status = res.status || res.statusCode
@@ -109,9 +110,7 @@ class HttpClientPlugin extends ClientPlugin {
109
110
 
110
111
  this.config.hooks.request(span, req, res)
111
112
 
112
- this.tagPeerService(span)
113
-
114
- span.finish()
113
+ super.finish(ctx)
115
114
  }
116
115
 
117
116
  error ({ span, error, args, customRequestTimeout }) {
@@ -73,7 +73,9 @@ class Http2ClientPlugin extends ClientPlugin {
73
73
  return message.currentStore
74
74
  }
75
75
 
76
- bindAsyncStart ({ eventName, eventData, currentStore, parentStore }) {
76
+ bindAsyncStart (ctx) {
77
+ const { eventName, eventData, currentStore, parentStore } = ctx
78
+
77
79
  // Plugin wasn't enabled when the request started.
78
80
  if (!currentStore) return storage('legacy').getStore()
79
81
 
@@ -82,10 +84,10 @@ class Http2ClientPlugin extends ClientPlugin {
82
84
  this._onResponse(currentStore, eventData)
83
85
  return parentStore
84
86
  case 'error':
85
- this._onError(currentStore, eventData)
87
+ this._onError(currentStore, eventData, ctx)
86
88
  return parentStore
87
89
  case 'close':
88
- this._onClose(currentStore, eventData)
90
+ this._onClose(ctx)
89
91
  return parentStore
90
92
  }
91
93
 
@@ -108,14 +110,13 @@ class Http2ClientPlugin extends ClientPlugin {
108
110
  addHeaderTags(store.span, headers, HTTP_RESPONSE_HEADERS, this.config)
109
111
  }
110
112
 
111
- _onError ({ span }, error) {
113
+ _onError ({ span }, error, ctx) {
112
114
  span.setTag('error', error)
113
- span.finish()
115
+ super.finish(ctx)
114
116
  }
115
117
 
116
- _onClose ({ span }) {
117
- this.tagPeerService(span)
118
- span.finish()
118
+ _onClose (ctx) {
119
+ super.finish(ctx)
119
120
  }
120
121
  }
121
122
 
@@ -13,7 +13,7 @@ class LangChainChainHandler extends LangChainHandler {
13
13
 
14
14
  for (const idx in inputs) {
15
15
  const input = inputs[idx]
16
- if (typeof input === 'object') {
16
+ if (input !== null && typeof input === 'object') {
17
17
  for (const [key, value] of Object.entries(input)) {
18
18
  // these are mappings to the python client names, ie lc_kwargs
19
19
  // only present on BaseMessage types
@@ -27,7 +27,7 @@ class LangChainChatModelHandler extends LangChainLanguageModelHandler {
27
27
  const identifyingParams = (typeof instance._identifyingParams === 'function' && instance._identifyingParams()) || {}
28
28
  for (const [param, val] of Object.entries(identifyingParams)) {
29
29
  if (param.toLowerCase().includes('apikey') || param.toLowerCase().includes('apitoken')) continue
30
- if (typeof val === 'object') {
30
+ if (val !== null && typeof val === 'object') {
31
31
  for (const [key, value] of Object.entries(val)) {
32
32
  tags[`langchain.request.${provider}.parameters.${param}.${key}`] = value
33
33
  }
@@ -18,7 +18,7 @@ class LangChainLLMHandler extends LangChainLanguageModelHandler {
18
18
  const identifyingParams = (typeof instance._identifyingParams === 'function' && instance._identifyingParams()) || {}
19
19
  for (const [param, val] of Object.entries(identifyingParams)) {
20
20
  if (param.toLowerCase().includes('apikey') || param.toLowerCase().includes('apitoken')) continue
21
- if (typeof val === 'object') {
21
+ if (val !== null && typeof val === 'object') {
22
22
  for (const [key, value] of Object.entries(val)) {
23
23
  tags[`langchain.request.${provider}.parameters.${param}.${key}`] = value
24
24
  }
@@ -0,0 +1,35 @@
1
+ const { URL } = require('url')
2
+ const log = require('../../dd-trace/src/log')
3
+
4
+ function parseOracleDescriptor (descriptor) {
5
+ const hostnameMatch = descriptor.match(/HOST\s*=\s*([^)]+)/i)
6
+ const hostname = hostnameMatch?.[1] || 'localhost' // Default Oracle hostname
7
+
8
+ const portMatch = descriptor.match(/PORT\s*=\s*([^)]+)/i)
9
+ const port = portMatch?.[1] || '1521' // Default Oracle port
10
+
11
+ const sidMatch = descriptor.match(/SID\s*=\s*([^)]+)/i)
12
+
13
+ const dbInstance = sidMatch?.[1] || descriptor.match(/SERVICE_NAME\s*=\s*([^)]+)/i)?.[1] || 'XEPDB1' // Default Oracle service name
14
+
15
+ return { hostname, port, dbInstance }
16
+ }
17
+
18
+ module.exports = function getDBInformation (connAttrs) {
19
+ // Users can pass either connectString or connectionString
20
+ const connectString = ((connAttrs.connectString || connAttrs.connectionString) ?? '').trim()
21
+ if (connectString.startsWith('(')) {
22
+ return parseOracleDescriptor(connectString)
23
+ }
24
+ try {
25
+ const url = new URL(`oracle://${connectString}`)
26
+ return {
27
+ hostname: url.hostname || 'localhost', // Default Oracle hostname
28
+ port: url.port || '1521', // Default Oracle port
29
+ dbInstance: url.pathname && url.pathname.slice(1) || 'XEPDB1' // Default Oracle service name
30
+ }
31
+ } catch (error) {
32
+ log.error('Invalid oracle connection string', error)
33
+ return {}
34
+ }
35
+ }