dd-trace 3.50.0 → 3.52.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 (80) hide show
  1. package/README.md +7 -0
  2. package/ci/cypress/after-spec.js +1 -0
  3. package/index.d.ts +1502 -1485
  4. package/package.json +4 -4
  5. package/packages/datadog-core/src/utils/src/get.js +11 -0
  6. package/packages/datadog-core/src/utils/src/has.js +14 -0
  7. package/packages/datadog-core/src/utils/src/set.js +16 -0
  8. package/packages/datadog-instrumentations/src/amqplib.js +1 -1
  9. package/packages/datadog-instrumentations/src/cucumber.js +2 -1
  10. package/packages/datadog-instrumentations/src/grpc/server.js +3 -1
  11. package/packages/datadog-instrumentations/src/jest.js +11 -5
  12. package/packages/datadog-instrumentations/src/mocha.js +4 -1
  13. package/packages/datadog-instrumentations/src/mongodb-core.js +34 -3
  14. package/packages/datadog-instrumentations/src/playwright.js +78 -16
  15. package/packages/datadog-plugin-amqplib/src/consumer.js +5 -4
  16. package/packages/datadog-plugin-amqplib/src/producer.js +3 -4
  17. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
  18. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -11
  19. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -6
  20. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +5 -7
  21. package/packages/datadog-plugin-cucumber/src/index.js +2 -2
  22. package/packages/datadog-plugin-cypress/src/after-spec.js +3 -0
  23. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +123 -58
  24. package/packages/datadog-plugin-cypress/src/support.js +50 -3
  25. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  26. package/packages/datadog-plugin-graphql/src/resolve.js +10 -8
  27. package/packages/datadog-plugin-grpc/src/util.js +1 -1
  28. package/packages/datadog-plugin-jest/src/index.js +13 -4
  29. package/packages/datadog-plugin-kafkajs/src/consumer.js +4 -3
  30. package/packages/datadog-plugin-kafkajs/src/producer.js +3 -5
  31. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  32. package/packages/datadog-plugin-playwright/src/index.js +34 -3
  33. package/packages/datadog-plugin-rhea/src/consumer.js +5 -3
  34. package/packages/datadog-plugin-rhea/src/producer.js +3 -4
  35. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +23 -12
  36. package/packages/dd-trace/src/appsec/iast/index.js +10 -0
  37. package/packages/dd-trace/src/appsec/iast/path-line.js +9 -6
  38. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +1 -1
  39. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +6 -2
  40. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +1 -1
  41. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +14 -2
  42. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
  43. package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +34 -27
  44. package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +39 -11
  45. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +7 -6
  46. package/packages/dd-trace/src/appsec/recommended.json +67 -27
  47. package/packages/dd-trace/src/appsec/remote_config/index.js +1 -1
  48. package/packages/dd-trace/src/appsec/reporter.js +24 -11
  49. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -3
  50. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +6 -1
  51. package/packages/dd-trace/src/config.js +451 -460
  52. package/packages/dd-trace/src/data_streams_context.js +1 -1
  53. package/packages/dd-trace/src/datastreams/pathway.js +58 -1
  54. package/packages/dd-trace/src/datastreams/processor.js +3 -5
  55. package/packages/dd-trace/src/format.js +0 -1
  56. package/packages/dd-trace/src/lambda/runtime/ritm.js +1 -1
  57. package/packages/dd-trace/src/opentracing/propagation/text_map.js +22 -3
  58. package/packages/dd-trace/src/opentracing/span.js +2 -0
  59. package/packages/dd-trace/src/opentracing/span_context.js +1 -0
  60. package/packages/dd-trace/src/plugins/util/test.js +4 -2
  61. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  62. package/packages/dd-trace/src/priority_sampler.js +11 -6
  63. package/packages/dd-trace/src/profiling/exporters/agent.js +38 -2
  64. package/packages/dd-trace/src/telemetry/index.js +32 -33
  65. package/packages/dd-trace/src/tracer.js +3 -3
  66. package/register.js +4 -0
  67. package/CONTRIBUTING.md +0 -171
  68. package/MIGRATING.md +0 -224
  69. package/packages/dd-trace/src/external-logger/test/index.spec.js +0 -147
  70. package/scripts/check-proposal-labels.js +0 -71
  71. package/scripts/check_licenses.js +0 -69
  72. package/scripts/helpers/color.js +0 -8
  73. package/scripts/helpers/exec.js +0 -22
  74. package/scripts/helpers/title.js +0 -15
  75. package/scripts/install_plugin_modules.js +0 -248
  76. package/scripts/publish_docs.js +0 -21
  77. package/scripts/st.js +0 -105
  78. /package/packages/{utils → datadog-core/src/utils}/src/kebabcase.js +0 -0
  79. /package/packages/{utils → datadog-core/src/utils}/src/pick.js +0 -0
  80. /package/packages/{utils → datadog-core/src/utils}/src/uniq.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "3.50.0",
3
+ "version": "3.52.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -69,11 +69,11 @@
69
69
  "node": ">=14"
70
70
  },
71
71
  "dependencies": {
72
- "@datadog/native-appsec": "7.0.0",
73
- "@datadog/native-iast-rewriter": "2.2.3",
72
+ "@datadog/native-appsec": "7.1.0",
73
+ "@datadog/native-iast-rewriter": "2.3.0",
74
74
  "@datadog/native-iast-taint-tracking": "1.7.0",
75
75
  "@datadog/native-metrics": "^2.0.0",
76
- "@datadog/pprof": "5.0.0",
76
+ "@datadog/pprof": "5.1.0",
77
77
  "@datadog/sketches-js": "^2.1.0",
78
78
  "@opentelemetry/api": "^1.0.0",
79
79
  "@opentelemetry/core": "^1.14.0",
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ module.exports = (object, path) => {
4
+ const pathArr = path.split('.')
5
+ let val = object
6
+ for (const p of pathArr) {
7
+ if (val === undefined) return val
8
+ val = val[p]
9
+ }
10
+ return val
11
+ }
@@ -0,0 +1,14 @@
1
+ 'use strict'
2
+
3
+ module.exports = (object, path) => {
4
+ const pathArr = path.split('.')
5
+ let property = object
6
+ for (const n of pathArr) {
7
+ if (property.hasOwnProperty(n)) {
8
+ property = property[n]
9
+ } else {
10
+ return false
11
+ }
12
+ }
13
+ return true
14
+ }
@@ -0,0 +1,16 @@
1
+ 'use strict'
2
+
3
+ module.exports = (object, path, value) => {
4
+ const pathArr = path.split('.')
5
+ let property = object
6
+ let i
7
+ for (i = 0; i < pathArr.length - 1; i++) {
8
+ const n = pathArr[i]
9
+ if (property.hasOwnProperty(n)) {
10
+ property = property[n]
11
+ } else {
12
+ property[n] = property = {}
13
+ }
14
+ }
15
+ property[pathArr[i]] = value
16
+ }
@@ -5,7 +5,7 @@ const {
5
5
  addHook,
6
6
  AsyncResource
7
7
  } = require('./helpers/instrument')
8
- const kebabCase = require('../../utils/src/kebabcase')
8
+ const kebabCase = require('../../datadog-core/src/utils/src/kebabcase')
9
9
  const shimmer = require('../../datadog-shimmer')
10
10
 
11
11
  const startCh = channel('apm:amqplib:command:start')
@@ -92,7 +92,8 @@ function getStatusFromResultLatest (result) {
92
92
  }
93
93
 
94
94
  function isNewTest (testSuite, testName) {
95
- return !knownTests.includes(`cucumber.${testSuite}.${testName}`)
95
+ const testsForSuite = knownTests.cucumber?.[testSuite] || []
96
+ return !testsForSuite.includes(testName)
96
97
  }
97
98
 
98
99
  function getTestStatusFromRetries (testStatuses) {
@@ -92,7 +92,9 @@ function createWrapEmit (call, ctx, onCancel) {
92
92
  finishChannel.publish(ctx)
93
93
  call.removeListener('cancelled', onCancel)
94
94
  break
95
- case 'finish':
95
+ // Streams are always cancelled before `finish` since 1.10.0 so we have
96
+ // to use `prefinish` instead to avoid cancellation false positives.
97
+ case 'prefinish':
96
98
  if (call.status) {
97
99
  updateChannel.publish(call.status)
98
100
  }
@@ -115,6 +115,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
115
115
  this.nameToParams = {}
116
116
  this.global._ddtrace = global._ddtrace
117
117
 
118
+ this.displayName = config.projectConfig?.displayName?.name
118
119
  this.testEnvironmentOptions = getTestEnvironmentOptions(config)
119
120
 
120
121
  const repositoryRoot = this.testEnvironmentOptions._ddRepositoryRoot
@@ -139,14 +140,16 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
139
140
  // Function that receives a list of known tests for a test service and
140
141
  // returns the ones that belong to the current suite
141
142
  getKnownTestsForSuite (knownTests) {
143
+ if (this.knownTestsForThisSuite) {
144
+ return this.knownTestsForThisSuite
145
+ }
142
146
  let knownTestsForSuite = knownTests
143
- // If jest runs in band, the known tests are not serialized, so they're an array.
144
- if (!Array.isArray(knownTests)) {
147
+ // If jest is using workers, known tests are serialized to json.
148
+ // If jest runs in band, they are not.
149
+ if (typeof knownTestsForSuite === 'string') {
145
150
  knownTestsForSuite = JSON.parse(knownTestsForSuite)
146
151
  }
147
- return knownTestsForSuite
148
- .filter(test => test.includes(this.testSuite))
149
- .map(test => test.replace(`jest.${this.testSuite}.`, '').trim())
152
+ return knownTestsForSuite.jest?.[this.testSuite] || []
150
153
  }
151
154
 
152
155
  // Add the `add_test` event we don't have the test object yet, so
@@ -201,6 +204,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
201
204
  suite: this.testSuite,
202
205
  testSourceFile: this.testSourceFile,
203
206
  runner: 'jest-circus',
207
+ displayName: this.displayName,
204
208
  testParameters,
205
209
  frameworkVersion: jestVersion,
206
210
  isNew: isNewTest,
@@ -252,6 +256,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
252
256
  suite: this.testSuite,
253
257
  testSourceFile: this.testSourceFile,
254
258
  runner: 'jest-circus',
259
+ displayName: this.displayName,
255
260
  frameworkVersion: jestVersion,
256
261
  testStartLine: getTestLineStart(event.test.asyncError, this.testSuite)
257
262
  })
@@ -559,6 +564,7 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
559
564
  testSuiteStartCh.publish({
560
565
  testSuite: environment.testSuite,
561
566
  testEnvironmentOptions: environment.testEnvironmentOptions,
567
+ displayName: environment.displayName,
562
568
  frameworkVersion: jestVersion
563
569
  })
564
570
  return adapter.apply(this, arguments).then(suiteResults => {
@@ -106,7 +106,10 @@ function getTestFullName (test) {
106
106
  }
107
107
 
108
108
  function isNewTest (test) {
109
- return !knownTests.includes(getTestFullName(test))
109
+ const testSuite = getTestSuitePath(test.file, process.cwd())
110
+ const testName = removeEfdStringFromTestName(test.fullTitle())
111
+ const testsForSuite = knownTests.mocha?.[testSuite] || []
112
+ return !testsForSuite.includes(testName)
110
113
  }
111
114
 
112
115
  function retryTest (test) {
@@ -32,12 +32,18 @@ addHook({ name: 'mongodb', versions: ['>=4 <4.6.0'], file: 'lib/cmap/connection.
32
32
  return Connection
33
33
  })
34
34
 
35
- addHook({ name: 'mongodb', versions: ['>=4.6.0'], file: 'lib/cmap/connection.js' }, Connection => {
35
+ addHook({ name: 'mongodb', versions: ['>=4.6.0 <6.4.0'], file: 'lib/cmap/connection.js' }, Connection => {
36
36
  const proto = Connection.Connection.prototype
37
37
  shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command'))
38
38
  return Connection
39
39
  })
40
40
 
41
+ addHook({ name: 'mongodb', versions: ['>=6.4.0'], file: 'lib/cmap/connection.js' }, Connection => {
42
+ const proto = Connection.Connection.prototype
43
+ shimmer.wrap(proto, 'command', command => wrapConnectionCommand(command, 'command', undefined, instrumentPromise))
44
+ return Connection
45
+ })
46
+
41
47
  addHook({ name: 'mongodb', versions: ['>=3.3 <4'], file: 'lib/core/wireprotocol/index.js' }, wp => wrapWp(wp))
42
48
 
43
49
  addHook({ name: 'mongodb-core', versions: ['>=3.2'], file: 'lib/wireprotocol/index.js' }, wp => wrapWp(wp))
@@ -89,7 +95,7 @@ function wrapUnifiedCommand (command, operation, name) {
89
95
  return shimmer.wrap(command, wrapped)
90
96
  }
91
97
 
92
- function wrapConnectionCommand (command, operation, name) {
98
+ function wrapConnectionCommand (command, operation, name, instrumentFn = instrument) {
93
99
  const wrapped = function (ns, ops) {
94
100
  if (!startCh.hasSubscribers) {
95
101
  return command.apply(this, arguments)
@@ -101,7 +107,7 @@ function wrapConnectionCommand (command, operation, name) {
101
107
  const topology = { s: { options } }
102
108
 
103
109
  ns = `${ns.db}.${ns.collection}`
104
- return instrument(operation, command, this, arguments, topology, ns, ops, { name })
110
+ return instrumentFn(operation, command, this, arguments, topology, ns, ops, { name })
105
111
  }
106
112
  return shimmer.wrap(command, wrapped)
107
113
  }
@@ -179,3 +185,28 @@ function instrument (operation, command, ctx, args, server, ns, ops, options = {
179
185
  }
180
186
  })
181
187
  }
188
+
189
+ function instrumentPromise (operation, command, ctx, args, server, ns, ops, options = {}) {
190
+ const name = options.name || (ops && Object.keys(ops)[0])
191
+
192
+ const serverInfo = server && server.s && server.s.options
193
+ const asyncResource = new AsyncResource('bound-anonymous-fn')
194
+
195
+ return asyncResource.runInAsyncScope(() => {
196
+ startCh.publish({ ns, ops, options: serverInfo, name })
197
+
198
+ const promise = command.apply(ctx, args)
199
+
200
+ promise.then(function (res) {
201
+ finishCh.publish()
202
+ return res
203
+ }, function (err) {
204
+ errorCh.publish(err)
205
+ finishCh.publish()
206
+
207
+ return Promise.reject(err)
208
+ })
209
+
210
+ return promise
211
+ })
212
+ }
@@ -14,6 +14,7 @@ const testSuiteFinishCh = channel('ci:playwright:test-suite:finish')
14
14
  const testToAr = new WeakMap()
15
15
  const testSuiteToAr = new Map()
16
16
  const testSuiteToTestStatuses = new Map()
17
+ const testSuiteToErrors = new Map()
17
18
 
18
19
  let startedSuites = []
19
20
 
@@ -81,7 +82,12 @@ function getRootDir (playwrightRunner) {
81
82
 
82
83
  function getProjectsFromRunner (runner) {
83
84
  const config = getPlaywrightConfig(runner)
84
- return config.projects?.map(({ project }) => project)
85
+ return config.projects?.map((project) => {
86
+ if (project.project) {
87
+ return project.project
88
+ }
89
+ return project
90
+ })
85
91
  }
86
92
 
87
93
  function getProjectsFromDispatcher (dispatcher) {
@@ -93,13 +99,55 @@ function getProjectsFromDispatcher (dispatcher) {
93
99
  return dispatcher._loader?.fullConfig()?.projects
94
100
  }
95
101
 
96
- function getBrowserNameFromProjects (projects, projectId) {
97
- if (!projects) {
102
+ function getBrowserNameFromProjects (projects, test) {
103
+ if (!projects || !test) {
98
104
  return null
99
105
  }
100
- return projects.find(project =>
101
- project.__projectId === projectId || project._id === projectId
102
- )?.name
106
+ const { _projectIndex, _projectId: testProjectId } = test
107
+
108
+ if (_projectIndex !== undefined) {
109
+ return projects[_projectIndex]?.name
110
+ }
111
+
112
+ return projects.find(({ __projectId, _id, name }) => {
113
+ if (__projectId !== undefined) {
114
+ return __projectId === testProjectId
115
+ }
116
+ if (_id !== undefined) {
117
+ return _id === testProjectId
118
+ }
119
+ return name === testProjectId
120
+ })?.name
121
+ }
122
+
123
+ function formatTestHookError (error, hookType, isTimeout) {
124
+ let hookError = error
125
+ if (error) {
126
+ hookError.message = `Error in ${hookType} hook: ${error.message}`
127
+ }
128
+ if (!hookError && isTimeout) {
129
+ hookError = new Error(`${hookType} hook timed out`)
130
+ }
131
+ return hookError
132
+ }
133
+
134
+ function addErrorToTestSuite (testSuiteAbsolutePath, error) {
135
+ if (testSuiteToErrors.has(testSuiteAbsolutePath)) {
136
+ testSuiteToErrors.get(testSuiteAbsolutePath).push(error)
137
+ } else {
138
+ testSuiteToErrors.set(testSuiteAbsolutePath, [error])
139
+ }
140
+ }
141
+
142
+ function getTestSuiteError (testSuiteAbsolutePath) {
143
+ const errors = testSuiteToErrors.get(testSuiteAbsolutePath)
144
+ if (!errors) {
145
+ return null
146
+ }
147
+ if (errors.length === 1) {
148
+ return errors[0]
149
+ }
150
+ return new Error(`${errors.length} errors in this test suite:\n${errors.map(e => e.message).join('\n------\n')}`)
103
151
  }
104
152
 
105
153
  function testBeginHandler (test, browserName) {
@@ -131,7 +179,7 @@ function testBeginHandler (test, browserName) {
131
179
  })
132
180
  }
133
181
 
134
- function testEndHandler (test, annotations, testStatus, error) {
182
+ function testEndHandler (test, annotations, testStatus, error, isTimeout) {
135
183
  let annotationTags
136
184
  if (annotations.length) {
137
185
  annotationTags = parseAnnotations(annotations)
@@ -139,6 +187,11 @@ function testEndHandler (test, annotations, testStatus, error) {
139
187
  const { _requireFile: testSuiteAbsolutePath, results, _type } = test
140
188
 
141
189
  if (_type === 'beforeAll' || _type === 'afterAll') {
190
+ const hookError = formatTestHookError(error, _type, isTimeout)
191
+
192
+ if (hookError) {
193
+ addErrorToTestSuite(testSuiteAbsolutePath, hookError)
194
+ }
142
195
  return
143
196
  }
144
197
 
@@ -148,15 +201,20 @@ function testEndHandler (test, annotations, testStatus, error) {
148
201
  testFinishCh.publish({ testStatus, steps: testResult.steps, error, extraTags: annotationTags })
149
202
  })
150
203
 
151
- if (!testSuiteToTestStatuses.has(testSuiteAbsolutePath)) {
152
- testSuiteToTestStatuses.set(testSuiteAbsolutePath, [testStatus])
153
- } else {
204
+ if (testSuiteToTestStatuses.has(testSuiteAbsolutePath)) {
154
205
  testSuiteToTestStatuses.get(testSuiteAbsolutePath).push(testStatus)
206
+ } else {
207
+ testSuiteToTestStatuses.set(testSuiteAbsolutePath, [testStatus])
208
+ }
209
+
210
+ if (error) {
211
+ addErrorToTestSuite(testSuiteAbsolutePath, error)
155
212
  }
156
213
 
157
214
  remainingTestsByFile[testSuiteAbsolutePath] = remainingTestsByFile[testSuiteAbsolutePath]
158
215
  .filter(currentTest => currentTest !== test)
159
216
 
217
+ // Last test, we finish the suite
160
218
  if (!remainingTestsByFile[testSuiteAbsolutePath].length) {
161
219
  const testStatuses = testSuiteToTestStatuses.get(testSuiteAbsolutePath)
162
220
 
@@ -167,9 +225,10 @@ function testEndHandler (test, annotations, testStatus, error) {
167
225
  testSuiteStatus = 'skip'
168
226
  }
169
227
 
228
+ const suiteError = getTestSuiteError(testSuiteAbsolutePath)
170
229
  const testSuiteAsyncResource = testSuiteToAr.get(testSuiteAbsolutePath)
171
230
  testSuiteAsyncResource.runInAsyncScope(() => {
172
- testSuiteFinishCh.publish(testSuiteStatus)
231
+ testSuiteFinishCh.publish({ status: testSuiteStatus, error: suiteError })
173
232
  })
174
233
  }
175
234
  }
@@ -197,7 +256,7 @@ function dispatcherHook (dispatcherExport) {
197
256
  if (method === 'testBegin') {
198
257
  const { test } = dispatcher._testById.get(params.testId)
199
258
  const projects = getProjectsFromDispatcher(dispatcher)
200
- const browser = getBrowserNameFromProjects(projects, test._projectId)
259
+ const browser = getBrowserNameFromProjects(projects, test)
201
260
  testBeginHandler(test, browser)
202
261
  } else if (method === 'testEnd') {
203
262
  const { test } = dispatcher._testById.get(params.testId)
@@ -205,7 +264,8 @@ function dispatcherHook (dispatcherExport) {
205
264
  const { results } = test
206
265
  const testResult = results[results.length - 1]
207
266
 
208
- testEndHandler(test, params.annotations, STATUS_TO_TEST_STATUS[testResult.status], testResult.error)
267
+ const isTimeout = testResult.status === 'timedOut'
268
+ testEndHandler(test, params.annotations, STATUS_TO_TEST_STATUS[testResult.status], testResult.error, isTimeout)
209
269
  }
210
270
  })
211
271
 
@@ -232,13 +292,14 @@ function dispatcherHookNew (dispatcherExport, runWrapper) {
232
292
  worker.on('testBegin', ({ testId }) => {
233
293
  const test = getTestByTestId(dispatcher, testId)
234
294
  const projects = getProjectsFromDispatcher(dispatcher)
235
- const browser = getBrowserNameFromProjects(projects, test._projectId)
295
+ const browser = getBrowserNameFromProjects(projects, test)
236
296
  testBeginHandler(test, browser)
237
297
  })
238
298
  worker.on('testEnd', ({ testId, status, errors, annotations }) => {
239
299
  const test = getTestByTestId(dispatcher, testId)
240
300
 
241
- testEndHandler(test, annotations, STATUS_TO_TEST_STATUS[status], errors && errors[0])
301
+ const isTimeout = status === 'timedOut'
302
+ testEndHandler(test, annotations, STATUS_TO_TEST_STATUS[status], errors && errors[0], isTimeout)
242
303
  })
243
304
 
244
305
  return worker
@@ -265,7 +326,7 @@ function runnerHook (runnerExport, playwrightVersion) {
265
326
  // there were tests that did not go through `testBegin` or `testEnd`,
266
327
  // because they were skipped
267
328
  tests.forEach(test => {
268
- const browser = getBrowserNameFromProjects(projects, test._projectId)
329
+ const browser = getBrowserNameFromProjects(projects, test)
269
330
  testBeginHandler(test, browser)
270
331
  testEndHandler(test, [], 'skip')
271
332
  })
@@ -327,6 +388,7 @@ addHook({
327
388
  file: 'lib/runner/runner.js',
328
389
  versions: ['>=1.38.0']
329
390
  }, runnerHook)
391
+
330
392
  addHook({
331
393
  name: 'playwright',
332
394
  file: 'lib/runner/dispatcher.js',
@@ -2,7 +2,8 @@
2
2
 
3
3
  const { TEXT_MAP } = require('../../../ext/formats')
4
4
  const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
5
- const { getAmqpMessageSize, CONTEXT_PROPAGATION_KEY } = require('../../dd-trace/src/datastreams/processor')
5
+ const { getAmqpMessageSize } = require('../../dd-trace/src/datastreams/processor')
6
+ const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
6
7
  const { getResourceName } = require('./util')
7
8
 
8
9
  class AmqplibConsumerPlugin extends ConsumerPlugin {
@@ -29,12 +30,12 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
29
30
  })
30
31
 
31
32
  if (
32
- this.config.dsmEnabled &&
33
- message?.properties?.headers?.[CONTEXT_PROPAGATION_KEY]
33
+ this.config.dsmEnabled && message?.properties?.headers &&
34
+ DsmPathwayCodec.contextExists(message.properties.headers)
34
35
  ) {
35
36
  const payloadSize = getAmqpMessageSize({ headers: message.properties.headers, content: message.content })
36
37
  const queue = fields.queue ? fields.queue : fields.routingKey
37
- this.tracer.decodeDataStreamsContext(message.properties.headers[CONTEXT_PROPAGATION_KEY])
38
+ this.tracer.decodeDataStreamsContext(message.properties.headers)
38
39
  this.tracer
39
40
  .setCheckpoint(['direction:in', `topic:${queue}`, 'type:rabbitmq'], span, payloadSize)
40
41
  }
@@ -3,8 +3,8 @@
3
3
  const { TEXT_MAP } = require('../../../ext/formats')
4
4
  const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
5
5
  const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
6
- const { encodePathwayContext } = require('../../dd-trace/src/datastreams/pathway')
7
- const { getAmqpMessageSize, CONTEXT_PROPAGATION_KEY } = require('../../dd-trace/src/datastreams/processor')
6
+ const { DsmPathwayCodec } = require('../../dd-trace/src/datastreams/pathway')
7
+ const { getAmqpMessageSize } = require('../../dd-trace/src/datastreams/processor')
8
8
  const { getResourceName } = require('./util')
9
9
 
10
10
  class AmqplibProducerPlugin extends ProducerPlugin {
@@ -40,8 +40,7 @@ class AmqplibProducerPlugin extends ProducerPlugin {
40
40
  .setCheckpoint(
41
41
  ['direction:out', `exchange:${fields.exchange}`, `has_routing_key:${hasRoutingKey}`, 'type:rabbitmq']
42
42
  , span, payloadSize)
43
- const pathwayCtx = encodePathwayContext(dataStreamsContext)
44
- fields.headers[CONTEXT_PROPAGATION_KEY] = pathwayCtx
43
+ DsmPathwayCodec.encode(dataStreamsContext, fields.headers)
45
44
  }
46
45
  }
47
46
  }
@@ -126,8 +126,9 @@ class BaseAwsSdkPlugin extends ClientPlugin {
126
126
  if (err) {
127
127
  span.setTag('error', err)
128
128
 
129
- if (err.requestId) {
130
- span.addTags({ 'aws.response.request_id': err.requestId })
129
+ const requestId = err.RequestId || err.requestId
130
+ if (requestId) {
131
+ span.addTags({ 'aws.response.request_id': requestId })
131
132
  }
132
133
  }
133
134
 
@@ -1,9 +1,8 @@
1
1
  'use strict'
2
2
  const {
3
- CONTEXT_PROPAGATION_KEY,
4
3
  getSizeOrZero
5
4
  } = require('../../../dd-trace/src/datastreams/processor')
6
- const { encodePathwayContext } = require('../../../dd-trace/src/datastreams/pathway')
5
+ const { DsmPathwayCodec } = require('../../../dd-trace/src/datastreams/pathway')
7
6
  const log = require('../../../dd-trace/src/log')
8
7
  const BaseAwsSdkPlugin = require('../base')
9
8
  const { storage } = require('../../../datadog-core')
@@ -113,13 +112,10 @@ class Kinesis extends BaseAwsSdkPlugin {
113
112
  const parsedAttributes = JSON.parse(Buffer.from(record.Data).toString())
114
113
 
115
114
  if (
116
- parsedAttributes &&
117
- parsedAttributes._datadog &&
118
- parsedAttributes._datadog[CONTEXT_PROPAGATION_KEY] &&
119
- streamName
115
+ parsedAttributes?._datadog && streamName && DsmPathwayCodec.contextExists(parsedAttributes._datadog)
120
116
  ) {
121
117
  const payloadSize = getSizeOrZero(record.Data)
122
- this.tracer.decodeDataStreamsContext(Buffer.from(parsedAttributes._datadog[CONTEXT_PROPAGATION_KEY]))
118
+ this.tracer.decodeDataStreamsContext(parsedAttributes._datadog)
123
119
  this.tracer
124
120
  .setCheckpoint(['direction:in', `topic:${streamName}`, 'type:kinesis'], span, payloadSize)
125
121
  }
@@ -182,10 +178,7 @@ class Kinesis extends BaseAwsSdkPlugin {
182
178
  if (this.config.dsmEnabled) {
183
179
  parsedData._datadog = ddInfo
184
180
  const dataStreamsContext = this.setDSMCheckpoint(span, parsedData, stream)
185
- if (dataStreamsContext) {
186
- const pathwayCtx = encodePathwayContext(dataStreamsContext)
187
- ddInfo[CONTEXT_PROPAGATION_KEY] = pathwayCtx.toJSON()
188
- }
181
+ DsmPathwayCodec.encode(dataStreamsContext, ddInfo)
189
182
  }
190
183
 
191
184
  if (Object.keys(ddInfo).length !== 0) {
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
- const { CONTEXT_PROPAGATION_KEY, getHeadersSize } = require('../../../dd-trace/src/datastreams/processor')
3
- const { encodePathwayContext } = require('../../../dd-trace/src/datastreams/pathway')
2
+ const { getHeadersSize } = require('../../../dd-trace/src/datastreams/processor')
3
+ const { DsmPathwayCodec } = require('../../../dd-trace/src/datastreams/pathway')
4
4
  const log = require('../../../dd-trace/src/log')
5
5
  const BaseAwsSdkPlugin = require('../base')
6
6
 
@@ -94,10 +94,7 @@ class Sns extends BaseAwsSdkPlugin {
94
94
  }
95
95
 
96
96
  const dataStreamsContext = this.setDSMCheckpoint(span, params, topicArn)
97
- if (dataStreamsContext) {
98
- const pathwayCtx = encodePathwayContext(dataStreamsContext)
99
- ddInfo[CONTEXT_PROPAGATION_KEY] = pathwayCtx.toJSON()
100
- }
97
+ DsmPathwayCodec.encode(dataStreamsContext, ddInfo)
101
98
  }
102
99
 
103
100
  if (Object.keys(ddInfo).length !== 0) {
@@ -3,8 +3,8 @@
3
3
  const log = require('../../../dd-trace/src/log')
4
4
  const BaseAwsSdkPlugin = require('../base')
5
5
  const { storage } = require('../../../datadog-core')
6
- const { CONTEXT_PROPAGATION_KEY, getHeadersSize } = require('../../../dd-trace/src/datastreams/processor')
7
- const { encodePathwayContext } = require('../../../dd-trace/src/datastreams/pathway')
6
+ const { getHeadersSize } = require('../../../dd-trace/src/datastreams/processor')
7
+ const { DsmPathwayCodec } = require('../../../dd-trace/src/datastreams/pathway')
8
8
 
9
9
  class Sqs extends BaseAwsSdkPlugin {
10
10
  static get id () { return 'sqs' }
@@ -192,13 +192,13 @@ class Sqs extends BaseAwsSdkPlugin {
192
192
  parsedAttributes = this.parseDatadogAttributes(message.MessageAttributes._datadog)
193
193
  }
194
194
  }
195
- if (parsedAttributes && parsedAttributes[CONTEXT_PROPAGATION_KEY]) {
195
+ if (parsedAttributes && DsmPathwayCodec.contextExists(parsedAttributes)) {
196
196
  const payloadSize = getHeadersSize({
197
197
  Body: message.Body,
198
198
  MessageAttributes: message.MessageAttributes
199
199
  })
200
200
  const queue = params.QueueUrl.split('/').pop()
201
- this.tracer.decodeDataStreamsContext(Buffer.from(parsedAttributes[CONTEXT_PROPAGATION_KEY]))
201
+ this.tracer.decodeDataStreamsContext(parsedAttributes)
202
202
  this.tracer
203
203
  .setCheckpoint(['direction:in', `topic:${queue}`, 'type:sqs'], span, payloadSize)
204
204
  }
@@ -252,9 +252,7 @@ class Sqs extends BaseAwsSdkPlugin {
252
252
 
253
253
  const dataStreamsContext = this.setDSMCheckpoint(span, params, queueUrl)
254
254
  if (dataStreamsContext) {
255
- const pathwayCtx = encodePathwayContext(dataStreamsContext)
256
- ddInfo[CONTEXT_PROPAGATION_KEY] = pathwayCtx.toJSON()
257
-
255
+ DsmPathwayCodec.encode(dataStreamsContext, ddInfo)
258
256
  params.MessageAttributes._datadog.StringValue = JSON.stringify(ddInfo)
259
257
  }
260
258
  }
@@ -18,7 +18,7 @@ const {
18
18
  TEST_SOURCE_FILE,
19
19
  TEST_EARLY_FLAKE_IS_ENABLED,
20
20
  TEST_IS_NEW,
21
- TEST_EARLY_FLAKE_IS_RETRY
21
+ TEST_IS_RETRY
22
22
  } = require('../../dd-trace/src/plugins/util/test')
23
23
  const { RESOURCE_NAME } = require('../../../ext/tags')
24
24
  const { COMPONENT, ERROR_MESSAGE } = require('../../dd-trace/src/constants')
@@ -181,7 +181,7 @@ class CucumberPlugin extends CiPlugin {
181
181
  if (isNew) {
182
182
  span.setTag(TEST_IS_NEW, 'true')
183
183
  if (isEfdRetry) {
184
- span.setTag(TEST_EARLY_FLAKE_IS_RETRY, 'true')
184
+ span.setTag(TEST_IS_RETRY, 'true')
185
185
  }
186
186
  }
187
187
 
@@ -0,0 +1,3 @@
1
+ const cypressPlugin = require('./cypress-plugin')
2
+
3
+ module.exports = cypressPlugin.afterSpec.bind(cypressPlugin)